Merge "Revert "Revert "Open up AndroidPackage as @SystemApi"""
diff --git a/Android.bp b/Android.bp
index 9127966f..0ac41c0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -238,6 +238,7 @@
         "android.hardware.contexthub-V1.0-java",
         "android.hardware.contexthub-V1.1-java",
         "android.hardware.contexthub-V1.2-java",
+        "android.hardware.contexthub-V1-java",
         "android.hardware.gnss-V1.0-java",
         "android.hardware.gnss-V2.1-java",
         "android.hardware.health-V1.0-java-constants",
diff --git a/apct-tests/perftests/multiuser/AndroidTest.xml b/apct-tests/perftests/multiuser/AndroidTest.xml
index bec3cc9..a93d7e0 100644
--- a/apct-tests/perftests/multiuser/AndroidTest.xml
+++ b/apct-tests/perftests/multiuser/AndroidTest.xml
@@ -44,6 +44,9 @@
         <option name="package" value="com.android.perftests.multiuser" />
         <option name="hidden-api-checks" value="false"/>
 
+        <!-- Timeout individual tests only after 25m (rather than 10m default) for slow devices. -->
+        <option name="test-timeout" value="1500000" />
+
         <!-- Listener related args for collecting the traces and waiting for the device to stabilize. -->
         <option name="device-listeners" value="android.device.collectors.ProcLoadListener,android.device.collectors.PerfettoListener" />
         <!-- Guarantee that user defined RunListeners will be running before any of the default listeners defined in this runner. -->
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index 6e2742c..b6f2152 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -89,8 +89,8 @@
     private static final String TAG = UserLifecycleTests.class.getSimpleName();
 
     /** Max runtime for each test (including all runs within that test). */
-    // No point exceeding 10 minutes, since device would likely be considered non-responsive anyway.
-    private static final long TIMEOUT_MAX_TEST_TIME_MS = 9 * 60_000;
+    // Must be less than the AndroidTest.xml test-timeout to avoid being considered non-responsive.
+    private static final long TIMEOUT_MAX_TEST_TIME_MS = 24 * 60_000;
 
     private static final int TIMEOUT_IN_SECOND = 30;
     private static final int CHECK_USER_REMOVED_INTERVAL_MS = 200;
diff --git a/apex/blobstore/README.md b/apex/blobstore/README.md
new file mode 100644
index 0000000..69af436
--- /dev/null
+++ b/apex/blobstore/README.md
@@ -0,0 +1,125 @@
+<!--
+  Copyright (C) 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License
+-->
+
+# BlobStore Manager
+
+## Introduction
+* BlobStoreManager is a system service added in Android R release that facilitates sharing of
+  data blobs among apps.
+* Apps that would like to share data blobs with other apps can do so by contributing those
+  data blobs with the System and can choose how they would like the System to share the data blobs
+  with other apps.
+* Apps can access data blobs shared by other apps from the System using checksum of the data blobs
+  (plus some other data attributes. More details [below](#blob-handle)).
+* The APIs provided by the BlobStoreManager are meant to reduce storage and network usage by
+  reusing the data available on the device instead of downloading the same data again and having
+  multiple copies of the same data on disk.
+* It is not meant to provide access to the data which apps otherwise would not be able to access.
+  In other words, if an app’s only means of obtaining access to certain data is through
+  BlobStoreManager, then that use case is not really intended or supported.
+* For example, if earlier an app was downloading certain shared data from a server, then by using
+  BlobStoreManager, it can first check whether or not the data is already available on the device
+  before downloading.
+
+## Concepts
+### Blob handle
+Blob handle is the identifier of the data and it is what apps need to use for referring to the
+data blobs. Currently, this is made of following bits of information:
+* SHA256 checksum of data
+* Data label: A user readable string that indicates what the data blob is.
+  This is meant to be used when surfacing a list of blobs to the user.
+* Data expiry time: A timestamp after which the data blob should be considered invalid and not
+  allowed to be accessed by any app.
+* Data tag: An opaque string associated with the blob. System does not interpret this in any way or
+  use it for any purposes other than when checking whether two Blob handle identifiers are referring
+  to the same data blob. This is meant to be used by the apps, either for categorization for
+  data blobs or for adding additional identifiers. For example, an app can add tags like
+  *machine_learning* or *media* depending on the data blob if necessary.
+
+When comparing two Blob handles, the System will compare all the pieces of information above and
+only when two Blob handles are equal, the data blobs corresponding to those identifiers are
+considered equal.
+
+### Blob sharing session
+Session is a way to allow apps to contribute data over multiple time intervals. Each session is
+associated with a unique Identifier that is created and obtained by the apps by calling
+[BlobStoreManager#createSession](https://developer.android.com/reference/android/app/blob/BlobStoreManager#createSession(android.app.blob.BlobHandle)).
+Apps can save the Identifier associated with a session and use it to open and close it
+multiple times for contributing the data. For example, if an app is downloading
+some content over the network, it can start a Session and start contributing this data to the
+System immediately and if the network connection is lost for any reason, the app can close this
+session. When the download resumes, the app can reopen the session and start contributing again.
+Note that once the entire data is contributed, the app has no reason to hold on to the Session Id.
+
+### Blob commit
+Since a data blob can be contributed in a session over multiple time intervals, an app closing a
+session does not imply that the contribution is completed. So, *commit* is added as an explicit
+event / signal for the app to indicate that the contribution of the data blob is completed.
+At this point, the System can verify the data blob does indeed correspond to the Blob handle used
+by the app and prevent the app from making any further modifications to the data blob. Once the
+data blob is committed and verified by the System, it is available for other applications to access.
+
+### Access modes
+When an application contributes a data blob to the System, it can choose to specify how it would
+like the System to share this data blob with other applications. Access modes refer to the type of
+access that apps specified when contributing a data blob. As of Android S release, there are
+four access modes:
+* Allow specific packages: Apps can specify a specific set of applications that are allowed to
+  access their data blob.
+* Allow packages with the same signature: Apps can specify that only the applications that are
+  signed with the same certificate as them can access their data blob.
+* Allow public access: Apps can specify that any other app on the device can access their data blob.
+* Allow private access: Apps can specify that no other app can access their data blob unless they
+  happen to contribute the same data blob.
+  * Note that in this case, two apps might download the same data blob and contribute to the System
+    in which case we are not saving anything in terms of bandwidth usage, but we would still be
+    saving disk usage since we would be keeping only one copy of data on disk.
+
+### Lease
+Leasing a blob is a way to specify that an application is interested in using a data blob
+and would like the System to not delete this data blob. Applications can also access a blob
+without holding a lease on it, in which case the System can choose to delete the data blob at any
+time. So, if an application wants to make sure a data blob is available for access for a certain
+period, it is recommended that the application acquire a lease on the data blob. Applications can
+either specify upfront how long they would like to hold the lease for (which is called the lease
+expiry time), or they can acquire a lease without specifying a time period and release the lease
+when they are done with the data blob.
+
+## Sharing data blobs across users
+By default, data blobs are only accessible to applications in the user in which the data blob was
+contributed, but if an application holds the permission
+[ACCESS_BLOBS_ACROSS_USERS](https://developer.android.com/reference/android/Manifest.permission#ACCESS_BLOBS_ACROSS_USERS),
+then they are allowed to access blobs that are contributed by the applications in the other users.
+As of Android S, this permission is only available to following set of applications:
+* Apps signed with the platform certificate
+* Privileged applications
+* Applications holding the
+  [ASSISTANT](https://developer.android.com/reference/android/app/role/RoleManager#ROLE_ASSISTANT)
+  role
+* Development applications
+
+Note that the access modes that applications choose while committing the data blobs still apply
+when these data blobs are accessed across users. So for example, if *appA* contributed a
+data blob in *user0* and specified to share this data blob with only a specific set of
+applications [*appB*, *appC*], then *appD* on *user10* will not be able to access this data blob
+even if the app is granted the `ACCESS_BLOBS_ACROSS_USERS` permission.
+
+When apps that are allowed to access blobs across users
+(i.e. those holding the permission `ACCESS_BLOBS_ACROSS_USERS`) try to access a data blob,
+they can do so as if it is any other data blob. In other words, the applications don’t need to
+know where the data blob is contributed, because the System will automatically check and will
+allow access if this data blob is available either on the user in which the calling application
+is running in or other users.
\ No newline at end of file
diff --git a/apex/jobscheduler/service/java/com/android/server/AnyMotionDetector.java b/apex/jobscheduler/service/java/com/android/server/AnyMotionDetector.java
index 316306d..5ab4207 100644
--- a/apex/jobscheduler/service/java/com/android/server/AnyMotionDetector.java
+++ b/apex/jobscheduler/service/java/com/android/server/AnyMotionDetector.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import android.annotation.Nullable;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
@@ -26,6 +27,8 @@
 import android.os.SystemClock;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
+
 /**
  * Determines if the device has been set upon a stationary object.
  */
@@ -54,6 +57,7 @@
     private static final int STATE_ACTIVE = 1;
 
     /** Current measurement state. */
+    @GuardedBy("mLock")
     private int mState;
 
     /** Threshold energy above which the device is considered moving. */
@@ -82,38 +86,47 @@
 
     private final Handler mHandler;
     private final Object mLock = new Object();
-    private Sensor mAccelSensor;
-    private SensorManager mSensorManager;
-    private PowerManager.WakeLock mWakeLock;
+    private final Sensor mAccelSensor;
+    private final SensorManager mSensorManager;
+    private final PowerManager.WakeLock mWakeLock;
 
     /** Threshold angle in degrees beyond which the device is considered moving. */
     private final float mThresholdAngle;
 
     /** The minimum number of samples required to detect AnyMotion. */
+    @GuardedBy("mLock")
     private int mNumSufficientSamples;
 
     /** True if an orientation measurement is in progress. */
+    @GuardedBy("mLock")
     private boolean mMeasurementInProgress;
 
     /** True if sendMessageDelayed() for the mMeasurementTimeout callback has been scheduled */
+    @GuardedBy("mLock")
     private boolean mMeasurementTimeoutIsActive;
 
     /** True if sendMessageDelayed() for the mWakelockTimeout callback has been scheduled */
-    private boolean mWakelockTimeoutIsActive;
+    private volatile boolean mWakelockTimeoutIsActive;
 
     /** True if sendMessageDelayed() for the mSensorRestart callback has been scheduled */
+    @GuardedBy("mLock")
     private boolean mSensorRestartIsActive;
 
     /** The most recent gravity vector. */
+    @Nullable
+    @GuardedBy("mLock")
     private Vector3 mCurrentGravityVector = null;
 
     /** The second most recent gravity vector. */
+    @Nullable
+    @GuardedBy("mLock")
     private Vector3 mPreviousGravityVector = null;
 
     /** Running sum of squared errors. */
-    private RunningSignalStats mRunningStats;
+    @GuardedBy("mLock")
+    private final RunningSignalStats mRunningStats;
 
-    private DeviceIdleCallback mCallback = null;
+    private final DeviceIdleCallback mCallback;
 
     public AnyMotionDetector(PowerManager pm, Handler handler, SensorManager sm,
             DeviceIdleCallback callback, float thresholdAngle) {
@@ -149,11 +162,11 @@
      * Acquire accel data until we determine AnyMotion status.
      */
     public void checkForAnyMotion() {
-        if (DEBUG) {
-            Slog.d(TAG, "checkForAnyMotion(). mState = " + mState);
-        }
-        if (mState != STATE_ACTIVE) {
-            synchronized (mLock) {
+        synchronized (mLock) {
+            if (DEBUG) {
+                Slog.d(TAG, "checkForAnyMotion(). mState = " + mState);
+            }
+            if (mState != STATE_ACTIVE) {
                 mState = STATE_ACTIVE;
                 if (DEBUG) {
                     Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_ACTIVE.");
@@ -193,6 +206,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void startOrientationMeasurementLocked() {
         if (DEBUG) Slog.d(TAG, "startOrientationMeasurementLocked: mMeasurementInProgress=" +
             mMeasurementInProgress + ", (mAccelSensor != null)=" + (mAccelSensor != null));
@@ -208,6 +222,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private int stopOrientationMeasurementLocked() {
         if (DEBUG) Slog.d(TAG, "stopOrientationMeasurement. mMeasurementInProgress=" +
                 mMeasurementInProgress);
@@ -231,7 +246,7 @@
                 Slog.d(TAG, "mCurrentGravityVector = " + currentGravityVectorString);
                 Slog.d(TAG, "mPreviousGravityVector = " + previousGravityVectorString);
             }
-            status = getStationaryStatus();
+            status = getStationaryStatusLocked();
             mRunningStats.reset();
             if (DEBUG) Slog.d(TAG, "getStationaryStatus() returned " + status);
             if (status != RESULT_UNKNOWN) {
@@ -261,9 +276,10 @@
     }
 
     /*
-     * Updates mStatus to the current AnyMotion status.
+     * Returns the current AnyMotion status.
      */
-    public int getStationaryStatus() {
+    @GuardedBy("mLock")
+    private int getStationaryStatusLocked() {
         if ((mPreviousGravityVector == null) || (mCurrentGravityVector == null)) {
             return RESULT_UNKNOWN;
         }
@@ -341,13 +357,13 @@
                           "data within " + ACCELEROMETER_DATA_TIMEOUT_MILLIS + " ms. Stopping " +
                           "orientation measurement.");
                     status = stopOrientationMeasurementLocked();
-                    if (status != RESULT_UNKNOWN) {
-                        mHandler.removeCallbacks(mWakelockTimeout);
-                        mWakelockTimeoutIsActive = false;
-                        mCallback.onAnyMotionResult(status);
-                    }
                 }
             }
+            if (status != RESULT_UNKNOWN) {
+                mHandler.removeCallbacks(mWakelockTimeout);
+                mWakelockTimeoutIsActive = false;
+                mCallback.onAnyMotionResult(status);
+            }
         }
     };
 
@@ -488,9 +504,10 @@
             }
         }
 
+        @Nullable
         public Vector3 getRunningAverage() {
             if (sampleCount > 0) {
-              return runningSum.times((float)(1.0f / sampleCount));
+                return runningSum.times(1.0f / sampleCount);
             }
             return null;
         }
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 19aed49..0116364 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -298,27 +298,45 @@
     private Intent mLightIdleIntent;
     private AnyMotionDetector mAnyMotionDetector;
     private final AppStateTrackerImpl mAppStateTracker;
+    @GuardedBy("this")
     private boolean mLightEnabled;
+    @GuardedBy("this")
     private boolean mDeepEnabled;
+    @GuardedBy("this")
     private boolean mQuickDozeActivated;
+    @GuardedBy("this")
     private boolean mQuickDozeActivatedWhileIdling;
+    @GuardedBy("this")
     private boolean mForceIdle;
+    @GuardedBy("this")
     private boolean mNetworkConnected;
+    @GuardedBy("this")
     private boolean mScreenOn;
+    @GuardedBy("this")
     private boolean mCharging;
+    @GuardedBy("this")
     private boolean mNotMoving;
+    @GuardedBy("this")
     private boolean mLocating;
+    @GuardedBy("this")
     private boolean mLocated;
+    @GuardedBy("this")
     private boolean mHasGps;
+    @GuardedBy("this")
     private boolean mHasNetworkLocation;
+    @GuardedBy("this")
     private Location mLastGenericLocation;
+    @GuardedBy("this")
     private Location mLastGpsLocation;
 
     /** Time in the elapsed realtime timebase when this listener last received a motion event. */
+    @GuardedBy("this")
     private long mLastMotionEventElapsed;
 
     // Current locked state of the screen
+    @GuardedBy("this")
     private boolean mScreenLocked;
+    @GuardedBy("this")
     private int mNumBlockingConstraints = 0;
 
     /**
@@ -434,19 +452,30 @@
         }
     }
 
+    @GuardedBy("this")
     private int mState;
+    @GuardedBy("this")
     private int mLightState;
 
+    @GuardedBy("this")
     private long mInactiveTimeout;
+    @GuardedBy("this")
     private long mNextAlarmTime;
+    @GuardedBy("this")
     private long mNextIdlePendingDelay;
+    @GuardedBy("this")
     private long mNextIdleDelay;
+    @GuardedBy("this")
     private long mNextLightIdleDelay;
+    @GuardedBy("this")
     private long mNextLightIdleDelayFlex;
+    @GuardedBy("this")
     private long mNextLightAlarmTime;
+    @GuardedBy("this")
     private long mNextSensingTimeoutAlarmTime;
 
     /** How long a light idle maintenance window should last. */
+    @GuardedBy("this")
     private long mCurLightIdleBudget;
 
     /**
@@ -454,15 +483,20 @@
      * only if {@link #mState} == {@link #STATE_IDLE_MAINTENANCE} or
      * {@link #mLightState} == {@link #LIGHT_STATE_IDLE_MAINTENANCE}.
      */
+    @GuardedBy("this")
     private long mMaintenanceStartTime;
+    @GuardedBy("this")
     private long mIdleStartTime;
 
+    @GuardedBy("this")
     private int mActiveIdleOpCount;
     private PowerManager.WakeLock mActiveIdleWakeLock; // held when there are operations in progress
     private PowerManager.WakeLock mGoingIdleWakeLock;  // held when we are going idle so hardware
                                                        // (especially NetworkPolicyManager) can shut
                                                        // down.
+    @GuardedBy("this")
     private boolean mJobsActive;
+    @GuardedBy("this")
     private boolean mAlarmsActive;
 
     /* Factor to apply to INACTIVE_TIMEOUT and IDLE_AFTER_INACTIVE_TIMEOUT in order to enter
@@ -472,8 +506,11 @@
      * Also don't apply the factor if the device is in motion because device motion provides a
      * stronger signal than a prediction algorithm.
      */
+    @GuardedBy("this")
     private float mPreIdleFactor;
+    @GuardedBy("this")
     private float mLastPreIdleFactor;
+    @GuardedBy("this")
     private int mActiveReason;
 
     public final AtomicFile mConfigFile;
@@ -659,8 +696,8 @@
             = new AlarmManager.OnAlarmListener() {
         @Override
         public void onAlarm() {
-            if (mState == STATE_SENSING) {
-                synchronized (DeviceIdleController.this) {
+            synchronized (DeviceIdleController.this) {
+                if (mState == STATE_SENSING) {
                     // Restart the device idle progression in case the device moved but the screen
                     // didn't turn on.
                     becomeInactiveIfAppropriateLocked();
@@ -714,6 +751,7 @@
         mHandler.sendEmptyMessage(MSG_REPORT_STATIONARY_STATUS);
     }
 
+    @GuardedBy("this")
     private boolean isStationaryLocked() {
         final long now = mInjector.getElapsedRealtime();
         return mMotionListener.active
@@ -1592,27 +1630,21 @@
     @Override
     public void onAnyMotionResult(int result) {
         if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
-        if (result != AnyMotionDetector.RESULT_UNKNOWN) {
-            synchronized (this) {
+        synchronized (this) {
+            if (result != AnyMotionDetector.RESULT_UNKNOWN) {
                 cancelSensingTimeoutAlarmLocked();
             }
-        }
-        if ((result == AnyMotionDetector.RESULT_MOVED) ||
-            (result == AnyMotionDetector.RESULT_UNKNOWN)) {
-            synchronized (this) {
+            if ((result == AnyMotionDetector.RESULT_MOVED)
+                    || (result == AnyMotionDetector.RESULT_UNKNOWN)) {
                 handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "non_stationary");
-            }
-        } else if (result == AnyMotionDetector.RESULT_STATIONARY) {
-            if (mState == STATE_SENSING) {
-                // If we are currently sensing, it is time to move to locating.
-                synchronized (this) {
+            } else if (result == AnyMotionDetector.RESULT_STATIONARY) {
+                if (mState == STATE_SENSING) {
+                    // If we are currently sensing, it is time to move to locating.
                     mNotMoving = true;
                     stepIdleStateLocked("s:stationary");
-                }
-            } else if (mState == STATE_LOCATING) {
-                // If we are currently locating, note that we are not moving and step
-                // if we have located the position.
-                synchronized (this) {
+                } else if (mState == STATE_LOCATING) {
+                    // If we are currently locating, note that we are not moving and step
+                    // if we have located the position.
                     mNotMoving = true;
                     if (mLocated) {
                         stepIdleStateLocked("s:stationary");
@@ -3062,6 +3094,7 @@
         }
     }
 
+    @GuardedBy("this")
     void updateInteractivityLocked() {
         // The interactivity state from the power manager tells us whether the display is
         // in a state that we need to keep things running so they will update at a normal
@@ -3089,6 +3122,7 @@
         }
     }
 
+    @GuardedBy("this")
     void updateChargingLocked(boolean charging) {
         if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
         if (!charging && mCharging) {
@@ -3114,6 +3148,7 @@
 
     /** Updates the quick doze flag and enters deep doze if appropriate. */
     @VisibleForTesting
+    @GuardedBy("this")
     void updateQuickDozeFlagLocked(boolean enabled) {
         if (DEBUG) Slog.i(TAG, "updateQuickDozeFlagLocked: enabled=" + enabled);
         mQuickDozeActivated = enabled;
@@ -3138,6 +3173,7 @@
     }
 
     @VisibleForTesting
+    @GuardedBy("this")
     void keyguardShowingLocked(boolean showing) {
         if (DEBUG) Slog.i(TAG, "keyguardShowing=" + showing);
         if (mScreenLocked != showing) {
@@ -3150,15 +3186,18 @@
     }
 
     @VisibleForTesting
+    @GuardedBy("this")
     void scheduleReportActiveLocked(String activeReason, int activeUid) {
         Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 0, activeReason);
         mHandler.sendMessage(msg);
     }
 
+    @GuardedBy("this")
     void becomeActiveLocked(String activeReason, int activeUid) {
         becomeActiveLocked(activeReason, activeUid, mConstants.INACTIVE_TIMEOUT, true);
     }
 
+    @GuardedBy("this")
     private void becomeActiveLocked(String activeReason, int activeUid,
             long newInactiveTimeout, boolean changeLightIdle) {
         if (DEBUG) {
@@ -3204,6 +3243,7 @@
     }
 
     /** Sanity check to make sure DeviceIdleController and AlarmManager are on the same page. */
+    @GuardedBy("this")
     private void verifyAlarmStateLocked() {
         if (mState == STATE_ACTIVE && mNextAlarmTime != 0) {
             Slog.wtf(TAG, "mState=ACTIVE but mNextAlarmTime=" + mNextAlarmTime);
@@ -3221,6 +3261,7 @@
         }
     }
 
+    @GuardedBy("this")
     void becomeInactiveIfAppropriateLocked() {
         verifyAlarmStateLocked();
 
@@ -3300,6 +3341,7 @@
         }
     }
 
+    @GuardedBy("this")
     private void resetIdleManagementLocked() {
         mNextIdlePendingDelay = 0;
         mNextIdleDelay = 0;
@@ -3313,6 +3355,7 @@
         updateActiveConstraintsLocked();
     }
 
+    @GuardedBy("this")
     private void resetLightIdleManagementLocked() {
         mNextLightIdleDelay = 0;
         mNextLightIdleDelayFlex = 0;
@@ -3320,6 +3363,7 @@
         cancelLightAlarmLocked();
     }
 
+    @GuardedBy("this")
     void exitForceIdleLocked() {
         if (mForceIdle) {
             mForceIdle = false;
@@ -3344,9 +3388,12 @@
 
     @VisibleForTesting
     int getLightState() {
-        return mLightState;
+        synchronized (this) {
+            return mLightState;
+        }
     }
 
+    @GuardedBy("this")
     void stepLightIdleStateLocked(String reason) {
         if (mLightState == LIGHT_STATE_OVERRIDE) {
             // If we are already in deep device idle mode, then
@@ -3435,7 +3482,9 @@
 
     @VisibleForTesting
     int getState() {
-        return mState;
+        synchronized (this) {
+            return mState;
+        }
     }
 
     /**
@@ -3448,6 +3497,7 @@
     }
 
     @VisibleForTesting
+    @GuardedBy("this")
     void stepIdleStateLocked(String reason) {
         if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
         EventLogTags.writeDeviceIdleStep();
@@ -3588,6 +3638,7 @@
         }
     }
 
+    @GuardedBy("this")
     private void moveToStateLocked(int state, String reason) {
         final int oldState = mState;
         mState = state;
@@ -3667,22 +3718,26 @@
 
     @VisibleForTesting
     float getPreIdleTimeoutFactor() {
-        return mPreIdleFactor;
+        synchronized (this) {
+            return mPreIdleFactor;
+        }
     }
 
     @VisibleForTesting
     int setPreIdleTimeoutFactor(float ratio) {
-        if (!mDeepEnabled) {
-            if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: Deep Idle disable");
-            return SET_IDLE_FACTOR_RESULT_NOT_SUPPORT;
-        } else if (ratio <= MIN_PRE_IDLE_FACTOR_CHANGE) {
-            if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: Invalid input");
-            return SET_IDLE_FACTOR_RESULT_INVALID;
-        } else if (Math.abs(ratio - mPreIdleFactor) < MIN_PRE_IDLE_FACTOR_CHANGE) {
-            if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: New factor same as previous factor");
-            return SET_IDLE_FACTOR_RESULT_IGNORED;
-        }
         synchronized (this) {
+            if (!mDeepEnabled) {
+                if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: Deep Idle disable");
+                return SET_IDLE_FACTOR_RESULT_NOT_SUPPORT;
+            } else if (ratio <= MIN_PRE_IDLE_FACTOR_CHANGE) {
+                if (DEBUG) Slog.d(TAG, "setPreIdleTimeoutFactor: Invalid input");
+                return SET_IDLE_FACTOR_RESULT_INVALID;
+            } else if (Math.abs(ratio - mPreIdleFactor) < MIN_PRE_IDLE_FACTOR_CHANGE) {
+                if (DEBUG) {
+                    Slog.d(TAG, "setPreIdleTimeoutFactor: New factor same as previous factor");
+                }
+                return SET_IDLE_FACTOR_RESULT_IGNORED;
+            }
             mLastPreIdleFactor = mPreIdleFactor;
             mPreIdleFactor = ratio;
         }
@@ -3744,6 +3799,7 @@
         }
     }
 
+    @GuardedBy("this")
     private boolean shouldUseIdleTimeoutFactorLocked() {
         // exclude ACTIVE_REASON_MOTION, for exclude device in pocket case
         if (mActiveReason == ACTIVE_REASON_MOTION) {
@@ -3763,13 +3819,17 @@
 
     @VisibleForTesting
     long getNextAlarmTime() {
-        return mNextAlarmTime;
+        synchronized (this) {
+            return mNextAlarmTime;
+        }
     }
 
+    @GuardedBy("this")
     boolean isOpsInactiveLocked() {
         return mActiveIdleOpCount <= 0 && !mJobsActive && !mAlarmsActive;
     }
 
+    @GuardedBy("this")
     void exitMaintenanceEarlyIfNeededLocked() {
         if (mState == STATE_IDLE_MAINTENANCE || mLightState == LIGHT_STATE_IDLE_MAINTENANCE
                 || mLightState == LIGHT_STATE_PRE_IDLE) {
@@ -3794,12 +3854,14 @@
         }
     }
 
+    @GuardedBy("this")
     void motionLocked() {
         if (DEBUG) Slog.d(TAG, "motionLocked()");
         mLastMotionEventElapsed = mInjector.getElapsedRealtime();
         handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion");
     }
 
+    @GuardedBy("this")
     void handleMotionDetectedLocked(long timeout, String type) {
         if (mStationaryListeners.size() > 0) {
             postStationaryStatusUpdated();
@@ -3829,6 +3891,7 @@
         }
     }
 
+    @GuardedBy("this")
     void receivedGenericLocationLocked(Location location) {
         if (mState != STATE_LOCATING) {
             cancelLocatingLocked();
@@ -3845,6 +3908,7 @@
         }
     }
 
+    @GuardedBy("this")
     void receivedGpsLocationLocked(Location location) {
         if (mState != STATE_LOCATING) {
             cancelLocatingLocked();
@@ -3883,6 +3947,7 @@
         }
     }
 
+    @GuardedBy("this")
     void cancelAlarmLocked() {
         if (mNextAlarmTime != 0) {
             mNextAlarmTime = 0;
@@ -3890,6 +3955,7 @@
         }
     }
 
+    @GuardedBy("this")
     void cancelLightAlarmLocked() {
         if (mNextLightAlarmTime != 0) {
             mNextLightAlarmTime = 0;
@@ -3897,6 +3963,7 @@
         }
     }
 
+    @GuardedBy("this")
     void cancelLocatingLocked() {
         if (mLocating) {
             LocationManager locationManager = mInjector.getLocationManager();
@@ -3914,6 +3981,7 @@
         mAlarmManager.cancel(mMotionRegistrationAlarmListener);
     }
 
+    @GuardedBy("this")
     void cancelSensingTimeoutAlarmLocked() {
         if (mNextSensingTimeoutAlarmTime != 0) {
             mNextSensingTimeoutAlarmTime = 0;
@@ -3921,6 +3989,7 @@
         }
     }
 
+    @GuardedBy("this")
     void scheduleAlarmLocked(long delay, boolean idleUntil) {
         if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
 
@@ -3957,6 +4026,7 @@
         }
     }
 
+    @GuardedBy("this")
     void scheduleLightAlarmLocked(long delay, long flex) {
         if (DEBUG) {
             Slog.d(TAG, "scheduleLightAlarmLocked(" + delay
@@ -4003,6 +4073,7 @@
         }
     }
 
+    @GuardedBy("this")
     void scheduleSensingTimeoutAlarmLocked(long delay) {
         if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
         mNextSensingTimeoutAlarmTime = SystemClock.elapsedRealtime() + delay;
@@ -4071,6 +4142,7 @@
      * @param callingUid the callingUid that setup this temp-allowlist, only valid when param adding
      *                   is true.
      */
+    @GuardedBy("this")
     private void updateTempWhitelistAppIdsLocked(int uid, boolean adding, long durationMs,
             @TempAllowListType int type, @ReasonCode int reasonCode, @Nullable String reason,
             int callingUid) {
@@ -4120,6 +4192,7 @@
                 mTempWhitelistAppIdArray);
     }
 
+    @GuardedBy("this")
     void readConfigFileLocked() {
         if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());
         mPowerSaveWhitelistUserApps.clear();
@@ -4142,6 +4215,7 @@
         }
     }
 
+    @GuardedBy("this")
     private void readConfigFileLocked(XmlPullParser parser) {
         final PackageManager pm = getContext().getPackageManager();
 
@@ -4987,7 +5061,7 @@
                 pw.println();
             }
             if (mNextLightIdleDelay != 0) {
-                pw.print("  mNextIdleDelay=");
+                pw.print("  mNextLightIdleDelay=");
                 TimeUtils.formatDuration(mNextLightIdleDelay, pw);
                 if (mConstants.USE_WINDOW_ALARMS) {
                     pw.print(" (flex=");
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
index 5d29515..8a1a07c 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
@@ -33,8 +33,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AlarmManager;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -55,6 +55,7 @@
 
 import libcore.util.EmptyArray;
 
+import java.util.Comparator;
 import java.util.List;
 import java.util.Objects;
 import java.util.PriorityQueue;
@@ -131,6 +132,54 @@
     private final BalanceThresholdAlarmListener mBalanceThresholdAlarmListener =
             new BalanceThresholdAlarmListener();
 
+    /**
+     * Comparator to use to sort apps before we distribute ARCs so that we try to give the most
+     * important apps ARCs first.
+     */
+    @VisibleForTesting
+    final Comparator<PackageInfo> mPackageDistributionComparator =
+            new Comparator<PackageInfo>() {
+                @Override
+                public int compare(PackageInfo pi1, PackageInfo pi2) {
+                    final ApplicationInfo appInfo1 = pi1.applicationInfo;
+                    final ApplicationInfo appInfo2 = pi2.applicationInfo;
+                    // Put any packages that don't declare an application at the end. A missing
+                    // <application> tag likely means the app won't be doing any work anyway.
+                    if (appInfo1 == null) {
+                        if (appInfo2 == null) {
+                            return 0;
+                        }
+                        return 1;
+                    } else if (appInfo2 == null) {
+                        return -1;
+                    }
+                    // Privileged apps eat first. They're likely required for the device to
+                    // function properly.
+                    // TODO: include headless system apps
+                    if (appInfo1.isPrivilegedApp()) {
+                        if (!appInfo2.isPrivilegedApp()) {
+                            return -1;
+                        }
+                    } else if (appInfo2.isPrivilegedApp()) {
+                        return 1;
+                    }
+
+                    // Sort by most recently used.
+                    final long timeSinceLastUsedMs1 =
+                            mAppStandbyInternal.getTimeSinceLastUsedByUser(
+                                    pi1.packageName, UserHandle.getUserId(pi1.applicationInfo.uid));
+                    final long timeSinceLastUsedMs2 =
+                            mAppStandbyInternal.getTimeSinceLastUsedByUser(
+                                    pi2.packageName, UserHandle.getUserId(pi2.applicationInfo.uid));
+                    if (timeSinceLastUsedMs1 < timeSinceLastUsedMs2) {
+                        return -1;
+                    } else if (timeSinceLastUsedMs1 > timeSinceLastUsedMs2) {
+                        return 1;
+                    }
+                    return 0;
+                }
+            };
+
     private static final int MSG_CHECK_BALANCE = 0;
     private static final int MSG_CLEAN_LEDGER = 1;
     private static final int MSG_SET_ALARMS = 2;
@@ -249,6 +298,11 @@
     private void noteOngoingEventLocked(final int userId, @NonNull final String pkgName,
             final int eventId, @Nullable String tag, final long startElapsed,
             final boolean updateBalanceCheck) {
+        if (mIrs.isSystem(userId, pkgName)) {
+            // Events are free for the system. Don't bother recording them.
+            return;
+        }
+
         SparseArrayMap<String, OngoingEvent> ongoingEvents =
                 mCurrentOngoingEvents.get(userId, pkgName);
         if (ongoingEvents == null) {
@@ -410,6 +464,11 @@
     private void stopOngoingActionLocked(final int userId, @NonNull final String pkgName,
             final int eventId, @Nullable String tag, final long nowElapsed, final long now,
             final boolean updateBalanceCheck, final boolean notifyOnAffordabilityChange) {
+        if (mIrs.isSystem(userId, pkgName)) {
+            // Events are free for the system. Don't bother recording them.
+            return;
+        }
+
         final Ledger ledger = getLedgerLocked(userId, pkgName);
 
         SparseArrayMap<String, OngoingEvent> ongoingEvents =
@@ -431,15 +490,13 @@
         }
         ongoingEvent.refCount--;
         if (ongoingEvent.refCount <= 0) {
-            if (!mIrs.isSystem(userId, pkgName)) {
-                final long startElapsed = ongoingEvent.startTimeElapsed;
-                final long startTime = now - (nowElapsed - startElapsed);
-                final long actualDelta =
-                        getActualDeltaLocked(ongoingEvent, ledger, nowElapsed, now);
-                recordTransactionLocked(userId, pkgName, ledger,
-                        new Ledger.Transaction(startTime, now, eventId, tag, actualDelta),
-                        notifyOnAffordabilityChange);
-            }
+            final long startElapsed = ongoingEvent.startTimeElapsed;
+            final long startTime = now - (nowElapsed - startElapsed);
+            final long actualDelta = getActualDeltaLocked(ongoingEvent, ledger, nowElapsed, now);
+            recordTransactionLocked(userId, pkgName, ledger,
+                    new Ledger.Transaction(startTime, now, eventId, tag, actualDelta),
+                    notifyOnAffordabilityChange);
+
             ongoingEvents.delete(eventId, tag);
         }
         if (updateBalanceCheck) {
@@ -576,18 +633,31 @@
         }
     }
 
+    /** Returns true if an app should be given credits in the general distributions. */
+    private boolean shouldGiveCredits(@NonNull PackageInfo packageInfo) {
+        final ApplicationInfo applicationInfo = packageInfo.applicationInfo;
+        // Skip apps that wouldn't be doing any work. Giving them ARCs would be wasteful.
+        if (applicationInfo == null || !applicationInfo.hasCode()) {
+            return false;
+        }
+        final int userId = UserHandle.getUserId(packageInfo.applicationInfo.uid);
+        // No point allocating ARCs to the system. It can do whatever it wants.
+        return !mIrs.isSystem(userId, packageInfo.packageName);
+    }
+
     @GuardedBy("mLock")
     void distributeBasicIncomeLocked(int batteryLevel) {
         List<PackageInfo> pkgs = mIrs.getInstalledPackages();
+        pkgs.sort(mPackageDistributionComparator);
+
         final long now = getCurrentTimeMillis();
         for (int i = 0; i < pkgs.size(); ++i) {
             final PackageInfo pkgInfo = pkgs.get(i);
-            final int userId = UserHandle.getUserId(pkgInfo.applicationInfo.uid);
-            final String pkgName = pkgInfo.packageName;
-            if (mIrs.isSystem(userId, pkgName)) {
-                // No point allocating ARCs to the system. It can do whatever it wants.
+            if (!shouldGiveCredits(pkgInfo)) {
                 continue;
             }
+            final int userId = UserHandle.getUserId(pkgInfo.applicationInfo.uid);
+            final String pkgName = pkgInfo.packageName;
             Ledger ledger = getLedgerLocked(userId, pkgName);
             final long minBalance = mIrs.getMinBalanceLocked(userId, pkgName);
             final double perc = batteryLevel / 100d;
@@ -614,20 +684,20 @@
 
     @GuardedBy("mLock")
     void grantBirthrightsLocked(final int userId) {
-        PackageManager packageManager = mIrs.getContext().getPackageManager();
-        List<PackageInfo> pkgs = packageManager.getInstalledPackagesAsUser(0, userId);
+        final List<PackageInfo> pkgs = mIrs.getInstalledPackages(userId);
         final long maxBirthright =
                 mIrs.getMaxCirculationLocked() / mIrs.getInstalledPackages().size();
         final long now = getCurrentTimeMillis();
 
+        pkgs.sort(mPackageDistributionComparator);
+
         for (int i = 0; i < pkgs.size(); ++i) {
             final PackageInfo packageInfo = pkgs.get(i);
-            final String pkgName = packageInfo.packageName;
-            final Ledger ledger = getLedgerLocked(userId, pkgName);
-            if (mIrs.isSystem(userId, pkgName)) {
-                // No point allocating ARCs to the system. It can do whatever it wants.
+            if (!shouldGiveCredits(packageInfo)) {
                 continue;
             }
+            final String pkgName = packageInfo.packageName;
+            final Ledger ledger = getLedgerLocked(userId, pkgName);
             if (ledger.getCurrentBalance() > 0) {
                 // App already got credits somehow. Move along.
                 Slog.wtf(TAG, "App " + pkgName + " had credits before economy was set up");
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
index 6538229..40ab49c 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -60,6 +60,7 @@
 import com.android.internal.util.DumpUtils;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.pm.UserManagerInternal;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -82,8 +83,11 @@
     static final long UNUSED_RECLAMATION_PERIOD_MS = 24 * HOUR_IN_MILLIS;
     /** How much of an app's unused wealth should be reclaimed periodically. */
     private static final float DEFAULT_UNUSED_RECLAMATION_PERCENTAGE = .1f;
+    private static final int PACKAGE_QUERY_FLAGS =
+            PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                    | PackageManager.MATCH_APEX;
 
-    /** Global local for all resource economy state. */
+    /** Global lock for all resource economy state. */
     private final Object mLock = new Object();
 
     private final Handler mHandler;
@@ -240,6 +244,7 @@
         return mLock;
     }
 
+    /** Returns the installed packages for all users. */
     @NonNull
     List<PackageInfo> getInstalledPackages() {
         synchronized (mLock) {
@@ -247,6 +252,22 @@
         }
     }
 
+    /** Returns the installed packages for the specified user. */
+    @NonNull
+    List<PackageInfo> getInstalledPackages(final int userId) {
+        final List<PackageInfo> userPkgs = new ArrayList<>();
+        synchronized (mLock) {
+            for (int i = 0; i < mPkgCache.size(); ++i) {
+                final PackageInfo packageInfo = mPkgCache.get(i);
+                if (packageInfo.applicationInfo != null
+                        && UserHandle.getUserId(packageInfo.applicationInfo.uid) == userId) {
+                    userPkgs.add(packageInfo);
+                }
+            }
+        }
+        return userPkgs;
+    }
+
     @GuardedBy("mLock")
     long getMaxCirculationLocked() {
         return mCurrentBatteryLevel * mCompleteEconomicPolicy.getMaxSatiatedCirculation() / 100;
@@ -300,9 +321,10 @@
         final int userId = UserHandle.getUserId(uid);
         final PackageInfo packageInfo;
         try {
-            packageInfo = mPackageManager.getPackageInfoAsUser(pkgName, 0, userId);
+            packageInfo =
+                    mPackageManager.getPackageInfoAsUser(pkgName, PACKAGE_QUERY_FLAGS, userId);
         } catch (PackageManager.NameNotFoundException e) {
-            Slog.wtf(TAG, "PM couldn't find newly added package: " + pkgName);
+            Slog.wtf(TAG, "PM couldn't find newly added package: " + pkgName, e);
             return;
         }
         synchronized (mPackageToUidCache) {
@@ -354,7 +376,8 @@
 
     void onUserAdded(final int userId) {
         synchronized (mLock) {
-            loadInstalledPackageListLocked();
+            mPkgCache.addAll(
+                    mPackageManager.getInstalledPackagesAsUser(PACKAGE_QUERY_FLAGS, userId));
             mAgent.grantBirthrightsLocked(userId);
         }
     }
@@ -371,7 +394,6 @@
                     break;
                 }
             }
-            loadInstalledPackageListLocked();
             mAgent.onUserRemovedLocked(userId, removedPkgs);
         }
     }
@@ -468,7 +490,14 @@
 
     @GuardedBy("mLock")
     private void loadInstalledPackageListLocked() {
-        mPkgCache = mPackageManager.getInstalledPackages(0);
+        mPkgCache.clear();
+        final UserManagerInternal userManagerInternal =
+                LocalServices.getService(UserManagerInternal.class);
+        final int[] userIds = userManagerInternal.getUserIds();
+        for (int userId : userIds) {
+            mPkgCache.addAll(
+                    mPackageManager.getInstalledPackagesAsUser(PACKAGE_QUERY_FLAGS, userId));
+        }
     }
 
     private void registerListeners() {
diff --git a/apex/media/framework/java/android/media/MediaCommunicationManager.java b/apex/media/framework/java/android/media/MediaCommunicationManager.java
index b2528cd..0f00dbb 100644
--- a/apex/media/framework/java/android/media/MediaCommunicationManager.java
+++ b/apex/media/framework/java/android/media/MediaCommunicationManager.java
@@ -74,6 +74,9 @@
     @GuardedBy("mLock")
     private MediaCommunicationServiceCallbackStub mCallbackStub;
 
+    // TODO: remove this when MCS implements dispatchMediaKeyEvent.
+    private MediaSessionManager mMediaSessionManager;
+
     /**
      * @hide
      */
@@ -222,6 +225,14 @@
         return mService;
     }
 
+    // TODO: remove this when MCS implements dispatchMediaKeyEvent.
+    private MediaSessionManager getMediaSessionManager() {
+        if (mMediaSessionManager == null) {
+            mMediaSessionManager = mContext.getSystemService(MediaSessionManager.class);
+        }
+        return mMediaSessionManager;
+    }
+
     private List<Session2Token> getSession2Tokens(int userId) {
         try {
             MediaParceledListSlice slice = getService().getSession2Tokens(userId);
@@ -243,6 +254,14 @@
     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
     public void dispatchMediaKeyEvent(@NonNull KeyEvent keyEvent, boolean asSystemService) {
         Objects.requireNonNull(keyEvent, "keyEvent shouldn't be null");
+
+        // When MCS handles this, caller is changed.
+        // TODO: remove this when MCS implementation is done.
+        if (!asSystemService) {
+            getMediaSessionManager().dispatchMediaKeyEvent(keyEvent, false);
+            return;
+        }
+
         try {
             getService().dispatchMediaKeyEvent(mContext.getPackageName(),
                     keyEvent, asSystemService);
diff --git a/apex/media/framework/java/android/media/MediaSession2.java b/apex/media/framework/java/android/media/MediaSession2.java
index e76d61c..cb6e1a0 100644
--- a/apex/media/framework/java/android/media/MediaSession2.java
+++ b/apex/media/framework/java/android/media/MediaSession2.java
@@ -262,7 +262,7 @@
     }
 
     /**
-     * Returns whehther the playback is active (i.e. playing something)
+     * Returns whether the playback is active (i.e. playing something)
      *
      * @return {@code true} if the playback active, {@code false} otherwise.
      */
diff --git a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
index 03a2372..74abf31 100644
--- a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
+++ b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
@@ -54,7 +54,6 @@
 import java.util.Objects;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
-import java.util.stream.Collectors;
 
 /**
  * A system service that manages {@link android.media.MediaSession2} creations
@@ -281,6 +280,16 @@
         session.close();
     }
 
+    void onSessionPlaybackStateChanged(Session2Record session, boolean promotePriority) {
+        FullUserRecord user = session.getFullUser();
+        if (user == null || !user.containsSession(session)) {
+            Log.d(TAG, "Unknown session changed playback state. Ignoring.");
+            return;
+        }
+        user.onPlaybackStateChanged(session, promotePriority);
+    }
+
+
     static boolean isMediaSessionKey(int keyCode) {
         switch (keyCode) {
             case KeyEvent.KEYCODE_MEDIA_PLAY:
@@ -395,11 +404,7 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 //TODO: Dispatch key event to media session 2 if required
-                if (asSystemService) {
-                    mSessionManager.dispatchMediaKeyEventAsSystemService(keyEvent);
-                } else {
-                    mSessionManager.dispatchMediaKeyEvent(keyEvent, false);
-                }
+                mSessionManager.dispatchMediaKeyEvent(keyEvent, asSystemService);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -524,26 +529,20 @@
 
     final class FullUserRecord {
         private final int mFullUserId;
-        private final Object mUserLock = new Object();
-        @GuardedBy("mUserLock")
-        private final List<Session2Record> mSessionRecords = new ArrayList<>();
+        private final SessionPriorityList mSessionPriorityList = new SessionPriorityList();
 
         FullUserRecord(int fullUserId) {
             mFullUserId = fullUserId;
         }
 
         public void addSession(Session2Record record) {
-            synchronized (mUserLock) {
-                mSessionRecords.add(record);
-            }
+            mSessionPriorityList.addSession(record);
             mHandler.post(() -> dispatchSession2Created(record.mSessionToken));
             mHandler.post(() -> dispatchSession2Changed(mFullUserId));
         }
 
         private void removeSession(Session2Record record) {
-            synchronized (mUserLock) {
-                mSessionRecords.remove(record);
-            }
+            mSessionPriorityList.removeSession(record);
             mHandler.post(() -> dispatchSession2Changed(mFullUserId));
             //TODO: Handle if the removed session was the media button session.
         }
@@ -553,48 +552,31 @@
         }
 
         public List<Session2Token> getAllSession2Tokens() {
-            synchronized (mUserLock) {
-                return mSessionRecords.stream()
-                        .map(Session2Record::getSessionToken)
-                        .collect(Collectors.toList());
-            }
+            return mSessionPriorityList.getAllTokens();
         }
 
         public List<Session2Token> getSession2Tokens(int userId) {
-            synchronized (mUserLock) {
-                return mSessionRecords.stream()
-                        .filter(record -> record.getUserId() == userId)
-                        .map(Session2Record::getSessionToken)
-                        .collect(Collectors.toList());
-            }
+            return mSessionPriorityList.getTokensByUserId(userId);
         }
 
         public void destroyAllSessions() {
-            synchronized (mUserLock) {
-                for (Session2Record session : mSessionRecords) {
-                    session.close();
-                }
-                mSessionRecords.clear();
-            }
+            mSessionPriorityList.destroyAllSessions();
             mHandler.post(() -> dispatchSession2Changed(mFullUserId));
         }
 
         public void destroySessionsForUser(int userId) {
-            boolean changed = false;
-            synchronized (mUserLock) {
-                for (int i = mSessionRecords.size() - 1; i >= 0; i--) {
-                    Session2Record session = mSessionRecords.get(i);
-                    if (session.getUserId() == userId) {
-                        mSessionRecords.remove(i);
-                        session.close();
-                        changed = true;
-                    }
-                }
-            }
-            if (changed) {
+            if (mSessionPriorityList.destroySessionsByUserId(userId)) {
                 mHandler.post(() -> dispatchSession2Changed(mFullUserId));
             }
         }
+
+        public boolean containsSession(Session2Record session) {
+            return mSessionPriorityList.contains(session);
+        }
+
+        public void onPlaybackStateChanged(Session2Record session, boolean promotePriority) {
+            mSessionPriorityList.onPlaybackStateChanged(session, promotePriority);
+        }
     }
 
     static final class Session2Record {
@@ -610,6 +592,7 @@
         @GuardedBy("mSession2RecordLock")
         private boolean mIsClosed;
 
+        //TODO: introduce policy (See MediaSessionPolicyProvider)
         Session2Record(MediaCommunicationService service, FullUserRecord fullUser,
                 Session2Token token, Executor controllerExecutor) {
             mServiceRef = new WeakReference<>(service);
@@ -645,6 +628,12 @@
             return mSessionToken;
         }
 
+        public boolean checkPlaybackActiveState(boolean expected) {
+            synchronized (mSession2RecordLock) {
+                return mIsConnected && mController.isPlaybackActive() == expected;
+            }
+        }
+
         private class Controller2Callback extends MediaController2.ControllerCallback {
             @Override
             public void onConnected(MediaController2 controller,
@@ -670,6 +659,20 @@
                     service.onSessionDied(Session2Record.this);
                 }
             }
+
+            @Override
+            public void onPlaybackActiveChanged(
+                    @NonNull MediaController2 controller,
+                    boolean playbackActive) {
+                if (DEBUG) {
+                    Log.d(TAG, "playback active changed, " + mSessionToken + ", active="
+                            + playbackActive);
+                }
+                MediaCommunicationService service = mServiceRef.get();
+                if (service != null) {
+                    service.onSessionPlaybackStateChanged(Session2Record.this, playbackActive);
+                }
+            }
         }
     }
 }
diff --git a/apex/media/service/java/com/android/server/media/SessionPriorityList.java b/apex/media/service/java/com/android/server/media/SessionPriorityList.java
new file mode 100644
index 0000000..47b14b6
--- /dev/null
+++ b/apex/media/service/java/com/android/server/media/SessionPriorityList.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.media;
+
+import android.annotation.Nullable;
+import android.media.Session2Token;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.media.MediaCommunicationService.Session2Record;
+
+import java.util.ArrayList;
+import java.util.List;
+
+//TODO: Define the priority specifically.
+/**
+ * Keeps track of media sessions and their priority for notifications, media
+ * button dispatch, etc.
+ * Higher priority session has more chance to be selected as media button session,
+ * which receives the media button events.
+ */
+class SessionPriorityList {
+    private static final String TAG = "SessionPriorityList";
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    private final List<Session2Record> mSessions = new ArrayList<>();
+
+    @Nullable
+    private Session2Record mMediaButtonSession;
+    @Nullable
+    private Session2Record mCachedVolumeSession;
+
+    //TODO: integrate AudioPlayerStateMonitor
+
+    public void addSession(Session2Record record) {
+        synchronized (mLock) {
+            mSessions.add(record);
+        }
+    }
+
+    public void removeSession(Session2Record record) {
+        synchronized (mLock) {
+            mSessions.remove(record);
+        }
+        if (record == mMediaButtonSession) {
+            updateMediaButtonSession(null);
+        }
+    }
+
+    public void destroyAllSessions() {
+        synchronized (mLock) {
+            for (Session2Record session : mSessions) {
+                session.close();
+            }
+            mSessions.clear();
+        }
+    }
+
+    public boolean destroySessionsByUserId(int userId) {
+        boolean changed = false;
+        synchronized (mLock) {
+            for (int i = mSessions.size() - 1; i >= 0; i--) {
+                Session2Record session = mSessions.get(i);
+                if (session.getUserId() == userId) {
+                    mSessions.remove(i);
+                    session.close();
+                    changed = true;
+                }
+            }
+        }
+        return changed;
+    }
+
+    public List<Session2Token> getAllTokens() {
+        List<Session2Token> sessions = new ArrayList<>();
+        synchronized (mLock) {
+            for (Session2Record session : mSessions) {
+                sessions.add(session.getSessionToken());
+            }
+        }
+        return sessions;
+    }
+
+    public List<Session2Token> getTokensByUserId(int userId) {
+        List<Session2Token> sessions = new ArrayList<>();
+        synchronized (mLock) {
+            for (Session2Record session : mSessions) {
+                if (session.getUserId() == userId) {
+                    sessions.add(session.getSessionToken());
+                }
+            }
+        }
+        return sessions;
+    }
+
+    /** Gets the media button session which receives the media button events. */
+    @Nullable
+    public Session2Record getMediaButtonSession() {
+        return mMediaButtonSession;
+    }
+
+    /** Gets the media volume session which receives the volume key events. */
+    @Nullable
+    public Session2Record getMediaVolumeSession() {
+        //TODO: if null, calculate it.
+        return mCachedVolumeSession;
+    }
+
+    public boolean contains(Session2Record session) {
+        synchronized (mLock) {
+            return mSessions.contains(session);
+        }
+    }
+
+    public void onPlaybackStateChanged(Session2Record session, boolean promotePriority) {
+        if (promotePriority) {
+            synchronized (mLock) {
+                if (mSessions.remove(session)) {
+                    mSessions.add(0, session);
+                } else {
+                    Log.w(TAG, "onPlaybackStateChanged: Ignoring unknown session");
+                    return;
+                }
+            }
+        } else if (session.checkPlaybackActiveState(false)) {
+            // Just clear the cached volume session when a state goes inactive
+            mCachedVolumeSession = null;
+        }
+
+        // In most cases, playback state isn't needed for finding the media button session,
+        // but we only use it as a hint if an app has multiple local media sessions.
+        // In that case, we pick the media session whose PlaybackState matches
+        // the audio playback configuration.
+        if (mMediaButtonSession != null
+                && mMediaButtonSession.getSessionToken().getUid()
+                == session.getSessionToken().getUid()) {
+            Session2Record newMediaButtonSession =
+                    findMediaButtonSession(mMediaButtonSession.getSessionToken().getUid());
+            if (newMediaButtonSession != mMediaButtonSession) {
+                // Check if the policy states that this session should not be updated as a media
+                // button session.
+                updateMediaButtonSession(newMediaButtonSession);
+            }
+        }
+    }
+
+    private void updateMediaButtonSession(@Nullable Session2Record newSession) {
+        mMediaButtonSession = newSession;
+        //TODO: invoke callbacks for media button session changed listeners
+    }
+
+    /**
+     * Finds the media button session with the given {@param uid}.
+     * If the app has multiple media sessions, the media session whose playback state is not null
+     * and matches the audio playback state becomes the media button session. Otherwise the top
+     * priority session becomes the media button session.
+     *
+     * @return The media button session. Returns {@code null} if the app doesn't have a media
+     *   session.
+     */
+    @Nullable
+    private Session2Record findMediaButtonSession(int uid) {
+        Session2Record mediaButtonSession = null;
+        synchronized (mLock) {
+            for (Session2Record session : mSessions) {
+                if (uid != session.getSessionToken().getUid()) {
+                    continue;
+                }
+                // TODO: check audio player state monitor
+                if (mediaButtonSession == null) {
+                    // Pick the top priority session as a default.
+                    mediaButtonSession = session;
+                }
+            }
+        }
+        return mediaButtonSession;
+    }
+}
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 54fd430..59f602c 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -127,7 +127,7 @@
     })";
 static const char IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE[] = R"(
     precision mediump float;
-    const float cWhiteMaskThreshold = 0.05f;
+    const float cWhiteMaskThreshold = 0.05;
     uniform sampler2D uTexture;
     uniform float uFade;
     uniform float uColorProgress;
@@ -155,7 +155,7 @@
                 + g * mix(uStartColor1, uEndColor1, uColorProgress)
                 + b * mix(uStartColor2, uEndColor2, uColorProgress)
                 + a * mix(uStartColor3, uEndColor3, uColorProgress);
-        color = mix(color, vec4(vec3((r + g + b + a) * 0.25f), 1.0), useWhiteMask);
+        color = mix(color, vec4(vec3((r + g + b + a) * 0.25), 1.0), useWhiteMask);
         gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a;
     })";
 static const char IMAGE_FRAG_SHADER_SOURCE[] = R"(
@@ -698,6 +698,11 @@
     glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
     if (isCompiled == GL_FALSE) {
         SLOGE("Compile shader failed. Shader type: %d", shaderType);
+        GLint maxLength = 0;
+        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
+        std::vector<GLchar> errorLog(maxLength);
+        glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
+        SLOGE("Shader compilation error: %s", &errorLog[0]);
         return 0;
     }
     return shader;
@@ -788,6 +793,8 @@
     // clear screen
     glDisable(GL_DITHER);
     glDisable(GL_SCISSOR_TEST);
+    glUseProgram(mImageShader);
+
     glClearColor(0,0,0,1);
     glClear(GL_COLOR_BUFFER_BIT);
     eglSwapBuffers(mDisplay, mSurface);
diff --git a/core/api/current.txt b/core/api/current.txt
index f67c338..78c4cdf 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -99,6 +99,7 @@
     field public static final String INTERACT_ACROSS_PROFILES = "android.permission.INTERACT_ACROSS_PROFILES";
     field public static final String INTERNET = "android.permission.INTERNET";
     field public static final String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
+    field public static final String LAUNCH_TWO_PANE_SETTINGS_DEEP_LINK = "android.permission.LAUNCH_TWO_PANE_SETTINGS_DEEP_LINK";
     field public static final String LOADER_USAGE_STATS = "android.permission.LOADER_USAGE_STATS";
     field public static final String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
     field public static final String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS";
@@ -6693,6 +6694,16 @@
   }
 
   public class StatusBarManager {
+    method public int requestAddTileService(@NonNull android.content.ComponentName, @NonNull CharSequence, @NonNull android.graphics.drawable.Icon, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+    field public static final int TILE_ADD_REQUEST_ANSWER_FAILED_BAD_COMPONENT = 3; // 0x3
+    field public static final int TILE_ADD_REQUEST_ANSWER_FAILED_MISMATCHED_PACKAGE = 1; // 0x1
+    field public static final int TILE_ADD_REQUEST_ANSWER_FAILED_NOT_CURRENT_USER = 4; // 0x4
+    field public static final int TILE_ADD_REQUEST_ANSWER_FAILED_REQUEST_IN_PROGRESS = 2; // 0x2
+    field public static final int TILE_ADD_REQUEST_ANSWER_FAILED_UNKNOWN_REASON = 5; // 0x5
+    field public static final int TILE_ADD_REQUEST_ANSWER_SUCCESS = 0; // 0x0
+    field public static final int TILE_ADD_REQUEST_RESULT_TILE_ADDED = 2; // 0x2
+    field public static final int TILE_ADD_REQUEST_RESULT_TILE_ALREADY_ADDED = 1; // 0x1
+    field public static final int TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED = 0; // 0x0
   }
 
   public final class SyncNotedAppOp implements android.os.Parcelable {
@@ -9856,7 +9867,7 @@
     method @RequiresPermission(value=android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH, conditional=true) public void associate(@NonNull android.companion.AssociationRequest, @NonNull android.companion.CompanionDeviceManager.Callback, @Nullable android.os.Handler);
     method public void disassociate(@NonNull String);
     method @NonNull public java.util.List<java.lang.String> getAssociations();
-    method public boolean hasNotificationAccess(android.content.ComponentName);
+    method @Deprecated public boolean hasNotificationAccess(android.content.ComponentName);
     method public void requestNotificationAccess(android.content.ComponentName);
     method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void startObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException;
     method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void stopObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException;
@@ -10695,6 +10706,7 @@
     field public static final String SEARCH_SERVICE = "search";
     field public static final String SENSOR_SERVICE = "sensor";
     field public static final String SHORTCUT_SERVICE = "shortcut";
+    field public static final String STATUS_BAR_SERVICE = "statusbar";
     field public static final String STORAGE_SERVICE = "storage";
     field public static final String STORAGE_STATS_SERVICE = "storagestats";
     field public static final String SYSTEM_HEALTH_SERVICE = "systemhealth";
@@ -12619,6 +12631,7 @@
     method public boolean isPackageSuspended();
     method @CheckResult public abstract boolean isPermissionRevokedByPolicy(@NonNull String, @NonNull String);
     method public abstract boolean isSafeMode();
+    method public boolean mayPackageQuery(@NonNull String, @NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryActivityProperty(@NonNull String);
     method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryApplicationProperty(@NonNull String);
     method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(@NonNull android.content.Intent, int);
@@ -35294,6 +35307,7 @@
     field public static final String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
     field public static final String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS";
     field public static final String ACTION_SETTINGS = "android.settings.SETTINGS";
+    field public static final String ACTION_SETTINGS_LARGE_SCREEN_DEEP_LINK = "android.settings.SETTINGS_LARGE_SCREEN_DEEP_LINK";
     field public static final String ACTION_SHOW_REGULATORY_INFO = "android.settings.SHOW_REGULATORY_INFO";
     field public static final String ACTION_SHOW_WORK_POLICY_INFO = "android.settings.SHOW_WORK_POLICY_INFO";
     field public static final String ACTION_SOUND_SETTINGS = "android.settings.SOUND_SETTINGS";
@@ -35334,6 +35348,9 @@
     field public static final String EXTRA_EASY_CONNECT_ERROR_CODE = "android.provider.extra.EASY_CONNECT_ERROR_CODE";
     field public static final String EXTRA_INPUT_METHOD_ID = "input_method_id";
     field public static final String EXTRA_NOTIFICATION_LISTENER_COMPONENT_NAME = "android.provider.extra.NOTIFICATION_LISTENER_COMPONENT_NAME";
+    field public static final String EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_URI = "android.provider.extra.SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_URI";
+    field public static final String EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_PENDING_INTENT = "android.provider.extra.SETTINGS_LARGE_SCREEN_DEEP_LINK_PENDING_INTENT";
+    field public static final String EXTRA_SETTINGS_LARGE_SCREEN_HIGHLIGHT_MENU_KEY = "android.provider.extra.SETTINGS_LARGE_SCREEN_HIGHLIGHT_MENU_KEY";
     field public static final String EXTRA_SUB_ID = "android.provider.extra.SUB_ID";
     field public static final String EXTRA_WIFI_NETWORK_LIST = "android.provider.extra.WIFI_NETWORK_LIST";
     field public static final String EXTRA_WIFI_NETWORK_RESULT_LIST = "android.provider.extra.WIFI_NETWORK_RESULT_LIST";
@@ -49304,6 +49321,7 @@
     field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
     field public static final int AUTOFILL_TYPE_TEXT = 1; // 0x1
     field public static final int AUTOFILL_TYPE_TOGGLE = 2; // 0x2
+    field public static final int DRAG_FLAG_ACCESSIBILITY_ACTION = 1024; // 0x400
     field public static final int DRAG_FLAG_GLOBAL = 256; // 0x100
     field public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 64; // 0x40
     field public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 128; // 0x80
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 37bbebf..27d78e5 100755
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -26,6 +26,7 @@
     field public static final String ADJUST_RUNTIME_PERMISSIONS_POLICY = "android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY";
     field public static final String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE";
     field public static final String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK";
+    field public static final String ALLOW_PLACE_IN_TWO_PANE_SETTINGS = "android.permission.ALLOW_PLACE_IN_TWO_PANE_SETTINGS";
     field public static final String AMBIENT_WALLPAPER = "android.permission.AMBIENT_WALLPAPER";
     field public static final String APPROVE_INCIDENT_REPORTS = "android.permission.APPROVE_INCIDENT_REPORTS";
     field public static final String ASSOCIATE_COMPANION_DEVICES = "android.permission.ASSOCIATE_COMPANION_DEVICES";
@@ -205,6 +206,7 @@
     field public static final String QUERY_TIME_ZONE_RULES = "android.permission.QUERY_TIME_ZONE_RULES";
     field public static final String RADIO_SCAN_WITHOUT_LOCATION = "android.permission.RADIO_SCAN_WITHOUT_LOCATION";
     field public static final String READ_ACTIVE_EMERGENCY_SESSION = "android.permission.READ_ACTIVE_EMERGENCY_SESSION";
+    field public static final String READ_APP_SPECIFIC_LOCALES = "android.permission.READ_APP_SPECIFIC_LOCALES";
     field public static final String READ_CARRIER_APP_INFO = "android.permission.READ_CARRIER_APP_INFO";
     field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
     field public static final String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS";
@@ -2319,6 +2321,7 @@
     method @Nullable public abstract java.io.File getPreloadsFileCache();
     method public abstract boolean isCredentialProtectedStorage();
     method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public android.content.Intent registerReceiverForAllUsers(@Nullable android.content.BroadcastReceiver, @NonNull android.content.IntentFilter, @Nullable String, @Nullable android.os.Handler);
+    method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public android.content.Intent registerReceiverForAllUsers(@Nullable android.content.BroadcastReceiver, @NonNull android.content.IntentFilter, @Nullable String, @Nullable android.os.Handler, int);
     method public abstract void sendBroadcast(android.content.Intent, @Nullable String, @Nullable android.os.Bundle);
     method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String, @Nullable android.os.Bundle);
     method public abstract void sendOrderedBroadcast(@NonNull android.content.Intent, @Nullable String, @Nullable android.os.Bundle, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle);
@@ -2350,7 +2353,6 @@
     field public static final String SECURE_ELEMENT_SERVICE = "secure_element";
     field public static final String SMARTSPACE_SERVICE = "smartspace";
     field public static final String STATS_MANAGER = "stats";
-    field public static final String STATUS_BAR_SERVICE = "statusbar";
     field public static final String SYSTEM_CONFIG_SERVICE = "system_config";
     field public static final String SYSTEM_UPDATE_SERVICE = "system_update";
     field public static final String TETHERING_SERVICE = "tethering";
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 56c14fc..efd96b9 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -425,6 +425,7 @@
 
   public class DevicePolicyManager {
     method public int checkProvisioningPreCondition(@Nullable String, @NonNull String);
+    method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void clearOrganizationId();
     method @RequiresPermission(android.Manifest.permission.CLEAR_FREEZE_PERIOD) public void clearSystemUpdatePolicyFreezePeriodRecord();
     method @Nullable public android.os.UserHandle createAndProvisionManagedProfile(@NonNull android.app.admin.ManagedProfileProvisioningParams) throws android.app.admin.ProvisioningException;
     method @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS) public long forceNetworkLogs();
@@ -1179,12 +1180,15 @@
 
   public final class DisplayManager {
     method public boolean areUserDisabledHdrTypesAllowed();
+    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void clearUserPreferredDisplayMode();
     method @NonNull public int[] getUserDisabledHdrTypes();
+    method @Nullable public android.view.Display.Mode getUserPreferredDisplayMode();
     method public boolean isMinimalPostProcessingRequested(int);
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setAreUserDisabledHdrTypesAllowed(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE) public void setRefreshRateSwitchingType(int);
     method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public void setShouldAlwaysRespectAppRequestedMode(boolean);
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setUserDisabledHdrTypes(@NonNull int[]);
+    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setUserPreferredDisplayMode(@NonNull android.view.Display.Mode);
     method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public boolean shouldAlwaysRespectAppRequestedMode();
     field public static final int SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS = 2; // 0x2
     field public static final int SWITCHING_TYPE_NONE = 0; // 0x0
@@ -2167,6 +2171,9 @@
     field public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices";
     field public static final String SHOW_FIRST_CRASH_DIALOG = "show_first_crash_dialog";
     field public static final String USER_DISABLED_HDR_FORMATS = "user_disabled_hdr_formats";
+    field public static final String USER_PREFERRED_REFRESH_RATE = "user_preferred_refresh_rate";
+    field public static final String USER_PREFERRED_RESOLUTION_HEIGHT = "user_preferred_resolution_height";
+    field public static final String USER_PREFERRED_RESOLUTION_WIDTH = "user_preferred_resolution_width";
     field public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
   }
 
@@ -2734,6 +2741,7 @@
   }
 
   public final class Display {
+    method @NonNull public android.view.Display.Mode getDefaultMode();
     method @NonNull public int[] getReportedHdrTypes();
     method @NonNull public android.graphics.ColorSpace[] getSupportedWideColorGamut();
     method public int getType();
@@ -2747,6 +2755,11 @@
     field public static final int TYPE_WIFI = 3; // 0x3
   }
 
+  public static final class Display.Mode implements android.os.Parcelable {
+    ctor public Display.Mode(int, int, float);
+    method public boolean matches(int, int, float);
+  }
+
   public class FocusFinder {
     method public static void sort(android.view.View[], int, int, android.view.ViewGroup, boolean);
   }
@@ -3245,10 +3258,12 @@
     method @NonNull public android.content.res.Configuration getConfiguration();
     method @NonNull public android.os.IBinder getFragmentToken();
     method @NonNull public android.graphics.Point getPositionInParent();
+    method public int getRunningActivityCount();
     method @NonNull public android.window.WindowContainerToken getToken();
     method public int getWindowingMode();
     method public boolean hasRunningActivity();
     method public boolean isEmpty();
+    method public boolean isTaskClearedForReuse();
     method public boolean isVisible();
     field @NonNull public static final android.os.Parcelable.Creator<android.window.TaskFragmentInfo> CREATOR;
   }
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 427bbd8..0703f7c 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -380,6 +380,27 @@
     ],
 }
 
+java_library {
+    name: "modules-utils-statemachine",
+    srcs: [
+        "com/android/internal/util/IState.java",
+        "com/android/internal/util/State.java",
+        "com/android/internal/util/StateMachine.java",
+    ],
+    libs: [
+        "framework-annotations-lib",
+        "unsupportedappusage",
+    ],
+    sdk_version: "module_current",
+    min_sdk_version: "29",
+
+    visibility: ["//visibility:public"],
+    apex_available: [
+        "//apex_available:anyapex",
+        "//apex_available:platform",
+    ],
+}
+
 filegroup {
     name: "framework-ims-common-shared-srcs",
     srcs: [
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 76f8731..d1def7e 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -55,7 +55,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
-import android.window.IRemoteTransition;
+import android.window.RemoteTransition;
 import android.window.SplashScreen;
 import android.window.WindowContainerToken;
 
@@ -426,7 +426,7 @@
     private IAppTransitionAnimationSpecsFuture mSpecsFuture;
     private RemoteAnimationAdapter mRemoteAnimationAdapter;
     private IBinder mLaunchCookie;
-    private IRemoteTransition mRemoteTransition;
+    private RemoteTransition mRemoteTransition;
     private boolean mOverrideTaskTransition;
     private String mSplashScreenThemeResName;
     @SplashScreen.SplashScreenStyle
@@ -1054,7 +1054,7 @@
      */
     @RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS)
     public static ActivityOptions makeRemoteAnimation(RemoteAnimationAdapter remoteAnimationAdapter,
-            IRemoteTransition remoteTransition) {
+            RemoteTransition remoteTransition) {
         final ActivityOptions opts = new ActivityOptions();
         opts.mRemoteAnimationAdapter = remoteAnimationAdapter;
         opts.mAnimationType = ANIM_REMOTE_ANIMATION;
@@ -1064,11 +1064,11 @@
 
     /**
      * Create an {@link ActivityOptions} instance that lets the application control the entire
-     * transition using a {@link IRemoteTransition}.
+     * transition using a {@link RemoteTransition}.
      * @hide
      */
     @RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS)
-    public static ActivityOptions makeRemoteTransition(IRemoteTransition remoteTransition) {
+    public static ActivityOptions makeRemoteTransition(RemoteTransition remoteTransition) {
         final ActivityOptions opts = new ActivityOptions();
         opts.mRemoteTransition = remoteTransition;
         return opts;
@@ -1181,8 +1181,7 @@
         }
         mRemoteAnimationAdapter = opts.getParcelable(KEY_REMOTE_ANIMATION_ADAPTER);
         mLaunchCookie = opts.getBinder(KEY_LAUNCH_COOKIE);
-        mRemoteTransition = IRemoteTransition.Stub.asInterface(opts.getBinder(
-                KEY_REMOTE_TRANSITION));
+        mRemoteTransition = opts.getParcelable(KEY_REMOTE_TRANSITION);
         mOverrideTaskTransition = opts.getBoolean(KEY_OVERRIDE_TASK_TRANSITION);
         mSplashScreenThemeResName = opts.getString(KEY_SPLASH_SCREEN_THEME);
         mRemoveWithTaskOrganizer = opts.getBoolean(KEY_REMOVE_WITH_TASK_ORGANIZER);
@@ -1348,7 +1347,7 @@
     }
 
     /** @hide */
-    public IRemoteTransition getRemoteTransition() {
+    public RemoteTransition getRemoteTransition() {
         return mRemoteTransition;
     }
 
@@ -1965,7 +1964,7 @@
             b.putBinder(KEY_LAUNCH_COOKIE, mLaunchCookie);
         }
         if (mRemoteTransition != null) {
-            b.putBinder(KEY_REMOTE_TRANSITION, mRemoteTransition.asBinder());
+            b.putParcelable(KEY_REMOTE_TRANSITION, mRemoteTransition);
         }
         if (mOverrideTaskTransition) {
             b.putBoolean(KEY_OVERRIDE_TASK_TRANSITION, mOverrideTaskTransition);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 57de588..7ddc2c94d 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -3575,4 +3575,19 @@
             throw e.rethrowAsRuntimeException();
         }
     }
+
+    @Override
+    public boolean mayPackageQuery(@NonNull String sourcePackageName,
+            @NonNull String targetPackageName) throws NameNotFoundException {
+        Objects.requireNonNull(sourcePackageName);
+        Objects.requireNonNull(targetPackageName);
+        try {
+            return mPM.mayPackageQuery(sourcePackageName, targetPackageName, getUserId());
+        } catch (ParcelableException e) {
+            e.maybeRethrow(PackageManager.NameNotFoundException.class);
+            throw new RuntimeException(e);
+        } catch (RemoteException re) {
+            throw re.rethrowAsRuntimeException();
+        }
+    }
 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index d0acacf..1ab6e97 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1739,12 +1739,26 @@
     }
 
     @Override
+    public Intent registerReceiverForAllUsers(BroadcastReceiver receiver,
+            IntentFilter filter, String broadcastPermission, Handler scheduler, int flags) {
+        return registerReceiverAsUser(receiver, UserHandle.ALL,
+                filter, broadcastPermission, scheduler, flags);
+    }
+
+    @Override
     public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
             IntentFilter filter, String broadcastPermission, Handler scheduler) {
         return registerReceiverInternal(receiver, user.getIdentifier(),
                 filter, broadcastPermission, scheduler, getOuterContext(), 0);
     }
 
+    @Override
+    public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+            IntentFilter filter, String broadcastPermission, Handler scheduler, int flags) {
+        return registerReceiverInternal(receiver, user.getIdentifier(),
+                filter, broadcastPermission, scheduler, getOuterContext(), flags);
+    }
+
     private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
             IntentFilter filter, String broadcastPermission,
             Handler scheduler, Context context, int flags) {
@@ -3124,6 +3138,7 @@
             mIsConfigurationBasedContext = container.mIsConfigurationBasedContext;
             mContextType = container.mContextType;
             mContentCaptureOptions = container.mContentCaptureOptions;
+            mAutofillOptions = container.mAutofillOptions;
         } else {
             mBasePackageName = packageInfo.mPackageName;
             ApplicationInfo ainfo = packageInfo.getApplicationInfo();
diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java
index 856c13c..5de0d69 100644
--- a/core/java/android/app/IntentService.java
+++ b/core/java/android/app/IntentService.java
@@ -55,7 +55,7 @@
  * @see android.support.v4.app.JobIntentService
  *
  * @deprecated IntentService is subject to all the
- *   <a href="/preview/features/background.html">background execution limits</a>
+ *   <a href="{@docRoot}about/versions/oreo/background.html">background execution limits</a>
  *   imposed with Android 8.0 (API level 26). Consider using {@link androidx.work.WorkManager}
  *   or {@link androidx.core.app.JobIntentService}, which uses jobs
  *   instead of services when running on Android 8.0 or higher.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index ea7fa2e..8ecfb5a 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1884,6 +1884,14 @@
              * clicks. To launch an activity in those cases, provide a {@link PendingIntent} for the
              * activity itself.
              *
+             * <p>How an Action is displayed, including whether the {@code icon}, {@code text}, or
+             * both are displayed or required, depends on where and how the action is used, and the
+             * {@link Style} applied to the Notification.
+             *
+             * <p>When the {@code title} is a {@link android.text.Spanned}, any colors set by a
+             * {@link ForegroundColorSpan} or {@link TextAppearanceSpan} may be removed or displayed
+             * with an altered in luminance to ensure proper contrast within the Notification.
+             *
              * @param icon icon to show for this action
              * @param title the title of the action
              * @param intent the {@link PendingIntent} to fire when users trigger this action
@@ -6119,21 +6127,22 @@
             if (emphasizedMode) {
                 // change the background bgColor
                 CharSequence title = action.title;
-                ColorStateList[] outResultColor = new ColorStateList[1];
                 int buttonFillColor = getColors(p).getSecondaryAccentColor();
                 if (isLegacy()) {
                     title = ContrastColorUtil.clearColorSpans(title);
                 } else {
-                    int notifBackgroundColor = getColors(p).getBackgroundColor();
-                    title = ensureColorSpanContrast(title, notifBackgroundColor, outResultColor);
+                    // Check for a full-length span color to use as the button fill color.
+                    Integer fullLengthColor = getFullLengthSpanColor(title);
+                    if (fullLengthColor != null) {
+                        // Ensure the custom button fill has 1.3:1 contrast w/ notification bg.
+                        int notifBackgroundColor = getColors(p).getBackgroundColor();
+                        buttonFillColor = ensureButtonFillContrast(
+                                fullLengthColor, notifBackgroundColor);
+                    }
+                    // Remove full-length color spans and ensure text contrast with the button fill.
+                    title = ensureColorSpanContrast(title, buttonFillColor);
                 }
                 button.setTextViewText(R.id.action0, processTextSpans(title));
-                boolean hasColorOverride = outResultColor[0] != null;
-                if (hasColorOverride) {
-                    // There's a span spanning the full text, let's take it and use it as the
-                    // background color
-                    buttonFillColor = outResultColor[0].getDefaultColor();
-                }
                 final int textColor = ContrastColorUtil.resolvePrimaryColor(mContext,
                         buttonFillColor, mInNightMode);
                 button.setTextColor(R.id.action0, textColor);
@@ -6166,17 +6175,58 @@
         }
 
         /**
-         * Ensures contrast on color spans against a background color. also returns the color of the
-         * text if a span was found that spans over the whole text.
+         * Extract the color from a full-length span from the text.
+         *
+         * @param charSequence the charSequence containing spans
+         * @return the raw color of the text's last full-length span containing a color, or null if
+         * no full-length span sets the text color.
+         * @hide
+         */
+        @VisibleForTesting
+        @Nullable
+        public static Integer getFullLengthSpanColor(CharSequence charSequence) {
+            // NOTE: this method preserves the functionality that for a CharSequence with multiple
+            // full-length spans, the color of the last one is used.
+            Integer result = null;
+            if (charSequence instanceof Spanned) {
+                Spanned ss = (Spanned) charSequence;
+                Object[] spans = ss.getSpans(0, ss.length(), Object.class);
+                // First read through all full-length spans to get the button fill color, which will
+                //  be used as the background color for ensuring contrast of non-full-length spans.
+                for (Object span : spans) {
+                    int spanStart = ss.getSpanStart(span);
+                    int spanEnd = ss.getSpanEnd(span);
+                    boolean fullLength = (spanEnd - spanStart) == charSequence.length();
+                    if (!fullLength) {
+                        continue;
+                    }
+                    if (span instanceof TextAppearanceSpan) {
+                        TextAppearanceSpan originalSpan = (TextAppearanceSpan) span;
+                        ColorStateList textColor = originalSpan.getTextColor();
+                        if (textColor != null) {
+                            result = textColor.getDefaultColor();
+                        }
+                    } else if (span instanceof ForegroundColorSpan) {
+                        ForegroundColorSpan originalSpan = (ForegroundColorSpan) span;
+                        result = originalSpan.getForegroundColor();
+                    }
+                }
+            }
+            return result;
+        }
+
+        /**
+         * Ensures contrast on color spans against a background color.
+         * Note that any full-length color spans will be removed instead of being contrasted.
          *
          * @param charSequence the charSequence on which the spans are
          * @param background the background color to ensure the contrast against
-         * @param outResultColor an array in which a color will be returned as the first element if
-         *                    there exists a full length color span.
          * @return the contrasted charSequence
+         * @hide
          */
-        private static CharSequence ensureColorSpanContrast(CharSequence charSequence,
-                int background, ColorStateList[] outResultColor) {
+        @VisibleForTesting
+        public static CharSequence ensureColorSpanContrast(CharSequence charSequence,
+                int background) {
             if (charSequence instanceof Spanned) {
                 Spanned ss = (Spanned) charSequence;
                 Object[] spans = ss.getSpans(0, ss.length(), Object.class);
@@ -6193,19 +6243,19 @@
                         TextAppearanceSpan originalSpan = (TextAppearanceSpan) resultSpan;
                         ColorStateList textColor = originalSpan.getTextColor();
                         if (textColor != null) {
-                            int[] colors = textColor.getColors();
-                            int[] newColors = new int[colors.length];
-                            for (int i = 0; i < newColors.length; i++) {
-                                boolean isBgDark = isColorDark(background);
-                                newColors[i] = ContrastColorUtil.ensureLargeTextContrast(
-                                        colors[i], background, isBgDark);
-                            }
-                            textColor = new ColorStateList(textColor.getStates().clone(),
-                                    newColors);
                             if (fullLength) {
-                                outResultColor[0] = textColor;
                                 // Let's drop the color from the span
                                 textColor = null;
+                            } else {
+                                int[] colors = textColor.getColors();
+                                int[] newColors = new int[colors.length];
+                                for (int i = 0; i < newColors.length; i++) {
+                                    boolean isBgDark = isColorDark(background);
+                                    newColors[i] = ContrastColorUtil.ensureLargeTextContrast(
+                                            colors[i], background, isBgDark);
+                                }
+                                textColor = new ColorStateList(textColor.getStates().clone(),
+                                        newColors);
                             }
                             resultSpan = new TextAppearanceSpan(
                                     originalSpan.getFamily(),
@@ -6215,15 +6265,14 @@
                                     originalSpan.getLinkTextColor());
                         }
                     } else if (resultSpan instanceof ForegroundColorSpan) {
-                        ForegroundColorSpan originalSpan = (ForegroundColorSpan) resultSpan;
-                        int foregroundColor = originalSpan.getForegroundColor();
-                        boolean isBgDark = isColorDark(background);
-                        foregroundColor = ContrastColorUtil.ensureLargeTextContrast(
-                                foregroundColor, background, isBgDark);
                         if (fullLength) {
-                            outResultColor[0] = ColorStateList.valueOf(foregroundColor);
                             resultSpan = null;
                         } else {
+                            ForegroundColorSpan originalSpan = (ForegroundColorSpan) resultSpan;
+                            int foregroundColor = originalSpan.getForegroundColor();
+                            boolean isBgDark = isColorDark(background);
+                            foregroundColor = ContrastColorUtil.ensureLargeTextContrast(
+                                    foregroundColor, background, isBgDark);
                             resultSpan = new ForegroundColorSpan(foregroundColor);
                         }
                     } else {
@@ -6253,6 +6302,21 @@
         }
 
         /**
+         * Finds a button fill color with sufficient contrast over bg (1.3:1) that has the same hue
+         * as the original color, but is lightened or darkened depending on whether the background
+         * is dark or light.
+         *
+         * @hide
+         */
+        @VisibleForTesting
+        public static int ensureButtonFillContrast(int color, int bg) {
+            return isColorDark(bg)
+                    ? ContrastColorUtil.findContrastColorAgainstDark(color, bg, true, 1.3)
+                    : ContrastColorUtil.findContrastColor(color, bg, true, 1.3);
+        }
+
+
+        /**
          * @return Whether we are currently building a notification from a legacy (an app that
          *         doesn't create material notifications by itself) app.
          */
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 77bcef3..d9a3390 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -24,7 +24,9 @@
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
+import android.content.ComponentName;
 import android.content.Context;
+import android.graphics.drawable.Icon;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -35,11 +37,15 @@
 import android.util.Slog;
 import android.view.View;
 
+import com.android.internal.statusbar.IAddTileResultCallback;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
 
 /**
  * Allows an app to control the status bar.
@@ -206,6 +212,71 @@
     /** @hide */
     public static final int CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER = 2;
 
+    /**
+     * Response indicating that the tile was not added.
+     */
+    public static final int TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED = 0;
+    /**
+     * Response indicating that the tile was already added and the user was not prompted.
+     */
+    public static final int TILE_ADD_REQUEST_RESULT_TILE_ALREADY_ADDED = 1;
+    /**
+     * Response indicating that the tile was added.
+     */
+    public static final int TILE_ADD_REQUEST_RESULT_TILE_ADDED = 2;
+    /** @hide */
+    public static final int TILE_ADD_REQUEST_RESULT_DIALOG_DISMISSED = 3;
+
+    /** @hide */
+    @IntDef(prefix = {"TILE_ADD_REQUEST_RESULT_"}, value = {
+            TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED,
+            TILE_ADD_REQUEST_RESULT_TILE_ALREADY_ADDED,
+            TILE_ADD_REQUEST_RESULT_TILE_ADDED,
+            TILE_ADD_REQUEST_RESULT_DIALOG_DISMISSED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RequestResult {}
+
+    /**
+     * Indicates that the request was sent successfully. Does not indicate that the user
+     * has accepted the request.
+     */
+    public static final int TILE_ADD_REQUEST_ANSWER_SUCCESS = 0;
+    /**
+     * Indicates that this package does not match that of the
+     * {@link android.service.quicksettings.TileService}.
+     */
+    public static final int TILE_ADD_REQUEST_ANSWER_FAILED_MISMATCHED_PACKAGE = 1;
+    /**
+     * Indicates that there's a request in progress for this package.
+     */
+    public static final int TILE_ADD_REQUEST_ANSWER_FAILED_REQUEST_IN_PROGRESS = 2;
+    /**
+     * Indicates that the component does not match an enabled
+     * {@link android.service.quicksettings.TileService} for the current user.
+     */
+    public static final int TILE_ADD_REQUEST_ANSWER_FAILED_BAD_COMPONENT = 3;
+    /**
+     * Indicates that the user is not the current user.
+     */
+    public static final int TILE_ADD_REQUEST_ANSWER_FAILED_NOT_CURRENT_USER = 4;
+    /**
+     * The request could not be processed due to an unkonwn reason.
+     */
+    public static final int TILE_ADD_REQUEST_ANSWER_FAILED_UNKNOWN_REASON = 5;
+
+    /** @hide */
+    @IntDef(prefix = {"TILE_ADD_REQUEST_ANSWER_"}, value = {
+            TILE_ADD_REQUEST_ANSWER_SUCCESS,
+            TILE_ADD_REQUEST_ANSWER_FAILED_MISMATCHED_PACKAGE,
+            TILE_ADD_REQUEST_ANSWER_FAILED_REQUEST_IN_PROGRESS,
+            TILE_ADD_REQUEST_ANSWER_FAILED_BAD_COMPONENT,
+            TILE_ADD_REQUEST_ANSWER_FAILED_NOT_CURRENT_USER,
+            TILE_ADD_REQUEST_ANSWER_FAILED_UNKNOWN_REASON
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RequestAnswer {}
+
     @UnsupportedAppUsage
     private Context mContext;
     private IStatusBarService mService;
@@ -529,6 +600,69 @@
         }
     }
 
+    /**
+     * Request to the user to add a {@link android.service.quicksettings.TileService}
+     * to the set of current QS tiles.
+     * <p>
+     * Calling this will prompt the user to decide whether they want to add the shown
+     * {@link android.service.quicksettings.TileService} to their current tiles. The user can
+     * deny the request and the system can stop processing requests for a given
+     * {@link ComponentName} after a number of requests.
+     * <p>
+     * The request will show to the user information about the tile:
+     * <ul>
+     *     <li>Application name</li>
+     *     <li>Label for the tile</li>
+     *     <li>Icon for the tile</li>
+     * </ul>
+     * <p>
+     * The user for which this will be added is determined from the {@link Context} used to retrieve
+     * this service, and must match the current user.
+     *
+     * @param tileServiceComponentName {@link ComponentName} of the
+     *        {@link android.service.quicksettings.TileService} for the request.
+     * @param tileLabel label of the tile to show to the user.
+     * @param icon icon to use in the tile shown to the user.
+     * @param resultExecutor an executor to run the callback on
+     * @param resultCallback callback to indicate the {@link RequestResult}.
+     * @return whether the request was successfully sent.
+     *
+     * @see android.service.quicksettings.TileService
+     */
+    @RequestAnswer
+    public int requestAddTileService(
+            @NonNull ComponentName tileServiceComponentName,
+            @NonNull CharSequence tileLabel,
+            @NonNull Icon icon,
+            @NonNull Executor resultExecutor,
+            @NonNull Consumer<Integer> resultCallback
+    ) {
+        Objects.requireNonNull(tileServiceComponentName);
+        Objects.requireNonNull(tileLabel);
+        Objects.requireNonNull(icon);
+        Objects.requireNonNull(resultExecutor);
+        Objects.requireNonNull(resultCallback);
+        if (!tileServiceComponentName.getPackageName().equals(mContext.getPackageName())) {
+            return TILE_ADD_REQUEST_ANSWER_FAILED_MISMATCHED_PACKAGE;
+        }
+        int userId = mContext.getUserId();
+        RequestResultCallback callbackProxy = new RequestResultCallback(resultExecutor,
+                resultCallback);
+        IStatusBarService svc = getService();
+        try {
+            return svc.requestAddTile(
+                    tileServiceComponentName,
+                    tileLabel,
+                    icon,
+                    userId,
+                    callbackProxy
+            );
+        } catch (RemoteException ex) {
+            ex.rethrowFromSystemServer();
+        }
+        return TILE_ADD_REQUEST_ANSWER_FAILED_UNKNOWN_REASON;
+    }
+
     /** @hide */
     public static String windowStateToString(int state) {
         if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING";
@@ -773,4 +907,25 @@
             return new Pair<Integer, Integer>(disable1, disable2);
         }
     }
+
+    /**
+     * @hide
+     */
+    static final class RequestResultCallback extends IAddTileResultCallback.Stub {
+
+        @NonNull
+        private final Executor mExecutor;
+        @NonNull
+        private final Consumer<Integer> mCallback;
+
+        RequestResultCallback(@NonNull Executor executor, @NonNull Consumer<Integer> callback) {
+            mExecutor = executor;
+            mCallback = callback;
+        }
+
+        @Override
+        public void onTileRequest(int userResponse) {
+            mExecutor.execute(() -> mCallback.accept(userResponse));
+        }
+    }
 }
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 84752be..963d2a8 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -574,6 +574,53 @@
             return null;
         }
 
+        public Rect peekWallpaperDimensions(Context context, boolean returnDefault, int userId) {
+            if (mService != null) {
+                try {
+                    if (!mService.isWallpaperSupported(context.getOpPackageName())) {
+                        return new Rect();
+                    }
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                }
+            }
+
+            Rect dimensions = null;
+            synchronized (this) {
+                try {
+                    Bundle params = new Bundle();
+                    // Let's peek user wallpaper first.
+                    ParcelFileDescriptor pfd = mService.getWallpaperWithFeature(
+                            context.getOpPackageName(), context.getAttributionTag(), this,
+                            FLAG_SYSTEM, params, userId);
+                    if (pfd != null) {
+                        BitmapFactory.Options options = new BitmapFactory.Options();
+                        options.inJustDecodeBounds = true;
+                        BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor(), null, options);
+                        dimensions = new Rect(0, 0, options.outWidth, options.outHeight);
+                    }
+                } catch (RemoteException ex) {
+                    Log.w(TAG, "peek wallpaper dimensions failed", ex);
+                }
+            }
+            // If user wallpaper is unavailable, may be the default one instead.
+            if ((dimensions == null || dimensions.width() == 0 || dimensions.height() == 0)
+                    && returnDefault) {
+                InputStream is = openDefaultWallpaper(context, FLAG_SYSTEM);
+                if (is != null) {
+                    try {
+                        BitmapFactory.Options options = new BitmapFactory.Options();
+                        options.inJustDecodeBounds = true;
+                        BitmapFactory.decodeStream(is, null, options);
+                        dimensions = new Rect(0, 0, options.outWidth, options.outHeight);
+                    } finally {
+                        IoUtils.closeQuietly(is);
+                    }
+                }
+            }
+            return dimensions;
+        }
+
         void forgetLoadedWallpaper() {
             synchronized (this) {
                 mCachedWallpaper = null;
@@ -1054,6 +1101,17 @@
     }
 
     /**
+     * Peek the dimensions of system wallpaper of the user without decoding it.
+     *
+     * @return the dimensions of system wallpaper
+     * @hide
+     */
+    public Rect peekBitmapDimensions() {
+        return sGlobals.peekWallpaperDimensions(
+                mContext, true /* returnDefault */, mContext.getUserId());
+    }
+
+    /**
      * Get an open, readable file descriptor to the given wallpaper image file.
      * The caller is responsible for closing the file descriptor when done ingesting the file.
      *
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 7102314..7a043a8 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -13754,6 +13754,23 @@
     }
 
     /**
+     * Clears organization ID set by the DPC and resets the precomputed enrollment specific ID.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
+    public void clearOrganizationId() {
+        if (mService == null) {
+            return;
+        }
+        try {
+            mService.clearOrganizationIdForUser(myUserId());
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Creates and provisions a managed profile and sets the
      * {@link ManagedProfileProvisioningParams#getProfileAdminComponentName()} as the profile
      * owner.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 4e4c221..fc49f79 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -375,6 +375,7 @@
 
     void setOrganizationColor(in ComponentName admin, in int color);
     void setOrganizationColorForUser(in int color, in int userId);
+    void clearOrganizationIdForUser(int userHandle);
     int getOrganizationColor(in ComponentName admin);
     int getOrganizationColorForUser(int userHandle);
 
diff --git a/core/java/android/app/search/Query.java b/core/java/android/app/search/Query.java
index c64e107..f073b4e 100644
--- a/core/java/android/app/search/Query.java
+++ b/core/java/android/app/search/Query.java
@@ -70,7 +70,7 @@
             @NonNull Bundle extras) {
         mInput = input;
         mTimestampMillis = timestampMillis;
-        mExtras = extras == null ? extras : new Bundle();
+        mExtras = extras != null ? extras : new Bundle();
     }
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothLeAudio.java b/core/java/android/bluetooth/BluetoothLeAudio.java
index c438dd3..3ea865b 100644
--- a/core/java/android/bluetooth/BluetoothLeAudio.java
+++ b/core/java/android/bluetooth/BluetoothLeAudio.java
@@ -97,12 +97,148 @@
             "android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED";
 
     /**
+     * Intent used to broadcast group node status information.
+     *
+     * <p>This intent will have 3 extra:
+     * <ul>
+     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
+     * be null if no device is active. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_GROUP_ID} - Group id. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_GROUP_NODE_STATUS} - Group node status. </li>
+     * </ul>
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LE_AUDIO_GROUP_NODE_STATUS_CHANGED =
+            "android.bluetooth.action.LE_AUDIO_GROUP_NODE_STATUS_CHANGED";
+
+
+    /**
+     * Intent used to broadcast group status information.
+     *
+     * <p>This intent will have 4 extra:
+     * <ul>
+     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
+     * be null if no device is active. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_GROUP_ID} - Group id. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_GROUP_STATUS} - Group status. </li>
+     * </ul>
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LE_AUDIO_GROUP_STATUS_CHANGED =
+            "android.bluetooth.action.LE_AUDIO_GROUP_STATUS_CHANGED";
+
+    /**
+     * Intent used to broadcast group audio configuration changed information.
+     *
+     * <p>This intent will have 5 extra:
+     * <ul>
+     * <li> {@link #EXTRA_LE_AUDIO_GROUP_ID} - Group id. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_DIRECTION} - Direction as bit mask. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_SINK_LOCATION} - Sink location as per Bluetooth Assigned
+     * Numbers </li>
+     * <li> {@link #EXTRA_LE_AUDIO_SOURCE_LOCATION} - Source location as per Bluetooth Assigned
+     * Numbers </li>
+     * <li> {@link #EXTRA_LE_AUDIO_AVAILABLE_CONTEXTS} - Available contexts for group as per
+     * Bluetooth Assigned Numbers </li>
+     * </ul>
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LE_AUDIO_CONF_CHANGED =
+            "android.bluetooth.action.LE_AUDIO_CONF_CHANGED";
+
+    /**
+     * Indicates conversation between humans as, for example, in telephony or video calls.
+     * @hide
+     */
+    public static final int CONTEXT_TYPE_COMMUNICATION = 0x0002;
+
+    /**
+     * Indicates media as, for example, in music, public radio, podcast or video soundtrack.
+     * @hide
+     */
+    public static final int CONTEXT_TYPE_MEDIA = 0x0004;
+
+    /**
      * This represents an invalid group ID.
      *
      * @hide
      */
     public static final int GROUP_ID_INVALID = IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID;
 
+    /**
+     * Contains group id.
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_GROUP_ID =
+            "android.bluetooth.extra.LE_AUDIO_GROUP_ID";
+
+    /**
+     * Contains group node status, can be any of
+     * <p>
+     * <ul>
+     * <li> {@link #GROUP_NODE_ADDED} </li>
+     * <li> {@link #GROUP_NODE_REMOVED} </li>
+     * </ul>
+     * <p>
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_GROUP_NODE_STATUS =
+            "android.bluetooth.extra.LE_AUDIO_GROUP_NODE_STATUS";
+
+    /**
+     * Contains group status, can be any of
+     *
+     * <p>
+     * <ul>
+     * <li> {@link #GROUP_STATUS_IDLE} </li>
+     * <li> {@link #GROUP_STATUS_STREAMING} </li>
+     * <li> {@link #GROUP_STATUS_SUSPENDED} </li>
+     * <li> {@link #GROUP_STATUS_RECONFIGURED} </li>
+     * <li> {@link #GROUP_STATUS_DESTROYED} </li>
+     * </ul>
+     * <p>
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_GROUP_STATUS =
+            "android.bluetooth.extra.LE_AUDIO_GROUP_STATUS";
+
+    /**
+     * Contains bit mask for direction, bit 0 set when Sink, bit 1 set when Source.
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_DIRECTION =
+            "android.bluetooth.extra.LE_AUDIO_DIRECTION";
+
+    /**
+     * Contains source location as per Bluetooth Assigned Numbers
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_SOURCE_LOCATION =
+            "android.bluetooth.extra.LE_AUDIO_SOURCE_LOCATION";
+
+    /**
+     * Contains sink location as per Bluetooth Assigned Numbers
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_SINK_LOCATION =
+            "android.bluetooth.extra.LE_AUDIO_SINK_LOCATION";
+
+    /**
+     * Contains available context types for group as per Bluetooth Assigned Numbers
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_AVAILABLE_CONTEXTS =
+            "android.bluetooth.extra.LE_AUDIO_AVAILABLE_CONTEXTS";
+
     private final BluetoothAdapter mAdapter;
     private final AttributionSource mAttributionSource;
     private final BluetoothProfileConnector<IBluetoothLeAudio> mProfileConnector =
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index b99ad51..6a527a5 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -24,6 +24,7 @@
 import android.annotation.SystemService;
 import android.app.Activity;
 import android.app.Application;
+import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.bluetooth.BluetoothDevice;
 import android.content.ComponentName;
@@ -259,7 +260,11 @@
      *
      * @param component the name of the component
      * @return whether the given component has the notification listener permission
+     *
+     * @deprecated Use
+     * {@link NotificationManager#isNotificationListenerAccessGranted(ComponentName)} instead.
      */
+    @Deprecated
     public boolean hasNotificationAccess(ComponentName component) {
         if (!checkFeaturePresent()) {
             return false;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9ff13a47..cd9c81a 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3130,6 +3130,42 @@
     }
 
     /**
+     * Same as {@link #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler, int)}
+     * but this receiver will receive broadcasts that are sent to all users. The receiver can
+     * use {@link BroadcastReceiver#getSendingUser} to determine on which user the broadcast
+     * was sent.
+     *
+     * @param receiver The BroadcastReceiver to handle the broadcast.
+     * @param filter Selects the Intent broadcasts to be received.
+     * @param broadcastPermission String naming a permissions that a
+     *      broadcaster must hold in order to send an Intent to you. If {@code null},
+     *      no permission is required.
+     * @param scheduler Handler identifying the thread that will receive
+     *      the Intent. If {@code null}, the main thread of the process will be used.
+     * @param flags Additional options for the receiver. As of
+     *      {@link android.os.Build.VERSION_CODES#TIRAMISU}, either {@link #RECEIVER_EXPORTED} or
+     *      {@link #RECEIVER_NOT_EXPORTED} must be specified if the receiver isn't being
+     *      registered for protected broadcasts
+     *
+     * @return The first sticky intent found that matches <var>filter</var>,
+     *         or {@code null} if there are none.
+     *
+     * @see #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler, int)
+     * @see #sendBroadcast
+     * @see #unregisterReceiver
+     * @hide
+     */
+    @SuppressLint("IntentBuilderName")
+    @Nullable
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+    @SystemApi
+    public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver,
+            @NonNull IntentFilter filter, @Nullable String broadcastPermission,
+            @Nullable Handler scheduler, @RegisterReceiverFlags int flags) {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
+    }
+
+    /**
      * @hide
      * Same as {@link #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)
      * but for a specific user.  This receiver will receiver broadcasts that
@@ -3160,6 +3196,41 @@
             @Nullable Handler scheduler);
 
     /**
+     * @hide
+     * Same as {@link #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler, int)
+     * but for a specific user.  This receiver will receiver broadcasts that
+     * are sent to the requested user.
+     *
+     * @param receiver The BroadcastReceiver to handle the broadcast.
+     * @param user UserHandle to send the intent to.
+     * @param filter Selects the Intent broadcasts to be received.
+     * @param broadcastPermission String naming a permissions that a
+     *      broadcaster must hold in order to send an Intent to you.  If null,
+     *      no permission is required.
+     * @param scheduler Handler identifying the thread that will receive
+     *      the Intent.  If null, the main thread of the process will be used.
+     * @param flags Additional options for the receiver. As of
+     *      {@link android.os.Build.VERSION_CODES#TIRAMISU}, either {@link #RECEIVER_EXPORTED} or
+     *      {@link #RECEIVER_NOT_EXPORTED} must be specified if the receiver isn't being
+     *      registered for protected broadcasts
+     *
+     * @return The first sticky intent found that matches <var>filter</var>,
+     *         or null if there are none.
+     *
+     * @see #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler, int)
+     * @see #sendBroadcast
+     * @see #unregisterReceiver
+     */
+    @SuppressWarnings("HiddenAbstractMethod")
+    @SuppressLint("IntentBuilderName")
+    @Nullable
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+    @UnsupportedAppUsage
+    public abstract Intent registerReceiverAsUser(BroadcastReceiver receiver,
+            UserHandle user, IntentFilter filter, @Nullable String broadcastPermission,
+            @Nullable Handler scheduler, @RegisterReceiverFlags int flags);
+
+    /**
      * Unregister a previously registered BroadcastReceiver.  <em>All</em>
      * filters that have been registered for this BroadcastReceiver will be
      * removed.
@@ -4224,14 +4295,12 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a {@link
-     * android.app.StatusBarManager} for interacting with the status bar.
+     * android.app.StatusBarManager} for interacting with the status bar and quick settings.
      *
      * @see #getSystemService(String)
      * @see android.app.StatusBarManager
      *
-     * @hide
      */
-    @SystemApi
     @SuppressLint("ServiceName")
     public static final String STATUS_BAR_SERVICE = "statusbar";
 
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 6324d0e..3a02004 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -756,6 +756,16 @@
 
     /** @hide */
     @Override
+    @Nullable
+    public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver,
+            @NonNull IntentFilter filter, @Nullable String broadcastPermission,
+            @Nullable Handler scheduler, int flags) {
+        return mBase.registerReceiverForAllUsers(receiver, filter, broadcastPermission,
+                scheduler, flags);
+    }
+
+    /** @hide */
+    @Override
     @UnsupportedAppUsage
     public Intent registerReceiverAsUser(@Nullable BroadcastReceiver receiver, UserHandle user,
             IntentFilter filter, @Nullable String broadcastPermission,
@@ -764,6 +774,16 @@
                 scheduler);
     }
 
+    /** @hide */
+    @Override
+    @UnsupportedAppUsage
+    public Intent registerReceiverAsUser(@Nullable BroadcastReceiver receiver, UserHandle user,
+            IntentFilter filter, @Nullable String broadcastPermission,
+            @Nullable Handler scheduler, int flags) {
+        return mBase.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
+                scheduler, flags);
+    }
+
     @Override
     public void unregisterReceiver(BroadcastReceiver receiver) {
         mBase.unregisterReceiver(receiver);
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 86030fd..df29249 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -818,4 +818,6 @@
     ParceledListSlice queryProperty(String propertyName, int componentType);
 
     void setKeepUninstalledPackages(in List<String> packageList);
+
+    boolean mayPackageQuery(String sourcePackageName, String targetPackageName, int userId);
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 31b9c30..6b672ff 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -9330,6 +9330,31 @@
     }
 
     /**
+     * Returns {@code true} if the source package is able to query for details about the
+     * target package. Applications that share details about other applications should
+     * use this API to determine if those details should be withheld from callers that
+     * do not otherwise have visibility of them.
+     * <p>
+     * Note: The caller must be able to query for details about the source and target
+     * package. A {@link NameNotFoundException} is thrown if it isn't.
+     *
+     * @param sourcePackageName The source package that would receive details about the
+     *                          target package.
+     * @param targetPackageName The target package whose details would be shared with the
+     *                          source package.
+     * @return {@code true} if the source package is able to query for details about the
+     * target package.
+     * @throws NameNotFoundException if either a given package can not be found on the
+     * system, or if the caller is not able to query for details about the source or
+     * target package.
+     */
+    public boolean mayPackageQuery(@NonNull String sourcePackageName,
+            @NonNull String targetPackageName) throws NameNotFoundException {
+        throw new UnsupportedOperationException(
+                "mayPackageQuery not implemented in subclass");
+    }
+
+    /**
      * Grants implicit visibility of the package that provides an authority to a querying UID.
      *
      * @throws SecurityException when called by a package other than the contacts provider
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 865940e..01e237d 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -153,7 +153,8 @@
             int index, byte[] value);
     private static native void nativeResetStatementAndClearBindings(
             long connectionPtr, long statementPtr);
-    private static native void nativeExecute(long connectionPtr, long statementPtr);
+    private static native void nativeExecute(long connectionPtr, long statementPtr,
+            boolean isPragmaStmt);
     private static native long nativeExecuteForLong(long connectionPtr, long statementPtr);
     private static native String nativeExecuteForString(long connectionPtr, long statementPtr);
     private static native int nativeExecuteForBlobFileDescriptor(
@@ -699,6 +700,8 @@
 
         final int cookie = mRecentOperations.beginOperation("execute", sql, bindArgs);
         try {
+            final boolean isPragmaStmt =
+                DatabaseUtils.getSqlStatementType(sql) == DatabaseUtils.STATEMENT_PRAGMA;
             final PreparedStatement statement = acquirePreparedStatement(sql);
             try {
                 throwIfStatementForbidden(statement);
@@ -706,7 +709,7 @@
                 applyBlockGuardPolicy(statement);
                 attachCancellationSignal(cancellationSignal);
                 try {
-                    nativeExecute(mConnectionPtr, statement.mStatementPtr);
+                    nativeExecute(mConnectionPtr, statement.mStatementPtr, isPragmaStmt);
                 } finally {
                     detachCancellationSignal(cancellationSignal);
                 }
diff --git a/core/java/android/hardware/CameraStatus.java b/core/java/android/hardware/CameraStatus.java
index 29802cb..874af29 100644
--- a/core/java/android/hardware/CameraStatus.java
+++ b/core/java/android/hardware/CameraStatus.java
@@ -31,6 +31,7 @@
     public String cameraId;
     public int status;
     public String[] unavailablePhysicalCameras;
+    public String clientPackage;
 
     @Override
     public int describeContents() {
@@ -42,12 +43,14 @@
         out.writeString(cameraId);
         out.writeInt(status);
         out.writeStringArray(unavailablePhysicalCameras);
+        out.writeString(clientPackage);
     }
 
     public void readFromParcel(Parcel in) {
         cameraId = in.readString();
         status = in.readInt();
         unavailablePhysicalCameras = in.readStringArray();
+        clientPackage = in.readString();
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<CameraStatus> CREATOR =
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index ad4e64b..47659a9 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -1450,14 +1450,14 @@
      *                Assuming that the bottom edge of the device faces the
      *                user and that the screen is face-up, tilting the top edge
      *                of the device toward the ground creates a positive pitch
-     *                angle. The range of values is -&pi; to &pi;.</li>
+     *                angle. The range of values is -&pi;/2 to &pi;/2.</li>
      * <li>values[2]: <i>Roll</i>, angle of rotation about the y axis. This
      *                value represents the angle between a plane perpendicular
      *                to the device's screen and a plane perpendicular to the
      *                ground. Assuming that the bottom edge of the device faces
      *                the user and that the screen is face-up, tilting the left
      *                edge of the device toward the ground creates a positive
-     *                roll angle. The range of values is -&pi;/2 to &pi;/2.</li>
+     *                roll angle. The range of values is -&pi; to &pi;.</li>
      * </ul>
      * <p>
      * Applying these three rotations in the azimuth, pitch, roll order
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 5833b3d..f5306b8 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -24,6 +24,7 @@
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.hardware.CameraStatus;
 import android.hardware.ICameraService;
 import android.hardware.ICameraServiceListener;
@@ -90,12 +91,19 @@
     private final Context mContext;
     private final Object mLock = new Object();
 
+    private static final String CAMERA_OPEN_CLOSE_LISTENER_PERMISSION =
+            "android.permission.CAMERA_OPEN_CLOSE_LISTENER";
+    private final boolean mHasOpenCloseListenerPermission;
+
     /**
      * @hide
      */
     public CameraManager(Context context) {
         synchronized(mLock) {
             mContext = context;
+            mHasOpenCloseListenerPermission =
+                    mContext.checkSelfPermission(CAMERA_OPEN_CLOSE_LISTENER_PERMISSION) ==
+                    PackageManager.PERMISSION_GRANTED;
         }
     }
 
@@ -253,7 +261,7 @@
     public void registerAvailabilityCallback(@NonNull AvailabilityCallback callback,
             @Nullable Handler handler) {
         CameraManagerGlobal.get().registerAvailabilityCallback(callback,
-                CameraDeviceImpl.checkAndWrapHandler(handler));
+                CameraDeviceImpl.checkAndWrapHandler(handler), mHasOpenCloseListenerPermission);
     }
 
     /**
@@ -274,7 +282,8 @@
         if (executor == null) {
             throw new IllegalArgumentException("executor was null");
         }
-        CameraManagerGlobal.get().registerAvailabilityCallback(callback, executor);
+        CameraManagerGlobal.get().registerAvailabilityCallback(callback, executor,
+                mHasOpenCloseListenerPermission);
     }
 
     /**
@@ -1303,6 +1312,8 @@
         // Camera ID -> (physical camera ID -> Status map)
         private final ArrayMap<String, ArrayList<String>> mUnavailablePhysicalDevices =
                 new ArrayMap<String, ArrayList<String>>();
+        // Opened Camera ID -> apk name map
+        private final ArrayMap<String, String> mOpenedDevices = new ArrayMap<String, String>();
 
         private final Set<Set<String>> mConcurrentCameraIdCombinations =
                 new ArraySet<Set<String>>();
@@ -1325,6 +1336,7 @@
 
         // Access only through getCameraService to deal with binder death
         private ICameraService mCameraService;
+        private boolean mHasOpenCloseListenerPermission = false;
 
         // Singleton, don't allow construction
         private CameraManagerGlobal() {
@@ -1403,6 +1415,12 @@
                                     c.cameraId, unavailPhysicalCamera);
                         }
                     }
+
+                    if (mHasOpenCloseListenerPermission &&
+                            c.status == ICameraServiceListener.STATUS_NOT_AVAILABLE &&
+                            !c.clientPackage.isEmpty()) {
+                        onCameraOpenedLocked(c.cameraId, c.clientPackage);
+                    }
                 }
                 mCameraService = cameraService;
             } catch(ServiceSpecificException e) {
@@ -1893,6 +1911,12 @@
                                 ICameraServiceListener.STATUS_NOT_PRESENT);
                     }
                 }
+
+            }
+            for (int i = 0; i < mOpenedDevices.size(); i++) {
+                String id = mOpenedDevices.keyAt(i);
+                String clientPackageId = mOpenedDevices.valueAt(i);
+                postSingleCameraOpenedUpdate(callback, executor, id, clientPackageId);
             }
         }
 
@@ -2058,9 +2082,15 @@
          *
          * @param callback the new callback to send camera availability notices to
          * @param executor The executor which should invoke the callback. May not be null.
+         * @param hasOpenCloseListenerPermission whether the client has permission for
+         *                                       onCameraOpened/onCameraClosed callback
          */
-        public void registerAvailabilityCallback(AvailabilityCallback callback, Executor executor) {
+        public void registerAvailabilityCallback(AvailabilityCallback callback, Executor executor,
+                boolean hasOpenCloseListenerPermission) {
             synchronized (mLock) {
+                // In practice, this permission doesn't change. So we don't need one flag for each
+                // callback object.
+                mHasOpenCloseListenerPermission = hasOpenCloseListenerPermission;
                 connectCameraServiceLocked();
 
                 Executor oldExecutor = mCallbackMap.put(callback, executor);
@@ -2152,26 +2182,53 @@
         @Override
         public void onCameraOpened(String cameraId, String clientPackageId) {
             synchronized (mLock) {
-                final int callbackCount = mCallbackMap.size();
-                for (int i = 0; i < callbackCount; i++) {
-                    Executor executor = mCallbackMap.valueAt(i);
-                    final AvailabilityCallback callback = mCallbackMap.keyAt(i);
+                onCameraOpenedLocked(cameraId, clientPackageId);
+            }
+        }
 
-                    postSingleCameraOpenedUpdate(callback, executor, cameraId, clientPackageId);
+        private void onCameraOpenedLocked(String cameraId, String clientPackageId) {
+            String oldApk = mOpenedDevices.put(cameraId, clientPackageId);
+
+            if (oldApk != null) {
+                if (oldApk.equals(clientPackageId)) {
+                    Log.w(TAG,
+                            "onCameraOpened was previously called for " + oldApk
+                            + " and is now again called for the same package name, "
+                            + "so no new client visible update will be sent");
+                    return;
+                } else {
+                    Log.w(TAG,
+                            "onCameraOpened was previously called for " + oldApk
+                            + " and is now called for " + clientPackageId
+                            + " without onCameraClosed being called first");
                 }
             }
+
+            final int callbackCount = mCallbackMap.size();
+            for (int i = 0; i < callbackCount; i++) {
+                Executor executor = mCallbackMap.valueAt(i);
+                final AvailabilityCallback callback = mCallbackMap.keyAt(i);
+
+                postSingleCameraOpenedUpdate(callback, executor, cameraId, clientPackageId);
+            }
         }
 
         @Override
         public void onCameraClosed(String cameraId) {
             synchronized (mLock) {
-                final int callbackCount = mCallbackMap.size();
-                for (int i = 0; i < callbackCount; i++) {
-                    Executor executor = mCallbackMap.valueAt(i);
-                    final AvailabilityCallback callback = mCallbackMap.keyAt(i);
+                onCameraClosedLocked(cameraId);
+            }
+        }
 
-                    postSingleCameraClosedUpdate(callback, executor, cameraId);
-                }
+        private void onCameraClosedLocked(String cameraId) {
+            mOpenedDevices.remove(cameraId);
+
+            final int callbackCount = mCallbackMap.size();
+            for (int i = 0; i < callbackCount; i++) {
+                Executor executor = mCallbackMap.valueAt(i);
+                final AvailabilityCallback callback = mCallbackMap.keyAt(i);
+
+                postSingleCameraClosedUpdate(callback, executor, cameraId);
             }
         }
 
@@ -2229,6 +2286,10 @@
                 for (int i = mDeviceStatus.size() - 1; i >= 0; i--) {
                     String cameraId = mDeviceStatus.keyAt(i);
                     onStatusChangedLocked(ICameraServiceListener.STATUS_NOT_PRESENT, cameraId);
+
+                    if (mHasOpenCloseListenerPermission) {
+                        onCameraClosedLocked(cameraId);
+                    }
                 }
                 for (int i = 0; i < mTorchStatus.size(); i++) {
                     String cameraId = mTorchStatus.keyAt(i);
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 5034ef1..209ee40e 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -864,7 +864,8 @@
         if (surface != null) {
             builder.setSurface(surface);
         }
-        return createVirtualDisplay(null /* projection */, builder.build(), callback, handler);
+        return createVirtualDisplay(null /* projection */, builder.build(), callback, handler,
+                null /* windowContext */);
     }
 
     // TODO : Remove this hidden API after remove all callers. (Refer to MultiDisplayService)
@@ -882,15 +883,17 @@
         if (surface != null) {
             builder.setSurface(surface);
         }
-        return createVirtualDisplay(projection, builder.build(), callback, handler);
+        return createVirtualDisplay(projection, builder.build(), callback, handler,
+                null /* windowContext */);
     }
 
     /** @hide */
     public VirtualDisplay createVirtualDisplay(@Nullable MediaProjection projection,
             @NonNull VirtualDisplayConfig virtualDisplayConfig,
-            @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
+            @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler,
+            @Nullable Context windowContext) {
         return mGlobal.createVirtualDisplay(mContext, projection, virtualDisplayConfig, callback,
-                handler);
+                handler, windowContext);
     }
 
     /**
@@ -1110,6 +1113,44 @@
     }
 
     /**
+     * Sets the default display mode, according to the refresh rate and the resolution chosen by the
+     * user.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+    public void setUserPreferredDisplayMode(@NonNull Display.Mode mode) {
+        // Create a new object containing default values for the unused fields like mode ID and
+        // alternative refresh rates.
+        Display.Mode preferredMode = new Display.Mode(mode.getPhysicalWidth(),
+                mode.getPhysicalHeight(), mode.getRefreshRate());
+        mGlobal.setUserPreferredDisplayMode(preferredMode);
+    }
+
+    /**
+     * Removes the user preferred display mode.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+    public void clearUserPreferredDisplayMode() {
+        mGlobal.setUserPreferredDisplayMode(null);
+    }
+
+    /**
+     * Returns the user preferred display mode.
+     *
+     * @hide
+     */
+    @TestApi
+    @Nullable
+    public Display.Mode getUserPreferredDisplayMode() {
+        return mGlobal.getUserPreferredDisplayMode();
+    }
+
+    /**
      * When enabled the app requested mode is always selected regardless of user settings and
      * policies for low brightness, low battery, etc.
      *
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 2025f40..75155bb 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -583,7 +583,7 @@
 
     public VirtualDisplay createVirtualDisplay(@NonNull Context context, MediaProjection projection,
             @NonNull VirtualDisplayConfig virtualDisplayConfig, VirtualDisplay.Callback callback,
-            Handler handler) {
+            Handler handler, @Nullable Context windowContext) {
         VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, handler);
         IMediaProjection projectionToken = projection != null ? projection.getProjection() : null;
         int displayId;
@@ -609,7 +609,7 @@
             return null;
         }
         return new VirtualDisplay(this, display, callbackWrapper,
-                virtualDisplayConfig.getSurface());
+                virtualDisplayConfig.getSurface(), windowContext);
     }
 
     public void setVirtualDisplaySurface(IVirtualDisplayCallback token, Surface surface) {
@@ -877,6 +877,29 @@
     }
 
     /**
+     * Sets the default display mode, according to the refresh rate and the resolution chosen by the
+     * user.
+     */
+    public void setUserPreferredDisplayMode(Display.Mode mode) {
+        try {
+            mDm.setUserPreferredDisplayMode(mode);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the user preferred display mode.
+     */
+    public Display.Mode getUserPreferredDisplayMode() {
+        try {
+            return mDm.getUserPreferredDisplayMode();
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * When enabled the app requested display resolution and refresh rate is always selected
      * in DisplayModeDirector regardless of user settings and policies for low brightness, low
      * battery etc.
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 1162146..b3be9da 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -27,6 +27,7 @@
 import android.hardware.display.WifiDisplay;
 import android.hardware.display.WifiDisplayStatus;
 import android.media.projection.IMediaProjection;
+import android.view.Display.Mode;
 import android.view.DisplayInfo;
 import android.view.Surface;
 
@@ -162,6 +163,11 @@
     // based on hardware capability.
     int getPreferredWideGamutColorSpaceId();
 
+    // Sets the user preferred display mode.
+    // Requires WRITE_SECURE_SETTINGS permission.
+    void setUserPreferredDisplayMode(in Mode mode);
+    Mode getUserPreferredDisplayMode();
+
     // When enabled the app requested display resolution and refresh rate is always selected
     // in DisplayModeDirector regardless of user settings and policies for low brightness, low
     // battery etc.
diff --git a/core/java/android/hardware/display/VirtualDisplay.java b/core/java/android/hardware/display/VirtualDisplay.java
index bf62c95..71cbd20 100644
--- a/core/java/android/hardware/display/VirtualDisplay.java
+++ b/core/java/android/hardware/display/VirtualDisplay.java
@@ -15,6 +15,8 @@
  */
 package android.hardware.display;
 
+import android.annotation.Nullable;
+import android.content.Context;
 import android.view.Display;
 import android.view.Surface;
 
@@ -36,13 +38,19 @@
     private final Display mDisplay;
     private IVirtualDisplayCallback mToken;
     private Surface mSurface;
+    /**
+     * Store the WindowContext in a field. If it is a local variable, and it is garbage collected
+     * during a MediaProjection session, the WindowContainer listener no longer exists.
+     */
+    @Nullable private final Context mWindowContext;
 
     VirtualDisplay(DisplayManagerGlobal global, Display display,
-            IVirtualDisplayCallback token, Surface surface) {
+            IVirtualDisplayCallback token, Surface surface, Context windowContext) {
         mGlobal = global;
         mDisplay = display;
         mToken = token;
         mSurface = surface;
+        mWindowContext = windowContext;
     }
 
     /**
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 7c42dc0..d48d562 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -850,26 +850,6 @@
     }
 
     /**
-     * Checks if the specified user has enrollments in any of the specified sensors.
-     * @hide
-     */
-    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
-    public boolean hasEnrolledTemplatesForAnySensor(int userId,
-            @NonNull List<FingerprintSensorPropertiesInternal> sensors) {
-        if (mService == null) {
-            Slog.w(TAG, "hasEnrolledTemplatesForAnySensor: no fingerprint service");
-            return false;
-        }
-
-        try {
-            return mService.hasEnrolledTemplatesForAnySensor(userId, sensors,
-                    mContext.getOpPackageName());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * @hide
      */
     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
diff --git a/core/java/android/hardware/fingerprint/FingerprintStateListener.java b/core/java/android/hardware/fingerprint/FingerprintStateListener.java
index 6e607a2..cf914c5 100644
--- a/core/java/android/hardware/fingerprint/FingerprintStateListener.java
+++ b/core/java/android/hardware/fingerprint/FingerprintStateListener.java
@@ -49,5 +49,10 @@
      * Defines behavior in response to state update
      * @param newState new state of fingerprint sensor
      */
-    public abstract void onStateChanged(@FingerprintStateListener.State int newState);
+    public void onStateChanged(@FingerprintStateListener.State int newState) {};
+
+    /**
+     * Invoked when enrollment state changes for the specified user
+     */
+    public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {};
 }
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 4774827..de94b2f 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -120,9 +120,6 @@
     // Determine if a user has at least one enrolled fingerprint.
     boolean hasEnrolledFingerprints(int sensorId, int userId, String opPackageName);
 
-    // Determine if a user has at least one enrolled fingerprint in any of the specified sensors
-    boolean hasEnrolledTemplatesForAnySensor(int userId, in List<FingerprintSensorPropertiesInternal> sensors, String opPackageName);
-
     // Return the LockoutTracker status for the specified user
     int getLockoutModeForUser(int sensorId, int userId);
 
diff --git a/core/java/android/hardware/fingerprint/IFingerprintStateListener.aidl b/core/java/android/hardware/fingerprint/IFingerprintStateListener.aidl
index 56dba7e..1aa6fa1 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintStateListener.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintStateListener.aidl
@@ -24,4 +24,5 @@
  */
 oneway interface IFingerprintStateListener {
     void onStateChanged(int newState);
+    void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments);
 }
diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java
index 6d56d2d..51045a4 100644
--- a/core/java/android/hardware/location/ContextHubInfo.java
+++ b/core/java/android/hardware/location/ContextHubInfo.java
@@ -79,6 +79,29 @@
         mSupportedSensors = new int[0];
         mMemoryRegions = new MemoryRegion[0];
     }
+    /**
+     * @hide
+     */
+    public ContextHubInfo(android.hardware.contexthub.ContextHubInfo contextHub) {
+        mId = contextHub.id;
+        mName = contextHub.name;
+        mVendor = contextHub.vendor;
+        mToolchain = contextHub.toolchain;
+        mPlatformVersion = 0;
+        mToolchainVersion = 0;
+        mPeakMips = contextHub.peakMips;
+        mStoppedPowerDrawMw = 0;
+        mSleepPowerDrawMw = 0;
+        mPeakPowerDrawMw = 0;
+        mMaxPacketLengthBytes = contextHub.maxSupportedMessageLengthBytes;
+        mChrePlatformId = contextHub.chrePlatformId;
+        mChreApiMajorVersion = contextHub.chreApiMajorVersion;
+        mChreApiMinorVersion = contextHub.chreApiMinorVersion;
+        mChrePatchVersion = (short) contextHub.chrePatchVersion;
+
+        mSupportedSensors = new int[0];
+        mMemoryRegions = new MemoryRegion[0];
+    }
 
     /**
      * returns the maximum number of bytes that can be sent per message to the hub
diff --git a/core/java/android/os/AggregateBatteryConsumer.java b/core/java/android/os/AggregateBatteryConsumer.java
index 802387c..e088f30 100644
--- a/core/java/android/os/AggregateBatteryConsumer.java
+++ b/core/java/android/os/AggregateBatteryConsumer.java
@@ -31,18 +31,23 @@
  *
  * {@hide}
  */
-public final class AggregateBatteryConsumer extends BatteryConsumer implements Parcelable {
+public final class AggregateBatteryConsumer extends BatteryConsumer {
+    static final int CONSUMER_TYPE_AGGREGATE = 0;
 
-    private final double mConsumedPowerMah;
+    static final int COLUMN_INDEX_SCOPE = BatteryConsumer.COLUMN_COUNT;
+    static final int COLUMN_INDEX_CONSUMED_POWER = COLUMN_INDEX_SCOPE + 1;
+    static final int COLUMN_COUNT = BatteryConsumer.COLUMN_COUNT + 2;
 
-    public AggregateBatteryConsumer(@NonNull Builder builder) {
-        super(builder.mPowerComponentsBuilder.build());
-        mConsumedPowerMah = builder.mConsumedPowerMah;
+    AggregateBatteryConsumer(BatteryConsumerData data) {
+        super(data);
     }
 
-    private AggregateBatteryConsumer(@NonNull Parcel source) {
-        super(new PowerComponents(source));
-        mConsumedPowerMah = source.readDouble();
+    private AggregateBatteryConsumer(@NonNull Builder builder) {
+        super(builder.mData, builder.mPowerComponentsBuilder.build());
+    }
+
+    int getScope() {
+        return mData.getInt(COLUMN_INDEX_SCOPE);
     }
 
     @Override
@@ -51,31 +56,8 @@
     }
 
     @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
-        dest.writeDouble(mConsumedPowerMah);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @NonNull
-    public static final Creator<AggregateBatteryConsumer> CREATOR =
-            new Creator<AggregateBatteryConsumer>() {
-                public AggregateBatteryConsumer createFromParcel(@NonNull Parcel source) {
-                    return new AggregateBatteryConsumer(source);
-                }
-
-                public AggregateBatteryConsumer[] newArray(int size) {
-                    return new AggregateBatteryConsumer[size];
-                }
-            };
-
-    @Override
     public double getConsumedPower() {
-        return mConsumedPowerMah;
+        return mData.getDouble(COLUMN_INDEX_CONSUMED_POWER);
     }
 
     /** Serializes this object to XML */
@@ -83,7 +65,7 @@
             @BatteryUsageStats.AggregateBatteryConsumerScope int scope) throws IOException {
         serializer.startTag(null, BatteryUsageStats.XML_TAG_AGGREGATE);
         serializer.attributeInt(null, BatteryUsageStats.XML_ATTR_SCOPE, scope);
-        serializer.attributeDouble(null, BatteryUsageStats.XML_ATTR_POWER, mConsumedPowerMah);
+        serializer.attributeDouble(null, BatteryUsageStats.XML_ATTR_POWER, getConsumedPower());
         mPowerComponents.writeToXml(serializer);
         serializer.endTag(null, BatteryUsageStats.XML_TAG_AGGREGATE);
     }
@@ -119,17 +101,16 @@
      * Builder for DeviceBatteryConsumer.
      */
     public static final class Builder extends BaseBuilder<AggregateBatteryConsumer.Builder> {
-        private double mConsumedPowerMah;
-
-        public Builder(@NonNull String[] customPowerComponentNames, boolean includePowerModels) {
-            super(customPowerComponentNames, includePowerModels);
+        public Builder(BatteryConsumer.BatteryConsumerData data, int scope) {
+            super(data, CONSUMER_TYPE_AGGREGATE);
+            data.putInt(COLUMN_INDEX_SCOPE, scope);
         }
 
         /**
          * Sets the total power included in this aggregate.
          */
         public Builder setConsumedPower(double consumedPowerMah) {
-            mConsumedPowerMah = consumedPowerMah;
+            mData.putDouble(COLUMN_INDEX_CONSUMED_POWER, consumedPowerMah);
             return this;
         }
 
@@ -137,7 +118,8 @@
          * Adds power and usage duration from the supplied AggregateBatteryConsumer.
          */
         public void add(AggregateBatteryConsumer aggregateBatteryConsumer) {
-            mConsumedPowerMah += aggregateBatteryConsumer.mConsumedPowerMah;
+            setConsumedPower(mData.getDouble(COLUMN_INDEX_CONSUMED_POWER)
+                    + aggregateBatteryConsumer.getConsumedPower());
             mPowerComponentsBuilder.addPowerAndDuration(aggregateBatteryConsumer.mPowerComponents);
         }
 
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index da94d74..34f079a 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -19,6 +19,8 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.database.CursorWindow;
+import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
 import java.io.PrintWriter;
@@ -32,6 +34,8 @@
  */
 public abstract class BatteryConsumer {
 
+    private static final String TAG = "BatteryConsumer";
+
     /**
      * Power usage component, describing the particular part of the system
      * responsible for power drain.
@@ -147,12 +151,22 @@
      */
     public static final int POWER_MODEL_MEASURED_ENERGY = 2;
 
+    static final int COLUMN_INDEX_BATTERY_CONSUMER_TYPE = 0;
+    static final int COLUMN_COUNT = 1;
+
+    protected final BatteryConsumerData mData;
     protected final PowerComponents mPowerComponents;
 
-    protected BatteryConsumer(@NonNull PowerComponents powerComponents) {
+    protected BatteryConsumer(BatteryConsumerData data, @NonNull PowerComponents powerComponents) {
+        mData = data;
         mPowerComponents = powerComponents;
     }
 
+    public BatteryConsumer(BatteryConsumerData data) {
+        mData = data;
+        mPowerComponents = new PowerComponents(data);
+    }
+
     /**
      * Total power consumed by this consumer, in mAh.
      */
@@ -192,11 +206,7 @@
     }
 
     public int getCustomPowerComponentCount() {
-        return mPowerComponents.getCustomPowerComponentCount();
-    }
-
-    void setCustomPowerComponentNames(String[] customPowerComponentNames) {
-        mPowerComponents.setCustomPowerComponentNames(customPowerComponentNames);
+        return mData.layout.customPowerComponentCount;
     }
 
     /**
@@ -231,10 +241,6 @@
         return mPowerComponents.getUsageDurationForCustomComponentMillis(componentId);
     }
 
-    protected void writeToParcel(Parcel dest, int flags) {
-        mPowerComponents.writeToParcel(dest, flags);
-    }
-
     /**
      * Returns the name of the specified component.  Intended for logging and debugging.
      */
@@ -318,13 +324,151 @@
         return (long) (powerMah * (10 * 3600 / 1000) + 0.5);
     }
 
-    protected abstract static class BaseBuilder<T extends BaseBuilder<?>> {
-        final PowerComponents.Builder mPowerComponentsBuilder;
+    static class BatteryConsumerData {
+        private final CursorWindow mCursorWindow;
+        private final int mCursorRow;
+        public final BatteryConsumerDataLayout layout;
 
-        public BaseBuilder(@NonNull String[] customPowerComponentNames,
-                boolean includePowerModels) {
-            mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentNames,
-                    includePowerModels);
+        BatteryConsumerData(CursorWindow cursorWindow, int cursorRow,
+                BatteryConsumerDataLayout layout) {
+            mCursorWindow = cursorWindow;
+            mCursorRow = cursorRow;
+            this.layout = layout;
+        }
+
+        @Nullable
+        static BatteryConsumerData create(CursorWindow cursorWindow,
+                BatteryConsumerDataLayout layout) {
+            int cursorRow = cursorWindow.getNumRows();
+            if (!cursorWindow.allocRow()) {
+                Slog.e(TAG, "Cannot allocate BatteryConsumerData: too many UIDs: " + cursorRow);
+                cursorRow = -1;
+            }
+            return new BatteryConsumerData(cursorWindow, cursorRow, layout);
+        }
+
+        void putInt(int columnIndex, int value) {
+            if (mCursorRow == -1) {
+                return;
+            }
+            mCursorWindow.putLong(value, mCursorRow, columnIndex);
+        }
+
+        int getInt(int columnIndex) {
+            if (mCursorRow == -1) {
+                return 0;
+            }
+            return mCursorWindow.getInt(mCursorRow, columnIndex);
+        }
+
+        void putDouble(int columnIndex, double value) {
+            if (mCursorRow == -1) {
+                return;
+            }
+            mCursorWindow.putDouble(value, mCursorRow, columnIndex);
+        }
+
+        double getDouble(int columnIndex) {
+            if (mCursorRow == -1) {
+                return 0;
+            }
+            return mCursorWindow.getDouble(mCursorRow, columnIndex);
+        }
+
+        void putLong(int columnIndex, long value) {
+            if (mCursorRow == -1) {
+                return;
+            }
+            mCursorWindow.putLong(value, mCursorRow, columnIndex);
+        }
+
+        long getLong(int columnIndex) {
+            if (mCursorRow == -1) {
+                return 0;
+            }
+            return mCursorWindow.getLong(mCursorRow, columnIndex);
+        }
+
+        void putString(int columnIndex, String value) {
+            if (mCursorRow == -1) {
+                return;
+            }
+            mCursorWindow.putString(value, mCursorRow, columnIndex);
+        }
+
+        String getString(int columnIndex) {
+            if (mCursorRow == -1) {
+                return null;
+            }
+            return mCursorWindow.getString(mCursorRow, columnIndex);
+        }
+    }
+
+    static class BatteryConsumerDataLayout {
+        public final String[] customPowerComponentNames;
+        public final int customPowerComponentCount;
+        public final boolean powerModelsIncluded;
+
+        public final int consumedPowerColumn;
+        public final int firstConsumedPowerColumn;
+        public final int firstCustomConsumedPowerColumn;
+        public final int firstUsageDurationColumn;
+        public final int firstCustomUsageDurationColumn;
+        public final int firstPowerModelColumn;
+        public final int columnCount;
+
+        private BatteryConsumerDataLayout(int firstColumn, String[] customPowerComponentNames,
+                boolean powerModelsIncluded) {
+            this.customPowerComponentNames = customPowerComponentNames;
+            this.customPowerComponentCount = customPowerComponentNames.length;
+            this.powerModelsIncluded = powerModelsIncluded;
+
+            int columnIndex = firstColumn;
+            consumedPowerColumn = columnIndex++;
+
+            firstConsumedPowerColumn = columnIndex;
+            columnIndex += BatteryConsumer.POWER_COMPONENT_COUNT;
+
+            firstCustomConsumedPowerColumn = columnIndex;
+            columnIndex += customPowerComponentCount;
+
+            firstUsageDurationColumn = columnIndex;
+            columnIndex += BatteryConsumer.POWER_COMPONENT_COUNT;
+
+            firstCustomUsageDurationColumn = columnIndex;
+            columnIndex += customPowerComponentCount;
+
+            if (powerModelsIncluded) {
+                firstPowerModelColumn = columnIndex;
+                columnIndex += BatteryConsumer.POWER_COMPONENT_COUNT;
+            } else {
+                firstPowerModelColumn = -1;
+            }
+
+            columnCount = columnIndex;
+        }
+    }
+
+    static BatteryConsumerDataLayout createBatteryConsumerDataLayout(
+            String[] customPowerComponentNames, boolean includePowerModels) {
+        int columnCount = BatteryConsumer.COLUMN_COUNT;
+        columnCount = Math.max(columnCount, AggregateBatteryConsumer.COLUMN_COUNT);
+        columnCount = Math.max(columnCount, UidBatteryConsumer.COLUMN_COUNT);
+        columnCount = Math.max(columnCount, UserBatteryConsumer.COLUMN_COUNT);
+
+        return new BatteryConsumerDataLayout(columnCount, customPowerComponentNames,
+                includePowerModels);
+    }
+
+    protected abstract static class BaseBuilder<T extends BaseBuilder<?>> {
+        protected final BatteryConsumer.BatteryConsumerData mData;
+        protected final PowerComponents.Builder mPowerComponentsBuilder;
+
+        public BaseBuilder(BatteryConsumer.BatteryConsumerData data, int consumerType) {
+            mData = data;
+            data.putLong(COLUMN_INDEX_BATTERY_CONSUMER_TYPE, consumerType);
+
+            mPowerComponentsBuilder = new PowerComponents.Builder(data);
         }
 
         /**
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index a7b67ef..591b665 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -18,6 +18,8 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.database.Cursor;
+import android.database.CursorWindow;
 import android.util.Range;
 import android.util.SparseArray;
 import android.util.TypedXmlPullParser;
@@ -31,6 +33,7 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -51,7 +54,7 @@
  *
  * @hide
  */
-public final class BatteryUsageStats implements Parcelable {
+public final class BatteryUsageStats implements Parcelable, Closeable {
 
     /**
      * Scope of battery stats included in a BatteryConsumer: the entire device, just
@@ -110,6 +113,9 @@
     static final String XML_ATTR_TIME_IN_FOREGROUND = "time_in_foreground";
     static final String XML_ATTR_TIME_IN_BACKGROUND = "time_in_background";
 
+    // We need about 700 bytes per UID
+    private static final long BATTERY_CONSUMER_CURSOR_WINDOW_SIZE = 5_000 * 700;
+
     private static final int STATSD_PULL_ATOM_MAX_BYTES = 45000;
 
     private final int mDischargePercentage;
@@ -122,11 +128,13 @@
     private final long mBatteryTimeRemainingMs;
     private final long mChargeTimeRemainingMs;
     private final String[] mCustomPowerComponentNames;
+    private final boolean mIncludesPowerModels;
     private final List<UidBatteryConsumer> mUidBatteryConsumers;
     private final List<UserBatteryConsumer> mUserBatteryConsumers;
     private final AggregateBatteryConsumer[] mAggregateBatteryConsumers;
     private final Parcel mHistoryBuffer;
     private final List<BatteryStats.HistoryTag> mHistoryTagPool;
+    private CursorWindow mBatteryConsumersCursorWindow;
 
     private BatteryUsageStats(@NonNull Builder builder) {
         mStatsStartTimestampMs = builder.mStatsStartTimestampMs;
@@ -141,6 +149,8 @@
         mBatteryTimeRemainingMs = builder.mBatteryTimeRemainingMs;
         mChargeTimeRemainingMs = builder.mChargeTimeRemainingMs;
         mCustomPowerComponentNames = builder.mCustomPowerComponentNames;
+        mIncludesPowerModels = builder.mIncludePowerModels;
+        mBatteryConsumersCursorWindow = builder.mBatteryConsumersCursorWindow;
 
         double totalPowerMah = 0;
         final int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size();
@@ -309,38 +319,43 @@
         mBatteryTimeRemainingMs = source.readLong();
         mChargeTimeRemainingMs = source.readLong();
         mCustomPowerComponentNames = source.readStringArray();
+        mIncludesPowerModels = source.readBoolean();
+
+        mBatteryConsumersCursorWindow = CursorWindow.newFromParcel(source);
+        BatteryConsumer.BatteryConsumerDataLayout dataLayout =
+                BatteryConsumer.createBatteryConsumerDataLayout(mCustomPowerComponentNames,
+                        mIncludesPowerModels);
+
+        final int numRows = mBatteryConsumersCursorWindow.getNumRows();
+
         mAggregateBatteryConsumers =
                 new AggregateBatteryConsumer[AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT];
-        for (int i = 0; i < AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT; i++) {
-            mAggregateBatteryConsumers[i] =
-                    AggregateBatteryConsumer.CREATOR.createFromParcel(source);
-            mAggregateBatteryConsumers[i].setCustomPowerComponentNames(mCustomPowerComponentNames);
+        mUidBatteryConsumers = new ArrayList<>(numRows);
+        mUserBatteryConsumers = new ArrayList<>();
+
+        for (int i = 0; i < numRows; i++) {
+            final BatteryConsumer.BatteryConsumerData data =
+                    new BatteryConsumer.BatteryConsumerData(mBatteryConsumersCursorWindow, i,
+                            dataLayout);
+
+            int consumerType = mBatteryConsumersCursorWindow.getInt(i,
+                            BatteryConsumer.COLUMN_INDEX_BATTERY_CONSUMER_TYPE);
+            switch (consumerType) {
+                case AggregateBatteryConsumer.CONSUMER_TYPE_AGGREGATE: {
+                    final AggregateBatteryConsumer consumer = new AggregateBatteryConsumer(data);
+                    mAggregateBatteryConsumers[consumer.getScope()] = consumer;
+                    break;
+                }
+                case UidBatteryConsumer.CONSUMER_TYPE_UID: {
+                    mUidBatteryConsumers.add(new UidBatteryConsumer(data));
+                    break;
+                }
+                case UserBatteryConsumer.CONSUMER_TYPE_USER:
+                    mUserBatteryConsumers.add(new UserBatteryConsumer(data));
+                    break;
+            }
         }
 
-        // UidBatteryConsumers are included as a blob to avoid a TransactionTooLargeException
-        final Parcel blob = Parcel.obtain();
-        final byte[] bytes = source.readBlob();
-        blob.unmarshall(bytes, 0, bytes.length);
-        blob.setDataPosition(0);
-
-        final int uidCount = blob.readInt();
-        mUidBatteryConsumers = new ArrayList<>(uidCount);
-        for (int i = 0; i < uidCount; i++) {
-            final UidBatteryConsumer consumer =
-                    UidBatteryConsumer.CREATOR.createFromParcel(blob);
-            consumer.setCustomPowerComponentNames(mCustomPowerComponentNames);
-            mUidBatteryConsumers.add(consumer);
-        }
-        blob.recycle();
-
-        int userCount = source.readInt();
-        mUserBatteryConsumers = new ArrayList<>(userCount);
-        for (int i = 0; i < userCount; i++) {
-            final UserBatteryConsumer consumer =
-                    UserBatteryConsumer.CREATOR.createFromParcel(source);
-            consumer.setCustomPowerComponentNames(mCustomPowerComponentNames);
-            mUserBatteryConsumers.add(consumer);
-        }
         if (source.readBoolean()) {
             final byte[] historyBlob = source.readBlob();
 
@@ -374,26 +389,9 @@
         dest.writeLong(mBatteryTimeRemainingMs);
         dest.writeLong(mChargeTimeRemainingMs);
         dest.writeStringArray(mCustomPowerComponentNames);
-        for (int i = 0; i < AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT; i++) {
-            mAggregateBatteryConsumers[i].writeToParcel(dest, flags);
-        }
+        dest.writeBoolean(mIncludesPowerModels);
+        mBatteryConsumersCursorWindow.writeToParcel(dest, flags);
 
-        // UidBatteryConsumers are included as a blob, because each UidBatteryConsumer
-        // takes > 300 bytes, so a typical number of UIDs in the system, 300 would result
-        // in a 90 kB Parcel, which is not safe to pass in a binder transaction because
-        // of the possibility of TransactionTooLargeException
-        final Parcel blob = Parcel.obtain();
-        blob.writeInt(mUidBatteryConsumers.size());
-        for (int i = mUidBatteryConsumers.size() - 1; i >= 0; i--) {
-            mUidBatteryConsumers.get(i).writeToParcel(blob, flags);
-        }
-        dest.writeBlob(blob.marshall());
-        blob.recycle();
-
-        dest.writeInt(mUserBatteryConsumers.size());
-        for (int i = mUserBatteryConsumers.size() - 1; i >= 0; i--) {
-            mUserBatteryConsumers.get(i).writeToParcel(dest, flags);
-        }
         if (mHistoryBuffer != null) {
             dest.writeBoolean(true);
             dest.writeBlob(mHistoryBuffer.marshall());
@@ -682,8 +680,7 @@
                     i++;
                 }
 
-                builder = new Builder(
-                        customComponentNames.toArray(new String[0]), true);
+                builder = new Builder(customComponentNames.toArray(new String[0]), true);
 
                 builder.setStatsStartTimestamp(
                         parser.getAttributeLong(null, XML_ATTR_START_TIMESTAMP));
@@ -733,13 +730,29 @@
         return builder.build();
     }
 
+    @Override
+    public void close() throws IOException {
+        mBatteryConsumersCursorWindow.close();
+        mBatteryConsumersCursorWindow = null;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        if (mBatteryConsumersCursorWindow != null) {
+            mBatteryConsumersCursorWindow.close();
+        }
+        super.finalize();
+    }
+
     /**
      * Builder for BatteryUsageStats.
      */
     public static final class Builder {
+        private final CursorWindow mBatteryConsumersCursorWindow;
         @NonNull
         private final String[] mCustomPowerComponentNames;
         private final boolean mIncludePowerModels;
+        private final BatteryConsumer.BatteryConsumerDataLayout mBatteryConsumerDataLayout;
         private long mStatsStartTimestampMs;
         private long mStatsEndTimestampMs;
         private long mStatsDurationMs = -1;
@@ -762,12 +775,22 @@
             this(customPowerComponentNames, false);
         }
 
-        public Builder(@NonNull String[] customPowerComponentNames,  boolean includePowerModels) {
+        public Builder(@NonNull String[] customPowerComponentNames, boolean includePowerModels) {
+            mBatteryConsumersCursorWindow =
+                    new CursorWindow(null, BATTERY_CONSUMER_CURSOR_WINDOW_SIZE);
+            mBatteryConsumerDataLayout =
+                    BatteryConsumer.createBatteryConsumerDataLayout(customPowerComponentNames,
+                            includePowerModels);
+            mBatteryConsumersCursorWindow.setNumColumns(mBatteryConsumerDataLayout.columnCount);
+
             mCustomPowerComponentNames = customPowerComponentNames;
             mIncludePowerModels = includePowerModels;
-            for (int i = 0; i < AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT; i++) {
-                mAggregateBatteryConsumersBuilders[i] = new AggregateBatteryConsumer.Builder(
-                        customPowerComponentNames, includePowerModels);
+            for (int scope = 0; scope < AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT; scope++) {
+                final BatteryConsumer.BatteryConsumerData data =
+                        BatteryConsumer.BatteryConsumerData.create(mBatteryConsumersCursorWindow,
+                                mBatteryConsumerDataLayout);
+                mAggregateBatteryConsumersBuilders[scope] =
+                        new AggregateBatteryConsumer.Builder(data, scope);
             }
         }
 
@@ -892,8 +915,10 @@
             int uid = batteryStatsUid.getUid();
             UidBatteryConsumer.Builder builder = mUidBatteryConsumerBuilders.get(uid);
             if (builder == null) {
-                builder = new UidBatteryConsumer.Builder(mCustomPowerComponentNames,
-                        mIncludePowerModels, batteryStatsUid);
+                final BatteryConsumer.BatteryConsumerData data =
+                        BatteryConsumer.BatteryConsumerData.create(mBatteryConsumersCursorWindow,
+                                mBatteryConsumerDataLayout);
+                builder = new UidBatteryConsumer.Builder(data, batteryStatsUid);
                 mUidBatteryConsumerBuilders.put(uid, builder);
             }
             return builder;
@@ -908,8 +933,10 @@
         public UidBatteryConsumer.Builder getOrCreateUidBatteryConsumerBuilder(int uid) {
             UidBatteryConsumer.Builder builder = mUidBatteryConsumerBuilders.get(uid);
             if (builder == null) {
-                builder = new UidBatteryConsumer.Builder(mCustomPowerComponentNames,
-                        mIncludePowerModels, uid);
+                final BatteryConsumer.BatteryConsumerData data =
+                        BatteryConsumer.BatteryConsumerData.create(mBatteryConsumersCursorWindow,
+                                mBatteryConsumerDataLayout);
+                builder = new UidBatteryConsumer.Builder(data, uid);
                 mUidBatteryConsumerBuilders.put(uid, builder);
             }
             return builder;
@@ -923,8 +950,10 @@
         public UserBatteryConsumer.Builder getOrCreateUserBatteryConsumerBuilder(int userId) {
             UserBatteryConsumer.Builder builder = mUserBatteryConsumerBuilders.get(userId);
             if (builder == null) {
-                builder = new UserBatteryConsumer.Builder(mCustomPowerComponentNames,
-                        mIncludePowerModels, userId);
+                final BatteryConsumer.BatteryConsumerData data =
+                        BatteryConsumer.BatteryConsumerData.create(mBatteryConsumersCursorWindow,
+                                mBatteryConsumerDataLayout);
+                builder = new UserBatteryConsumer.Builder(data, userId);
                 mUserBatteryConsumerBuilders.put(userId, builder);
             }
             return builder;
@@ -988,5 +1017,38 @@
 
             return this;
         }
+
+        /**
+         * Dumps raw contents of the cursor window for debugging.
+         */
+        void dump(PrintWriter writer) {
+            final int numRows = mBatteryConsumersCursorWindow.getNumRows();
+            int numColumns = mBatteryConsumerDataLayout.columnCount;
+            for (int i = 0; i < numRows; i++) {
+                StringBuilder sb = new StringBuilder();
+                for (int j = 0; j < numColumns; j++) {
+                    final int type = mBatteryConsumersCursorWindow.getType(i, j);
+                    switch (type) {
+                        case Cursor.FIELD_TYPE_NULL:
+                            sb.append("null, ");
+                            break;
+                        case Cursor.FIELD_TYPE_INTEGER:
+                            sb.append(mBatteryConsumersCursorWindow.getInt(i, j)).append(", ");
+                            break;
+                        case Cursor.FIELD_TYPE_FLOAT:
+                            sb.append(mBatteryConsumersCursorWindow.getFloat(i, j)).append(", ");
+                            break;
+                        case Cursor.FIELD_TYPE_STRING:
+                            sb.append(mBatteryConsumersCursorWindow.getString(i, j)).append(", ");
+                            break;
+                        case Cursor.FIELD_TYPE_BLOB:
+                            sb.append("BLOB, ");
+                            break;
+                    }
+                }
+                sb.setLength(sb.length() - 2);
+                writer.println(sb);
+            }
+        }
     }
 }
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index c42c1d9..f5d8346 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -304,6 +304,8 @@
 
     @CriticalNative
     private static native void nativeMarkSensitive(long nativePtr);
+    @FastNative
+    private static native void nativeMarkForBinder(long nativePtr, IBinder binder);
     @CriticalNative
     private static native int nativeDataSize(long nativePtr);
     @CriticalNative
@@ -528,6 +530,16 @@
 
     /**
      * Parcel data should be zero'd before realloc'd or deleted.
+     *
+     * Note: currently this feature requires multiple things to work in concert:
+     * - markSensitive must be called on every relative Parcel
+     * - FLAG_CLEAR_BUF must be passed into the kernel
+     * This requires having code which does the right thing in every method and in every backend
+     * of AIDL. Rather than exposing this API, it should be replaced with a single API on
+     * IBinder objects which can be called once, and the information should be fed into the
+     * Parcel using markForBinder APIs. In terms of code size and number of API calls, this is
+     * much more extensible.
+     *
      * @hide
      */
     public final void markSensitive() {
@@ -535,9 +547,23 @@
     }
 
     /**
+     * Associate this parcel with a binder object. This marks the parcel as being prepared for a
+     * transaction on this specific binder object. Based on this, the format of the wire binder
+     * protocol may change. This should be called before any data is written to the parcel. If this
+     * is called multiple times, this will only be marked for the last binder. For future
+     * compatibility, it is recommended to call this on all parcels which are being sent over
+     * binder.
+     *
+     * @hide
+     */
+    public void markForBinder(@NonNull IBinder binder) {
+        nativeMarkForBinder(mNativePtr, binder);
+    }
+
+    /**
      * Returns the total amount of data contained in the parcel.
      */
-    public final int dataSize() {
+    public int dataSize() {
         return nativeDataSize(mNativePtr);
     }
 
@@ -695,7 +721,6 @@
      * @hide
      */
     public static boolean hasFileDescriptors(Object value) {
-        getValueType(value); // Will throw if value is not supported
         if (value instanceof LazyValue) {
             return ((LazyValue) value).hasFileDescriptors();
         } else if (value instanceof Parcelable) {
@@ -736,6 +761,8 @@
                     }
                 }
             }
+        } else {
+            getValueType(value); // Will throw if value is not supported
         }
         return false;
     }
@@ -3459,15 +3486,7 @@
 
         public void writeToParcel(Parcel out) {
             if (mObject == null) {
-                int restore = mSource.dataPosition();
-                try {
-                    mSource.setDataPosition(mPosition);
-                    out.writeInt(mSource.readInt()); // Type
-                    out.writeInt(mSource.readInt()); // Length
-                    out.appendFrom(mSource, mSource.dataPosition(), mLength);
-                } finally {
-                    mSource.setDataPosition(restore);
-                }
+                out.appendFrom(mSource, mPosition, mLength + 8);
             } else {
                 out.writeValue(mObject);
             }
diff --git a/core/java/android/os/PowerComponents.java b/core/java/android/os/PowerComponents.java
index db3d13b..259e673 100644
--- a/core/java/android/os/PowerComponents.java
+++ b/core/java/android/os/PowerComponents.java
@@ -30,7 +30,6 @@
 
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.util.Arrays;
 
 /**
  * Contains details of battery attribution data broken down to individual power drain types
@@ -39,61 +38,21 @@
  * @hide
  */
 class PowerComponents {
-    private static final int CUSTOM_POWER_COMPONENT_OFFSET = BatteryConsumer.POWER_COMPONENT_COUNT
-            - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
-
-    private final double mConsumedPowerMah;
-    @NonNull
-    private final double[] mPowerComponentsMah;
-    @NonNull
-    private final long[] mUsageDurationsMs;
-    private final int mCustomPowerComponentCount;
-    @Nullable
-    private final byte[] mPowerModels;
-    // Not written to Parcel and must be explicitly restored during the parent object's unparceling
-    private String[] mCustomPowerComponentNames;
+    private final BatteryConsumer.BatteryConsumerData mData;
 
     PowerComponents(@NonNull Builder builder) {
-        mCustomPowerComponentNames = builder.mCustomPowerComponentNames;
-        mCustomPowerComponentCount = mCustomPowerComponentNames.length;
-        mPowerComponentsMah = builder.mPowerComponentsMah;
-        mUsageDurationsMs = builder.mUsageDurationsMs;
-        mConsumedPowerMah = builder.getTotalPower();
-        mPowerModels = builder.getPowerModels();
+        mData = builder.mData;
     }
 
-    PowerComponents(@NonNull Parcel source) {
-        mConsumedPowerMah = source.readDouble();
-        mCustomPowerComponentCount = source.readInt();
-        mPowerComponentsMah = source.createDoubleArray();
-        mUsageDurationsMs = source.createLongArray();
-        if (source.readBoolean()) {
-            mPowerModels = new byte[BatteryConsumer.POWER_COMPONENT_COUNT];
-            source.readByteArray(mPowerModels);
-        } else {
-            mPowerModels = null;
-        }
-    }
-
-    /** Writes contents to Parcel */
-    void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeDouble(mConsumedPowerMah);
-        dest.writeInt(mCustomPowerComponentCount);
-        dest.writeDoubleArray(mPowerComponentsMah);
-        dest.writeLongArray(mUsageDurationsMs);
-        if (mPowerModels != null) {
-            dest.writeBoolean(true);
-            dest.writeByteArray(mPowerModels);
-        } else {
-            dest.writeBoolean(false);
-        }
+    PowerComponents(BatteryConsumer.BatteryConsumerData data) {
+        mData = data;
     }
 
     /**
      * Total power consumed by this consumer, in mAh.
      */
     public double getConsumedPower() {
-        return mConsumedPowerMah;
+        return mData.getDouble(mData.layout.consumedPowerColumn);
     }
 
     /**
@@ -108,11 +67,7 @@
             throw new IllegalArgumentException(
                     "Unsupported power component ID: " + componentId);
         }
-        try {
-            return mPowerComponentsMah[componentId];
-        } catch (ArrayIndexOutOfBoundsException e) {
-            throw new IllegalArgumentException("Unsupported power component ID: " + componentId);
-        }
+        return mData.getDouble(mData.layout.firstConsumedPowerColumn + componentId);
     }
 
     /**
@@ -122,30 +77,20 @@
      * @return Amount of consumed power in mAh.
      */
     public double getConsumedPowerForCustomComponent(int componentId) {
-        if (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
-                && componentId < BatteryConsumer.LAST_CUSTOM_POWER_COMPONENT_ID) {
-            try {
-                return mPowerComponentsMah[CUSTOM_POWER_COMPONENT_OFFSET + componentId];
-            } catch (ArrayIndexOutOfBoundsException e) {
-                throw new IllegalArgumentException(
-                        "Unsupported custom power component ID: " + componentId);
-            }
+        final int index = componentId - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
+        if (index >= 0 && index < mData.layout.customPowerComponentCount) {
+            return mData.getDouble(mData.layout.firstCustomConsumedPowerColumn + index);
         } else {
             throw new IllegalArgumentException(
                     "Unsupported custom power component ID: " + componentId);
         }
     }
 
-    void setCustomPowerComponentNames(String[] customPowerComponentNames) {
-        mCustomPowerComponentNames = customPowerComponentNames;
-    }
-
     public String getCustomPowerComponentName(int componentId) {
-        if (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
-                && componentId < BatteryConsumer.LAST_CUSTOM_POWER_COMPONENT_ID) {
+        final int index = componentId - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
+        if (index >= 0 && index < mData.layout.customPowerComponentCount) {
             try {
-                return mCustomPowerComponentNames[componentId
-                        - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID];
+                return mData.layout.customPowerComponentNames[index];
             } catch (ArrayIndexOutOfBoundsException e) {
                 throw new IllegalArgumentException(
                         "Unsupported custom power component ID: " + componentId);
@@ -156,17 +101,13 @@
         }
     }
 
-    public boolean hasPowerModels() {
-        return mPowerModels != null;
-    }
-
     @BatteryConsumer.PowerModel
-    int getPowerModel(@BatteryConsumer.PowerComponent int component) {
-        if (!hasPowerModels()) {
+    int getPowerModel(@BatteryConsumer.PowerComponent int componentId) {
+        if (!mData.layout.powerModelsIncluded) {
             throw new IllegalStateException(
                     "Power model IDs were not requested in the BatteryUsageStatsQuery");
         }
-        return mPowerModels[component];
+        return mData.getInt(mData.layout.firstPowerModelColumn + componentId);
     }
 
     /**
@@ -181,11 +122,7 @@
             throw new IllegalArgumentException(
                     "Unsupported power component ID: " + componentId);
         }
-        try {
-            return mUsageDurationsMs[componentId];
-        } catch (ArrayIndexOutOfBoundsException e) {
-            throw new IllegalArgumentException("Unsupported power component ID: " + componentId);
-        }
+        return mData.getLong(mData.layout.firstUsageDurationColumn + componentId);
     }
 
     /**
@@ -195,33 +132,13 @@
      * @return Amount of time in milliseconds.
      */
     public long getUsageDurationForCustomComponentMillis(int componentId) {
-        if (componentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID) {
+        final int index = componentId - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
+        if (index >= 0 && index < mData.layout.customPowerComponentCount) {
+            return mData.getLong(mData.layout.firstCustomUsageDurationColumn + index);
+        } else {
             throw new IllegalArgumentException(
                     "Unsupported custom power component ID: " + componentId);
         }
-        try {
-            return mUsageDurationsMs[CUSTOM_POWER_COMPONENT_OFFSET + componentId];
-        } catch (ArrayIndexOutOfBoundsException e) {
-            throw new IllegalArgumentException(
-                    "Unsupported custom power component ID: " + componentId);
-        }
-    }
-
-    public int getCustomPowerComponentCount() {
-        return mCustomPowerComponentCount;
-    }
-
-    /**
-     * Returns the largest usage duration among all power components.
-     */
-    public long getMaxComponentUsageDurationMillis() {
-        long max = 0;
-        for (int i = mUsageDurationsMs.length - 1; i >= 0; i--) {
-            if (mUsageDurationsMs[i] > max) {
-                max = mUsageDurationsMs[i];
-            }
-        }
-        return max;
     }
 
     public void dump(PrintWriter pw, boolean skipEmptyComponents) {
@@ -232,13 +149,14 @@
             if (skipEmptyComponents && componentPower == 0) {
                 continue;
             }
-            pw.print(separator); separator = " ";
+            pw.print(separator);
+            separator = " ";
             pw.print(BatteryConsumer.powerComponentIdToString(componentId));
             pw.print("=");
             PowerCalculator.printPowerMah(pw, componentPower);
         }
 
-        final int customComponentCount = getCustomPowerComponentCount();
+        final int customComponentCount = mData.layout.customPowerComponentCount;
         for (int customComponentId = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
                 customComponentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
                         + customComponentCount;
@@ -248,7 +166,8 @@
             if (skipEmptyComponents && customComponentPower == 0) {
                 continue;
             }
-            pw.print(separator); separator = " ";
+            pw.print(separator);
+            separator = " ";
             pw.print(getCustomPowerComponentName(customComponentId));
             pw.print("=");
             PowerCalculator.printPowerMah(pw, customComponentPower);
@@ -272,11 +191,10 @@
     private boolean writeStatsProtoImpl(@Nullable ProtoOutputStream proto) {
         boolean interestingData = false;
 
-        for (int idx = 0; idx < mPowerComponentsMah.length; idx++) {
-            final int componentId = idx < BatteryConsumer.POWER_COMPONENT_COUNT ?
-                    idx : idx - CUSTOM_POWER_COMPONENT_OFFSET;
-            final long powerDeciCoulombs = convertMahToDeciCoulombs(mPowerComponentsMah[idx]);
-            final long durationMs = mUsageDurationsMs[idx];
+        for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT;
+                componentId++) {
+            final long powerDeciCoulombs = convertMahToDeciCoulombs(getConsumedPower(componentId));
+            final long durationMs = getUsageDurationMillis(componentId);
 
             if (powerDeciCoulombs == 0 && durationMs == 0) {
                 // No interesting data. Make sure not to even write the COMPONENT int.
@@ -289,25 +207,49 @@
                 return true;
             }
 
-            final long token =
-                    proto.start(BatteryUsageStatsAtomsProto.BatteryConsumerData.POWER_COMPONENTS);
-            proto.write(
-                    BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage
-                            .COMPONENT,
-                    componentId);
-            proto.write(
-                    BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage
-                            .POWER_DECI_COULOMBS,
-                    powerDeciCoulombs);
-            proto.write(
-                    BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage
-                            .DURATION_MILLIS,
-                    durationMs);
-            proto.end(token);
+            writePowerComponent(proto, componentId, powerDeciCoulombs, durationMs);
+        }
+        for (int idx = 0; idx < mData.layout.customPowerComponentCount; idx++) {
+            final int componentId = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + idx;
+            final long powerDeciCoulombs =
+                    convertMahToDeciCoulombs(getConsumedPowerForCustomComponent(componentId));
+            final long durationMs = getUsageDurationForCustomComponentMillis(componentId);
+
+            if (powerDeciCoulombs == 0 && durationMs == 0) {
+                // No interesting data. Make sure not to even write the COMPONENT int.
+                continue;
+            }
+
+            interestingData = true;
+            if (proto == null) {
+                // We're just asked whether there is data, not to actually write it. And there is.
+                return true;
+            }
+
+            writePowerComponent(proto, componentId, powerDeciCoulombs, durationMs);
         }
         return interestingData;
     }
 
+    private void writePowerComponent(ProtoOutputStream proto, int componentId,
+            long powerDeciCoulombs, long durationMs) {
+        final long token =
+                proto.start(BatteryUsageStatsAtomsProto.BatteryConsumerData.POWER_COMPONENTS);
+        proto.write(
+                BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage
+                        .COMPONENT,
+                componentId);
+        proto.write(
+                BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage
+                        .POWER_DECI_COULOMBS,
+                powerDeciCoulombs);
+        proto.write(
+                BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage
+                        .DURATION_MILLIS,
+                durationMs);
+        proto.end(token);
+    }
+
     void writeToXml(TypedXmlSerializer serializer) throws IOException {
         serializer.startTag(null, BatteryUsageStats.XML_TAG_POWER_COMPONENTS);
         for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT;
@@ -326,15 +268,15 @@
             if (durationMs != 0) {
                 serializer.attributeLong(null, BatteryUsageStats.XML_ATTR_DURATION, durationMs);
             }
-            if (mPowerModels != null) {
+            if (mData.layout.powerModelsIncluded) {
                 serializer.attributeInt(null, BatteryUsageStats.XML_ATTR_MODEL,
-                        mPowerModels[componentId]);
+                        getPowerModel(componentId));
             }
             serializer.endTag(null, BatteryUsageStats.XML_TAG_COMPONENT);
         }
 
-        final int customComponentEnd =
-                BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + mCustomPowerComponentCount;
+        final int customComponentEnd = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
+                + mData.layout.customPowerComponentCount;
         for (int componentId = BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
                 componentId < customComponentEnd;
                 componentId++) {
@@ -430,22 +372,15 @@
     static final class Builder {
         private static final byte POWER_MODEL_UNINITIALIZED = -1;
 
-        private final double[] mPowerComponentsMah;
-        private final String[] mCustomPowerComponentNames;
-        private final long[] mUsageDurationsMs;
-        private final byte[] mPowerModels;
+        private final BatteryConsumer.BatteryConsumerData mData;
 
-        Builder(@NonNull String[] customPowerComponentNames, boolean includePowerModels) {
-            mCustomPowerComponentNames = customPowerComponentNames;
-            int powerComponentCount =
-                    BatteryConsumer.POWER_COMPONENT_COUNT + mCustomPowerComponentNames.length;
-            mPowerComponentsMah = new double[powerComponentCount];
-            mUsageDurationsMs = new long[powerComponentCount];
-            if (includePowerModels) {
-                mPowerModels = new byte[BatteryConsumer.POWER_COMPONENT_COUNT];
-                Arrays.fill(mPowerModels, POWER_MODEL_UNINITIALIZED);
-            } else {
-                mPowerModels = null;
+        Builder(BatteryConsumer.BatteryConsumerData data) {
+            mData = data;
+            if (mData.layout.powerModelsIncluded) {
+                for (int i = 0; i < BatteryConsumer.POWER_COMPONENT_COUNT; i++) {
+                    mData.putLong(mData.layout.firstPowerModelColumn + i,
+                            POWER_MODEL_UNINITIALIZED);
+                }
             }
         }
 
@@ -463,15 +398,11 @@
                 throw new IllegalArgumentException(
                         "Unsupported power component ID: " + componentId);
             }
-            try {
-                mPowerComponentsMah[componentId] = componentPower;
-            } catch (ArrayIndexOutOfBoundsException e) {
-                throw new IllegalArgumentException(
-                        "Unsupported power component ID: " + componentId);
+            mData.putDouble(mData.layout.firstConsumedPowerColumn + componentId, componentPower);
+            if (mData.layout.powerModelsIncluded) {
+                mData.putLong(mData.layout.firstPowerModelColumn + componentId, powerModel);
             }
-            if (mPowerModels != null) {
-                mPowerModels[componentId] = (byte) powerModel;
-            }
+
             return this;
         }
 
@@ -483,19 +414,12 @@
          */
         @NonNull
         public Builder setConsumedPowerForCustomComponent(int componentId, double componentPower) {
-            if (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
-                    && componentId < BatteryConsumer.LAST_CUSTOM_POWER_COMPONENT_ID) {
-                try {
-                    mPowerComponentsMah[CUSTOM_POWER_COMPONENT_OFFSET + componentId] =
-                            componentPower;
-                } catch (ArrayIndexOutOfBoundsException e) {
-                    throw new IllegalArgumentException(
-                            "Unsupported custom power component ID: " + componentId);
-                }
-            } else {
+            final int index = componentId - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
+            if (index < 0 || index >= mData.layout.customPowerComponentCount) {
                 throw new IllegalArgumentException(
                         "Unsupported custom power component ID: " + componentId);
             }
+            mData.putDouble(mData.layout.firstCustomConsumedPowerColumn + index, componentPower);
             return this;
         }
 
@@ -513,12 +437,8 @@
                 throw new IllegalArgumentException(
                         "Unsupported power component ID: " + componentId);
             }
-            try {
-                mUsageDurationsMs[componentId] = componentUsageDurationMillis;
-            } catch (ArrayIndexOutOfBoundsException e) {
-                throw new IllegalArgumentException(
-                        "Unsupported power component ID: " + componentId);
-            }
+            mData.putLong(mData.layout.firstUsageDurationColumn + componentId,
+                    componentUsageDurationMillis);
             return this;
         }
 
@@ -531,51 +451,67 @@
         @NonNull
         public Builder setUsageDurationForCustomComponentMillis(int componentId,
                 long componentUsageDurationMillis) {
-            if (componentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID) {
+            final int index = componentId - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
+            if (index < 0 || index >= mData.layout.customPowerComponentCount) {
                 throw new IllegalArgumentException(
                         "Unsupported custom power component ID: " + componentId);
             }
-            try {
-                mUsageDurationsMs[CUSTOM_POWER_COMPONENT_OFFSET + componentId] =
-                        componentUsageDurationMillis;
-            } catch (ArrayIndexOutOfBoundsException e) {
-                throw new IllegalArgumentException(
-                        "Unsupported custom power component ID: " + componentId);
-            }
+
+            mData.putLong(mData.layout.firstCustomUsageDurationColumn + index,
+                    componentUsageDurationMillis);
             return this;
         }
 
         public void addPowerAndDuration(PowerComponents.Builder other) {
-            addPowerAndDuration(other.mPowerComponentsMah, other.mUsageDurationsMs,
-                    other.mPowerModels);
+            addPowerAndDuration(other.mData);
         }
 
         public void addPowerAndDuration(PowerComponents other) {
-            addPowerAndDuration(other.mPowerComponentsMah, other.mUsageDurationsMs,
-                    other.mPowerModels);
+            addPowerAndDuration(other.mData);
         }
 
-        private void addPowerAndDuration(double[] powerComponentsMah,
-                long[] usageDurationsMs, byte[] powerModels) {
-            if (mPowerComponentsMah.length != powerComponentsMah.length) {
+        private void addPowerAndDuration(BatteryConsumer.BatteryConsumerData otherData) {
+            if (mData.layout.customPowerComponentCount
+                    != otherData.layout.customPowerComponentCount) {
                 throw new IllegalArgumentException(
-                        "Number of power components does not match: " + powerComponentsMah.length
-                                + ", expected: " + mPowerComponentsMah.length);
+                        "Number of power components does not match: "
+                                + otherData.layout.customPowerComponentCount
+                                + ", expected: " + mData.layout.customPowerComponentCount);
             }
 
-            for (int i = mPowerComponentsMah.length - 1; i >= 0; i--) {
-                mPowerComponentsMah[i] += powerComponentsMah[i];
+            for (int i = BatteryConsumer.POWER_COMPONENT_COUNT - 1; i >= 0; i--) {
+                final int powerColumnIndex = mData.layout.firstConsumedPowerColumn + i;
+                mData.putDouble(powerColumnIndex,
+                        mData.getDouble(powerColumnIndex)
+                                + otherData.getDouble(powerColumnIndex));
+
+                final int durationColumnIndex = mData.layout.firstUsageDurationColumn + i;
+                mData.putLong(durationColumnIndex,
+                        mData.getLong(durationColumnIndex)
+                                + otherData.getLong(durationColumnIndex));
             }
-            for (int i = mUsageDurationsMs.length - 1; i >= 0; i--) {
-                mUsageDurationsMs[i] += usageDurationsMs[i];
+
+            for (int i = mData.layout.customPowerComponentCount - 1; i >= 0; i--) {
+                final int powerColumnIndex = mData.layout.firstCustomConsumedPowerColumn + i;
+                mData.putDouble(powerColumnIndex,
+                        mData.getDouble(powerColumnIndex) + otherData.getDouble(powerColumnIndex));
+
+                final int usageColumnIndex = mData.layout.firstCustomUsageDurationColumn + i;
+                mData.putLong(usageColumnIndex,
+                        mData.getLong(usageColumnIndex) + otherData.getLong(usageColumnIndex)
+                );
             }
-            if (mPowerModels != null && powerModels != null) {
-                for (int i = mPowerModels.length - 1; i >= 0; i--) {
-                    if (mPowerModels[i] == POWER_MODEL_UNINITIALIZED) {
-                        mPowerModels[i] = powerModels[i];
-                    } else if (mPowerModels[i] != powerModels[i]
-                            && powerModels[i] != POWER_MODEL_UNINITIALIZED) {
-                        mPowerModels[i] = BatteryConsumer.POWER_MODEL_UNDEFINED;
+
+            if (mData.layout.powerModelsIncluded && otherData.layout.powerModelsIncluded) {
+                for (int i = BatteryConsumer.POWER_COMPONENT_COUNT - 1; i >= 0; i--) {
+                    final int columnIndex = mData.layout.firstPowerModelColumn + i;
+                    int powerModel = mData.getInt(columnIndex);
+                    int otherPowerModel = otherData.getInt(columnIndex);
+                    if (powerModel == POWER_MODEL_UNINITIALIZED) {
+                        mData.putLong(columnIndex, otherPowerModel);
+                    } else if (powerModel != otherPowerModel
+                            && otherPowerModel != POWER_MODEL_UNINITIALIZED) {
+                        mData.putLong(columnIndex, BatteryConsumer.POWER_MODEL_UNDEFINED);
                     }
                 }
             }
@@ -587,30 +523,34 @@
          */
         public double getTotalPower() {
             double totalPowerMah = 0;
-            for (int i = mPowerComponentsMah.length - 1; i >= 0; i--) {
-                totalPowerMah += mPowerComponentsMah[i];
+            for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT;
+                    componentId++) {
+                totalPowerMah +=
+                        mData.getDouble(mData.layout.firstConsumedPowerColumn + componentId);
+            }
+            for (int i = 0; i < mData.layout.customPowerComponentCount; i++) {
+                totalPowerMah += mData.getDouble(mData.layout.firstCustomConsumedPowerColumn + i);
             }
             return totalPowerMah;
         }
 
-        private byte[] getPowerModels() {
-            if (mPowerModels == null) {
-                return null;
-            }
-
-            byte[] powerModels = new byte[mPowerModels.length];
-            for (int i = mPowerModels.length - 1; i >= 0; i--) {
-                powerModels[i] = mPowerModels[i] != POWER_MODEL_UNINITIALIZED ? mPowerModels[i]
-                        : BatteryConsumer.POWER_MODEL_UNDEFINED;
-            }
-            return powerModels;
-        }
-
         /**
          * Creates a read-only object out of the Builder values.
          */
         @NonNull
         public PowerComponents build() {
+            mData.putDouble(mData.layout.consumedPowerColumn, getTotalPower());
+
+            if (mData.layout.powerModelsIncluded) {
+                for (int i = BatteryConsumer.POWER_COMPONENT_COUNT - 1; i >= 0; i--) {
+                    final int powerModel = mData.getInt(mData.layout.firstPowerModelColumn + i);
+                    if (powerModel == POWER_MODEL_UNINITIALIZED) {
+                        mData.putInt(mData.layout.firstPowerModelColumn + i,
+                                BatteryConsumer.POWER_MODEL_UNDEFINED);
+                    }
+                }
+            }
+
             return new PowerComponents(this);
         }
     }
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index 06a2c87..4e8418b 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -29,7 +29,14 @@
 
 import java.util.Map;
 
-/** @hide */
+/**
+ * Manage binder services as registered with the binder context manager. These services must be
+ * declared statically on an Android device (SELinux access_vector service_manager, w/ service
+ * names in service_contexts files), and they do not follow the activity lifecycle. When
+ * building applications, android.app.Service should be preferred.
+ *
+ * @hide
+ **/
 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
 public final class ServiceManager {
     private static final String TAG = "ServiceManager";
diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java
index bfc4f73..f9f4463 100644
--- a/core/java/android/os/UidBatteryConsumer.java
+++ b/core/java/android/os/UidBatteryConsumer.java
@@ -38,7 +38,9 @@
  *
  * @hide
  */
-public final class UidBatteryConsumer extends BatteryConsumer implements Parcelable {
+public final class UidBatteryConsumer extends BatteryConsumer {
+
+    static final int CONSUMER_TYPE_UID = 1;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
@@ -66,19 +68,27 @@
      */
     public static final int STATE_BACKGROUND = 1;
 
-    private final int mUid;
-    @Nullable
-    private final String mPackageWithHighestDrain;
-    private final long mTimeInForegroundMs;
-    private final long mTimeInBackgroundMs;
+    static final int COLUMN_INDEX_UID = BatteryConsumer.COLUMN_COUNT;
+    static final int COLUMN_INDEX_PACKAGE_WITH_HIGHEST_DRAIN = COLUMN_INDEX_UID + 1;
+    static final int COLUMN_INDEX_TIME_IN_FOREGROUND = COLUMN_INDEX_UID + 2;
+    static final int COLUMN_INDEX_TIME_IN_BACKGROUND = COLUMN_INDEX_UID + 3;
+    static final int COLUMN_COUNT = BatteryConsumer.COLUMN_COUNT + 4;
+
+    UidBatteryConsumer(BatteryConsumerData data) {
+        super(data);
+    }
+
+    private UidBatteryConsumer(@NonNull Builder builder) {
+        super(builder.mData, builder.mPowerComponentsBuilder.build());
+    }
 
     public int getUid() {
-        return mUid;
+        return mData.getInt(COLUMN_INDEX_UID);
     }
 
     @Nullable
     public String getPackageWithHighestDrain() {
-        return mPackageWithHighestDrain;
+        return mData.getString(COLUMN_INDEX_PACKAGE_WITH_HIGHEST_DRAIN);
     }
 
     /**
@@ -87,41 +97,13 @@
     public long getTimeInStateMs(@State int state) {
         switch (state) {
             case STATE_BACKGROUND:
-                return mTimeInBackgroundMs;
+                return mData.getInt(COLUMN_INDEX_TIME_IN_BACKGROUND);
             case STATE_FOREGROUND:
-                return mTimeInForegroundMs;
+                return mData.getInt(COLUMN_INDEX_TIME_IN_FOREGROUND);
         }
         return 0;
     }
 
-    private UidBatteryConsumer(@NonNull Builder builder) {
-        super(builder.mPowerComponentsBuilder.build());
-        mUid = builder.mUid;
-        mPackageWithHighestDrain = builder.mPackageWithHighestDrain;
-        mTimeInForegroundMs = builder.mTimeInForegroundMs;
-        mTimeInBackgroundMs = builder.mTimeInBackgroundMs;
-    }
-
-    private UidBatteryConsumer(@NonNull Parcel source) {
-        super(new PowerComponents(source));
-        mUid = source.readInt();
-        mPackageWithHighestDrain = source.readString();
-        mTimeInForegroundMs = source.readLong();
-        mTimeInBackgroundMs = source.readLong();
-    }
-
-    /**
-     * Writes the contents into a Parcel.
-     */
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
-        dest.writeInt(mUid);
-        dest.writeString(mPackageWithHighestDrain);
-        dest.writeLong(mTimeInForegroundMs);
-        dest.writeLong(mTimeInBackgroundMs);
-    }
-
     @Override
     public void dump(PrintWriter pw, boolean skipEmptyComponents) {
         final double consumedPower = getConsumedPower();
@@ -134,20 +116,8 @@
         pw.print(" ) ");
     }
 
-    @NonNull
-    public static final Creator<UidBatteryConsumer> CREATOR = new Creator<UidBatteryConsumer>() {
-        public UidBatteryConsumer createFromParcel(@NonNull Parcel source) {
-            return new UidBatteryConsumer(source);
-        }
-
-        public UidBatteryConsumer[] newArray(int size) {
-            return new UidBatteryConsumer[size];
-        }
-    };
-
-    @Override
-    public int describeContents() {
-        return 0;
+    static UidBatteryConsumer create(BatteryConsumerData data) {
+        return new UidBatteryConsumer(data);
     }
 
     /** Serializes this object to XML */
@@ -158,14 +128,15 @@
 
         serializer.startTag(null, BatteryUsageStats.XML_TAG_UID);
         serializer.attributeInt(null, BatteryUsageStats.XML_ATTR_UID, getUid());
-        if (!TextUtils.isEmpty(mPackageWithHighestDrain)) {
+        final String packageWithHighestDrain = getPackageWithHighestDrain();
+        if (!TextUtils.isEmpty(packageWithHighestDrain)) {
             serializer.attribute(null, BatteryUsageStats.XML_ATTR_HIGHEST_DRAIN_PACKAGE,
-                    mPackageWithHighestDrain);
+                    packageWithHighestDrain);
         }
         serializer.attributeLong(null, BatteryUsageStats.XML_ATTR_TIME_IN_FOREGROUND,
-                mTimeInForegroundMs);
+                getTimeInStateMs(STATE_FOREGROUND));
         serializer.attributeLong(null, BatteryUsageStats.XML_ATTR_TIME_IN_BACKGROUND,
-                mTimeInBackgroundMs);
+                getTimeInStateMs(STATE_BACKGROUND));
         mPowerComponents.writeToXml(serializer);
         serializer.endTag(null, BatteryUsageStats.XML_TAG_UID);
     }
@@ -209,22 +180,20 @@
         private final BatteryStats.Uid mBatteryStatsUid;
         private final int mUid;
         private String mPackageWithHighestDrain = PACKAGE_NAME_UNINITIALIZED;
-        public long mTimeInForegroundMs;
-        public long mTimeInBackgroundMs;
         private boolean mExcludeFromBatteryUsageStats;
 
-        public Builder(@NonNull String[] customPowerComponentNames,
-                boolean includePowerModels, @NonNull BatteryStats.Uid batteryStatsUid) {
-            super(customPowerComponentNames, includePowerModels);
+        public Builder(BatteryConsumerData data, @NonNull BatteryStats.Uid batteryStatsUid) {
+            super(data, CONSUMER_TYPE_UID);
             mBatteryStatsUid = batteryStatsUid;
             mUid = batteryStatsUid.getUid();
+            data.putLong(COLUMN_INDEX_UID, mUid);
         }
 
-        public Builder(@NonNull String[] customPowerComponentNames, boolean includePowerModels,
-                int uid) {
-            super(customPowerComponentNames, includePowerModels);
+        public Builder(BatteryConsumerData data, int uid) {
+            super(data, CONSUMER_TYPE_UID);
             mBatteryStatsUid = null;
             mUid = uid;
+            data.putLong(COLUMN_INDEX_UID, mUid);
         }
 
         @NonNull
@@ -258,10 +227,10 @@
         public Builder setTimeInStateMs(@State int state, long timeInStateMs) {
             switch (state) {
                 case STATE_FOREGROUND:
-                    mTimeInForegroundMs = timeInStateMs;
+                    mData.putLong(COLUMN_INDEX_TIME_IN_FOREGROUND, timeInStateMs);
                     break;
                 case STATE_BACKGROUND:
-                    mTimeInBackgroundMs = timeInStateMs;
+                    mData.putLong(COLUMN_INDEX_TIME_IN_BACKGROUND, timeInStateMs);
                     break;
                 default:
                     throw new IllegalArgumentException("Unsupported state: " + state);
@@ -282,13 +251,18 @@
          */
         public Builder add(UidBatteryConsumer consumer) {
             mPowerComponentsBuilder.addPowerAndDuration(consumer.mPowerComponents);
-            mTimeInBackgroundMs += consumer.mTimeInBackgroundMs;
-            mTimeInForegroundMs += consumer.mTimeInForegroundMs;
+
+            setTimeInStateMs(STATE_FOREGROUND,
+                    mData.getLong(COLUMN_INDEX_TIME_IN_FOREGROUND)
+                            + consumer.getTimeInStateMs(STATE_FOREGROUND));
+            setTimeInStateMs(STATE_BACKGROUND,
+                    mData.getLong(COLUMN_INDEX_TIME_IN_BACKGROUND)
+                            + consumer.getTimeInStateMs(STATE_BACKGROUND));
 
             if (mPackageWithHighestDrain == PACKAGE_NAME_UNINITIALIZED) {
-                mPackageWithHighestDrain = consumer.mPackageWithHighestDrain;
+                mPackageWithHighestDrain = consumer.getPackageWithHighestDrain();
             } else if (!TextUtils.equals(mPackageWithHighestDrain,
-                    consumer.mPackageWithHighestDrain)) {
+                    consumer.getPackageWithHighestDrain())) {
                 // Consider combining two UidBatteryConsumers with this distribution
                 // of power drain between packages:
                 // (package1=100, package2=10) and (package1=100, package2=101).
@@ -317,6 +291,9 @@
             if (mPackageWithHighestDrain == PACKAGE_NAME_UNINITIALIZED) {
                 mPackageWithHighestDrain = null;
             }
+            if (mPackageWithHighestDrain != null) {
+                mData.putString(COLUMN_INDEX_PACKAGE_WITH_HIGHEST_DRAIN, mPackageWithHighestDrain);
+            }
             return new UidBatteryConsumer(this);
         }
     }
diff --git a/core/java/android/os/UserBatteryConsumer.java b/core/java/android/os/UserBatteryConsumer.java
index b508a8c..c2d20a6 100644
--- a/core/java/android/os/UserBatteryConsumer.java
+++ b/core/java/android/os/UserBatteryConsumer.java
@@ -35,37 +35,30 @@
  *
  * {@hide}
  */
-public class UserBatteryConsumer extends BatteryConsumer implements Parcelable {
-    private final int mUserId;
+public class UserBatteryConsumer extends BatteryConsumer {
+    static final int CONSUMER_TYPE_USER = 2;
 
-    public int getUserId() {
-        return mUserId;
+    private static final int COLUMN_INDEX_USER_ID = BatteryConsumer.COLUMN_COUNT;
+
+    static final int COLUMN_COUNT = BatteryConsumer.COLUMN_COUNT + 1;
+
+    UserBatteryConsumer(BatteryConsumerData data) {
+        super(data);
     }
 
     private UserBatteryConsumer(@NonNull UserBatteryConsumer.Builder builder) {
-        super(builder.mPowerComponentsBuilder.build());
-        mUserId = builder.mUserId;
+        super(builder.mData, builder.mPowerComponentsBuilder.build());
     }
 
-    private UserBatteryConsumer(Parcel in) {
-        super(new PowerComponents(in));
-        mUserId = in.readInt();
-    }
-
-    /**
-     * Writes the contents into a Parcel.
-     */
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
-        dest.writeInt(mUserId);
+    public int getUserId() {
+        return mData.getInt(COLUMN_INDEX_USER_ID);
     }
 
     @Override
     public void dump(PrintWriter pw, boolean skipEmptyComponents) {
         final double consumedPower = getConsumedPower();
         pw.print("User ");
-        pw.print(mUserId);
+        pw.print(getUserId());
         pw.print(": ");
         PowerCalculator.printPowerMah(pw, consumedPower);
         pw.print(" ( ");
@@ -73,24 +66,6 @@
         pw.print(" ) ");
     }
 
-    public static final Creator<UserBatteryConsumer> CREATOR =
-            new Creator<UserBatteryConsumer>() {
-                @Override
-                public UserBatteryConsumer createFromParcel(Parcel in) {
-                    return new UserBatteryConsumer(in);
-                }
-
-                @Override
-                public UserBatteryConsumer[] newArray(int size) {
-                    return new UserBatteryConsumer[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
     /** Serializes this object to XML */
     void writeToXml(TypedXmlSerializer serializer) throws IOException {
         if (getConsumedPower() == 0) {
@@ -131,13 +106,11 @@
      * Builder for UserBatteryConsumer.
      */
     public static final class Builder extends BaseBuilder<Builder> {
-        private final int mUserId;
         private List<UidBatteryConsumer.Builder> mUidBatteryConsumers;
 
-        Builder(@NonNull String[] customPowerComponentNames, boolean includePowerModels,
-                int userId) {
-            super(customPowerComponentNames, includePowerModels);
-            mUserId = userId;
+        Builder(BatteryConsumerData data, int userId) {
+            super(data, CONSUMER_TYPE_USER);
+            data.putLong(COLUMN_INDEX_USER_ID, userId);
         }
 
         /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 79a3c03..7002a38 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -28,12 +28,14 @@
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UserIdInt;
+import android.app.Activity;
 import android.app.ActivityThread;
 import android.app.AppOpsManager;
 import android.app.Application;
 import android.app.AutomaticZenRule;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.app.SearchManager;
 import android.app.WallpaperManager;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -11978,7 +11980,6 @@
          * Whether UWB should be enabled.
          * @hide
          */
-        @Readable
         public static final String UWB_ENABLED = "uwb_enabled";
 
         /**
@@ -14603,6 +14604,38 @@
         public static final int HEADS_UP_ON = 1;
 
         /**
+         * The refresh rate chosen by the user.
+         *
+         * @hide
+         */
+        @TestApi
+        @Readable
+        @SuppressLint("NoSettingsProvider")
+        public static final String USER_PREFERRED_REFRESH_RATE = "user_preferred_refresh_rate";
+
+        /**
+         * The resolution height chosen by the user.
+         *
+         * @hide
+         */
+        @TestApi
+        @Readable
+        @SuppressLint("NoSettingsProvider")
+        public static final String USER_PREFERRED_RESOLUTION_HEIGHT =
+                "user_preferred_resolution_height";
+
+        /**
+         * The resolution width chosen by the user.
+         *
+         * @hide
+         */
+        @TestApi
+        @Readable
+        @SuppressLint("NoSettingsProvider")
+        public static final String USER_PREFERRED_RESOLUTION_WIDTH =
+                "user_preferred_resolution_width";
+
+        /**
          * The name of the device
          */
         @Readable
@@ -15470,9 +15503,27 @@
          */
         public static int getInt(ContentResolver cr, String name, int def) {
             String v = getString(cr, name);
+            final boolean isQueryForDeviceProvision = name.equals(DEVICE_PROVISIONED);
             try {
-                return v != null ? Integer.parseInt(v) : def;
+                // TODO(b/197879371): remove the extra logging after bug is fixed
+                final int result;
+                if (v != null) {
+                    result = Integer.parseInt(v);
+                    if (isQueryForDeviceProvision) {
+                        Log.w(TAG, "Found settings value for provision. Returning " + result);
+                    }
+                } else {
+                    result = def;
+                    if (isQueryForDeviceProvision) {
+                        Log.w(TAG, "Missing settings value for provision. Returning " + result);
+                    }
+                }
+                return result;
             } catch (NumberFormatException e) {
+                if (isQueryForDeviceProvision) {
+                    Log.w(TAG, "Wrong settings value for provision. Found: " + v
+                            + ". Returning " + v);
+                }
                 return def;
             }
         }
@@ -17680,6 +17731,54 @@
             "android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION";
 
     /**
+     * Activity Action: For system or preinstalled apps to show their {@link Activity} in 2-pane
+     * mode in Settings app on large screen devices.
+     * <p>
+     *     Input: {@link #EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_URI} must be included to
+     * specify the intent for the activity which will be displayed in 2-pane mode in Settings app.
+     * It's an intent URI string from {@code intent.toUri(Intent.URI_INTENT_SCHEME)}.
+     *
+     *     Input: {@link #EXTRA_SETTINGS_LARGE_SCREEN_HIGHLIGHT_MENU_KEY} must be included to
+     * specify a key that indicates the menu item which will be highlighted on settings home menu.
+     *
+     *     Input: {@link #EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_PENDING_INTENT} is optional. Apps
+     * can use the {@link PendingIntent} extra to launch into its private {@link Activity}.
+     * <p>
+     * Output: Nothing.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_SETTINGS_LARGE_SCREEN_DEEP_LINK =
+            "android.settings.SETTINGS_LARGE_SCREEN_DEEP_LINK";
+
+    /**
+     * Activity Extra: Specify the intent for the {@link Activity} which will be displayed in 2-pane
+     * mode in Settings app. It's an intent URI string from
+     * {@code intent.toUri(Intent.URI_INTENT_SCHEME)}.
+     * <p>
+     * This must be passed as an extra field to {@link #ACTION_SETTINGS_LARGE_SCREEN_DEEP_LINK}.
+     */
+    public static final String EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_URI =
+            "android.provider.extra.SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_URI";
+
+    /**
+     * Activity Extra: Specify a key that indicates the menu item which should be highlighted on
+     * settings home menu.
+     * <p>
+     * This must be passed as an extra field to {@link #ACTION_SETTINGS_LARGE_SCREEN_DEEP_LINK}.
+     */
+    public static final String EXTRA_SETTINGS_LARGE_SCREEN_HIGHLIGHT_MENU_KEY =
+            "android.provider.extra.SETTINGS_LARGE_SCREEN_HIGHLIGHT_MENU_KEY";
+
+    /**
+     * Activity Extra: Apps can use the {@link PendingIntent} extra to launch into its private
+     * {@link Activity}.
+     * <p>
+     * This is an optional extra field to {@link #ACTION_SETTINGS_LARGE_SCREEN_DEEP_LINK}.
+     */
+    public static final String EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_PENDING_INTENT =
+            "android.provider.extra.SETTINGS_LARGE_SCREEN_DEEP_LINK_PENDING_INTENT";
+
+    /**
      * Performs a strict and comprehensive check of whether a calling package is allowed to
      * write/modify system settings, as the condition differs for pre-M, M+, and
      * privileged/preinstalled apps. If the provided uid does not match the
diff --git a/core/java/android/service/translation/ITranslationService.aidl b/core/java/android/service/translation/ITranslationService.aidl
index e9dd2c3b..4cc732a 100644
--- a/core/java/android/service/translation/ITranslationService.aidl
+++ b/core/java/android/service/translation/ITranslationService.aidl
@@ -24,7 +24,7 @@
 /**
  * System-wide on-device translation service.
  *
- * <p>Services requests to translate text between different languages. The primary use case for this
+ * <p>Services requests to translate data between different languages. The primary use case for this
  * service is automatic translation of text and web views, when the auto Translate feature is
  * enabled.
  *
diff --git a/core/java/android/service/translation/TranslationService.java b/core/java/android/service/translation/TranslationService.java
index 756a70c..de981e8 100644
--- a/core/java/android/service/translation/TranslationService.java
+++ b/core/java/android/service/translation/TranslationService.java
@@ -48,6 +48,7 @@
 import android.view.translation.TranslationRequest;
 import android.view.translation.TranslationResponse;
 import android.view.translation.TranslationSpec;
+import android.view.translation.Translator;
 
 import com.android.internal.os.IResultReceiver;
 
@@ -82,7 +83,10 @@
      * android.R.styleable#TranslationService translation-service}&gt;</code> tag.
      *
      * <p>Here's an example of how to use it on {@code AndroidManifest.xml}:
-     * TODO: fill in doc example (check CCService/AFService).
+     * <pre> &lt;translation-service
+     *     android:settingsActivity="foo.bar.SettingsActivity"
+     *     . . .
+     * /&gt;</pre>
      */
     public static final String SERVICE_META_DATA = "android.translation_service";
 
@@ -149,7 +153,6 @@
         void onTranslationSuccess(@NonNull TranslationResponse response);
 
         /**
-         * TODO: implement javadoc
          * @removed use {@link #onTranslationSuccess} with an error response instead.
          */
         @Deprecated
@@ -226,7 +229,7 @@
      * should call back with {@code false}.</p>
      *
      * @param translationContext the {@link TranslationContext} of the session being created.
-     * @param sessionId the int id of the session.
+     * @param sessionId the id of the session.
      * @param callback {@link Consumer} to notify whether the session was successfully created.
      */
     // TODO(b/176464808): the session id won't be unique cross client/server process. Need to find
@@ -235,8 +238,6 @@
             int sessionId, @NonNull Consumer<Boolean> callback);
 
     /**
-     * TODO: fill in javadoc.
-     *
      * @removed use {@link #onCreateTranslationSession(TranslationContext, int, Consumer)}
      * instead.
      */
@@ -247,19 +248,16 @@
     }
 
     /**
-     * TODO: fill in javadoc.
+     * Called when a translation session is finished.
      *
-     * @param sessionId
+     * <p>The translation session is finished when the client calls {@link Translator#destroy()} on
+     * the corresponding translator.
+     *
+     * @param sessionId id of the session that finished.
      */
     public abstract void onFinishTranslationSession(int sessionId);
 
     /**
-     * TODO: fill in javadoc.
-     *
-     * @param request
-     * @param sessionId
-     * @param callback
-     * @param cancellationSignal
      * @removed use
      * {@link #onTranslationRequest(TranslationRequest, int, CancellationSignal, Consumer)} instead.
      */
@@ -277,23 +275,29 @@
      * {@link TranslationRequest#FLAG_PARTIAL_RESPONSES} was set, the service may call
      * {@code callback.accept()} multiple times with partial responses.</p>
      *
-     * @param request
-     * @param sessionId
-     * @param callback
-     * @param cancellationSignal
+     * @param request The translation request containing the data to be translated.
+     * @param sessionId id of the session that sent the translation request.
+     * @param cancellationSignal A {@link CancellationSignal} that notifies when a client has
+     *                           cancelled the operation in progress.
+     * @param callback {@link Consumer} to pass back the translation response.
      */
     public abstract void onTranslationRequest(@NonNull TranslationRequest request, int sessionId,
             @Nullable CancellationSignal cancellationSignal,
             @NonNull Consumer<TranslationResponse> callback);
 
     /**
-     * TODO: fill in javadoc
+     * Called to request a set of {@link TranslationCapability}s that are supported by the service.
+     *
+     * <p>The set of translation capabilities are limited to those supporting the source and target
+     * {@link TranslationSpec.DataFormat}. e.g. Calling this with
+     * {@link TranslationSpec#DATA_FORMAT_TEXT} as source and target returns only capabilities that
+     * translates text to text.</p>
      *
      * <p>Must call {@code callback.accept} to pass back the set of translation capabilities.</p>
      *
-     * @param sourceFormat
-     * @param targetFormat
-     * @param callback
+     * @param sourceFormat data format restriction of the translation source spec.
+     * @param targetFormat data format restriction of the translation target spec.
+     * @param callback {@link Consumer} to pass back the set of translation capabilities.
      */
     public abstract void onTranslationCapabilitiesRequest(
             @TranslationSpec.DataFormat int sourceFormat,
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 4bf6049..cb5e51c 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -102,6 +102,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Supplier;
 
@@ -158,6 +159,7 @@
     private static final int MSG_REQUEST_WALLPAPER_COLORS = 10050;
     private static final int MSG_ZOOM = 10100;
     private static final int MSG_SCALE_PREVIEW = 10110;
+    private static final int MSG_REPORT_SHOWN = 10150;
     private static final List<Float> PROHIBITED_STEPS = Arrays.asList(0f, Float.POSITIVE_INFINITY,
             Float.NEGATIVE_INFINITY);
 
@@ -540,6 +542,35 @@
         }
 
         /**
+         * This will be called in the end of {@link #updateSurface(boolean, boolean, boolean)}.
+         * If true is returned, the engine will not report shown until rendering finished is
+         * reported. Otherwise, the engine will report shown immediately right after redraw phase
+         * in {@link #updateSurface(boolean, boolean, boolean)}.
+         *
+         * @hide
+         */
+        public boolean shouldWaitForEngineShown() {
+            return false;
+        }
+
+        /**
+         * Reports the rendering is finished, stops waiting, then invokes
+         * {@link IWallpaperEngineWrapper#reportShown()}.
+         *
+         * @hide
+         */
+        public void reportEngineShown(boolean waitForEngineShown) {
+            if (mIWallpaperEngine.mShownReported) return;
+            Message message = mCaller.obtainMessage(MSG_REPORT_SHOWN);
+            if (!waitForEngineShown) {
+                mCaller.removeMessages(MSG_REPORT_SHOWN);
+                mCaller.sendMessage(message);
+            } else {
+                mCaller.sendMessageDelayed(message, TimeUnit.SECONDS.toMillis(1));
+            }
+        }
+
+        /**
          * Control whether this wallpaper will receive raw touch events
          * from the window manager as the user interacts with the window
          * that is currently displaying the wallpaper.  By default they
@@ -943,7 +974,8 @@
 
         void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNeeded) {
             if (mDestroyed) {
-                Log.w(TAG, "Ignoring updateSurface: destroyed");
+                Log.w(TAG, "Ignoring updateSurface due to destroyed");
+                return;
             }
 
             boolean fixedSize = false;
@@ -1210,7 +1242,6 @@
                                         + this);
                             onVisibilityChanged(false);
                         }
-
                     } finally {
                         mIsCreating = false;
                         mSurfaceCreated = true;
@@ -1220,7 +1251,7 @@
                             processLocalColors(mPendingXOffset, mPendingXOffsetStep);
                         }
                         reposition();
-                        mIWallpaperEngine.reportShown();
+                        reportEngineShown(shouldWaitForEngineShown());
                     }
                 } catch (RemoteException ex) {
                 }
@@ -2379,6 +2410,9 @@
                         // Connection went away, nothing to do in here.
                     }
                 } break;
+                case MSG_REPORT_SHOWN: {
+                    reportShown();
+                } break;
                 default :
                     Log.w(TAG, "Unknown message type " + message.what);
             }
diff --git a/core/java/android/util/DisplayUtils.java b/core/java/android/util/DisplayUtils.java
new file mode 100644
index 0000000..4fe7f83
--- /dev/null
+++ b/core/java/android/util/DisplayUtils.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.content.res.Resources;
+
+import com.android.internal.R;
+
+/**
+ * Utils for loading resources for multi-display.
+ *
+ * @hide
+ */
+public class DisplayUtils {
+
+    /**
+     * Gets the index of the given display unique id in {@link R.array#config_displayUniqueIdArray}
+     * which is used to get the related cutout configs for that display.
+     *
+     * For multi-display device, {@link R.array#config_displayUniqueIdArray} should be set for each
+     * display if there are different type of cutouts on each display.
+     * For single display device, {@link R.array#config_displayUniqueIdArray} should not to be set
+     * and the system will load the default configs for main built-in display.
+     */
+    public static int getDisplayUniqueIdConfigIndex(Resources res, String displayUniqueId) {
+        int index = -1;
+        if (displayUniqueId == null || displayUniqueId.isEmpty()) {
+            return index;
+        }
+        final String[] ids = res.getStringArray(R.array.config_displayUniqueIdArray);
+        final int size = ids.length;
+        for (int i = 0; i < size; i++) {
+            if (displayUniqueId.equals(ids[i])) {
+                index = i;
+                break;
+            }
+        }
+        return index;
+    }
+}
diff --git a/core/java/android/util/apk/OWNERS b/core/java/android/util/apk/OWNERS
index 52c9550..0f4e869 100644
--- a/core/java/android/util/apk/OWNERS
+++ b/core/java/android/util/apk/OWNERS
@@ -1 +1,3 @@
 include /core/java/android/content/pm/OWNERS
+cbrubaker@google.com
+mpgroover@google.com
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index e7ff978..8259a9d 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -1000,6 +1000,18 @@
     }
 
     /**
+     * Returns the default mode of the display.
+     * @hide
+     */
+    @TestApi
+    public @NonNull Mode getDefaultMode() {
+        synchronized (mLock) {
+            updateDisplayInfoLocked();
+            return mDisplayInfo.getDefaultMode();
+        }
+    }
+
+    /**
      * Gets the supported modes of this display.
      */
     public Mode[] getSupportedModes() {
@@ -1699,6 +1711,11 @@
          */
         public static final Mode[] EMPTY_ARRAY = new Mode[0];
 
+        /**
+         * @hide
+         */
+        public static final int INVALID_MODE_ID = -1;
+
         private final int mModeId;
         private final int mWidth;
         private final int mHeight;
@@ -1709,6 +1726,14 @@
         /**
          * @hide
          */
+        @TestApi
+        public Mode(int width, int height, float refreshRate) {
+            this(INVALID_MODE_ID, width, height, refreshRate, new float[0]);
+        }
+
+        /**
+         * @hide
+         */
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
         public Mode(int modeId, int width, int height, float refreshRate) {
             this(modeId, width, height, refreshRate, new float[0]);
@@ -1804,6 +1829,7 @@
          *
          * @hide
          */
+        @TestApi
         public boolean matches(int width, int height, float refreshRate) {
             return mWidth == width &&
                     mHeight == height &&
diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java
index 0257e55..c1a5636 100644
--- a/core/java/android/view/DisplayCutout.java
+++ b/core/java/android/view/DisplayCutout.java
@@ -39,6 +39,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
+import android.util.DisplayUtils;
 import android.util.Pair;
 import android.util.RotationUtils;
 import android.util.proto.ProtoOutputStream;
@@ -874,38 +875,13 @@
     }
 
     /**
-     * Gets the index of the given display unique id in {@link R.array#config_displayUniqueIdArray}
-     * which is used to get the related cutout configs for that display.
-     *
-     * For multi-display device, {@link R.array#config_displayUniqueIdArray} should be set for each
-     * display if there are different type of cutouts on each display.
-     * For single display device, {@link R.array#config_displayUniqueIdArray} should not to be set
-     * and the system will load the default configs for main built-in display.
-     */
-    private static int getDisplayCutoutConfigIndex(Resources res, String displayUniqueId) {
-        int index = -1;
-        if (displayUniqueId == null || displayUniqueId.isEmpty()) {
-            return index;
-        }
-        final String[] ids = res.getStringArray(R.array.config_displayUniqueIdArray);
-        final int size = ids.length;
-        for (int i = 0; i < size; i++) {
-            if (displayUniqueId.equals(ids[i])) {
-                index = i;
-                break;
-            }
-        }
-        return index;
-    }
-
-    /**
      * Gets the display cutout by the given display unique id.
      *
      * Loads the default config {@link R.string#config_mainBuiltInDisplayCutout) if
      * {@link R.array#config_displayUniqueIdArray} is not set.
      */
     private static String getDisplayCutoutPath(Resources res, String displayUniqueId) {
-        final int index = getDisplayCutoutConfigIndex(res, displayUniqueId);
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
         final String[] array = res.getStringArray(R.array.config_displayCutoutPathArray);
         if (index >= 0 && index < array.length) {
             return array[index];
@@ -920,7 +896,7 @@
      * {@link R.array#config_displayUniqueIdArray} is not set.
      */
     private static String getDisplayCutoutApproximationRect(Resources res, String displayUniqueId) {
-        final int index = getDisplayCutoutConfigIndex(res, displayUniqueId);
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
         final String[] array = res.getStringArray(
                 R.array.config_displayCutoutApproximationRectArray);
         if (index >= 0 && index < array.length) {
@@ -939,7 +915,7 @@
      * @hide
      */
     public static boolean getMaskBuiltInDisplayCutout(Resources res, String displayUniqueId) {
-        final int index = getDisplayCutoutConfigIndex(res, displayUniqueId);
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
         final TypedArray array = res.obtainTypedArray(R.array.config_maskBuiltInDisplayCutoutArray);
         boolean maskCutout;
         if (index >= 0 && index < array.length()) {
@@ -961,7 +937,7 @@
      * @hide
      */
     public static boolean getFillBuiltInDisplayCutout(Resources res, String displayUniqueId) {
-        final int index = getDisplayCutoutConfigIndex(res, displayUniqueId);
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
         final TypedArray array = res.obtainTypedArray(R.array.config_fillBuiltInDisplayCutoutArray);
         boolean fillCutout;
         if (index >= 0 && index < array.length()) {
@@ -984,7 +960,7 @@
      */
     private static Insets getWaterfallInsets(Resources res, String displayUniqueId) {
         Insets insets;
-        final int index = getDisplayCutoutConfigIndex(res, displayUniqueId);
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
         final TypedArray array = res.obtainTypedArray(R.array.config_waterfallCutoutArray);
         if (index >= 0 && index < array.length() && array.getResourceId(index, 0) > 0) {
             final int resourceId = array.getResourceId(index, 0);
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 371d3d0..ae2eed8 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -33,6 +33,7 @@
 import android.os.IRemoteCallback;
 import android.os.ParcelFileDescriptor;
 import android.view.DisplayCutout;
+import android.view.DisplayInfo;
 import android.view.IApplicationToken;
 import android.view.IAppTransitionAnimationSpecsFuture;
 import android.view.ICrossWindowBlurEnabledListener;
@@ -736,6 +737,17 @@
             out InsetsState outInsetsState);
 
     /**
+     * Returns a list of {@link android.view.DisplayInfo} for the logical display. This is not
+     * guaranteed to include all possible device states. The list items are unique.
+     *
+     * If invoked through a package other than a launcher app, returns an empty list.
+     *
+     * @param displayId the id of the logical display
+     * @param packageName the name of the calling package
+     */
+    List<DisplayInfo> getPossibleDisplayInfo(int displayId, String packageName);
+
+    /**
      * Called to show global actions.
      */
     void showGlobalActions();
diff --git a/core/java/android/view/InsetsAnimationControlCallbacks.java b/core/java/android/view/InsetsAnimationControlCallbacks.java
index 7696bbb..04bb609 100644
--- a/core/java/android/view/InsetsAnimationControlCallbacks.java
+++ b/core/java/android/view/InsetsAnimationControlCallbacks.java
@@ -35,7 +35,7 @@
      *     <li>Dispatch {@link WindowInsetsAnimationControlListener#onReady}</li>
      * </ul>
      */
-    <T extends InsetsAnimationControlRunner & WindowInsetsAnimationController>
+    <T extends InsetsAnimationControlRunner & InternalInsetsAnimationController>
     void startAnimation(T runner, WindowInsetsAnimationControlListener listener, int types,
             WindowInsetsAnimation animation, Bounds bounds);
 
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index b92d24f..7d8d653 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -69,7 +69,7 @@
  * @hide
  */
 @VisibleForTesting
-public class InsetsAnimationControlImpl implements WindowInsetsAnimationController,
+public class InsetsAnimationControlImpl implements InternalInsetsAnimationController,
         InsetsAnimationControlRunner {
 
     private static final String TAG = "InsetsAnimationCtrlImpl";
diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java
index c11bde8..fc97541 100644
--- a/core/java/android/view/InsetsAnimationThreadControlRunner.java
+++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java
@@ -54,7 +54,7 @@
 
         @Override
         @UiThread
-        public <T extends InsetsAnimationControlRunner & WindowInsetsAnimationController>
+        public <T extends InsetsAnimationControlRunner & InternalInsetsAnimationController>
         void startAnimation(T runner, WindowInsetsAnimationControlListener listener, int types,
                 WindowInsetsAnimation animation, Bounds bounds) {
             // Animation will be started in constructor already.
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 5c56baa..1dd5a1b 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -632,7 +632,7 @@
                         runningAnimations.add(runner.getAnimation());
                     }
 
-                    if (((WindowInsetsAnimationController) runner).applyChangeInsets(state)) {
+                    if (((InternalInsetsAnimationController) runner).applyChangeInsets(state)) {
                         finishedAnimations.add(runner.getAnimation());
                     }
                 }
@@ -1513,7 +1513,7 @@
 
     @VisibleForTesting
     @Override
-    public <T extends InsetsAnimationControlRunner & WindowInsetsAnimationController>
+    public <T extends InsetsAnimationControlRunner & InternalInsetsAnimationController>
     void startAnimation(T runner, WindowInsetsAnimationControlListener listener, int types,
             WindowInsetsAnimation animation, Bounds bounds) {
         mHost.dispatchWindowInsetsAnimationPrepare(animation);
diff --git a/core/java/android/view/InsetsResizeAnimationRunner.java b/core/java/android/view/InsetsResizeAnimationRunner.java
index 83f51aa..e1352dd 100644
--- a/core/java/android/view/InsetsResizeAnimationRunner.java
+++ b/core/java/android/view/InsetsResizeAnimationRunner.java
@@ -43,7 +43,7 @@
  * @hide
  */
 public class InsetsResizeAnimationRunner implements InsetsAnimationControlRunner,
-        WindowInsetsAnimationController, WindowInsetsAnimationControlListener {
+        InternalInsetsAnimationController, WindowInsetsAnimationControlListener {
 
     private final InsetsState mFromState;
     private final InsetsState mToState;
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 75b69cb..3917279 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -202,7 +202,7 @@
             @Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
         Insets[] typeInsetsMap = new Insets[Type.SIZE];
         Insets[] typeMaxInsetsMap = new Insets[Type.SIZE];
-        boolean[] typeVisibilityMap = new boolean[SIZE];
+        boolean[] typeVisibilityMap = new boolean[Type.SIZE];
         final Rect relativeFrame = new Rect(frame);
         final Rect relativeFrameMax = new Rect(frame);
         for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
diff --git a/core/java/android/view/InternalInsetsAnimationController.java b/core/java/android/view/InternalInsetsAnimationController.java
new file mode 100644
index 0000000..d7f3e20
--- /dev/null
+++ b/core/java/android/view/InternalInsetsAnimationController.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+/**
+ * An internal interface which provides methods that will be only used by the framework.
+ * @hide
+ */
+public interface InternalInsetsAnimationController extends WindowInsetsAnimationController {
+
+    /**
+     * Flags whether {@link WindowInsetsAnimationControlListener#onReady(
+     * WindowInsetsAnimationController, int)} has been invoked.
+     * @hide
+     */
+    void setReadyDispatched(boolean dispatched);
+
+    /**
+     * Returns the {@link InsetsState} based on the current animation progress.
+     *
+     * @param outState the insets state which matches the current animation progress.
+     * @return {@code true} if the animation has been finished; {@code false} otherwise.
+     * @hide
+     */
+    boolean applyChangeInsets(InsetsState outState);
+}
+
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index bd68401..3f71d4d 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -233,7 +233,7 @@
         this.clipRect = new Rect(clipRect);
         this.contentInsets = new Rect(contentInsets);
         this.prefixOrderIndex = prefixOrderIndex;
-        this.position = new Point(position);
+        this.position = position == null ? new Point() : new Point(position);
         this.localBounds = new Rect(localBounds);
         this.sourceContainerBounds = new Rect(screenSpaceBounds);
         this.screenSpaceBounds = new Rect(screenSpaceBounds);
diff --git a/core/java/android/view/RoundedCorners.java b/core/java/android/view/RoundedCorners.java
index 623d969..6079d8e 100644
--- a/core/java/android/view/RoundedCorners.java
+++ b/core/java/android/view/RoundedCorners.java
@@ -27,9 +27,11 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.graphics.Point;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.DisplayUtils;
 import android.util.Pair;
 import android.view.RoundedCorner.Position;
 
@@ -94,8 +96,8 @@
      * @android:dimen/rounded_corner_radius_top and @android:dimen/rounded_corner_radius_bottom
      */
     public static RoundedCorners fromResources(
-            Resources res, int displayWidth, int displayHeight) {
-        return fromRadii(loadRoundedCornerRadii(res), displayWidth, displayHeight);
+            Resources res, String displayUniqueId, int displayWidth, int displayHeight) {
+        return fromRadii(loadRoundedCornerRadii(res, displayUniqueId), displayWidth, displayHeight);
     }
 
     /**
@@ -140,14 +142,16 @@
      * Loads the rounded corner radii from resources.
      *
      * @param res
+     * @param displayUniqueId the display unique id.
      * @return a Pair of radius. The first is the top rounded corner radius and second is the
      * bottom corner radius.
      */
     @Nullable
-    private static Pair<Integer, Integer> loadRoundedCornerRadii(Resources res) {
-        final int radiusDefault = res.getDimensionPixelSize(R.dimen.rounded_corner_radius);
-        final int radiusTop = res.getDimensionPixelSize(R.dimen.rounded_corner_radius_top);
-        final int radiusBottom = res.getDimensionPixelSize(R.dimen.rounded_corner_radius_bottom);
+    private static Pair<Integer, Integer> loadRoundedCornerRadii(
+            Resources res, String displayUniqueId) {
+        final int radiusDefault = getRoundedCornerRadius(res, displayUniqueId);
+        final int radiusTop = getRoundedCornerTopRadius(res, displayUniqueId);
+        final int radiusBottom = getRoundedCornerBottomRadius(res, displayUniqueId);
         if (radiusDefault == 0 && radiusTop == 0 && radiusBottom == 0) {
             return null;
         }
@@ -158,6 +162,164 @@
     }
 
     /**
+     * Gets the default rounded corner radius of a display which is determined by the
+     * given display unique id.
+     *
+     * Loads the default dimen{@link R.dimen#rounded_corner_radius} if
+     * {@link R.array#config_displayUniqueIdArray} is not set.
+     *
+     * @hide
+     */
+    public static int getRoundedCornerRadius(Resources res, String displayUniqueId) {
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
+        final TypedArray array = res.obtainTypedArray(R.array.config_roundedCornerRadiusArray);
+        int radius;
+        if (index >= 0 && index < array.length()) {
+            radius = array.getDimensionPixelSize(index, 0);
+        } else {
+            radius = res.getDimensionPixelSize(R.dimen.rounded_corner_radius);
+        }
+        array.recycle();
+        return radius;
+    }
+
+    /**
+     * Gets the top rounded corner radius of a display which is determined by the
+     * given display unique id.
+     *
+     * Loads the default dimen{@link R.dimen#rounded_corner_radius_top} if
+     * {@link R.array#config_displayUniqueIdArray} is not set.
+     *
+     * @hide
+     */
+    public static int getRoundedCornerTopRadius(Resources res, String displayUniqueId) {
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
+        final TypedArray array = res.obtainTypedArray(R.array.config_roundedCornerTopRadiusArray);
+        int radius;
+        if (index >= 0 && index < array.length()) {
+            radius = array.getDimensionPixelSize(index, 0);
+        } else {
+            radius = res.getDimensionPixelSize(R.dimen.rounded_corner_radius_top);
+        }
+        array.recycle();
+        return radius;
+    }
+
+    /**
+     * Gets the bottom rounded corner radius of a display which is determined by the
+     * given display unique id.
+     *
+     * Loads the default dimen{@link R.dimen#rounded_corner_radius_bottom} if
+     * {@link R.array#config_displayUniqueIdArray} is not set.
+     *
+     * @hide
+     */
+    public static int getRoundedCornerBottomRadius(Resources res, String displayUniqueId) {
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
+        final TypedArray array = res.obtainTypedArray(
+                R.array.config_roundedCornerBottomRadiusArray);
+        int radius;
+        if (index >= 0 && index < array.length()) {
+            radius = array.getDimensionPixelSize(index, 0);
+        } else {
+            radius = res.getDimensionPixelSize(R.dimen.rounded_corner_radius_bottom);
+        }
+        array.recycle();
+        return radius;
+    }
+
+    /**
+     * Gets the rounded corner radius adjustment of a display which is determined by the
+     * given display unique id.
+     *
+     * Loads the default dimen{@link R.dimen#rounded_corner_radius_adjustment} if
+     * {@link R.array#config_displayUniqueIdArray} is not set.
+     *
+     * @hide
+     */
+    public static int getRoundedCornerRadiusAdjustment(Resources res, String displayUniqueId) {
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
+        final TypedArray array = res.obtainTypedArray(
+                R.array.config_roundedCornerRadiusAdjustmentArray);
+        int radius;
+        if (index >= 0 && index < array.length()) {
+            radius = array.getDimensionPixelSize(index, 0);
+        } else {
+            radius = res.getDimensionPixelSize(R.dimen.rounded_corner_radius_adjustment);
+        }
+        array.recycle();
+        return radius;
+    }
+
+    /**
+     * Gets the rounded corner top radius adjustment of a display which is determined by the
+     * given display unique id.
+     *
+     * Loads the default dimen{@link R.dimen#rounded_corner_radius_top_adjustment} if
+     * {@link R.array#config_displayUniqueIdArray} is not set.
+     *
+     * @hide
+     */
+    public static int getRoundedCornerRadiusTopAdjustment(Resources res, String displayUniqueId) {
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
+        final TypedArray array = res.obtainTypedArray(
+                R.array.config_roundedCornerTopRadiusAdjustmentArray);
+        int radius;
+        if (index >= 0 && index < array.length()) {
+            radius = array.getDimensionPixelSize(index, 0);
+        } else {
+            radius = res.getDimensionPixelSize(R.dimen.rounded_corner_radius_top_adjustment);
+        }
+        array.recycle();
+        return radius;
+    }
+
+    /**
+     * Gets the rounded corner bottom radius adjustment of a display which is determined by the
+     * given display unique id.
+     *
+     * Loads the default dimen{@link R.dimen#rounded_corner_radius_bottom_adjustment} if
+     * {@link R.array#config_displayUniqueIdArray} is not set.
+     *
+     * @hide
+     */
+    public static int getRoundedCornerRadiusBottomAdjustment(
+            Resources res, String displayUniqueId) {
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
+        final TypedArray array = res.obtainTypedArray(
+                R.array.config_roundedCornerBottomRadiusAdjustmentArray);
+        int radius;
+        if (index >= 0 && index < array.length()) {
+            radius = array.getDimensionPixelSize(index, 0);
+        } else {
+            radius = res.getDimensionPixelSize(R.dimen.rounded_corner_radius_bottom_adjustment);
+        }
+        array.recycle();
+        return radius;
+    }
+
+    /**
+     * Gets whether a built-in display is round.
+     *
+     * Loads the default config{@link R.bool#config_mainBuiltInDisplayIsRound} if
+     * {@link R.array#config_displayUniqueIdArray} is not set.
+     *
+     * @hide
+     */
+    public static boolean getBuiltInDisplayIsRound(Resources res, String displayUniqueId) {
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
+        final TypedArray array = res.obtainTypedArray(R.array.config_builtInDisplayIsRoundArray);
+        boolean isRound;
+        if (index >= 0 && index < array.length()) {
+            isRound = array.getBoolean(index, false);
+        } else {
+            isRound = res.getBoolean(R.bool.config_mainBuiltInDisplayIsRound);
+        }
+        array.recycle();
+        return isRound;
+    }
+
+    /**
      * Insets the reference frame of the rounded corners.
      *
      * @return a copy of this instance which has been inset
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index aaf53ee..904aa73 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -99,6 +99,7 @@
 
     private static native int nativeSetFrameRate(
             long nativeObject, float frameRate, int compatibility, int changeFrameRateStrategy);
+    private static native void nativeDestroy(long nativeObject);
 
     public static final @android.annotation.NonNull Parcelable.Creator<Surface> CREATOR =
             new Parcelable.Creator<Surface>() {
@@ -340,6 +341,9 @@
      */
     @UnsupportedAppUsage
     public void destroy() {
+        if (mNativeObject != 0) {
+            nativeDestroy(mNativeObject);
+        }
         release();
     }
 
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 9972eba..9e5d122 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -1820,11 +1820,6 @@
      * @hide
      */
     public static final class DisplayMode {
-        /**
-         * Invalid display config id.
-         */
-        public static final int INVALID_DISPLAY_MODE_ID = -1;
-
         public int id;
         public int width;
         public int height;
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 643c1bc..ddc532c 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -903,7 +903,7 @@
         mSurfaceAlpha = 1f;
 
         synchronized (mSurfaceControlLock) {
-            mSurface.release();
+            mSurface.destroy();
             if (mBlastBufferQueue != null) {
                 mBlastBufferQueue.destroy();
                 mBlastBufferQueue = null;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index cfb2130..3924e9b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5036,6 +5036,14 @@
     public static final int DRAG_FLAG_OPAQUE = 1 << 9;
 
     /**
+     * Flag indicating that the drag was initiated with
+     * {@link AccessibilityNodeInfo.AccessibilityAction#ACTION_DRAG_START}. When
+     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called, this
+     * is used by the system to perform a drag without animations.
+     */
+    public static final int DRAG_FLAG_ACCESSIBILITY_ACTION = 1 << 10;
+
+    /**
      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
      */
     private float mVerticalScrollFactor;
@@ -26649,6 +26657,7 @@
      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
      *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
      *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
+     *         <li>{@link #DRAG_FLAG_ACCESSIBILITY_ACTION}</li>
      *     </ul>
      * @return {@code true} if the method completes successfully, or
      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 488f7c3..d229cf6 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2603,7 +2603,7 @@
      * It's the responsibility of the caller to recycle it once they're finished with it.
      * @param event The event to transform.
      * @param child The view whose coordinate space is to be used.
-     * @return A copy of the the given MotionEvent, transformed into the given View's coordinate
+     * @return A copy of the given MotionEvent, transformed into the given View's coordinate
      *         space.
      */
     private MotionEvent getTransformedMotionEvent(MotionEvent event, View child) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a8b21fb..0dd6e22 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -759,6 +759,12 @@
     private boolean mWaitForBlastSyncComplete = false;
 
     /**
+     * Keeps track of the last frame number that was attempted to draw. Should only be accessed on
+     * the RenderThread.
+     */
+    private long mRtLastAttemptedDrawFrameNum = 0;
+
+    /**
      * Keeps track of whether a traverse was triggered while the UI thread was paused. This can
      * occur when the client is waiting on another process to submit the transaction that
      * contains the buffer. The UI thread needs to wait on the callback before it can submit
@@ -3974,35 +3980,19 @@
     }
 
     /**
-     * The callback will run on the render thread.
+     * Only call this on the UI Thread.
      */
-    private HardwareRenderer.FrameCompleteCallback createFrameCompleteCallback(Handler handler,
-            boolean reportNextDraw, ArrayList<Runnable> commitCallbacks) {
-        return frameNr -> {
-            if (DEBUG_BLAST) {
-                Log.d(mTag, "Received frameCompleteCallback frameNum=" + frameNr);
-            }
-
-            handler.postAtFrontOfQueue(() -> {
-                if (mNextDrawUseBlastSync) {
-                    // We don't need to synchronize mRtBLASTSyncTransaction here since we're
-                    // guaranteed that this is called after onFrameDraw and mNextDrawUseBlastSync
-                    // is only true when the UI thread is paused. Therefore, no one should be
-                    // modifying this object until the next vsync.
-                    mSurfaceChangedTransaction.merge(mRtBLASTSyncTransaction);
-                }
-
-                if (reportNextDraw) {
-                    // TODO: Use the frame number
-                    pendingDrawFinished();
-                }
-                if (commitCallbacks != null) {
-                    for (int i = 0; i < commitCallbacks.size(); i++) {
-                        commitCallbacks.get(i).run();
-                    }
-                }
-            });
-        };
+    void clearBlastSync() {
+        mNextDrawUseBlastSync = false;
+        mWaitForBlastSyncComplete = false;
+        if (DEBUG_BLAST) {
+            Log.d(mTag, "Scheduling a traversal=" + mRequestedTraverseWhilePaused
+                    + " due to a previous skipped traversal.");
+        }
+        if (mRequestedTraverseWhilePaused) {
+            mRequestedTraverseWhilePaused = false;
+            scheduleTraversals();
+        }
     }
 
     /**
@@ -4012,46 +4002,104 @@
         return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled();
     }
 
-    private boolean addFrameCompleteCallbackIfNeeded() {
+    private boolean addFrameCompleteCallbackIfNeeded(boolean reportNextDraw) {
         if (!isHardwareEnabled()) {
             return false;
         }
 
+        if (!mNextDrawUseBlastSync && !reportNextDraw) {
+            return false;
+        }
+
+        if (DEBUG_BLAST) {
+            Log.d(mTag, "Creating frameCompleteCallback");
+        }
+
+        mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(() -> {
+            long frameNr = mBlastBufferQueue.getLastAcquiredFrameNum();
+            if (DEBUG_BLAST) {
+                Log.d(mTag, "Received frameCompleteCallback "
+                        + " lastAcquiredFrameNum=" + frameNr
+                        + " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum);
+            }
+
+            boolean frameWasNotDrawn = frameNr != mRtLastAttemptedDrawFrameNum;
+            // If frame wasn't drawn, clear out the next transaction so it doesn't affect the next
+            // draw attempt. The next transaction and transaction complete callback were only set
+            // for the current draw attempt.
+            if (frameWasNotDrawn) {
+                mBlastBufferQueue.setNextTransaction(null);
+                mBlastBufferQueue.setTransactionCompleteCallback(mRtLastAttemptedDrawFrameNum,
+                        null);
+                // Apply the transactions that were sent to mergeWithNextTransaction since the
+                // frame didn't draw on this vsync. It's possible the frame will draw later, but
+                // it's better to not be sync than to block on a frame that may never come.
+                mBlastBufferQueue.applyPendingTransactions(mRtLastAttemptedDrawFrameNum);
+            }
+
+            mHandler.postAtFrontOfQueue(() -> {
+                if (mNextDrawUseBlastSync) {
+                    // We don't need to synchronize mRtBLASTSyncTransaction here since we're
+                    // guaranteed that this is called after onFrameDraw and mNextDrawUseBlastSync
+                    // is only true when the UI thread is paused. Therefore, no one should be
+                    // modifying this object until the next vsync.
+                    mSurfaceChangedTransaction.merge(mRtBLASTSyncTransaction);
+                }
+
+                if (reportNextDraw) {
+                    pendingDrawFinished();
+                }
+
+                if (frameWasNotDrawn) {
+                    clearBlastSync();
+                }
+            });
+        });
+        return true;
+    }
+
+    private void addFrameCommitCallbackIfNeeded() {
+        if (!isHardwareEnabled()) {
+            return;
+        }
+
         ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
                 .captureFrameCommitCallbacks();
-        final boolean needFrameCompleteCallback =
-                mNextDrawUseBlastSync || mReportNextDraw
-                        || (commitCallbacks != null && commitCallbacks.size() > 0);
-        if (needFrameCompleteCallback) {
-            if (DEBUG_BLAST) {
-                Log.d(mTag, "Creating frameCompleteCallback"
-                        + " mNextDrawUseBlastSync=" + mNextDrawUseBlastSync
-                        + " mReportNextDraw=" + mReportNextDraw
-                        + " commitCallbacks size="
-                        + (commitCallbacks == null ? 0 : commitCallbacks.size()));
-            }
-            mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(
-                    createFrameCompleteCallback(mAttachInfo.mHandler, mReportNextDraw,
-                            commitCallbacks));
-            return true;
+        final boolean needFrameCommitCallback =
+                (commitCallbacks != null && commitCallbacks.size() > 0);
+        if (!needFrameCommitCallback) {
+            return;
         }
-        return false;
+
+        if (DEBUG_DRAW) {
+            Log.d(mTag, "Creating frameCommitCallback"
+                    + " commitCallbacks size=" + commitCallbacks.size());
+        }
+        mAttachInfo.mThreadedRenderer.setFrameCommitCallback(didProduceBuffer -> {
+            if (DEBUG_DRAW) {
+                Log.d(mTag, "Received frameCommitCallback didProduceBuffer=" + didProduceBuffer);
+            }
+
+            mHandler.postAtFrontOfQueue(() -> {
+                for (int i = 0; i < commitCallbacks.size(); i++) {
+                    commitCallbacks.get(i).run();
+                }
+            });
+        });
     }
 
     private void addFrameCallbackIfNeeded() {
         final boolean nextDrawUseBlastSync = mNextDrawUseBlastSync;
-        final boolean reportNextDraw = mReportNextDraw;
         final boolean hasBlurUpdates = mBlurRegionAggregator.hasUpdates();
         final boolean needsCallbackForBlur = hasBlurUpdates || mBlurRegionAggregator.hasRegions();
 
-        if (!nextDrawUseBlastSync && !reportNextDraw && !needsCallbackForBlur) {
+        if (!nextDrawUseBlastSync && !needsCallbackForBlur) {
             return;
         }
 
         if (DEBUG_BLAST) {
             Log.d(mTag, "Creating frameDrawingCallback"
                     + " nextDrawUseBlastSync=" + nextDrawUseBlastSync
-                    + " reportNextDraw=" + reportNextDraw
                     + " hasBlurUpdates=" + hasBlurUpdates);
         }
         mWaitForBlastSyncComplete = nextDrawUseBlastSync;
@@ -4065,6 +4113,8 @@
                         + " Creating transactionCompleteCallback=" + nextDrawUseBlastSync);
             }
 
+            mRtLastAttemptedDrawFrameNum = frame;
+
             if (needsCallbackForBlur) {
                 mBlurRegionAggregator
                     .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates);
@@ -4087,24 +4137,8 @@
                     if (DEBUG_BLAST) {
                         Log.d(mTag, "Received transactionCompleteCallback frameNum=" + frame);
                     }
-                    mHandler.postAtFrontOfQueue(() -> {
-                        mNextDrawUseBlastSync = false;
-                        mWaitForBlastSyncComplete = false;
-                        if (DEBUG_BLAST) {
-                            Log.d(mTag, "Scheduling a traversal=" + mRequestedTraverseWhilePaused
-                                    + " due to a previous skipped traversal.");
-                        }
-                        if (mRequestedTraverseWhilePaused) {
-                            mRequestedTraverseWhilePaused = false;
-                            scheduleTraversals();
-                        }
-                    });
+                    mHandler.postAtFrontOfQueue(this::clearBlastSync);
                 });
-            } else if (reportNextDraw) {
-                // If we need to report next draw, wait for adapter to flush its shadow queue
-                // by processing previously queued buffers so that we can submit the
-                // transaction a timely manner.
-                mBlastBufferQueue.flushShadowQueue();
             }
         };
         registerRtFrameCallback(frameDrawingCallback);
@@ -4124,8 +4158,9 @@
         mIsDrawing = true;
         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
 
-        boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded();
         addFrameCallbackIfNeeded();
+        addFrameCommitCallbackIfNeeded();
+        boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(mReportNextDraw);
 
         try {
             boolean canUseAsync = draw(fullRedrawNeeded);
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 0f1a9d9..cde1cc7 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -903,6 +903,16 @@
         result.append(mPrivacyIndicatorBounds != null ? "privacyIndicatorBounds="
                 + mPrivacyIndicatorBounds : "");
         result.append("\n    ");
+        result.append("compatInsetsTypes=" + mCompatInsetsTypes);
+        result.append("\n    ");
+        result.append("compatIgnoreVisibility=" + mCompatIgnoreVisibility);
+        result.append("\n    ");
+        result.append("systemWindowInsetsConsumed=" + mSystemWindowInsetsConsumed);
+        result.append("\n    ");
+        result.append("stableInsetsConsumed=" + mStableInsetsConsumed);
+        result.append("\n    ");
+        result.append("displayCutoutConsumed=" + mDisplayCutoutConsumed);
+        result.append("\n    ");
         result.append(isRound() ? "round" : "");
         result.append("}");
         return result.toString();
diff --git a/core/java/android/view/WindowInsetsAnimationController.java b/core/java/android/view/WindowInsetsAnimationController.java
index bdfeb74..6578e9b 100644
--- a/core/java/android/view/WindowInsetsAnimationController.java
+++ b/core/java/android/view/WindowInsetsAnimationController.java
@@ -188,20 +188,4 @@
      *  fullscreen or non-overlapping).
      */
     boolean hasZeroInsetsIme();
-
-    /**
-     * Flags whether {@link WindowInsetsAnimationControlListener#onReady(
-     * WindowInsetsAnimationController, int)} has been invoked.
-     * @hide
-     */
-    void setReadyDispatched(boolean dispatched);
-
-    /**
-     * Returns the {@link InsetsState} based on the current animation progress.
-     *
-     * @param outState the insets state which matches the current animation progress.
-     * @return {@code true} if the animation has been finished; {@code false} otherwise.
-     * @hide
-     */
-    boolean applyChangeInsets(InsetsState outState);
 }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 98947d2..d76f789 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -123,6 +123,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 
@@ -714,6 +715,20 @@
     }
 
     /**
+     * Returns a set of {@link WindowMetrics} for the given display. Each WindowMetrics instance
+     * is the maximum WindowMetrics for a device state, including rotations. This is not guaranteed
+     * to include all possible device states.
+     *
+     * This API can only be used by Launcher.
+     *
+     * @param displayId the id of the logical display
+     * @hide
+     */
+    default @NonNull Set<WindowMetrics> getPossibleMaximumWindowMetrics(int displayId) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
      * Used to asynchronously request Keyboard Shortcuts from the focused window.
      *
      * @hide
@@ -3532,6 +3547,14 @@
         public Insets providedInternalInsets = Insets.NONE;
 
         /**
+         * If specified, the insets provided by this window for the IME will be our window frame
+         * minus the insets specified by providedInternalImeInsets.
+         *
+         * @hide
+         */
+        public Insets providedInternalImeInsets = Insets.NONE;
+
+        /**
          * {@link LayoutParams} to be applied to the window when layout with a assigned rotation.
          * This will make layout during rotation change smoothly.
          *
@@ -3905,6 +3928,7 @@
                 out.writeInt(0);
             }
             providedInternalInsets.writeToParcel(out, 0 /* parcelableFlags */);
+            providedInternalImeInsets.writeToParcel(out, 0 /* parcelableFlags */);
             if (paramsForRotation != null) {
                 checkNonRecursiveParams();
                 out.writeInt(paramsForRotation.length);
@@ -3984,6 +4008,7 @@
                 in.readIntArray(providesInsetsTypes);
             }
             providedInternalInsets = Insets.CREATOR.createFromParcel(in);
+            providedInternalImeInsets = Insets.CREATOR.createFromParcel(in);
             int paramsForRotationLength = in.readInt();
             if (paramsForRotationLength > 0) {
                 paramsForRotation = new LayoutParams[paramsForRotationLength];
@@ -4290,6 +4315,11 @@
                 changes |= LAYOUT_CHANGED;
             }
 
+            if (!providedInternalImeInsets.equals(o.providedInternalImeInsets)) {
+                providedInternalImeInsets = o.providedInternalImeInsets;
+                changes |= LAYOUT_CHANGED;
+            }
+
             if (!Arrays.equals(paramsForRotation, o.paramsForRotation)) {
                 paramsForRotation = o.paramsForRotation;
                 checkNonRecursiveParams();
@@ -4495,6 +4525,10 @@
                 sb.append(" providedInternalInsets=");
                 sb.append(providedInternalInsets);
             }
+            if (!providedInternalImeInsets.equals(Insets.NONE)) {
+                sb.append(" providedInternalImeInsets=");
+                sb.append(providedInternalImeInsets);
+            }
             if (paramsForRotation != null && paramsForRotation.length != 0) {
                 sb.append(System.lineSeparator());
                 sb.append(prefix).append("  paramsForRotation=");
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 7bd156b..1f80f8a 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -17,12 +17,8 @@
 package android.view;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
-import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
 import static android.view.View.SYSTEM_UI_FLAG_VISIBLE;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
 import static android.window.WindowProviderService.isWindowProviderService;
@@ -47,7 +43,9 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.IResultReceiver;
 
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 
@@ -304,27 +302,38 @@
     private WindowInsets computeWindowInsets(Rect bounds) {
         // Initialize params which used for obtaining all system insets.
         final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
-        params.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
         final Context context = (mParentWindow != null) ? mParentWindow.getContext() : mContext;
         params.token = Context.getToken(context);
-        params.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
-                | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
-        params.setFitInsetsTypes(0);
-        params.setFitInsetsSides(0);
-
-        return getWindowInsetsFromServer(params, bounds);
+        return getWindowInsetsFromServerForCurrentDisplay(params, bounds);
     }
 
-    private WindowInsets getWindowInsetsFromServer(WindowManager.LayoutParams attrs, Rect bounds) {
+    private WindowInsets getWindowInsetsFromServerForCurrentDisplay(
+            WindowManager.LayoutParams attrs, Rect bounds) {
+        final Configuration config = mContext.getResources().getConfiguration();
+        return getWindowInsetsFromServerForDisplay(mContext.getDisplayId(), attrs, bounds,
+                config.isScreenRound(), config.windowConfiguration.getWindowingMode());
+    }
+
+    /**
+     * Retrieves WindowInsets for the given context and display, given the window bounds.
+     *
+     * @param displayId the ID of the logical display to calculate insets for
+     * @param attrs the LayoutParams for the calling app
+     * @param bounds the window bounds to calculate insets for
+     * @param isScreenRound if the display identified by displayId is round
+     * @param windowingMode the windowing mode of the window to calculate insets for
+     * @return WindowInsets calculated for the given window bounds, on the given display
+     */
+    private static WindowInsets getWindowInsetsFromServerForDisplay(int displayId,
+            WindowManager.LayoutParams attrs, Rect bounds, boolean isScreenRound,
+            int windowingMode) {
         try {
             final InsetsState insetsState = new InsetsState();
             final boolean alwaysConsumeSystemBars = WindowManagerGlobal.getWindowManagerService()
-                    .getWindowInsets(attrs, mContext.getDisplayId(), insetsState);
-            final Configuration config = mContext.getResources().getConfiguration();
-            final boolean isScreenRound = config.isScreenRound();
+                    .getWindowInsets(attrs, displayId, insetsState);
             return insetsState.calculateInsets(bounds, null /* ignoringVisibilityState*/,
                     isScreenRound, alwaysConsumeSystemBars, SOFT_INPUT_ADJUST_NOTHING, attrs.flags,
-                    SYSTEM_UI_FLAG_VISIBLE, attrs.type, WINDOWING_MODE_FULLSCREEN,
+                    SYSTEM_UI_FLAG_VISIBLE, attrs.type, windowingMode,
                     null /* typeSideMap */);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -332,6 +341,50 @@
     }
 
     @Override
+    @NonNull
+    public Set<WindowMetrics> getPossibleMaximumWindowMetrics(int displayId) {
+        List<DisplayInfo> possibleDisplayInfos;
+        try {
+            possibleDisplayInfos = WindowManagerGlobal.getWindowManagerService()
+                    .getPossibleDisplayInfo(displayId, mContext.getPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+
+        int size = possibleDisplayInfos.size();
+        DisplayInfo currentDisplayInfo;
+        WindowInsets windowInsets = null;
+        if (size > 0) {
+            currentDisplayInfo = possibleDisplayInfos.get(0);
+
+            final WindowManager.LayoutParams params =  new WindowManager.LayoutParams();
+            final boolean isScreenRound = (currentDisplayInfo.flags & Display.FLAG_ROUND) != 0;
+            // TODO(181127261) not computing insets correctly - need to have underlying
+            // frame reflect the faked orientation.
+            windowInsets = getWindowInsetsFromServerForDisplay(
+                    currentDisplayInfo.displayId, params,
+                    new Rect(0, 0, currentDisplayInfo.getNaturalWidth(),
+                            currentDisplayInfo.getNaturalHeight()), isScreenRound,
+                    WINDOWING_MODE_FULLSCREEN);
+        }
+
+        Set<WindowMetrics> maxMetrics = new HashSet<>();
+        for (int i = 0; i < size; i++) {
+            currentDisplayInfo = possibleDisplayInfos.get(i);
+
+            // Calculate max bounds for this rotation and state.
+            Rect maxBounds = new Rect(0, 0, currentDisplayInfo.getNaturalWidth(),
+                    currentDisplayInfo.getNaturalHeight());
+
+            // Calculate insets for the rotated max bounds.
+            // TODO(181127261) calculate insets for each display rotation and state.
+
+            maxMetrics.add(new WindowMetrics(maxBounds, windowInsets));
+        }
+        return maxMetrics;
+    }
+
+    @Override
     public void holdLock(IBinder token, int durationMs) {
         try {
             WindowManagerGlobal.getWindowManagerService().holdLock(token, durationMs);
diff --git a/core/java/android/view/translation/Helper.java b/core/java/android/view/translation/Helper.java
new file mode 100644
index 0000000..6e2850f
--- /dev/null
+++ b/core/java/android/view/translation/Helper.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.translation;
+
+/** @hide */
+public class Helper {
+
+    // Debug-level flags are defined when service is bound.
+    public static boolean sDebug = false;
+    public static boolean sVerbose = false;
+
+    // TODO: Use a device config value.
+    public static final int ANIMATION_DURATION_MILLIS = 250;
+
+    private Helper() {
+        throw new UnsupportedOperationException("contains static members only");
+    }
+}
diff --git a/core/java/android/view/translation/TranslationCapability.java b/core/java/android/view/translation/TranslationCapability.java
index 65b749a..b7e13dd 100644
--- a/core/java/android/view/translation/TranslationCapability.java
+++ b/core/java/android/view/translation/TranslationCapability.java
@@ -40,15 +40,18 @@
 public final class TranslationCapability implements Parcelable {
 
     /**
-     * TODO: fill in javadoc
+     * The translation service supports translation between the source and target specs, and it is
+     * ready to be downloaded onto the device.
      */
     public static final @ModelState int STATE_AVAILABLE_TO_DOWNLOAD = 1;
     /**
-     * TODO: fill in javadoc
+     * The translation service supports translation between the source and target specs, and it is
+     * being downloaded onto the device currently.
      */
     public static final @ModelState int STATE_DOWNLOADING = 2;
     /**
-     * TODO: fill in javadoc
+     * The translation service supports translation between the source and target specs, and it is
+     * downloaded and ready to use on device.
      */
     public static final @ModelState int STATE_ON_DEVICE = 3;
     /**
@@ -305,7 +308,7 @@
     };
 
     @DataClass.Generated(
-            time = 1624307114468L,
+            time = 1629158466039L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/view/translation/TranslationCapability.java",
             inputSignatures = "public static final @android.view.translation.TranslationCapability.ModelState int STATE_AVAILABLE_TO_DOWNLOAD\npublic static final @android.view.translation.TranslationCapability.ModelState int STATE_DOWNLOADING\npublic static final @android.view.translation.TranslationCapability.ModelState int STATE_ON_DEVICE\npublic static final @android.view.translation.TranslationCapability.ModelState int STATE_NOT_AVAILABLE\npublic static final @android.view.translation.TranslationCapability.ModelState int STATE_REMOVED_AND_AVAILABLE\nprivate final @android.view.translation.TranslationCapability.ModelState int mState\nprivate final @android.annotation.NonNull android.view.translation.TranslationSpec mSourceSpec\nprivate final @android.annotation.NonNull android.view.translation.TranslationSpec mTargetSpec\nprivate final  boolean mUiTranslationEnabled\nprivate final @android.view.translation.TranslationContext.TranslationFlag int mSupportedTranslationFlags\nclass TranslationCapability extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstDefs=true, genToString=true, genConstructor=false)")
diff --git a/core/java/android/view/translation/TranslationRequest.java b/core/java/android/view/translation/TranslationRequest.java
index df4836e..0d41851 100644
--- a/core/java/android/view/translation/TranslationRequest.java
+++ b/core/java/android/view/translation/TranslationRequest.java
@@ -39,12 +39,16 @@
     public static final @RequestFlags int FLAG_TRANSLATION_RESULT = 0x1;
     /**
      * Indicates this request wants to receive the dictionary result.
-     * TODO: describe the structure of the result.
+     *
+     * <p>See {@link TranslationResponseValue#EXTRA_DEFINITIONS} for more detail on the structure
+     * of the returned data.
      */
     public static final @RequestFlags int FLAG_DICTIONARY_RESULT = 0x2;
     /**
      * Indicates this request wants to receive the transliteration result.
-     * TODO: describe the structure of the result.
+     *
+     * <p>This returns a CharSequence representation of the transliteration of the translated text.
+     *  See {@link TranslationResponseValue#getTransliteration()}.
      */
     public static final @RequestFlags int FLAG_TRANSLITERATION_RESULT = 0x4;
     /**
@@ -327,7 +331,8 @@
             return this;
         }
 
-        /** @see #setTranslationRequestValues
+        /**
+         * @see #setTranslationRequestValues
          * @removed
          */
         @DataClass.Generated.Member
@@ -352,7 +357,8 @@
             return this;
         }
 
-        /** @see #setViewTranslationRequests
+        /**
+         * @see #setViewTranslationRequests
          * @removed
          */
         @DataClass.Generated.Member
@@ -394,7 +400,7 @@
     }
 
     @DataClass.Generated(
-            time = 1620429997487L,
+            time = 1629159107226L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/view/translation/TranslationRequest.java",
             inputSignatures = "public static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_TRANSLATION_RESULT\npublic static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_DICTIONARY_RESULT\npublic static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_TRANSLITERATION_RESULT\npublic static final @android.view.translation.TranslationRequest.RequestFlags int FLAG_PARTIAL_RESPONSES\nprivate final @android.view.translation.TranslationRequest.RequestFlags int mFlags\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"translationRequestValue\") java.util.List<android.view.translation.TranslationRequestValue> mTranslationRequestValues\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"viewTranslationRequest\") java.util.List<android.view.translation.ViewTranslationRequest> mViewTranslationRequests\nprivate static  int defaultFlags()\nprivate static  java.util.List<android.view.translation.TranslationRequestValue> defaultTranslationRequestValues()\nprivate static  java.util.List<android.view.translation.ViewTranslationRequest> defaultViewTranslationRequests()\nclass TranslationRequest extends java.lang.Object implements [android.os.Parcelable]\npublic abstract @java.lang.Deprecated android.view.translation.TranslationRequest.Builder addTranslationRequestValue(android.view.translation.TranslationRequestValue)\npublic abstract @java.lang.Deprecated android.view.translation.TranslationRequest.Builder addViewTranslationRequest(android.view.translation.ViewTranslationRequest)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstDefs=true, genBuilder=true)\npublic abstract @java.lang.Deprecated android.view.translation.TranslationRequest.Builder addTranslationRequestValue(android.view.translation.TranslationRequestValue)\npublic abstract @java.lang.Deprecated android.view.translation.TranslationRequest.Builder addViewTranslationRequest(android.view.translation.ViewTranslationRequest)\nclass BaseBuilder extends java.lang.Object implements []")
diff --git a/core/java/android/view/translation/TranslationResponseValue.java b/core/java/android/view/translation/TranslationResponseValue.java
index a24dbc3..9dff2d5 100644
--- a/core/java/android/view/translation/TranslationResponseValue.java
+++ b/core/java/android/view/translation/TranslationResponseValue.java
@@ -93,9 +93,11 @@
     @NonNull
     private final Bundle mExtras;
 
+    // TODO: Add example of transliteration.
     /**
      * The transliteration result of the translated text.
-     * TODO: Describe the result structure.
+     *
+     * <p>This returns a CharSequence representation of the transliteration of the translated text.
      */
     @Nullable
     private final CharSequence mTransliteration;
@@ -223,7 +225,8 @@
 
     /**
      * The transliteration result of the translated text.
-     * TODO: Describe the result structure.
+     *
+     * <p>This returns a CharSequence representation of the transliteration of the translated text.
      */
     @DataClass.Generated.Member
     public @Nullable CharSequence getTransliteration() {
@@ -407,7 +410,8 @@
 
         /**
          * The transliteration result of the translated text.
-         * TODO: Describe the result structure.
+         *
+         * <p>This returns a CharSequence representation of the transliteration of the translated text.
          */
         @DataClass.Generated.Member
         public @NonNull Builder setTransliteration(@NonNull CharSequence value) {
@@ -448,7 +452,7 @@
     }
 
     @DataClass.Generated(
-            time = 1622133051937L,
+            time = 1631057245846L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/view/translation/TranslationResponseValue.java",
             inputSignatures = "public static final  int STATUS_SUCCESS\npublic static final  int STATUS_ERROR\npublic static final  java.lang.String EXTRA_DEFINITIONS\nprivate final @android.view.translation.TranslationResponseValue.Status int mStatusCode\nprivate final @android.annotation.Nullable java.lang.CharSequence mText\nprivate final @android.annotation.NonNull android.os.Bundle mExtras\nprivate final @android.annotation.Nullable java.lang.CharSequence mTransliteration\npublic static @android.annotation.NonNull android.view.translation.TranslationResponseValue forError()\nprivate static  java.lang.CharSequence defaultText()\nprivate static  android.os.Bundle defaultExtras()\nprivate  boolean extrasEquals(android.os.Bundle)\nprivate static  java.lang.CharSequence defaultTransliteration()\nclass TranslationResponseValue extends java.lang.Object implements [android.os.Parcelable]\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true, genToString=true, genEqualsHashCode=true, genHiddenConstDefs=true)\nclass BaseBuilder extends java.lang.Object implements []")
diff --git a/core/java/android/view/translation/Translator.java b/core/java/android/view/translation/Translator.java
index 606f39d..70db6e5 100644
--- a/core/java/android/view/translation/Translator.java
+++ b/core/java/android/view/translation/Translator.java
@@ -53,9 +53,6 @@
 
     private static final String TAG = "Translator";
 
-    // TODO: make this configurable and cross the Translation component
-    private static boolean sDEBUG = false;
-
     private final Object mLock = new Object();
 
     private int mId;
diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java
index 442d099..b571560 100644
--- a/core/java/android/view/translation/UiTranslationController.java
+++ b/core/java/android/view/translation/UiTranslationController.java
@@ -16,6 +16,7 @@
 
 package android.view.translation;
 
+import static android.view.translation.Helper.ANIMATION_DURATION_MILLIS;
 import static android.view.translation.UiTranslationManager.STATE_UI_TRANSLATION_FINISHED;
 import static android.view.translation.UiTranslationManager.STATE_UI_TRANSLATION_PAUSED;
 import static android.view.translation.UiTranslationManager.STATE_UI_TRANSLATION_RESUMED;
@@ -26,6 +27,7 @@
 import android.app.Activity;
 import android.app.assist.ActivityId;
 import android.content.Context;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Process;
@@ -110,11 +112,10 @@
     public void updateUiTranslationState(@UiTranslationState int state, TranslationSpec sourceSpec,
             TranslationSpec targetSpec, List<AutofillId> views,
             UiTranslationSpec uiTranslationSpec) {
-        if (!mActivity.isResumed() && (state == STATE_UI_TRANSLATION_STARTED
-                || state == STATE_UI_TRANSLATION_RESUMED)) {
+        if (mActivity.isDestroyed()) {
+            Log.i(TAG, "Cannot update " + stateToString(state) + " for destroyed " + mActivity);
             return;
         }
-
         Log.i(TAG, "updateUiTranslationState state: " + stateToString(state)
                 + (DEBUG ? (", views: " + views + ", spec: " + uiTranslationSpec) : ""));
         synchronized (mLock) {
@@ -342,10 +343,8 @@
      */
     private void onVirtualViewTranslationCompleted(
             SparseArray<LongSparseArray<ViewTranslationResponse>> translatedResult) {
-        if (!mActivity.isResumed()) {
-            if (DEBUG) {
-                Log.v(TAG, "onTranslationCompleted: Activity is not resumed.");
-            }
+        if (mActivity.isDestroyed()) {
+            Log.v(TAG, "onTranslationCompleted:" + mActivity + "is destroyed.");
             return;
         }
         synchronized (mLock) {
@@ -393,10 +392,8 @@
      * The method is used to handle the translation result for non-vertual views.
      */
     private void onTranslationCompleted(SparseArray<ViewTranslationResponse> translatedResult) {
-        if (!mActivity.isResumed()) {
-            if (DEBUG) {
-                Log.v(TAG, "onTranslationCompleted: Activity is not resumed.");
-            }
+        if (mActivity.isDestroyed()) {
+            Log.v(TAG, "onTranslationCompleted:" + mActivity + "is destroyed.");
             return;
         }
         final int resultCount = translatedResult.size();
@@ -465,9 +462,6 @@
         }
     }
 
-    // TODO: Use a device config value.
-    private static final int ANIMATION_DURATION_MILLIS = 250;
-
     /**
      * Creates a Translator for the given source and target translation specs and start the ui
      * translation when the Translator is created successfully.
@@ -724,7 +718,21 @@
             msg.append("text=").append(value.getText() == null
                     ? "null"
                     : "string[" + value.getText().length() + "], ");
-            //TODO: append dictionary results.
+            final Bundle definitions =
+                    (Bundle) value.getExtras().get(TranslationResponseValue.EXTRA_DEFINITIONS);
+            if (definitions != null) {
+                msg.append("definitions={");
+                for (String partOfSpeech : definitions.keySet()) {
+                    msg.append(partOfSpeech).append(":[");
+                    for (CharSequence definition : definitions.getCharSequenceArray(partOfSpeech)) {
+                        msg.append(definition == null
+                                ? "null, "
+                                : "string[" + definition.length() + "], ");
+                    }
+                    msg.append("], ");
+                }
+                msg.append("}");
+            }
             msg.append("transliteration=").append(value.getTransliteration() == null
                     ? "null"
                     : "string[" + value.getTransliteration().length() + "]}, ");
diff --git a/core/java/android/webkit/URLUtil.java b/core/java/android/webkit/URLUtil.java
index 844b156..c7609a6 100644
--- a/core/java/android/webkit/URLUtil.java
+++ b/core/java/android/webkit/URLUtil.java
@@ -310,7 +310,7 @@
         String extension = null;
 
         // If we couldn't do anything with the hint, move toward the content disposition
-        if (filename == null && contentDisposition != null) {
+        if (contentDisposition != null) {
             filename = parseContentDisposition(contentDisposition);
             if (filename != null) {
                 int index = filename.lastIndexOf('/') + 1;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 91fc5a5..fe5eb08 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -740,6 +740,16 @@
         }
 
         @Override
+        public UserHandle getUser() {
+            return mContextForResources.getUser();
+        }
+
+        @Override
+        public int getUserId() {
+            return mContextForResources.getUserId();
+        }
+
+        @Override
         public boolean isRestricted() {
             // Override isRestricted and direct to resource's implementation. The isRestricted is
             // used for determining the risky resources loading, e.g. fonts, thus direct to context
diff --git a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java b/core/java/android/window/RemoteTransition.aidl
similarity index 85%
copy from tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
copy to core/java/android/window/RemoteTransition.aidl
index 0e51a6b..f3c3f54 100644
--- a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
+++ b/core/java/android/window/RemoteTransition.aidl
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.componentalias.tests.app.s;
 
-public class Target04 extends BaseService {
-}
+package android.window;
+
+parcelable RemoteTransition;
diff --git a/core/java/android/window/RemoteTransition.java b/core/java/android/window/RemoteTransition.java
new file mode 100644
index 0000000..b243b65
--- /dev/null
+++ b/core/java/android/window/RemoteTransition.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.IBinder;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Represents a remote transition animation and information required to run it (eg. the app thread
+ * that needs to be boosted).
+ * @hide
+ */
+@DataClass(genToString = true, genSetters = true, genAidl = true)
+public class RemoteTransition implements Parcelable {
+
+    /** The actual remote-transition interface used to run the transition animation. */
+    private @NonNull IRemoteTransition mRemoteTransition;
+
+    /** Get the IBinder associated with the underlying IRemoteTransition. */
+    public @Nullable IBinder asBinder() {
+        return mRemoteTransition.asBinder();
+    }
+
+
+
+    // Code below generated by codegen v1.0.23.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/window/RemoteTransition.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    /**
+     * Creates a new RemoteTransition.
+     *
+     * @param remoteTransition
+     *   The actual remote-transition interface used to run the transition animation.
+     */
+    @DataClass.Generated.Member
+    public RemoteTransition(
+            @NonNull IRemoteTransition remoteTransition) {
+        this.mRemoteTransition = remoteTransition;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mRemoteTransition);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * The actual remote-transition interface used to run the transition animation.
+     */
+    @DataClass.Generated.Member
+    public @NonNull IRemoteTransition getRemoteTransition() {
+        return mRemoteTransition;
+    }
+
+    /**
+     * The actual remote-transition interface used to run the transition animation.
+     */
+    @DataClass.Generated.Member
+    public @NonNull RemoteTransition setRemoteTransition(@NonNull IRemoteTransition value) {
+        mRemoteTransition = value;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mRemoteTransition);
+        return this;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "RemoteTransition { " +
+                "remoteTransition = " + mRemoteTransition +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeStrongInterface(mRemoteTransition);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    protected RemoteTransition(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        IRemoteTransition remoteTransition = IRemoteTransition.Stub.asInterface(in.readStrongBinder());
+
+        this.mRemoteTransition = remoteTransition;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mRemoteTransition);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<RemoteTransition> CREATOR
+            = new Parcelable.Creator<RemoteTransition>() {
+        @Override
+        public RemoteTransition[] newArray(int size) {
+            return new RemoteTransition[size];
+        }
+
+        @Override
+        public RemoteTransition createFromParcel(@NonNull android.os.Parcel in) {
+            return new RemoteTransition(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1630613039043L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/core/java/android/window/RemoteTransition.java",
+            inputSignatures = "private @android.annotation.NonNull android.window.IRemoteTransition mRemoteTransition\npublic @android.annotation.Nullable android.os.IBinder asBinder()\nclass RemoteTransition extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genAidl=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java
index acf20d7..f14294e 100644
--- a/core/java/android/window/SplashScreenView.java
+++ b/core/java/android/window/SplashScreenView.java
@@ -59,6 +59,7 @@
 
 import java.time.Duration;
 import java.time.Instant;
+import java.util.function.Consumer;
 
 /**
  * <p>The view which allows an activity to customize its splash screen exit animation.</p>
@@ -144,6 +145,7 @@
         private Bitmap mParceledBrandingBitmap;
         private Instant mIconAnimationStart;
         private Duration mIconAnimationDuration;
+        private Consumer<Runnable> mUiThreadInitTask;
 
         public Builder(@NonNull Context context) {
             mContext = context;
@@ -232,6 +234,15 @@
         }
 
         /**
+         * Set the Runnable that can receive the task which should be executed on UI thread.
+         * @param uiThreadInitTask
+         */
+        public Builder setUiThreadInitConsumer(Consumer<Runnable> uiThreadInitTask) {
+            mUiThreadInitTask = uiThreadInitTask;
+            return this;
+        }
+
+        /**
          * Set the Drawable object and size for the branding view.
          */
         public Builder setBrandingDrawable(@Nullable Drawable branding, int width, int height) {
@@ -262,7 +273,11 @@
             // center icon
             if (mIconDrawable instanceof SplashScreenView.IconAnimateListener
                     || mSurfacePackage != null) {
-                view.mIconView = createSurfaceView(view);
+                if (mUiThreadInitTask != null) {
+                    mUiThreadInitTask.accept(() -> view.mIconView = createSurfaceView(view));
+                } else {
+                    view.mIconView = createSurfaceView(view);
+                }
                 view.initIconAnimation(mIconDrawable,
                         mIconAnimationDuration != null ? mIconAnimationDuration.toMillis() : 0);
                 view.mIconAnimationStart = mIconAnimationStart;
@@ -316,7 +331,9 @@
         }
 
         private SurfaceView createSurfaceView(@NonNull SplashScreenView view) {
-            final SurfaceView surfaceView = new SurfaceView(view.getContext());
+            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "SplashScreenView#createSurfaceView");
+            final Context viewContext = view.getContext();
+            final SurfaceView surfaceView = new SurfaceView(viewContext);
             surfaceView.setPadding(0, 0, 0, 0);
             surfaceView.setBackground(mIconBackground);
             if (mSurfacePackage == null) {
@@ -326,10 +343,10 @@
                                     + Thread.currentThread().getId());
                 }
 
-                SurfaceControlViewHost viewHost = new SurfaceControlViewHost(mContext,
-                        mContext.getDisplay(),
+                SurfaceControlViewHost viewHost = new SurfaceControlViewHost(viewContext,
+                        viewContext.getDisplay(),
                         surfaceView.getHostToken());
-                ImageView imageView = new ImageView(mContext);
+                ImageView imageView = new ImageView(viewContext);
                 imageView.setBackground(mIconDrawable);
                 viewHost.setView(imageView, mIconSize, mIconSize);
                 SurfaceControlViewHost.SurfacePackage surfacePackage = viewHost.getSurfacePackage();
@@ -360,6 +377,7 @@
 
             view.addView(surfaceView);
             view.mSurfaceView = surfaceView;
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
             return surfaceView;
         }
     }
@@ -531,17 +549,14 @@
 
     private void releaseAnimationSurfaceHost() {
         if (mSurfaceHost != null && !mIsCopied) {
-            final SurfaceControlViewHost finalSurfaceHost = mSurfaceHost;
+            if (DEBUG) {
+                Log.d(TAG,
+                        "Shell removed splash screen."
+                                + " Releasing SurfaceControlViewHost on thread #"
+                                + Thread.currentThread().getId());
+            }
+            releaseIconHost(mSurfaceHost);
             mSurfaceHost = null;
-            finalSurfaceHost.getView().post(() -> {
-                if (DEBUG) {
-                    Log.d(TAG,
-                            "Shell removed splash screen."
-                                    + " Releasing SurfaceControlViewHost on thread #"
-                                    + Thread.currentThread().getId());
-                }
-                finalSurfaceHost.release();
-            });
         } else if (mSurfacePackage != null && mSurfaceHost == null) {
             mSurfacePackage = null;
             mClientCallback.sendResult(null);
@@ -549,6 +564,18 @@
     }
 
     /**
+     * Release the host which hold the SurfaceView of the icon.
+     * @hide
+     */
+    public static void releaseIconHost(SurfaceControlViewHost host) {
+        final Drawable background = host.getView().getBackground();
+        if (background instanceof SplashScreenView.IconAnimateListener) {
+            ((SplashScreenView.IconAnimateListener) background).stopAnimation();
+        }
+        host.release();
+    }
+
+    /**
      * Called when this view is attached to an activity. This also makes SystemUI colors
      * transparent so the content of splash screen view can draw fully.
      *
@@ -639,6 +666,11 @@
          * @return true if this drawable object can also be animated and it can be played now.
          */
         boolean prepareAnimate(long duration, Runnable startListener);
+
+        /**
+         * Stop animation.
+         */
+        void stopAnimation();
     }
 
     /**
diff --git a/core/java/android/window/TaskFragmentInfo.java b/core/java/android/window/TaskFragmentInfo.java
index dac420b..165dcdf 100644
--- a/core/java/android/window/TaskFragmentInfo.java
+++ b/core/java/android/window/TaskFragmentInfo.java
@@ -55,8 +55,8 @@
     /** Whether the TaskFragment contains any child Window Container. */
     private final boolean mIsEmpty;
 
-    /** Whether the TaskFragment contains any running Activity. */
-    private final boolean mHasRunningActivity;
+    /** The number of the running activities in the TaskFragment. */
+    private final int mRunningActivityCount;
 
     /** Whether this TaskFragment is visible on the window hierarchy. */
     private final boolean mIsVisible;
@@ -71,19 +71,27 @@
     /** Relative position of the fragment's top left corner in the parent container. */
     private final Point mPositionInParent;
 
+    /**
+     * Whether the last running activity in the TaskFragment was finished due to clearing task while
+     * launching an activity in the host Task.
+     */
+    private final boolean mIsTaskClearedForReuse;
+
     /** @hide */
     public TaskFragmentInfo(
             @NonNull IBinder fragmentToken, @NonNull WindowContainerToken token,
-            @NonNull Configuration configuration, boolean isEmpty, boolean hasRunningActivity,
-            boolean isVisible, @NonNull List<IBinder> activities, @NonNull Point positionInParent) {
+            @NonNull Configuration configuration, boolean isEmpty, int runningActivityCount,
+            boolean isVisible, @NonNull List<IBinder> activities, @NonNull Point positionInParent,
+            boolean isTaskClearedForReuse) {
         mFragmentToken = requireNonNull(fragmentToken);
         mToken = requireNonNull(token);
         mConfiguration.setTo(configuration);
         mIsEmpty = isEmpty;
-        mHasRunningActivity = hasRunningActivity;
+        mRunningActivityCount = runningActivityCount;
         mIsVisible = isVisible;
         mActivities.addAll(activities);
         mPositionInParent = requireNonNull(positionInParent);
+        mIsTaskClearedForReuse = isTaskClearedForReuse;
     }
 
     @NonNull
@@ -106,7 +114,11 @@
     }
 
     public boolean hasRunningActivity() {
-        return mHasRunningActivity;
+        return mRunningActivityCount > 0;
+    }
+
+    public int getRunningActivityCount() {
+        return mRunningActivityCount;
     }
 
     public boolean isVisible() {
@@ -124,6 +136,10 @@
         return mPositionInParent;
     }
 
+    public boolean isTaskClearedForReuse() {
+        return mIsTaskClearedForReuse;
+    }
+
     @WindowingMode
     public int getWindowingMode() {
         return mConfiguration.windowConfiguration.getWindowingMode();
@@ -141,11 +157,12 @@
         return mFragmentToken.equals(that.mFragmentToken)
                 && mToken.equals(that.mToken)
                 && mIsEmpty == that.mIsEmpty
-                && mHasRunningActivity == that.mHasRunningActivity
+                && mRunningActivityCount == that.mRunningActivityCount
                 && mIsVisible == that.mIsVisible
                 && getWindowingMode() == that.getWindowingMode()
                 && mActivities.equals(that.mActivities)
-                && mPositionInParent.equals(that.mPositionInParent);
+                && mPositionInParent.equals(that.mPositionInParent)
+                && mIsTaskClearedForReuse == that.mIsTaskClearedForReuse;
     }
 
     private TaskFragmentInfo(Parcel in) {
@@ -153,10 +170,11 @@
         mToken = in.readTypedObject(WindowContainerToken.CREATOR);
         mConfiguration.readFromParcel(in);
         mIsEmpty = in.readBoolean();
-        mHasRunningActivity = in.readBoolean();
+        mRunningActivityCount = in.readInt();
         mIsVisible = in.readBoolean();
         in.readBinderList(mActivities);
         mPositionInParent = requireNonNull(in.readTypedObject(Point.CREATOR));
+        mIsTaskClearedForReuse = in.readBoolean();
     }
 
     /** @hide */
@@ -166,10 +184,11 @@
         dest.writeTypedObject(mToken, flags);
         mConfiguration.writeToParcel(dest, flags);
         dest.writeBoolean(mIsEmpty);
-        dest.writeBoolean(mHasRunningActivity);
+        dest.writeInt(mRunningActivityCount);
         dest.writeBoolean(mIsVisible);
         dest.writeBinderList(mActivities);
         dest.writeTypedObject(mPositionInParent, flags);
+        dest.writeBoolean(mIsTaskClearedForReuse);
     }
 
     @NonNull
@@ -192,9 +211,10 @@
                 + " fragmentToken=" + mFragmentToken
                 + " token=" + mToken
                 + " isEmpty=" + mIsEmpty
-                + " hasRunningActivity=" + mHasRunningActivity
+                + " runningActivityCount=" + mRunningActivityCount
                 + " isVisible=" + mIsVisible
                 + " positionInParent=" + mPositionInParent
+                + " isTaskClearedForReuse=" + mIsTaskClearedForReuse
                 + "}";
     }
 
diff --git a/core/java/android/window/TransitionRequestInfo.java b/core/java/android/window/TransitionRequestInfo.java
index cc493ab..f770731 100644
--- a/core/java/android/window/TransitionRequestInfo.java
+++ b/core/java/android/window/TransitionRequestInfo.java
@@ -40,11 +40,11 @@
     private @Nullable ActivityManager.RunningTaskInfo mTriggerTask;
 
     /** If non-null, a remote-transition associated with the source of this transition. */
-    private @Nullable IRemoteTransition mRemoteTransition;
+    private @Nullable RemoteTransition mRemoteTransition;
 
 
 
-    // Code below generated by codegen v1.0.22.
+    // Code below generated by codegen v1.0.23.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -72,7 +72,7 @@
     public TransitionRequestInfo(
             @WindowManager.TransitionType int type,
             @Nullable ActivityManager.RunningTaskInfo triggerTask,
-            @Nullable IRemoteTransition remoteTransition) {
+            @Nullable RemoteTransition remoteTransition) {
         this.mType = type;
         com.android.internal.util.AnnotationValidations.validate(
                 WindowManager.TransitionType.class, null, mType);
@@ -103,7 +103,7 @@
      * If non-null, a remote-transition associated with the source of this transition.
      */
     @DataClass.Generated.Member
-    public @Nullable IRemoteTransition getRemoteTransition() {
+    public @Nullable RemoteTransition getRemoteTransition() {
         return mRemoteTransition;
     }
 
@@ -121,7 +121,7 @@
      * If non-null, a remote-transition associated with the source of this transition.
      */
     @DataClass.Generated.Member
-    public @android.annotation.NonNull TransitionRequestInfo setRemoteTransition(@android.annotation.NonNull IRemoteTransition value) {
+    public @android.annotation.NonNull TransitionRequestInfo setRemoteTransition(@android.annotation.NonNull RemoteTransition value) {
         mRemoteTransition = value;
         return this;
     }
@@ -151,7 +151,7 @@
         dest.writeByte(flg);
         dest.writeInt(mType);
         if (mTriggerTask != null) dest.writeTypedObject(mTriggerTask, flags);
-        if (mRemoteTransition != null) dest.writeStrongInterface(mRemoteTransition);
+        if (mRemoteTransition != null) dest.writeTypedObject(mRemoteTransition, flags);
     }
 
     @Override
@@ -168,7 +168,7 @@
         byte flg = in.readByte();
         int type = in.readInt();
         ActivityManager.RunningTaskInfo triggerTask = (flg & 0x2) == 0 ? null : (ActivityManager.RunningTaskInfo) in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
-        IRemoteTransition remoteTransition = (flg & 0x4) == 0 ? null : IRemoteTransition.Stub.asInterface(in.readStrongBinder());
+        RemoteTransition remoteTransition = (flg & 0x4) == 0 ? null : (RemoteTransition) in.readTypedObject(RemoteTransition.CREATOR);
 
         this.mType = type;
         com.android.internal.util.AnnotationValidations.validate(
@@ -194,10 +194,10 @@
     };
 
     @DataClass.Generated(
-            time = 1610060387917L,
-            codegenVersion = "1.0.22",
+            time = 1629321632222L,
+            codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/window/TransitionRequestInfo.java",
-            inputSignatures = "private final @android.view.WindowManager.TransitionType int mType\nprivate @android.annotation.Nullable android.app.ActivityManager.RunningTaskInfo mTriggerTask\nprivate @android.annotation.Nullable android.window.IRemoteTransition mRemoteTransition\nclass TransitionRequestInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genAidl=true)")
+            inputSignatures = "private final @android.view.WindowManager.TransitionType int mType\nprivate @android.annotation.Nullable android.app.ActivityManager.RunningTaskInfo mTriggerTask\nprivate @android.annotation.Nullable android.window.RemoteTransition mRemoteTransition\nclass TransitionRequestInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genAidl=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 4d0f4c2..019126f 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -140,6 +140,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Supplier;
 
 /**
  * The Chooser Activity handles intent resolution specifically for sharing intents -
@@ -234,11 +235,6 @@
 
     private static final float DIRECT_SHARE_EXPANSION_RATE = 0.78f;
 
-    // TODO(b/121287224): Re-evaluate this limit
-    private static final int SHARE_TARGET_QUERY_PACKAGE_LIMIT = 20;
-
-    private static final int QUERY_TARGET_SERVICE_LIMIT = 5;
-
     private static final int DEFAULT_SALT_EXPIRATION_DAYS = 7;
     private int mMaxHashSaltDays = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI,
             SystemUiDeviceConfigFlags.HASH_SALT_MAX_DAYS,
@@ -258,8 +254,6 @@
 
     private long mQueriedSharingShortcutsTimeMs;
 
-    private int mChooserRowServiceSpacing;
-
     private int mCurrAvailableWidth = 0;
     private int mLastNumberOfChildren = -1;
 
@@ -658,9 +652,6 @@
                 .addTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE, target.getType())
                 .addTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS, systemCost));
 
-        mChooserRowServiceSpacing = getResources()
-                                        .getDimensionPixelSize(R.dimen.chooser_service_spacing);
-
         if (mResolverDrawerLayout != null) {
             mResolverDrawerLayout.addOnLayoutChangeListener(this::handleLayoutChange);
 
@@ -2066,24 +2057,6 @@
         return chooserTargetList;
     }
 
-    private String convertServiceName(String packageName, String serviceName) {
-        if (TextUtils.isEmpty(serviceName)) {
-            return null;
-        }
-
-        final String fullName;
-        if (serviceName.startsWith(".")) {
-            // Relative to the app package. Prepend the app package name.
-            fullName = packageName + serviceName;
-        } else if (serviceName.indexOf('.') >= 0) {
-            // Fully qualified package name.
-            fullName = serviceName;
-        } else {
-            fullName = null;
-        }
-        return fullName;
-    }
-
     private void logDirectShareTargetReceived(int logCategory) {
         final int apiLatency = (int) (System.currentTimeMillis() - mQueriedSharingShortcutsTimeMs);
         getMetricsLogger().write(new LogMaker(logCategory).setSubtype(apiLatency));
@@ -2265,37 +2238,6 @@
         return false;
     }
 
-    void filterServiceTargets(Context contextAsUser, String packageName,
-            List<ChooserTarget> targets) {
-        if (targets == null) {
-            return;
-        }
-
-        final PackageManager pm = contextAsUser.getPackageManager();
-        for (int i = targets.size() - 1; i >= 0; i--) {
-            final ChooserTarget target = targets.get(i);
-            final ComponentName targetName = target.getComponentName();
-            if (packageName != null && packageName.equals(targetName.getPackageName())) {
-                // Anything from the original target's package is fine.
-                continue;
-            }
-
-            boolean remove;
-            try {
-                final ActivityInfo ai = pm.getActivityInfo(targetName, 0);
-                remove = !ai.exported || ai.permission != null;
-            } catch (NameNotFoundException e) {
-                Log.e(TAG, "Target " + target + " returned by " + packageName
-                        + " component not found");
-                remove = true;
-            }
-
-            if (remove) {
-                targets.remove(i);
-            }
-        }
-    }
-
     /**
      * Sort intents alphabetically based on display label.
      */
@@ -2854,7 +2796,7 @@
                 .setSubtype(previewType));
     }
 
-    class ViewHolderBase extends RecyclerView.ViewHolder {
+    abstract static class ViewHolderBase extends RecyclerView.ViewHolder {
         private int mViewType;
 
         ViewHolderBase(View itemView, int viewType) {
@@ -2902,7 +2844,7 @@
     /**
      * Add a footer to the list, to support scrolling behavior below the navbar.
      */
-    final class FooterViewHolder extends ViewHolderBase {
+    static final class FooterViewHolder extends ViewHolderBase {
         FooterViewHolder(View itemView, int viewType) {
             super(itemView, viewType);
         }
@@ -3327,7 +3269,8 @@
                 parentGroup.addView(row2);
 
                 mDirectShareViewHolder = new DirectShareViewHolder(parentGroup,
-                        Lists.newArrayList(row1, row2), getMaxTargetsPerRow(), viewType);
+                        Lists.newArrayList(row1, row2), getMaxTargetsPerRow(), viewType,
+                        mChooserMultiProfilePagerAdapter::getActiveListAdapter);
                 loadViewsIntoGroup(mDirectShareViewHolder);
 
                 return mDirectShareViewHolder;
@@ -3489,7 +3432,7 @@
      * {@link ChooserGridAdapter#VIEW_TYPE_DIRECT_SHARE},
      * and {@link ChooserGridAdapter#VIEW_TYPE_CALLER_AND_RANK}.
      */
-    abstract class ItemGroupViewHolder extends ViewHolderBase {
+    abstract static class ItemGroupViewHolder extends ViewHolderBase {
         protected int mMeasuredRowHeight;
         private int[] mItemIndices;
         protected final View[] mCells;
@@ -3539,7 +3482,7 @@
         }
     }
 
-    class SingleRowViewHolder extends ItemGroupViewHolder {
+    static class SingleRowViewHolder extends ItemGroupViewHolder {
         private final ViewGroup mRow;
 
         SingleRowViewHolder(ViewGroup row, int cellCount, int viewType) {
@@ -3573,7 +3516,7 @@
         }
     }
 
-    class DirectShareViewHolder extends ItemGroupViewHolder {
+    static class DirectShareViewHolder extends ItemGroupViewHolder {
         private final ViewGroup mParent;
         private final List<ViewGroup> mRows;
         private int mCellCountPerRow;
@@ -3585,14 +3528,17 @@
 
         private final boolean[] mCellVisibility;
 
+        private final Supplier<ChooserListAdapter> mListAdapterSupplier;
+
         DirectShareViewHolder(ViewGroup parent, List<ViewGroup> rows, int cellCountPerRow,
-                int viewType) {
+                int viewType, Supplier<ChooserListAdapter> listAdapterSupplier) {
             super(rows.size() * cellCountPerRow, parent, viewType);
 
             this.mParent = parent;
             this.mRows = rows;
             this.mCellCountPerRow = cellCountPerRow;
             this.mCellVisibility = new boolean[rows.size() * cellCountPerRow];
+            this.mListAdapterSupplier = listAdapterSupplier;
         }
 
         public ViewGroup addView(int index, View v) {
@@ -3666,8 +3612,7 @@
 
                 // only expand if we have more than maxTargetsPerRow, and delay that decision
                 // until they start to scroll
-                ChooserListAdapter adapter =
-                        mChooserMultiProfilePagerAdapter.getActiveListAdapter();
+                ChooserListAdapter adapter = mListAdapterSupplier.get();
                 int validTargets = adapter.getSelectableServiceTargetCount();
                 if (validTargets <= maxTargetsPerRow) {
                     mHideDirectShareExpansion = true;
diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java
index 7d2cb50..41efe28 100644
--- a/core/java/com/android/internal/app/ResolverListAdapter.java
+++ b/core/java/com/android/internal/app/ResolverListAdapter.java
@@ -838,6 +838,12 @@
             // check if subLabel matches label before final display
             return mRi.loadLabel(mPm).toString();
         }
+
+        @Override
+        String getAppLabelForSubstitutePermission() {
+            // Will default to app name if no activity label set
+            return mRi.getComponentInfo().loadLabel(mPm).toString();
+        }
     }
 
     /**
@@ -877,6 +883,11 @@
             // matches label before final display
             return (String) mActivityInfo.loadLabel(mPm);
         }
+
+        @Override
+        String getAppLabelForSubstitutePermission() {
+            return getAppSubLabelInternal();
+        }
     }
 
     /**
@@ -889,6 +900,7 @@
     private abstract static class TargetPresentationGetter {
         @Nullable abstract Drawable getIconSubstituteInternal();
         @Nullable abstract String getAppSubLabelInternal();
+        @Nullable abstract String getAppLabelForSubstitutePermission();
 
         private Context mCtx;
         private final int mIconDpi;
@@ -940,9 +952,10 @@
 
         public String getLabel() {
             String label = null;
-            // Apps with the substitute permission will always show the sublabel as their label
+            // Apps with the substitute permission will always show the activity label as the
+            // app label if provided
             if (mHasSubstitutePermission) {
-                label = getAppSubLabelInternal();
+                label = getAppLabelForSubstitutePermission();
             }
 
             if (label == null) {
@@ -953,8 +966,17 @@
         }
 
         public String getSubLabel() {
-            // Apps with the substitute permission will never have a sublabel
-            if (mHasSubstitutePermission) return null;
+            // Apps with the substitute permission will always show the resolve info label as the
+            // sublabel if provided
+            if (mHasSubstitutePermission){
+                String appSubLabel = getAppSubLabelInternal();
+                // Use the resolve info label as sublabel if it is set
+                if(!TextUtils.isEmpty(appSubLabel)
+                    && !TextUtils.equals(appSubLabel, getLabel())){
+                    return appSubLabel;
+                }
+                return null;
+            }
             return getAppSubLabelInternal();
         }
 
diff --git a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
index fc299fe..662bd28 100644
--- a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
+++ b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
@@ -223,518 +223,387 @@
     @Override
     public void getTextAfterCursor(int length, int flags,
             AndroidFuture future /* T=CharSequence */) {
-        dispatch(future, () -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getTextAfterCursor");
-            try {
-                final InputConnection ic = getInputConnection();
-                final CharSequence result;
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "getTextAfterCursor on inactive InputConnection");
-                    result = null;
-                } else {
-                    result = ic.getTextAfterCursor(length, flags);
-                }
-                if (ImeTracing.getInstance().isEnabled()) {
-                    final byte[] icProto = InputConnectionProtoDumper.buildGetTextAfterCursorProto(
-                            length, flags, result);
-                    ImeTracing.getInstance().triggerClientDump(
-                            TAG + "#getTextAfterCursor", mParentInputMethodManager, icProto);
-                }
-                return result;
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("getTextAfterCursor", future, () -> {
+            final InputConnection ic = getInputConnection();
+            final CharSequence result;
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "getTextAfterCursor on inactive InputConnection");
+                result = null;
+            } else {
+                result = ic.getTextAfterCursor(length, flags);
             }
+            if (ImeTracing.getInstance().isEnabled()) {
+                final byte[] icProto = InputConnectionProtoDumper.buildGetTextAfterCursorProto(
+                        length, flags, result);
+                ImeTracing.getInstance().triggerClientDump(
+                        TAG + "#getTextAfterCursor", mParentInputMethodManager, icProto);
+            }
+            return result;
         });
     }
 
     @Override
     public void getTextBeforeCursor(int length, int flags,
             AndroidFuture future /* T=CharSequence */) {
-        dispatch(future, () -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getTextBeforeCursor");
-            try {
-                final InputConnection ic = getInputConnection();
-                final CharSequence result;
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "getTextBeforeCursor on inactive InputConnection");
-                    result = null;
-                } else {
-                    result = ic.getTextBeforeCursor(length, flags);
-                }
-                if (ImeTracing.getInstance().isEnabled()) {
-                    final byte[] icProto = InputConnectionProtoDumper.buildGetTextBeforeCursorProto(
-                            length, flags, result);
-                    ImeTracing.getInstance().triggerClientDump(
-                            TAG + "#getTextBeforeCursor", mParentInputMethodManager, icProto);
-                }
-                return result;
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("getTextBeforeCursor", future, () -> {
+            final InputConnection ic = getInputConnection();
+            final CharSequence result;
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "getTextBeforeCursor on inactive InputConnection");
+                result = null;
+            } else {
+                result = ic.getTextBeforeCursor(length, flags);
             }
+            if (ImeTracing.getInstance().isEnabled()) {
+                final byte[] icProto = InputConnectionProtoDumper.buildGetTextBeforeCursorProto(
+                        length, flags, result);
+                ImeTracing.getInstance().triggerClientDump(
+                        TAG + "#getTextBeforeCursor", mParentInputMethodManager, icProto);
+            }
+            return result;
         });
     }
 
     @Override
     public void getSelectedText(int flags, AndroidFuture future /* T=CharSequence */) {
-        dispatch(future, () -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getSelectedText");
-            try {
-                final InputConnection ic = getInputConnection();
-                final CharSequence result;
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "getSelectedText on inactive InputConnection");
-                    result = null;
-                } else {
-                    result = ic.getSelectedText(flags);
-                }
-                if (ImeTracing.getInstance().isEnabled()) {
-                    final byte[] icProto = InputConnectionProtoDumper.buildGetSelectedTextProto(
-                            flags, result);
-                    ImeTracing.getInstance().triggerClientDump(
-                            TAG + "#getSelectedText", mParentInputMethodManager, icProto);
-                }
-                return result;
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("getSelectedText", future, () -> {
+            final InputConnection ic = getInputConnection();
+            final CharSequence result;
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "getSelectedText on inactive InputConnection");
+                result = null;
+            } else {
+                result = ic.getSelectedText(flags);
             }
+            if (ImeTracing.getInstance().isEnabled()) {
+                final byte[] icProto = InputConnectionProtoDumper.buildGetSelectedTextProto(
+                        flags, result);
+                ImeTracing.getInstance().triggerClientDump(
+                        TAG + "#getSelectedText", mParentInputMethodManager, icProto);
+            }
+            return result;
         });
     }
 
     @Override
     public void getSurroundingText(int beforeLength, int afterLength, int flags,
             AndroidFuture future /* T=SurroundingText */) {
-        dispatch(future, () -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getSurroundingText");
-            try {
-                final InputConnection ic = getInputConnection();
-                final SurroundingText result;
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "getSurroundingText on inactive InputConnection");
-                    result = null;
-                } else {
-                    result = ic.getSurroundingText(beforeLength, afterLength, flags);
-                }
-                if (ImeTracing.getInstance().isEnabled()) {
-                    final byte[] icProto = InputConnectionProtoDumper.buildGetSurroundingTextProto(
-                            beforeLength, afterLength, flags, result);
-                    ImeTracing.getInstance().triggerClientDump(
-                            TAG + "#getSurroundingText", mParentInputMethodManager, icProto);
-                }
-                return result;
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("getSurroundingText", future, () -> {
+            final InputConnection ic = getInputConnection();
+            final SurroundingText result;
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "getSurroundingText on inactive InputConnection");
+                result = null;
+            } else {
+                result = ic.getSurroundingText(beforeLength, afterLength, flags);
             }
+            if (ImeTracing.getInstance().isEnabled()) {
+                final byte[] icProto = InputConnectionProtoDumper.buildGetSurroundingTextProto(
+                        beforeLength, afterLength, flags, result);
+                ImeTracing.getInstance().triggerClientDump(
+                        TAG + "#getSurroundingText", mParentInputMethodManager, icProto);
+            }
+            return result;
         });
     }
 
     @Override
     public void getCursorCapsMode(int reqModes, AndroidFuture future /* T=Integer */) {
-        dispatch(future, () -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getCursorCapsMode");
-            try {
-                final InputConnection ic = getInputConnection();
-                final int result;
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "getCursorCapsMode on inactive InputConnection");
-                    result = 0;
-                } else {
-                    result = ic.getCursorCapsMode(reqModes);
-                }
-                if (ImeTracing.getInstance().isEnabled()) {
-                    final byte[] icProto = InputConnectionProtoDumper.buildGetCursorCapsModeProto(
-                            reqModes, result);
-                    ImeTracing.getInstance().triggerClientDump(
-                            TAG + "#getCursorCapsMode", mParentInputMethodManager, icProto);
-                }
-                return result;
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("getCursorCapsMode", future, () -> {
+            final InputConnection ic = getInputConnection();
+            final int result;
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "getCursorCapsMode on inactive InputConnection");
+                result = 0;
+            } else {
+                result = ic.getCursorCapsMode(reqModes);
             }
+            if (ImeTracing.getInstance().isEnabled()) {
+                final byte[] icProto = InputConnectionProtoDumper.buildGetCursorCapsModeProto(
+                        reqModes, result);
+                ImeTracing.getInstance().triggerClientDump(
+                        TAG + "#getCursorCapsMode", mParentInputMethodManager, icProto);
+            }
+            return result;
         });
     }
 
     @Override
     public void getExtractedText(ExtractedTextRequest request, int flags,
             AndroidFuture future /* T=ExtractedText */) {
-        dispatch(future, () -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getExtractedText");
-            try {
-                final InputConnection ic = getInputConnection();
-                final ExtractedText result;
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "getExtractedText on inactive InputConnection");
-                    result = null;
-                } else {
-                    result = ic.getExtractedText(request, flags);
-                }
-                if (ImeTracing.getInstance().isEnabled()) {
-                    final byte[] icProto = InputConnectionProtoDumper.buildGetExtractedTextProto(
-                            request, flags, result);
-                    ImeTracing.getInstance().triggerClientDump(
-                            TAG + "#getExtractedText", mParentInputMethodManager, icProto);
-                }
-                return result;
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("getExtractedText", future, () -> {
+            final InputConnection ic = getInputConnection();
+            final ExtractedText result;
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "getExtractedText on inactive InputConnection");
+                result = null;
+            } else {
+                result = ic.getExtractedText(request, flags);
             }
+            if (ImeTracing.getInstance().isEnabled()) {
+                final byte[] icProto = InputConnectionProtoDumper.buildGetExtractedTextProto(
+                        request, flags, result);
+                ImeTracing.getInstance().triggerClientDump(
+                        TAG + "#getExtractedText", mParentInputMethodManager, icProto);
+            }
+            return result;
         });
     }
 
     @Override
     public void commitText(CharSequence text, int newCursorPosition) {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitText");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "commitText on inactive InputConnection");
-                    return;
-                }
-                ic.commitText(text, newCursorPosition);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("commitText", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "commitText on inactive InputConnection");
+                return;
             }
+            ic.commitText(text, newCursorPosition);
         });
     }
 
     @Override
     public void commitCompletion(CompletionInfo text) {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitCompletion");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "commitCompletion on inactive InputConnection");
-                    return;
-                }
-                ic.commitCompletion(text);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("commitCompletion", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "commitCompletion on inactive InputConnection");
+                return;
             }
+            ic.commitCompletion(text);
         });
     }
 
     @Override
     public void commitCorrection(CorrectionInfo info) {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitCorrection");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "commitCorrection on inactive InputConnection");
-                    return;
-                }
-                ic.commitCorrection(info);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("commitCorrection", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "commitCorrection on inactive InputConnection");
+                return;
             }
+            ic.commitCorrection(info);
         });
     }
 
     @Override
     public void setSelection(int start, int end) {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#setSelection");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "setSelection on inactive InputConnection");
-                    return;
-                }
-                ic.setSelection(start, end);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("setSelection", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "setSelection on inactive InputConnection");
+                return;
             }
+            ic.setSelection(start, end);
         });
     }
 
     @Override
     public void performEditorAction(int id) {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performEditorAction");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "performEditorAction on inactive InputConnection");
-                    return;
-                }
-                ic.performEditorAction(id);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("performEditorAction", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "performEditorAction on inactive InputConnection");
+                return;
             }
+            ic.performEditorAction(id);
         });
     }
 
     @Override
     public void performContextMenuAction(int id) {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performContextMenuAction");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "performContextMenuAction on inactive InputConnection");
-                    return;
-                }
-                ic.performContextMenuAction(id);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("performContextMenuAction", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "performContextMenuAction on inactive InputConnection");
+                return;
             }
+            ic.performContextMenuAction(id);
         });
     }
 
     @Override
     public void setComposingRegion(int start, int end) {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#setComposingRegion");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "setComposingRegion on inactive InputConnection");
-                    return;
-                }
-                ic.setComposingRegion(start, end);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("setComposingRegion", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "setComposingRegion on inactive InputConnection");
+                return;
             }
+            ic.setComposingRegion(start, end);
         });
     }
 
     @Override
     public void setComposingText(CharSequence text, int newCursorPosition) {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#setComposingText");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "setComposingText on inactive InputConnection");
-                    return;
-                }
-                ic.setComposingText(text, newCursorPosition);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("setComposingText", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "setComposingText on inactive InputConnection");
+                return;
             }
+            ic.setComposingText(text, newCursorPosition);
         });
     }
 
     @Override
     public void finishComposingText() {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#finishComposingText");
-            try {
-                if (isFinished()) {
-                    // In this case, #finishComposingText() is guaranteed to be called already.
-                    // There should be no negative impact if we ignore this call silently.
-                    if (DEBUG) {
-                        Log.w(TAG, "Bug 35301295: Redundant finishComposingText.");
-                    }
-                    return;
+        dispatchWithTracing("finishComposingText", () -> {
+            if (isFinished()) {
+                // In this case, #finishComposingText() is guaranteed to be called already.
+                // There should be no negative impact if we ignore this call silently.
+                if (DEBUG) {
+                    Log.w(TAG, "Bug 35301295: Redundant finishComposingText.");
                 }
-                InputConnection ic = getInputConnection();
-                // Note we do NOT check isActive() here, because this is safe
-                // for an IME to call at any time, and we need to allow it
-                // through to clean up our state after the IME has switched to
-                // another client.
-                if (ic == null) {
-                    Log.w(TAG, "finishComposingText on inactive InputConnection");
-                    return;
-                }
-                ic.finishComposingText();
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+                return;
             }
+            InputConnection ic = getInputConnection();
+            // Note we do NOT check isActive() here, because this is safe
+            // for an IME to call at any time, and we need to allow it
+            // through to clean up our state after the IME has switched to
+            // another client.
+            if (ic == null) {
+                Log.w(TAG, "finishComposingText on inactive InputConnection");
+                return;
+            }
+            ic.finishComposingText();
         });
     }
 
     @Override
     public void sendKeyEvent(KeyEvent event) {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#sendKeyEvent");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "sendKeyEvent on inactive InputConnection");
-                    return;
-                }
-                ic.sendKeyEvent(event);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("sendKeyEvent", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "sendKeyEvent on inactive InputConnection");
+                return;
             }
+            ic.sendKeyEvent(event);
         });
     }
 
     @Override
     public void clearMetaKeyStates(int states) {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#clearMetaKeyStates");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "clearMetaKeyStates on inactive InputConnection");
-                    return;
-                }
-                ic.clearMetaKeyStates(states);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("clearMetaKeyStates", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "clearMetaKeyStates on inactive InputConnection");
+                return;
             }
+            ic.clearMetaKeyStates(states);
         });
     }
 
     @Override
     public void deleteSurroundingText(int beforeLength, int afterLength) {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#deleteSurroundingText");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "deleteSurroundingText on inactive InputConnection");
-                    return;
-                }
-                ic.deleteSurroundingText(beforeLength, afterLength);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("deleteSurroundingText", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "deleteSurroundingText on inactive InputConnection");
+                return;
             }
+            ic.deleteSurroundingText(beforeLength, afterLength);
         });
     }
 
     @Override
     public void deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT,
-                    "InputConnection#deleteSurroundingTextInCodePoints");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "deleteSurroundingTextInCodePoints on inactive InputConnection");
-                    return;
-                }
-                ic.deleteSurroundingTextInCodePoints(beforeLength, afterLength);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("deleteSurroundingTextInCodePoints", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "deleteSurroundingTextInCodePoints on inactive InputConnection");
+                return;
             }
+            ic.deleteSurroundingTextInCodePoints(beforeLength, afterLength);
         });
     }
 
     @Override
     public void beginBatchEdit() {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#beginBatchEdit");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "beginBatchEdit on inactive InputConnection");
-                    return;
-                }
-                ic.beginBatchEdit();
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("beginBatchEdit", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "beginBatchEdit on inactive InputConnection");
+                return;
             }
+            ic.beginBatchEdit();
         });
     }
 
     @Override
     public void endBatchEdit() {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#endBatchEdit");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "endBatchEdit on inactive InputConnection");
-                    return;
-                }
-                ic.endBatchEdit();
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("endBatchEdit", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "endBatchEdit on inactive InputConnection");
+                return;
             }
+            ic.endBatchEdit();
         });
     }
 
     @Override
     public void performSpellCheck() {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performSpellCheck");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "performSpellCheck on inactive InputConnection");
-                    return;
-                }
-                ic.performSpellCheck();
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("performSpellCheck", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "performSpellCheck on inactive InputConnection");
+                return;
             }
+            ic.performSpellCheck();
         });
     }
 
     @Override
     public void performPrivateCommand(String action, Bundle data) {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performPrivateCommand");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "performPrivateCommand on inactive InputConnection");
-                    return;
-                }
-                ic.performPrivateCommand(action, data);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("performPrivateCommand", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "performPrivateCommand on inactive InputConnection");
+                return;
             }
+            ic.performPrivateCommand(action, data);
         });
     }
 
     @Override
     public void requestCursorUpdates(int cursorUpdateMode, AndroidFuture future /* T=Boolean */) {
-        dispatch(future, () -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#requestCursorUpdates");
-            try {
-                final InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection");
-                    return false;
-                }
-                return ic.requestCursorUpdates(cursorUpdateMode);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("requestCursorUpdates", future, () -> {
+            final InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection");
+                return false;
             }
+            return ic.requestCursorUpdates(cursorUpdateMode);
         });
     }
 
     @Override
     public void commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts,
             AndroidFuture future /* T=Boolean */) {
-        dispatch(future, () -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitContent");
-            try {
-                final InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "commitContent on inactive InputConnection");
-                    return false;
-                }
-                if (inputContentInfo == null || !inputContentInfo.validate()) {
-                    Log.w(TAG, "commitContent with invalid inputContentInfo=" + inputContentInfo);
-                    return false;
-                }
-                return ic.commitContent(inputContentInfo, flags, opts);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("commitContent", future, () -> {
+            final InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "commitContent on inactive InputConnection");
+                return false;
             }
+            if (inputContentInfo == null || !inputContentInfo.validate()) {
+                Log.w(TAG, "commitContent with invalid inputContentInfo=" + inputContentInfo);
+                return false;
+            }
+            return ic.commitContent(inputContentInfo, flags, opts);
         });
     }
 
     @Override
     public void setImeConsumesInput(boolean imeConsumesInput) {
-        dispatch(() -> {
-            Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#setImeConsumesInput");
-            try {
-                InputConnection ic = getInputConnection();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "setImeConsumesInput on inactive InputConnection");
-                    return;
-                }
-                ic.setImeConsumesInput(imeConsumesInput);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+        dispatchWithTracing("setImeConsumesInput", () -> {
+            InputConnection ic = getInputConnection();
+            if (ic == null || !isActive()) {
+                Log.w(TAG, "setImeConsumesInput on inactive InputConnection");
+                return;
             }
+            ic.setImeConsumesInput(imeConsumesInput);
         });
     }
 
@@ -749,10 +618,29 @@
         mH.post(runnable);
     }
 
-    private <T> void dispatch(@NonNull AndroidFuture untypedFuture, @NonNull Supplier<T> supplier) {
+    private void dispatchWithTracing(@NonNull String methodName, @NonNull Runnable runnable) {
+        final Runnable actualRunnable;
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_INPUT)) {
+            actualRunnable = () -> {
+                Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#" + methodName);
+                try {
+                    runnable.run();
+                } finally {
+                    Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+                }
+            };
+        } else {
+            actualRunnable = runnable;
+        }
+
+        dispatch(actualRunnable);
+    }
+
+    private <T> void dispatchWithTracing(@NonNull String methodName,
+            @NonNull AndroidFuture untypedFuture, @NonNull Supplier<T> supplier) {
         @SuppressWarnings("unchecked")
         final AndroidFuture<T> future = untypedFuture;
-        dispatch(() -> {
+        dispatchWithTracing(methodName, () -> {
             final T result;
             try {
                 result = supplier.get();
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index aa7142e..c863292 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -51,6 +51,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.TimeUnit;
 
 /**
  * A class that allows the app to get the frame metrics from HardwareRendererObserver.
@@ -108,6 +109,7 @@
     private boolean mCancelled = false;
     private FrameTrackerListener mListener;
     private boolean mTracingStarted = false;
+    private Runnable mWaitForFinishTimedOut;
 
     private static class JankInfo {
         long frameVsyncId;
@@ -174,52 +176,51 @@
             // If the surface isn't valid yet, wait until it's created.
             if (mViewRoot.getSurfaceControl().isValid()) {
                 mSurfaceControl = mViewRoot.getSurfaceControl();
-                mSurfaceChangedCallback = null;
-            } else {
-                mSurfaceChangedCallback = new ViewRootImpl.SurfaceChangedCallback() {
-                    @Override
-                    public void surfaceCreated(SurfaceControl.Transaction t) {
-                        synchronized (FrameTracker.this) {
-                            if (mSurfaceControl == null) {
-                                mSurfaceControl = mViewRoot.getSurfaceControl();
-                                if (mBeginVsyncId != INVALID_ID) {
-                                    mSurfaceControlWrapper.addJankStatsListener(
-                                            FrameTracker.this, mSurfaceControl);
-                                    postTraceStartMarker();
-                                }
+            }
+
+            mSurfaceChangedCallback = new ViewRootImpl.SurfaceChangedCallback() {
+                @Override
+                public void surfaceCreated(SurfaceControl.Transaction t) {
+                    synchronized (FrameTracker.this) {
+                        if (mSurfaceControl == null) {
+                            mSurfaceControl = mViewRoot.getSurfaceControl();
+                            if (mBeginVsyncId != INVALID_ID) {
+                                mSurfaceControlWrapper.addJankStatsListener(
+                                        FrameTracker.this, mSurfaceControl);
+                                postTraceStartMarker();
                             }
                         }
                     }
+                }
 
-                    @Override
-                    public void surfaceReplaced(SurfaceControl.Transaction t) {
-                    }
+                @Override
+                public void surfaceReplaced(SurfaceControl.Transaction t) {
+                }
 
-                    @Override
-                    public void surfaceDestroyed() {
+                @Override
+                public void surfaceDestroyed() {
 
-                        // Wait a while to give the system a chance for the remaining
-                        // frames to arrive, then force finish the session.
-                        mHandler.postDelayed(() -> {
-                            synchronized (FrameTracker.this) {
-                                if (DEBUG) {
-                                    Log.d(TAG, "surfaceDestroyed: " + mSession.getName()
-                                            + ", finalized=" + mMetricsFinalized
-                                            + ", info=" + mJankInfos.size()
-                                            + ", vsync=" + mBeginVsyncId + "-" + mEndVsyncId);
-                                }
-                                if (!mMetricsFinalized) {
-                                    end(REASON_END_SURFACE_DESTROYED);
-                                    finish(mJankInfos.size() - 1);
-                                }
+                    // Wait a while to give the system a chance for the remaining
+                    // frames to arrive, then force finish the session.
+                    mHandler.postDelayed(() -> {
+                        synchronized (FrameTracker.this) {
+                            if (DEBUG) {
+                                Log.d(TAG, "surfaceDestroyed: " + mSession.getName()
+                                        + ", finalized=" + mMetricsFinalized
+                                        + ", info=" + mJankInfos.size()
+                                        + ", vsync=" + mBeginVsyncId + "-" + mEndVsyncId);
                             }
-                        }, 50);
-                    }
-                };
-                // This callback has a reference to FrameTracker,
-                // remember to remove it to avoid leakage.
-                mViewRoot.addSurfaceChangedCallback(mSurfaceChangedCallback);
-            }
+                            if (!mMetricsFinalized) {
+                                end(REASON_END_SURFACE_DESTROYED);
+                                finish(mJankInfos.size() - 1);
+                            }
+                        }
+                    }, 50);
+                }
+            };
+            // This callback has a reference to FrameTracker,
+            // remember to remove it to avoid leakage.
+            mViewRoot.addSurfaceChangedCallback(mSurfaceChangedCallback);
         }
     }
 
@@ -283,10 +284,17 @@
             if (mListener != null) {
                 mListener.onCujEvents(mSession, ACTION_SESSION_END);
             }
+
+            // We don't remove observer here,
+            // will remove it when all the frame metrics in this duration are called back.
+            // See onFrameMetricsAvailable for the logic of removing the observer.
+            // Waiting at most 10 seconds for all callbacks to finish.
+            mWaitForFinishTimedOut = () -> {
+                Log.e(TAG, "force finish cuj because of time out:" + mSession.getName());
+                finish(mJankInfos.size() - 1);
+            };
+            mHandler.postDelayed(mWaitForFinishTimedOut, TimeUnit.SECONDS.toMillis(10));
         }
-        // We don't remove observer here,
-        // will remove it when all the frame metrics in this duration are called back.
-        // See onFrameMetricsAvailable for the logic of removing the observer.
     }
 
     /**
@@ -423,7 +431,8 @@
     }
 
     private void finish(int indexOnOrAfterEnd) {
-
+        mHandler.removeCallbacks(mWaitForFinishTimedOut);
+        mWaitForFinishTimedOut = null;
         mMetricsFinalized = true;
 
         // The tracing has been ended, remove the observer, see if need to trigger perfetto.
@@ -509,7 +518,7 @@
             }
         }
         if (DEBUG) {
-            Log.i(TAG, "FrameTracker: CUJ=" + mSession.getName()
+            Log.i(TAG, "finish: CUJ=" + mSession.getName()
                     + " (" + mBeginVsyncId + "," + mEndVsyncId + ")"
                     + " totalFrames=" + totalFramesCount
                     + " missedAppFrames=" + missedAppFramesCount
diff --git a/core/java/com/android/internal/os/OWNERS b/core/java/com/android/internal/os/OWNERS
index ea3b3a7..7766b77 100644
--- a/core/java/com/android/internal/os/OWNERS
+++ b/core/java/com/android/internal/os/OWNERS
@@ -10,4 +10,6 @@
 per-file *ChargeCalculator* = file:/BATTERY_STATS_OWNERS
 per-file *PowerCalculator* = file:/BATTERY_STATS_OWNERS
 per-file *PowerEstimator* = file:/BATTERY_STATS_OWNERS
+per-file *Kernel* = file:/BATTERY_STATS_OWNERS
+per-file *MultiState* = file:/BATTERY_STATS_OWNERS
 
diff --git a/core/java/com/android/internal/policy/ScreenDecorationsUtils.java b/core/java/com/android/internal/policy/ScreenDecorationsUtils.java
index 52172cf..ec62839 100644
--- a/core/java/com/android/internal/policy/ScreenDecorationsUtils.java
+++ b/core/java/com/android/internal/policy/ScreenDecorationsUtils.java
@@ -16,7 +16,9 @@
 
 package com.android.internal.policy;
 
+import android.content.Context;
 import android.content.res.Resources;
+import android.view.RoundedCorners;
 
 import com.android.internal.R;
 
@@ -29,23 +31,28 @@
      * Corner radius that should be used on windows in order to cover the display.
      * These values are expressed in pixels because they should not respect display or font
      * scaling, this means that we don't have to reload them on config changes.
+     *
+     * Note that if the context is not an UI context(not associated with Display), it will use
+     * default display.
      */
-    public static float getWindowCornerRadius(Resources resources) {
+    public static float getWindowCornerRadius(Context context) {
+        final Resources resources = context.getResources();
         if (!supportsRoundedCornersOnWindows(resources)) {
             return 0f;
         }
-
+        // Use Context#getDisplayNoVerify() in case the context is not an UI context.
+        final String displayUniqueId = context.getDisplayNoVerify().getUniqueId();
         // Radius that should be used in case top or bottom aren't defined.
-        float defaultRadius = resources.getDimension(R.dimen.rounded_corner_radius)
-                - resources.getDimension(R.dimen.rounded_corner_radius_adjustment);
+        float defaultRadius = RoundedCorners.getRoundedCornerRadius(resources, displayUniqueId)
+                - RoundedCorners.getRoundedCornerRadiusAdjustment(resources, displayUniqueId);
 
-        float topRadius = resources.getDimension(R.dimen.rounded_corner_radius_top)
-                - resources.getDimension(R.dimen.rounded_corner_radius_top_adjustment);
+        float topRadius = RoundedCorners.getRoundedCornerTopRadius(resources, displayUniqueId)
+                - RoundedCorners.getRoundedCornerRadiusTopAdjustment(resources, displayUniqueId);
         if (topRadius == 0f) {
             topRadius = defaultRadius;
         }
-        float bottomRadius = resources.getDimension(R.dimen.rounded_corner_radius_bottom)
-                - resources.getDimension(R.dimen.rounded_corner_radius_bottom_adjustment);
+        float bottomRadius = RoundedCorners.getRoundedCornerBottomRadius(resources, displayUniqueId)
+                - RoundedCorners.getRoundedCornerRadiusBottomAdjustment(resources, displayUniqueId);
         if (bottomRadius == 0f) {
             bottomRadius = defaultRadius;
         }
diff --git a/core/java/com/android/internal/protolog/ProtoLogGroup.java b/core/java/com/android/internal/protolog/ProtoLogGroup.java
index 0f153bc..db019a67 100644
--- a/core/java/com/android/internal/protolog/ProtoLogGroup.java
+++ b/core/java/com/android/internal/protolog/ProtoLogGroup.java
@@ -82,6 +82,8 @@
             Consts.TAG_WM),
     WM_DEBUG_WINDOW_INSETS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
             Consts.TAG_WM),
+    WM_DEBUG_LAYER_MIRRORING(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
+            Consts.TAG_WM),
     TEST_GROUP(true, true, false, "WindowManagerProtoLogTest");
 
     private final boolean mEnabled;
diff --git a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java b/core/java/com/android/internal/statusbar/IAddTileResultCallback.aidl
similarity index 66%
copy from tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
copy to core/java/com/android/internal/statusbar/IAddTileResultCallback.aidl
index 0e51a6b..7053eef 100644
--- a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
+++ b/core/java/com/android/internal/statusbar/IAddTileResultCallback.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
+/**
+ * Copyright (c) 2021, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     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,
@@ -13,7 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.componentalias.tests.app.s;
 
-public class Target04 extends BaseService {
-}
+package com.android.internal.statusbar;
+
+/** {@hide} */
+oneway interface IAddTileResultCallback {
+    void onTileRequest(int userResponse);
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index b427e8b..0f245e6 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -18,6 +18,7 @@
 
 import android.app.ITransientNotificationCallback;
 import android.content.ComponentName;
+import android.graphics.drawable.Icon;
 import android.graphics.Rect;
 import android.hardware.biometrics.IBiometricSysuiReceiver;
 import android.hardware.biometrics.PromptInfo;
@@ -27,6 +28,7 @@
 import android.service.notification.StatusBarNotification;
 import android.view.InsetsVisibilities;
 
+import com.android.internal.statusbar.IAddTileResultCallback;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.view.AppearanceRegion;
 
@@ -286,4 +288,6 @@
      * Triggers a GC in the system and status bar.
      */
     void runGcForTest();
+
+    void requestAddTile(in ComponentName componentName, in CharSequence appName, in CharSequence label, in Icon icon, in IAddTileResultCallback callback);
 }
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index b3499db..92031b4 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -18,6 +18,7 @@
 
 import android.app.Notification;
 import android.content.ComponentName;
+import android.graphics.drawable.Icon;
 import android.graphics.Rect;
 import android.hardware.biometrics.IBiometricSysuiReceiver;
 import android.hardware.biometrics.PromptInfo;
@@ -27,6 +28,7 @@
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
 
+import com.android.internal.statusbar.IAddTileResultCallback;
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.RegisterStatusBarResult;
 import com.android.internal.statusbar.StatusBarIcon;
@@ -157,4 +159,6 @@
      * display.
      */
     void suppressAmbientDisplay(boolean suppress);
+
+    int requestAddTile(in ComponentName componentName, in CharSequence label, in Icon icon, int userId, in IAddTileResultCallback callback);
 }
diff --git a/core/java/com/android/internal/util/IState.java b/core/java/com/android/internal/util/IState.java
index 07837bf..41b3d5e 100644
--- a/core/java/com/android/internal/util/IState.java
+++ b/core/java/com/android/internal/util/IState.java
@@ -27,12 +27,12 @@
 public interface IState {
 
     /**
-     * Returned by processMessage to indicate the the message was processed.
+     * Returned by processMessage to indicate the message was processed.
      */
     static final boolean HANDLED = true;
 
     /**
-     * Returned by processMessage to indicate the the message was NOT processed.
+     * Returned by processMessage to indicate the message was NOT processed.
      */
     static final boolean NOT_HANDLED = false;
 
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index 4cff785..cb8d9d1 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -48,7 +48,7 @@
  * in Object Oriented programming and are used to perform initialization and
  * cleanup of the state respectively. The <code>getName</code> method returns the
  * name of the state; the default implementation returns the class name. It may be
- * desirable to have <code>getName</code> return the the state instance name instead,
+ * desirable to have <code>getName</code> return the state instance name instead,
  * in particular if a particular state class has multiple instances.</p>
  *
  * <p>When a state machine is created, <code>addState</code> is used to build the
@@ -433,14 +433,14 @@
 
     /**
      * Convenience constant that maybe returned by processMessage
-     * to indicate the the message was processed and is not to be
+     * to indicate the message was processed and is not to be
      * processed by parent states
      */
     public static final boolean HANDLED = true;
 
     /**
      * Convenience constant that maybe returned by processMessage
-     * to indicate the the message was NOT processed and is to be
+     * to indicate the message was NOT processed and is to be
      * processed by parent states
      */
     public static final boolean NOT_HANDLED = false;
diff --git a/core/java/com/android/internal/view/ScrollCaptureInternal.java b/core/java/com/android/internal/view/ScrollCaptureInternal.java
index e3a9fda..72b5488 100644
--- a/core/java/com/android/internal/view/ScrollCaptureInternal.java
+++ b/core/java/com/android/internal/view/ScrollCaptureInternal.java
@@ -25,6 +25,7 @@
 import android.view.ScrollCaptureCallback;
 import android.view.View;
 import android.view.ViewGroup;
+import android.webkit.WebView;
 import android.widget.ListView;
 
 /**
@@ -43,7 +44,7 @@
     private static final int DOWN = 1;
 
     /**
-     * Not a ViewGroup, or cannot scroll according to View APIs.
+     * Cannot scroll according to {@link View#canScrollVertically}.
      */
     public static final int TYPE_FIXED = 0;
 
@@ -60,7 +61,7 @@
     public static final int TYPE_RECYCLING = 2;
 
     /**
-     * The ViewGroup scrolls, but has no child views in
+     * Unknown scrollable view with no child views (or not a subclass of ViewGroup).
      */
     private static final int TYPE_OPAQUE = 3;
 
@@ -73,16 +74,6 @@
      * as excluded during scroll capture search.
      */
     private static int detectScrollingType(View view) {
-        // Must be a ViewGroup
-        if (!(view instanceof ViewGroup)) {
-            if (DEBUG_VERBOSE) {
-                Log.v(TAG, "hint: not a subclass of ViewGroup");
-            }
-            return TYPE_FIXED;
-        }
-        if (DEBUG_VERBOSE) {
-            Log.v(TAG, "hint: is a subclass of ViewGroup");
-        }
         // Confirm that it can scroll.
         if (!(view.canScrollVertically(DOWN) || view.canScrollVertically(UP))) {
             // Nothing to scroll here, move along.
@@ -94,6 +85,17 @@
         if (DEBUG_VERBOSE) {
             Log.v(TAG, "hint: can be scrolled up or down");
         }
+        // Must be a ViewGroup
+        if (!(view instanceof ViewGroup)) {
+            if (DEBUG_VERBOSE) {
+                Log.v(TAG, "hint: not a subclass of ViewGroup");
+            }
+            return TYPE_OPAQUE;
+        }
+        if (DEBUG_VERBOSE) {
+            Log.v(TAG, "hint: is a subclass of ViewGroup");
+        }
+
         // ScrollViews accept only a single child.
         if (((ViewGroup) view).getChildCount() > 1) {
             if (DEBUG_VERBOSE) {
@@ -188,6 +190,18 @@
                 }
                 return new ScrollCaptureViewSupport<>((ViewGroup) view,
                         new RecyclerViewCaptureHelper());
+            case TYPE_OPAQUE:
+                if (DEBUG) {
+                    Log.d(TAG, "scroll capture: FOUND " + view.getClass().getName()
+                            + "[" + resolveId(view.getContext(), view.getId()) + "]"
+                            + " -> TYPE_OPAQUE");
+                }
+                if (view instanceof WebView) {
+                    Log.d(TAG, "scroll capture: Using WebView support");
+                    return new ScrollCaptureViewSupport<>((WebView) view,
+                            new WebViewCaptureHelper());
+                }
+                break;
             case TYPE_FIXED:
                 // ignore
                 break;
diff --git a/core/java/com/android/internal/view/WebViewCaptureHelper.java b/core/java/com/android/internal/view/WebViewCaptureHelper.java
new file mode 100644
index 0000000..e6a311c
--- /dev/null
+++ b/core/java/com/android/internal/view/WebViewCaptureHelper.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view;
+
+import static android.util.MathUtils.constrain;
+
+import static java.lang.Math.max;
+import static java.lang.Math.min;
+
+import android.annotation.NonNull;
+import android.graphics.Rect;
+import android.webkit.WebView;
+
+/**
+ * ScrollCapture for WebView.
+ */
+class WebViewCaptureHelper implements ScrollCaptureViewHelper<WebView> {
+    private static final String TAG = "WebViewScrollCapture";
+
+    private final Rect mRequestWebViewLocal = new Rect();
+    private final Rect mWebViewBounds = new Rect();
+
+    private int mOriginScrollY;
+    private int mOriginScrollX;
+
+    @Override
+    public boolean onAcceptSession(@NonNull WebView view) {
+        return view.isVisibleToUser()
+                && (view.getContentHeight() * view.getScale()) > view.getHeight();
+    }
+
+    @Override
+    public void onPrepareForStart(@NonNull WebView view, @NonNull Rect scrollBounds) {
+        mOriginScrollX = view.getScrollX();
+        mOriginScrollY = view.getScrollY();
+    }
+
+    @NonNull
+    @Override
+    public ScrollResult onScrollRequested(@NonNull WebView view, @NonNull Rect scrollBounds,
+            @NonNull Rect requestRect) {
+
+        int scrollDelta = view.getScrollY() - mOriginScrollY;
+
+        ScrollResult result = new ScrollResult();
+        result.requestedArea = new Rect(requestRect);
+        result.availableArea = new Rect();
+        result.scrollDelta = scrollDelta;
+
+        mWebViewBounds.set(0, 0, view.getWidth(), view.getHeight());
+
+        if (!view.isVisibleToUser()) {
+            return result;
+        }
+
+        // Map the request into local coordinates
+        mRequestWebViewLocal.set(requestRect);
+        mRequestWebViewLocal.offset(0, -scrollDelta);
+
+        // Offset to center the rect vertically, clamp to available content
+        int upLimit = min(0, -view.getScrollY());
+        int contentHeightPx = (int) (view.getContentHeight() * view.getScale());
+        int downLimit = max(0, (contentHeightPx - view.getHeight()) - view.getScrollY());
+        int scrollToCenter = mRequestWebViewLocal.centerY() - mWebViewBounds.centerY();
+        int scrollMovement = constrain(scrollToCenter, upLimit, downLimit);
+
+        // Scroll and update relative based on  the new position
+        view.scrollBy(mOriginScrollX, scrollMovement);
+        scrollDelta = view.getScrollY() - mOriginScrollY;
+        mRequestWebViewLocal.offset(0, -scrollMovement);
+        result.scrollDelta = scrollDelta;
+
+        if (mRequestWebViewLocal.intersect(mWebViewBounds)) {
+            result.availableArea = new Rect(mRequestWebViewLocal);
+            result.availableArea.offset(0, result.scrollDelta);
+        }
+        return result;
+    }
+
+    @Override
+    public void onPrepareForEnd(@NonNull WebView view) {
+        view.scrollTo(mOriginScrollX, mOriginScrollY);
+    }
+
+}
+
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 3f756d7..3994fbd 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -18,17 +18,22 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
+import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.CanvasProperty;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.RecordingCanvas;
 import android.graphics.Rect;
+import android.graphics.Shader;
 import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
 import android.os.Bundle;
@@ -52,6 +57,7 @@
 import android.view.animation.Interpolator;
 
 import com.android.internal.R;
+import com.android.internal.graphics.ColorUtils;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -70,7 +76,12 @@
     private static final int ASPECT_LOCK_HEIGHT = 2; // Fixed height; width will be minimum of (w,h)
 
     private static final boolean PROFILE_DRAWING = false;
-    private static final float LINE_FADE_ALPHA_MULTIPLIER = 1.5f;
+    private static final int LINE_END_ANIMATION_DURATION_MILLIS = 50;
+    private static final int LINE_FADE_OUT_DURATION_MILLIS = 500;
+    private static final int LINE_FADE_OUT_DELAY_MILLIS = 150;
+    private static final int DOT_ACTIVATION_DURATION_MILLIS = 50;
+    private static final int DOT_RADIUS_INCREASE_DURATION_MILLIS = 96;
+    private static final int DOT_RADIUS_DECREASE_DURATION_MILLIS = 192;
     private final CellState[][] mCellStates;
 
     private final int mDotSize;
@@ -139,6 +150,7 @@
     private float mSquareWidth;
     @UnsupportedAppUsage
     private float mSquareHeight;
+    private final LinearGradient mFadeOutGradientShader;
 
     private final Path mCurrentPath = new Path();
     private final Rect mInvalidate = new Rect();
@@ -149,6 +161,7 @@
     private int mErrorColor;
     private int mSuccessColor;
     private int mDotColor;
+    private int mDotActivatedColor;
 
     private final Interpolator mFastOutSlowInInterpolator;
     private final Interpolator mLinearOutSlowInInterpolator;
@@ -230,9 +243,11 @@
         float radius;
         float translationY;
         float alpha = 1f;
+        float activationAnimationProgress;
         public float lineEndX = Float.MIN_VALUE;
         public float lineEndY = Float.MIN_VALUE;
-        public ValueAnimator lineAnimator;
+        @Nullable
+        Animator activationAnimator;
      }
 
     /**
@@ -320,6 +335,7 @@
         mErrorColor = a.getColor(R.styleable.LockPatternView_errorColor, 0);
         mSuccessColor = a.getColor(R.styleable.LockPatternView_successColor, 0);
         mDotColor = a.getColor(R.styleable.LockPatternView_dotColor, mRegularColor);
+        mDotActivatedColor = a.getColor(R.styleable.LockPatternView_dotActivatedColor, mDotColor);
 
         int pathColor = a.getColor(R.styleable.LockPatternView_pathColor, mRegularColor);
         mPathPaint.setColor(pathColor);
@@ -361,6 +377,14 @@
         mExploreByTouchHelper = new PatternExploreByTouchHelper(this);
         setAccessibilityDelegate(mExploreByTouchHelper);
         mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+
+        int fadeAwayGradientWidth = getResources().getDimensionPixelSize(
+                R.dimen.lock_pattern_fade_away_gradient_width);
+        // Set up gradient shader with the middle in point (0, 0).
+        mFadeOutGradientShader = new LinearGradient(/* x0= */ -fadeAwayGradientWidth / 2f,
+                /* y0= */ 0,/* x1= */ fadeAwayGradientWidth / 2f, /* y1= */ 0,
+                Color.TRANSPARENT, pathColor, Shader.TileMode.CLAMP);
+
         a.recycle();
     }
 
@@ -780,64 +804,111 @@
 
     private void startCellActivatedAnimation(Cell cell) {
         final CellState cellState = mCellStates[cell.row][cell.column];
-        startRadiusAnimation(mDotSize/2, mDotSizeActivated/2, 96, mLinearOutSlowInInterpolator,
-                cellState, new Runnable() {
-                    @Override
-                    public void run() {
-                        startRadiusAnimation(mDotSizeActivated/2, mDotSize/2, 192,
-                                mFastOutSlowInInterpolator,
-                                cellState, null);
-                    }
-                });
-        startLineEndAnimation(cellState, mInProgressX, mInProgressY,
-                getCenterXForColumn(cell.column), getCenterYForRow(cell.row));
-    }
 
-    private void startLineEndAnimation(final CellState state,
-            final float startX, final float startY, final float targetX, final float targetY) {
-        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
-        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                float t = (float) animation.getAnimatedValue();
-                state.lineEndX = (1 - t) * startX + t * targetX;
-                state.lineEndY = (1 - t) * startY + t * targetY;
-                invalidate();
-            }
-        });
-        valueAnimator.addListener(new AnimatorListenerAdapter() {
+        if (cellState.activationAnimator != null) {
+            cellState.activationAnimator.cancel();
+        }
+        AnimatorSet animatorSet = new AnimatorSet();
+        AnimatorSet.Builder animatorSetBuilder = animatorSet
+                .play(createLineDisappearingAnimation())
+                .with(createLineEndAnimation(cellState, mInProgressX, mInProgressY,
+                        getCenterXForColumn(cell.column), getCenterYForRow(cell.row)));
+        if (mDotSize != mDotSizeActivated) {
+            animatorSetBuilder.with(createDotRadiusAnimation(cellState));
+        }
+        if (mDotColor != mDotActivatedColor) {
+            animatorSetBuilder.with(createDotActivationColorAnimation(cellState));
+        }
+
+        animatorSet.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                state.lineAnimator = null;
-            }
-        });
-        valueAnimator.setInterpolator(mFastOutSlowInInterpolator);
-        valueAnimator.setDuration(100);
-        valueAnimator.start();
-        state.lineAnimator = valueAnimator;
-    }
-
-    private void startRadiusAnimation(float start, float end, long duration,
-            Interpolator interpolator, final CellState state, final Runnable endRunnable) {
-        ValueAnimator valueAnimator = ValueAnimator.ofFloat(start, end);
-        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                state.radius = (float) animation.getAnimatedValue();
+                cellState.activationAnimator = null;
                 invalidate();
             }
         });
-        if (endRunnable != null) {
-            valueAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    endRunnable.run();
-                }
-            });
-        }
-        valueAnimator.setInterpolator(interpolator);
-        valueAnimator.setDuration(duration);
-        valueAnimator.start();
+        cellState.activationAnimator = animatorSet;
+        animatorSet.start();
+    }
+
+    private Animator createDotActivationColorAnimation(CellState cellState) {
+        ValueAnimator.AnimatorUpdateListener updateListener =
+                valueAnimator -> {
+                    cellState.activationAnimationProgress =
+                            (float) valueAnimator.getAnimatedValue();
+                    invalidate();
+                };
+        ValueAnimator activateAnimator = ValueAnimator.ofFloat(0f, 1f);
+        ValueAnimator deactivateAnimator = ValueAnimator.ofFloat(1f, 0f);
+        activateAnimator.addUpdateListener(updateListener);
+        deactivateAnimator.addUpdateListener(updateListener);
+        activateAnimator.setInterpolator(mFastOutSlowInInterpolator);
+        deactivateAnimator.setInterpolator(mLinearOutSlowInInterpolator);
+
+        // Align dot animation duration with line fade out animation.
+        activateAnimator.setDuration(DOT_ACTIVATION_DURATION_MILLIS);
+        deactivateAnimator.setDuration(DOT_ACTIVATION_DURATION_MILLIS);
+        AnimatorSet set = new AnimatorSet();
+        set.play(deactivateAnimator)
+                .after(LINE_FADE_OUT_DELAY_MILLIS + LINE_FADE_OUT_DURATION_MILLIS
+                        - DOT_ACTIVATION_DURATION_MILLIS * 2)
+                .after(activateAnimator);
+        return set;
+    }
+
+    /**
+     * On the last frame before cell activates the end point of in progress line is not aligned
+     * with dot center so we execute a short animation moving the end point to exact dot center.
+     */
+    private Animator createLineEndAnimation(final CellState state,
+            final float startX, final float startY, final float targetX, final float targetY) {
+        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
+        valueAnimator.addUpdateListener(animation -> {
+            float t = (float) animation.getAnimatedValue();
+            state.lineEndX = (1 - t) * startX + t * targetX;
+            state.lineEndY = (1 - t) * startY + t * targetY;
+            invalidate();
+        });
+        valueAnimator.setInterpolator(mFastOutSlowInInterpolator);
+        valueAnimator.setDuration(LINE_END_ANIMATION_DURATION_MILLIS);
+        return valueAnimator;
+    }
+
+    /**
+     * Starts animator to fade out a line segment. It does only invalidate because all the
+     * transitions are applied in {@code onDraw} method.
+     */
+    private Animator createLineDisappearingAnimation() {
+        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
+        valueAnimator.addUpdateListener(animation -> invalidate());
+        valueAnimator.setStartDelay(LINE_FADE_OUT_DELAY_MILLIS);
+        valueAnimator.setDuration(LINE_FADE_OUT_DURATION_MILLIS);
+        return valueAnimator;
+    }
+
+    private Animator createDotRadiusAnimation(CellState state) {
+        float defaultRadius = mDotSize / 2f;
+        float activatedRadius = mDotSizeActivated / 2f;
+
+        ValueAnimator.AnimatorUpdateListener animatorUpdateListener =
+                animation -> {
+                    state.radius = (float) animation.getAnimatedValue();
+                    invalidate();
+                };
+
+        ValueAnimator activationAnimator = ValueAnimator.ofFloat(defaultRadius, activatedRadius);
+        activationAnimator.addUpdateListener(animatorUpdateListener);
+        activationAnimator.setInterpolator(mLinearOutSlowInInterpolator);
+        activationAnimator.setDuration(DOT_RADIUS_INCREASE_DURATION_MILLIS);
+
+        ValueAnimator deactivationAnimator = ValueAnimator.ofFloat(activatedRadius, defaultRadius);
+        deactivationAnimator.addUpdateListener(animatorUpdateListener);
+        deactivationAnimator.setInterpolator(mFastOutSlowInInterpolator);
+        deactivationAnimator.setDuration(DOT_RADIUS_DECREASE_DURATION_MILLIS);
+
+        AnimatorSet set = new AnimatorSet();
+        set.playSequentially(activationAnimator, deactivationAnimator);
+        return set;
     }
 
     // helper method to find which cell a point maps to
@@ -1051,8 +1122,11 @@
         for (int i = 0; i < 3; i++) {
             for (int j = 0; j < 3; j++) {
                 CellState state = mCellStates[i][j];
-                if (state.lineAnimator != null) {
-                    state.lineAnimator.cancel();
+                if (state.activationAnimator != null) {
+                    state.activationAnimator.cancel();
+                    state.activationAnimator = null;
+                    state.radius = mDotSize / 2f;
+                    state.activationAnimationProgress = 0f;
                     state.lineEndX = Float.MIN_VALUE;
                     state.lineEndY = Float.MIN_VALUE;
                 }
@@ -1195,29 +1269,19 @@
                 float centerX = getCenterXForColumn(cell.column);
                 float centerY = getCenterYForRow(cell.row);
                 if (i != 0) {
-                   // Set this line segment to fade away animated.
-                   int lineFadeVal = (int) Math.min((elapsedRealtime -
-                           mLineFadeStart[i]) * LINE_FADE_ALPHA_MULTIPLIER, 255f);
-
                     CellState state = mCellStates[cell.row][cell.column];
                     currentPath.rewind();
-                    currentPath.moveTo(lastX, lastY);
+                    float endX;
+                    float endY;
                     if (state.lineEndX != Float.MIN_VALUE && state.lineEndY != Float.MIN_VALUE) {
-                        currentPath.lineTo(state.lineEndX, state.lineEndY);
-                        if (mFadePattern) {
-                            mPathPaint.setAlpha((int) 255 - lineFadeVal );
-                        } else {
-                            mPathPaint.setAlpha(255);
-                        }
+                        endX = state.lineEndX;
+                        endY = state.lineEndY;
                     } else {
-                        currentPath.lineTo(centerX, centerY);
-                        if (mFadePattern) {
-                            mPathPaint.setAlpha((int) 255 - lineFadeVal );
-                        } else {
-                            mPathPaint.setAlpha(255);
-                        }
+                        endX = centerX;
+                        endY = centerY;
                     }
-                    canvas.drawPath(currentPath, mPathPaint);
+                    drawLineSegment(canvas, /* startX = */ lastX, /* startY = */ lastY, endX, endY,
+                            mLineFadeStart[i], elapsedRealtime);
                 }
                 lastX = centerX;
                 lastY = centerY;
@@ -1253,13 +1317,69 @@
                                 cellState.hwRadius, cellState.hwPaint);
                     } else {
                         drawCircle(canvas, (int) centerX, (int) centerY + translationY,
-                                cellState.radius, drawLookup[i][j], cellState.alpha);
+                                cellState.radius, drawLookup[i][j], cellState.alpha,
+                                cellState.activationAnimationProgress);
                     }
                 }
             }
         }
     }
 
+    private void drawLineSegment(Canvas canvas, float startX, float startY, float endX, float endY,
+            long lineFadeStart, long elapsedRealtime) {
+        float fadeAwayProgress;
+        if (mFadePattern) {
+            if (elapsedRealtime - lineFadeStart
+                    >= LINE_FADE_OUT_DELAY_MILLIS + LINE_FADE_OUT_DURATION_MILLIS) {
+                // Time for this segment animation is out so we don't need to draw it.
+                return;
+            }
+            // Set this line segment to fade away animated.
+            fadeAwayProgress = Math.max(
+                    ((float) (elapsedRealtime - lineFadeStart - LINE_FADE_OUT_DELAY_MILLIS))
+                            / LINE_FADE_OUT_DURATION_MILLIS, 0f);
+            drawFadingAwayLineSegment(canvas, startX, startY, endX, endY, fadeAwayProgress);
+        } else {
+            mPathPaint.setAlpha(255);
+            canvas.drawLine(startX, startY, endX, endY, mPathPaint);
+        }
+    }
+
+    private void drawFadingAwayLineSegment(Canvas canvas, float startX, float startY, float endX,
+            float endY, float fadeAwayProgress) {
+        mPathPaint.setAlpha((int) (255 * (1 - fadeAwayProgress)));
+
+        // To draw gradient segment we use mFadeOutGradientShader which has immutable coordinates
+        // thus we will need to translate and rotate the canvas.
+        mPathPaint.setShader(mFadeOutGradientShader);
+        canvas.save();
+
+        // First translate canvas to gradient middle point.
+        float gradientMidX = endX * fadeAwayProgress + startX * (1 - fadeAwayProgress);
+        float gradientMidY = endY * fadeAwayProgress + startY * (1 - fadeAwayProgress);
+        canvas.translate(gradientMidX, gradientMidY);
+
+        // Then rotate it to the direction of the segment.
+        double segmentAngleRad = Math.atan((endY - startY) / (endX - startX));
+        float segmentAngleDegrees = (float) Math.toDegrees(segmentAngleRad);
+        if (endX - startX < 0) {
+            // Arc tangent gives us angle degrees [-90; 90] thus to cover [90; 270] degrees we
+            // need this hack.
+            segmentAngleDegrees += 180f;
+        }
+        canvas.rotate(segmentAngleDegrees);
+
+        // Pythagoras theorem.
+        float segmentLength = (float) Math.hypot(endX - startX, endY - startY);
+
+        // Draw the segment in coordinates aligned with shader coordinates.
+        canvas.drawLine(/* startX= */ -segmentLength * fadeAwayProgress, /* startY= */
+                0,/* stopX= */ segmentLength * (1 - fadeAwayProgress), /* stopY= */ 0, mPathPaint);
+
+        canvas.restore();
+        mPathPaint.setShader(null);
+    }
+
     private float calculateLastSegmentAlpha(float x, float y, float lastX, float lastY) {
         float diffX = x - lastX;
         float diffY = y - lastY;
@@ -1298,8 +1418,14 @@
      * @param partOfPattern Whether this circle is part of the pattern.
      */
     private void drawCircle(Canvas canvas, float centerX, float centerY, float radius,
-            boolean partOfPattern, float alpha) {
-        mPaint.setColor(getDotColor());
+            boolean partOfPattern, float alpha, float activationAnimationProgress) {
+        if (mFadePattern && !mInStealthMode) {
+            int resultColor = ColorUtils.blendARGB(mDotColor, mDotActivatedColor,
+                    /* ratio= */ activationAnimationProgress);
+            mPaint.setColor(resultColor);
+        } else {
+            mPaint.setColor(getDotColor());
+        }
         mPaint.setAlpha((int) (alpha * 255));
         canvas.drawCircle(centerX, centerY, radius, mPaint);
     }
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 4bee976..6cea8bf 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -76,3 +76,7 @@
 # VINTF
 per-file android_os_VintfObject* = file:platform/system/libvintf:/OWNERS
 per-file android_os_VintfRuntimeInfo* = file:platform/system/libvintf:/OWNERS
+
+# Battery
+per-file com_android_internal_os_Kernel* = file:/BATTERY_STATS_OWNERS
+per-file com_android_internal_os_*MultiStateCounter* = file:/BATTERY_STATS_OWNERS
diff --git a/core/jni/android_database_SQLiteConnection.cpp b/core/jni/android_database_SQLiteConnection.cpp
index c80f1dc..32697ae 100644
--- a/core/jni/android_database_SQLiteConnection.cpp
+++ b/core/jni/android_database_SQLiteConnection.cpp
@@ -518,23 +518,29 @@
     }
 }
 
-static int executeNonQuery(JNIEnv* env, SQLiteConnection* connection, sqlite3_stmt* statement) {
-    int err = sqlite3_step(statement);
-    if (err == SQLITE_ROW) {
+static int executeNonQuery(JNIEnv* env, SQLiteConnection* connection, sqlite3_stmt* statement,
+        bool isPragmaStmt) {
+    int rc = sqlite3_step(statement);
+    if (isPragmaStmt) {
+        while (rc == SQLITE_ROW) {
+            rc = sqlite3_step(statement);
+        }
+    }
+    if (rc == SQLITE_ROW) {
         throw_sqlite3_exception(env,
                 "Queries can be performed using SQLiteDatabase query or rawQuery methods only.");
-    } else if (err != SQLITE_DONE) {
+    } else if (rc != SQLITE_DONE) {
         throw_sqlite3_exception(env, connection->db);
     }
-    return err;
+    return rc;
 }
 
-static void nativeExecute(JNIEnv* env, jclass clazz, jlong connectionPtr,
-        jlong statementPtr) {
+static void nativeExecute(JNIEnv* env, jclass clazz, jlong connectionPtr, jlong statementPtr,
+        jboolean isPragmaStmt) {
     SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
     sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
 
-    executeNonQuery(env, connection, statement);
+    executeNonQuery(env, connection, statement, isPragmaStmt);
 }
 
 static jint nativeExecuteForChangedRowCount(JNIEnv* env, jclass clazz,
@@ -542,7 +548,7 @@
     SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
     sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
 
-    int err = executeNonQuery(env, connection, statement);
+    int err = executeNonQuery(env, connection, statement, false);
     return err == SQLITE_DONE ? sqlite3_changes(connection->db) : -1;
 }
 
@@ -551,7 +557,7 @@
     SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
     sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
 
-    int err = executeNonQuery(env, connection, statement);
+    int err = executeNonQuery(env, connection, statement, false);
     return err == SQLITE_DONE && sqlite3_changes(connection->db) > 0
             ? sqlite3_last_insert_rowid(connection->db) : -1;
 }
@@ -912,7 +918,7 @@
             (void*)nativeBindBlob },
     { "nativeResetStatementAndClearBindings", "(JJ)V",
             (void*)nativeResetStatementAndClearBindings },
-    { "nativeExecute", "(JJ)V",
+    { "nativeExecute", "(JJZ)V",
             (void*)nativeExecute },
     { "nativeExecuteForLong", "(JJ)J",
             (void*)nativeExecuteForLong },
diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp
index d4ae6d7..d4fb3e3 100644
--- a/core/jni/android_graphics_BLASTBufferQueue.cpp
+++ b/core/jni/android_graphics_BLASTBufferQueue.cpp
@@ -112,11 +112,6 @@
                   transaction);
 }
 
-static void nativeFlushShadowQueue(JNIEnv* env, jclass clazz, jlong ptr) {
-    sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
-    queue->flushShadowQueue();
-}
-
 static void nativeMergeWithNextTransaction(JNIEnv*, jclass clazz, jlong ptr, jlong transactionPtr,
                                            jlong framenumber) {
     sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
@@ -139,6 +134,16 @@
     }
 }
 
+static jlong nativeGetLastAcquiredFrameNum(JNIEnv* env, jclass clazz, jlong ptr) {
+    sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
+    return queue->getLastAcquiredFrameNum();
+}
+
+static void nativeApplyPendingTransactions(JNIEnv* env, jclass clazz, jlong ptr, jlong frameNum) {
+    sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
+    queue->applyPendingTransactions(frameNum);
+}
+
 static const JNINativeMethod gMethods[] = {
         /* name, signature, funcPtr */
         // clang-format off
@@ -147,11 +152,12 @@
         {"nativeDestroy", "(J)V", (void*)nativeDestroy},
         {"nativeSetNextTransaction", "(JJ)V", (void*)nativeSetNextTransaction},
         {"nativeUpdate", "(JJJJIJ)V", (void*)nativeUpdate},
-        {"nativeFlushShadowQueue", "(J)V", (void*)nativeFlushShadowQueue},
         {"nativeMergeWithNextTransaction", "(JJJ)V", (void*)nativeMergeWithNextTransaction},
         {"nativeSetTransactionCompleteCallback",
                 "(JJLandroid/graphics/BLASTBufferQueue$TransactionCompleteCallback;)V",
-                (void*)nativeSetTransactionCompleteCallback}
+                (void*)nativeSetTransactionCompleteCallback},
+        {"nativeGetLastAcquiredFrameNum", "(J)J", (void*)nativeGetLastAcquiredFrameNum},
+        {"nativeApplyPendingTransactions", "(JJ)V", (void*)nativeApplyPendingTransactions},
         // clang-format on
 };
 
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 787d348..aadd320 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -98,6 +98,15 @@
     }
 }
 
+static void android_os_Parcel_markForBinder(JNIEnv* env, jclass clazz, jlong nativePtr,
+                                            jobject binder)
+{
+    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+    if (parcel) {
+        parcel->markForBinder(ibinderForJavaObject(env, binder));
+    }
+}
+
 static jint android_os_Parcel_dataSize(jlong nativePtr)
 {
     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
@@ -749,7 +758,9 @@
 
 static const JNINativeMethod gParcelMethods[] = {
     // @CriticalNative
-    {"nativeMarkSensitive",             "(J)V", (void*)android_os_Parcel_markSensitive},
+    {"nativeMarkSensitive",       "(J)V", (void*)android_os_Parcel_markSensitive},
+    // @FastNative
+    {"nativeMarkForBinder",       "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_markForBinder},
     // @CriticalNative
     {"nativeDataSize",            "(J)I", (void*)android_os_Parcel_dataSize},
     // @CriticalNative
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 0957067..869b53d 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -449,6 +449,11 @@
                         int(changeFrameRateStrategy));
 }
 
+static void nativeDestroy(JNIEnv* env, jclass clazz, jlong nativeObject) {
+    sp<Surface> surface(reinterpret_cast<Surface*>(nativeObject));
+    surface->destroy();
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gSurfaceMethods[] = {
@@ -477,6 +482,7 @@
         {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled},
         {"nativeSetFrameRate", "(JFII)I", (void*)nativeSetFrameRate},
         {"nativeGetFromBlastBufferQueue", "(JJ)J", (void*)nativeGetFromBlastBufferQueue},
+        {"nativeDestroy", "(J)V", (void*)nativeDestroy},
 };
 
 int register_android_view_Surface(JNIEnv* env)
diff --git a/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp b/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp
index 953902a..32c57d1 100644
--- a/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp
+++ b/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp
@@ -63,7 +63,7 @@
     *vector = counter->getCount(state);
 }
 
-static jobject native_toString(JNIEnv *env, jlong nativePtr, jobject self) {
+static jobject native_toString(JNIEnv *env, jobject self, jlong nativePtr) {
     battery::LongArrayMultiStateCounter *counter =
             reinterpret_cast<battery::LongArrayMultiStateCounter *>(nativePtr);
     return env->NewStringUTF(counter->toString().c_str());
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index bed0aae..ce44e07 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -62,7 +62,6 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/un.h>
-#include <sys/utsname.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
@@ -850,26 +849,6 @@
   }
 }
 
-static bool NeedsNoRandomizeWorkaround() {
-#if !defined(__arm__)
-    return false;
-#else
-    int major;
-    int minor;
-    struct utsname uts;
-    if (uname(&uts) == -1) {
-        return false;
-    }
-
-    if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
-        return false;
-    }
-
-    // Kernels before 3.4.* need the workaround.
-    return (major < 3) || ((major == 3) && (minor < 4));
-#endif
-}
-
 // Utility to close down the Zygote socket file descriptors while
 // the child is still running as root with Zygote's privileges.  Each
 // descriptor (if any) is closed via dup3(), replacing it with a valid
@@ -1740,15 +1719,6 @@
     // runtime.
     runtime_flags &= ~RuntimeFlags::GWP_ASAN_LEVEL_MASK;
 
-    if (NeedsNoRandomizeWorkaround()) {
-        // Work around ARM kernel ASLR lossage (http://b/5817320).
-        int old_personality = personality(0xffffffff);
-        int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
-        if (new_personality == -1) {
-            ALOGW("personality(%d) failed: %s", new_personality, strerror(errno));
-        }
-    }
-
     SetCapabilities(permitted_capabilities, effective_capabilities, permitted_capabilities,
                     fail_fn);
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f924229..8c28aec 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3152,6 +3152,12 @@
     <permission android:name="android.permission.READ_DEVICE_CONFIG"
         android:protectionLevel="signature|preinstalled" />
 
+    <!-- @SystemApi @hide Allows applications like settings to read system-owned
+     application-specific locale configs.
+     <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.READ_APP_SPECIFIC_LOCALES"
+                android:protectionLevel="signature" />
+
     <!-- @hide Allows an application to monitor {@link android.provider.Settings.Config} access.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS"
@@ -4864,6 +4870,18 @@
     <permission android:name="android.permission.WRITE_SETTINGS_HOMEPAGE_DATA"
                 android:protectionLevel="signature|privileged" />
 
+    <!-- An application needs this permission for
+         {@link android.provider.Settings#ACTION_SETTINGS_LARGE_SCREEN_DEEP_LINK} to show its
+         {@link android.app.Activity} in 2-pane of Settings app. -->
+    <permission android:name="android.permission.LAUNCH_TWO_PANE_SETTINGS_DEEP_LINK"
+                android:protectionLevel="signature|preinstalled" />
+
+    <!-- @SystemApi {@link android.app.Activity} should require this permission to ensure that only
+         the settings app can embed it in a 2-pane window.
+         @hide -->
+    <permission android:name="android.permission.ALLOW_PLACE_IN_TWO_PANE_SETTINGS"
+                android:protectionLevel="signature" />
+
     <!-- @SystemApi Allows applications to set a live wallpaper.
          @hide XXX Change to signature once the picker is moved to its
          own apk as Ghod Intended. -->
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 56d9a84..3666f48 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Gebruik jou vingerafdruk of skermslot om voort te gaan"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Vingerafdrukikoon"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Gesigslot"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Kwessie met Gesigslot"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gebruik jou gesig of skermslot om voort te gaan"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Gesig-ikoon"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lees sinkroniseer-instellings"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Laat die program toe om die sinkroniseringinstellings van \'n rekening te lees. Byvoorbeeld, dit kan bepaal of die People-program met \'n rekening gesinkroniseer is."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Wanneer die kortpad aan is, sal \'n toeganklikheidkenmerk begin word as albei volumeknoppies 3 sekondes lank gedruk word."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Skakel kortpad vir toeganklikheidskenmerke aan?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"As jy albei volumesleutels vir \'n paar sekondes hou, skakel dit toeganklikheidkenmerke aan. Dit kan verander hoe jou toestel werk.\n\nHuidige kenmerke:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nJy kan geselekteerde kenmerke in Instellings en Toeganklikheid verander."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Skakel <xliff:g id="SERVICE">%1$s</xliff:g>-kortpad aan?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"As jy albei volumesleutels vir \'n paar sekondes hou, skakel dit <xliff:g id="SERVICE">%1$s</xliff:g>, \'n toeganklikheidkenmerk, aan. Dit kan verander hoe jou toestel werk.\n\nJy kan hierdie kortpad na \'n ander kenmerk in Instellings en Toeganklikheid verander."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Skakel aan"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 39a3d6e..fb4669c 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ለመቀጠል የጣት አሻራዎን ወይም የማያ ገጽ ቁልፍዎን ይጠቀሙ"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"የጣት አሻራ አዶ"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"በመልክ መክፈት"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ከመልክ መክፈት ጋር በተያያዘ ችግር"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ለመቀጠል መልክዎን ወይም የማያ ገጽዎን መቆለፊያ ይጠቀሙ"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"የፊት አዶ"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"የሥምሪያ ቅንብሮች አንብብ"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"መተግበሪያው የአንድ መለያ የማመሳሰል ቅንብሮችን እንዲያነብ ይፈቅድለታል። ለምሳሌ ይህ የሰዎች መተግበሪያ ከመለያ ጋር መመሳሰሉን አለመመሳሰሉን ሊወስን ይችላል።"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"አቋራጩ ሲበራ ሁለቱንም የድምጽ አዝራሮች ለ3 ሰከንዶች ተጭኖ መቆየት የተደራሽነት ባህሪን ያስጀምረዋል።"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"የተደራሽነት ባህሪዎች አቋራጭ ይብራ?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ሁለቱንም የድምፅ ቁልፎች ወደ ታች ለጥቂት ሰከንዶች መያዝ የተደራሽነት ባሕሪያትን ያበራል። ይህ የእርስዎ መሣሪያ እንዴት እንደሚሠራ ሊለውጥ ይችላል።\n\nየአሁን ባሕሪያት፦\n<xliff:g id="SERVICE">%1$s</xliff:g>\nበቅንብሮች &gt; ተደራሽነት ውስጥ የተመረጡትን ባሕሪያት መለወጥ ይችላሉ።"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"የ<xliff:g id="SERVICE">%1$s</xliff:g> አቋራጭ ይብራ?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ሁለቱንም የድምፅ ቁልፎች ወደ ታች ለጥቂት ሰከንዶች መያዝ የተደራሽነት ባሕሪያትን <xliff:g id="SERVICE">%1$s</xliff:g> ያበራል። ይህ የእርስዎ መሣሪያ እንዴት እንደሚሠራ ሊለውጥ ይችላል።\n\nበቅንብሮች &gt; ተደራሽነት ውስጥ ወደ ሌላ ባሕሪ ይህን አቋራጭ መለወጥ ይችላሉ።"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"አብራ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index e854bd1..a7aefa7 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -621,6 +621,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"استخدام بصمة الإصبع أو قفل الشاشة للمتابعة"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"رمز بصمة الإصبع"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"فتح الجهاز بالتعرف على الوجه"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"مشكلة متعلّقة بميزة \"فتح الجهاز بالتعرف على الوجه\""</string>
@@ -673,6 +675,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"استخدام ميزة \"فتح القفل بالوجه\" أو ميزة \"قفل الشاشة\" للمتابعة"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"رمز الوجه"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"قراءة إعدادات المزامنة"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"للسماح للتطبيق بقراءة الإعدادات المتزامنة لحساب ما. على سبيل المثال، يمكن أن يؤدي هذا إلى تحديد ما إذا تمت مزامنة تطبيق \"الأشخاص\" مع حساب ما."</string>
@@ -1780,7 +1784,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"عند تفعيل الاختصار، يؤدي الضغط على زرّي التحكّم في مستوى الصوت معًا لمدة 3 ثوانٍ إلى تفعيل إحدى ميزات إمكانية الوصول."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"هل تريد تفعيل الاختصار لميزات إمكانية الوصول؟"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"يؤدي الضغط مع الاستمرار على كلا مفتاحَي التحكّم في مستوى الصوت لبضع ثوانٍ إلى تفعيل ميزات إمكانية الوصول. قد يؤدي هذا الإجراء إلى تغيير طريقة عمل جهازك.\n\nالميزات الحالية:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nيمكنك تغيير الميزات المحددة في الإعدادات &gt; إمكانية الوصول."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"هل تريد تفعيل اختصار <xliff:g id="SERVICE">%1$s</xliff:g>؟"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"‏يؤدي الضغط مع الاستمرار لبضع ثوانٍ على كلا مفتاحَي التحكّم في مستوى الصوت إلى تفعيل <xliff:g id="SERVICE">%1$s</xliff:g> وهي إحدى ميزات إمكانية الوصول. يمكن أن يؤدي هذا الإجراء إلى تغيير كيفية عمل جهازك.\n\nيمكنك تغيير هذا الاختصار لاستخدامه مع ميزة أخرى في الإعدادات &gt; أدوات تمكين الوصول."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"تفعيل"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 43e7fd6..7ea0542 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"অব্যাহত ৰাখিবলৈ আপোনাৰ ফিংগাৰপ্ৰিণ্ট অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ফিংগাৰপ্ৰিণ্ট আইকন"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ফেচ আনলক"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ফেচ আনলক ব্যৱহাৰ কৰোঁতে সমস্যা হৈছে"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"অব্যাহত ৰাখিবলৈ আপোনাৰ মুখাৱয়ব অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"মুখমণ্ডলৰ আইকন"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ছিংকৰ ছেটিংসমূহ পঢ়ক"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"একাউণ্টৰ ছিংক ছেটিংবোৰ পঢ়িবলৈ এপক অনুমতি দিয়ে। যেনে, People এপ কোনো একাউণ্টত ছিংক কৰা হৈছে নে নাই সেয়া নির্ধাৰণ কৰিব পাৰে।"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"শ্বৰ্টকাটটো অন হৈ থকাৰ সময়ত দুয়োটা ভলিউম বুটাম ৩ ছেকেণ্ডৰ বাবে হেঁচি ধৰি ৰাখিলে এটা সাধ্য সুবিধা আৰম্ভ হ’ব।"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"সাধ্য সুবিধাসমূহৰ বাবে শ্বৰ্টকাট অন কৰিবনে?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"দুয়োটা ভলিউম কী কিছুসময়ৰ বাবে ধৰি থাকিলে সাধ্য-সুবিধাসমূহ অন কৰে। এইটোৱে আপোনাৰ ডিভাইচটোৱে কাম কৰাৰ ধৰণ সলনি কৰিব পাৰে।\n\nবর্তমানৰ সুবিধাসমূহ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nআপুনি ছেটিংসমূহ &gt; সাধ্য-সুবিধাত কিছুমান নিৰ্দিষ্ট সুবিধা সলনি কৰিব পাৰে।"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g>ৰ শ্বৰ্টকাট অন কৰিবনে?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"দুয়োটা ভলিউম কী কিছুসময়ৰ বাবে ধৰি থাকিলে এটা সাধ্য- সুবিধা <xliff:g id="SERVICE">%1$s</xliff:g> অন কৰে। এইটোৱে আপোনাৰ ডিভাইচটোৱে কাম কৰাৰ ধৰণ সলনি কৰিব পাৰে।\n\nআপুনি ছেটিংসমূহ &gt; সাধ্য-সুবিধাসমূহত এই শ্বৰ্টকাটটো অন্য এটা সুবিধালৈ সলনি কৰিব পাৰে।"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"অন কৰক"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 00145ba..24ea7fc 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Davam etmək üçün barmaq izi və ya ekran kilidinizdən istifadə edin"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Barmaq izi ikonası"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Üz ilə kiliddən çıxarma"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Üz ilə kiliddən çıxarma problemi"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Davam etmək üçün üz və ya ekran kilidinizdən istifadə edin"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Üz işarəsi"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"sinx ayarlarını oxu"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Tətbiqə hesablar üçün sinxronizasiya nizamlarını oxuma icazəsi verir. Məsələn, bu Şəxslər tətbiqinin sinxronizə olunub-olunmadığını təyin edə bilər."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Qısayol aktiv olduqda, hər iki səs düyməsinə 3 saniyə basıb saxlamaqla əlçatımlılıq funksiyası başladılacaq."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Əlçatımlılıq funksiyaları üçün qısayol aktiv edilsin?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Hər iki səs səviyyəsi düyməsinə bir neçə saniyə basıb saxladıqda əlçatımlılıq funksiyaları aktiv olur. Cihazınızın işləmə qaydasını dəyişə bilər.\n\nCari funksiyalar:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nAyarlar və Əlçatımlılıq bölməsində seçilmiş funksiyaları dəyişə bilərsiniz."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> qısayolu aktiv edilsin?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Hər iki səs səviyyəsi düyməsinə bir neçə saniyə basıb saxladıqda əlçatımlılıq funksiyası olan <xliff:g id="SERVICE">%1$s</xliff:g> aktiv olur. Cihazınızın işləmə qaydasını dəyişə bilər.\n\nAyarlar və Əlçatımlılıq bölməsində bu qısayolu başqa bir funksiyaya dəyişə bilərsiniz."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktiv edin"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 65bfec1..80b3a3a 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -612,6 +612,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Koristite otisak prsta ili zaključavanje ekrana da biste nastavili"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona otiska prsta"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Otključavanje licem"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem sa otključavanje licem"</string>
@@ -664,6 +666,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Koristite lice ili zaključavanje ekrana da biste nastavili"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Ikona lica"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"čitanje podešavanja sinhronizacije"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Dozvoljava aplikaciji da čita podešavanja sinhronizacije za nalog. Na primer, ovako može da se utvrdi da li je aplikacija Ljudi sinhronizovana sa nalogom."</string>
@@ -1714,7 +1718,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kada je prečica uključena, pritisnite oba dugmeta za jačinu zvuka da biste pokrenuli funkciju pristupačnosti."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Želite da uključite prečicu za funkcije pristupačnosti?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ako zadržite oba tastera za jačinu zvuka par sekundi, uključiće se funkcije pristupačnosti. To može da promeni način rada uređaja.\n\nPostojeće funkcije:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nMožete da promenite izabrane funkcije u odeljku Podešavanja &gt; Pristupačnost."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Želite da uključite prečicu za uslugu <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ako zadržite oba tastera za jačinu zvuka par sekundi, uključuje se <xliff:g id="SERVICE">%1$s</xliff:g>, funkcija pristupačnosti. To može da promeni način rada uređaja.\n\nMožete da promenite funkciju na koju se odnosi ova prečica u odeljku Podešavanja &gt; Pristupačnost."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Uključi"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index a1a1731..8f74705 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -615,6 +615,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Каб працягнуць, скарыстайце адбітак пальца ці сродак разблакіроўкі экрана"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Значок адбіткаў пальцаў"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Распазнаванне твару"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Праблема з распазнаваннем твару"</string>
@@ -667,6 +669,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Каб працягнуць, скарыстайце распазнаванне твару ці сродак разблакіроўкі экрана"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Значок твару"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"чытаць параметры сінхранізацыі"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Дазваляе прыкладанням чытаць параметры сінхранізацыі для ўліковага запісу. Напрыклад, яны могуць вызначыць, цi сiнхранiзавана з улiковым запiсам прыкладанне \"Кантакты\"."</string>
@@ -1736,7 +1740,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Калі хуткі доступ уключаны, вы можаце націснуць абедзве кнопкі гучнасці і ўтрымліваць іх 3 секунды, каб запусціць функцыю спецыяльных магчымасцей."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Уключыць хуткі доступ да спецыяльных магчымасцей?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Утрымліванне націснутымі абедзвюх клавіш гучнасці на працягу некалькіх секунд уключае спецыяльныя магчымасці. У выніку ваша прылада можа пачаць працаваць па-іншаму.\n\nБягучыя функцыі:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nВыбраныя функцыі можна змяніць у меню \"Налады &gt; Спецыяльныя магчымасці\"."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Уключыць хуткі доступ да сэрвісу \"<xliff:g id="SERVICE">%1$s</xliff:g>\"?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Утрымліванне націснутымі абедзвюх клавіш гучнасці на працягу некалькіх секунд уключае службу \"<xliff:g id="SERVICE">%1$s</xliff:g>\", якая з\'яўляецца спецыяльнай магчымасцю. У выніку ваша прылада можа пачаць працаваць па-іншаму.\n\nВы можаце задаць гэта спалучэнне клавіш для іншай функцыі ў меню \"Налады &gt; Спецыяльныя магчымасці\"."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Уключыць"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index c74f488..01b2379 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Използвайте отпечатъка си или опцията за заключване на екрана, за да продължите"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Икона за отпечатък"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Отключване с лице"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Проблем с отключването с лице"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Използвайте лицето си или опцията за заключване на екрана, за да продължите"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Икона на лице"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"четене на настройките за синхронизиране"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Разрешава на приложението да чете настройките за синхронизиране на профил. Например това може да определи дали приложението Хора е синхронизирано с даден профил."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Когато прекият път е включен, можете да стартирате дадена функция за достъпност, като натиснете двата бутона за силата на звука и ги задържите за 3 секунди."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Искате ли да включите прекия път за функциите за достъпност?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Натиснете двата бутона за силата на звука и ги задръжте за няколко секунди, за да включите функциите за достъпност. Това може да промени начина, по който работи устройството ви.\n\nТекущи функции:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nМожете да промените избраните функции от „Настройки“ &gt; „Достъпност“."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Искате ли да включите прекия път за <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Натиснете двата бутона за силата на звука и ги задръжте за няколко секунди, за да включите функцията за достъпност <xliff:g id="SERVICE">%1$s</xliff:g>. Това може да промени начина, по който работи устройството ви.\n\nМожете да зададете друга функция за този пряк път от „Настройки“ &gt; „Достъпност“."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Включване"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 584fb61..5253e41 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"চালিয়ে যেতে আপনার আঙুলের ছাপ বা স্ক্রিন লক ব্য়বহার করুন"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"আঙ্গুলের ছাপ আইকন"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ফেস আনলক"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"\'ফেস আনলক\' ফিচার ব্যবহার করার ক্ষেত্রে হওয়া সমস্যা"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"চালিয়ে যেতে আপনার ফেস বা স্ক্রিন লক ব্যবহার করুন"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"ফেস আইকন"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"সিঙ্ক সেটিংস পড়ে"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"অ্যাপ্লিকেশানটিকে একটি অ্যাকাউন্টের জন্য সিঙ্ক সেটিংস পড়ার অনুমতি দেয়৷ উদাহরণস্বরূপ, \'পিপল\' অ্যাপ্লিকেশানটি কোনো অ্যাকাউন্টের সাথে সিঙ্ক করা আছে কিনা তা নির্ধারণ করতে পারে৷"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"শর্টকাট চালু করা থাকাকালীন দুটি ভলিউম বোতাম একসাথে ৩ সেকেন্ড টিপে ধরে রাখলে একটি অ্যাকসেসিবিলিটি ফিচার চালু হবে।"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"অ্যাক্সেসিবিলিটি ফিচারের শর্টকাট বন্ধ করতে চান?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"উভয় ভলিউম কী কয়েক সেকেন্ড ধরে থাকলে অ্যাক্সেসিবিলিটি ফিচার চালু হয়ে যাবে। এর ফলে, আপনার ডিভাইস কীভাবে কাজ করবে সেটিতে পরিবর্তন হতে পারে।\n\nবর্তমান ফিচার:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nসেটিংস &gt; অ্যাক্সেসিবিলিটি বিকল্প থেকে আপনি বাছাই করা ফিচার পরিবর্তন করতে পারবেন।"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> শর্টকাট চালু করতে চান?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"উভয় ভলিউম কী কয়েক সেকেন্ড ধরে থাকলে <xliff:g id="SERVICE">%1$s</xliff:g> চালু হয়ে যাবে। এটি একটি অ্যাক্সেসিবিলিটি ফিচার। এর ফলে, আপনার ডিভাইস কীভাবে কাজ করবে সেটিতে পরিবর্তন হতে পারে।\n\nসেটিংস &gt; অ্যাক্সেসিবিলিটি থেকে আপনি এই শর্টকাট পরিবর্তন করতে পারবেন।"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"চালু করুন"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index b6497ab..2995f3c 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -612,6 +612,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Koristite otisak prsta ili zaključavanje ekrana da nastavite"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona za otisak prsta"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Otključavanje licem"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem s otključavanjem licem"</string>
@@ -664,6 +666,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Koristite lice ili zaključavanje ekrana da nastavite"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Ikona lica"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"čitanje postavki za sinhroniziranje"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Omogućava aplikaciji čitanje postavki sinhroniziranja za račun. Naprimjer, ovim se može utvrditi da li je aplikacija People sinhronizirana sa računom."</string>
@@ -1714,7 +1718,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kada je prečica uključena, pritiskom i držanjem oba dugmeta za jačinu zvuka u trajanju od 3 sekunde pokrenut će se funkcija pristupačnosti."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Uključiti prečicu za funkcije pristupačnosti?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ako nekoliko sekundi držite pritisnute obje tipke za jačinu zvuka, uključit ćete funkcije pristupačnosti. Ovo može uticati na način rada uređaja.\n\nTrenutne funkcije:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nOdabrane funkcije možete promijeniti u odjeljku Postavke &gt; Pristupačnost."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Uključiti prečicu za uslugu <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ako nekoliko sekundi držite pritisnute obje tipke za jačinu zvuka, uključit ćete funkciju pristupačnosti <xliff:g id="SERVICE">%1$s</xliff:g>. Ovo može promijeniti način rada uređaja.\n\nOvu prečicu možete zamijeniti drugom funkcijom u odjeljku Postavke &gt; Pristupačnost."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Uključi"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 507fecd..a182585 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Utilitza l\'empremta digital o el bloqueig de pantalla per continuar"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icona d\'empremta digital"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueig facial"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema amb Desbloqueig facial"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Utilitza la cara o el bloqueig de pantalla per continuar"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Icona facial"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"llegir la configuració de sincronització"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permet que l\'aplicació llegeixi la configuració de sincronització d\'un compte. Per exemple, això pot determinar que l\'aplicació Contactes estigui sincronitzada amb un compte."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Si la drecera està activada, prem els dos botons de volum durant 3 segons per iniciar una funció d\'accessibilitat."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vols desactivar la drecera de les funcions d\'accessibilitat?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Si mantens premudes les dues tecles de volum durant uns segons, s\'activaran les funcions d\'accessibilitat. Això podria canviar el funcionament del teu dispositiu.\n\nFuncions actuals:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPots canviar les funcions seleccionades a Configuració &gt; Accessibilitat."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Vols activar la drecera de <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Si mantens premudes les dues tecles de volum durant uns segons, la funció d\'accessibilitat <xliff:g id="SERVICE">%1$s</xliff:g> s\'activarà. Això podria canviar el funcionament del teu dispositiu.\n\nPots canviar la funció d\'aquesta drecera a Configuració &gt; Accessibilitat."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Activa"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index fa1a665..75528bb 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -615,6 +615,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Pokračujte ověřením pomocí otisku prstu nebo zámku obrazovky"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona otisku prstů"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Odemknutí obličejem"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problém s odemykáním obličejem"</string>
@@ -667,6 +669,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Pokračujte ověřením pomocí obličeje nebo zámku obrazovky"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Ikona obličeje"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"čtení nastavení synchronizace"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Umožňuje aplikaci číst nastavení synchronizace v účtu. Může například určit, zda je s účtem synchronizována aplikace Lidé."</string>
@@ -1736,7 +1740,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Když je tato zkratka zapnutá, můžete funkci přístupnosti spustit tím, že na tři sekundy podržíte obě tlačítka hlasitosti."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Zapnout zkratku funkcí pro usnadnění přístupu?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Podržením obou tlačítek hlasitosti po dobu několika sekund zapnete funkce pro usnadnění přístupu. Tato funkce může změnit fungování zařízení.\n\nAktuální funkce:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nVybrané funkce můžete změnit v Nastavení &gt; Přístupnost."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Zapnout zkratku služby <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Podržením obou tlačítek hlasitosti po dobu několika sekund zapnete funkci pro usnadnění přístupu <xliff:g id="SERVICE">%1$s</xliff:g>. Tato funkce může změnit fungování zařízení.\n\nZkratku můžete nastavit na jinou funkci v Nastavení &gt; Přístupnost."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Zapnout"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 0c26400..f504cc7 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Brug dit fingeraftryk eller din skærmlås for at fortsætte"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon for fingeraftryk"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ansigtslås"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Der er et problem med Ansigtslås"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Brug din ansigts- eller skærmlås for at fortsætte"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Ansigt"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"læse indstillinger for synkronisering"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Tillader, at appen kan læse synkroniseringsindstillingerne for en konto. Denne tilladelse kan f.eks. fastslå, om appen Personer er synkroniseret med en konto."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Når genvejen er aktiveret, kan du starte en hjælpefunktion ved at trykke på begge lydstyrkeknapper i tre sekunder."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vil du aktivere genvejen til hjælpefunktioner?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Hvis du holder begge lydstyrkeknapperne nede i et par sekunder, aktiveres hjælpefunktionerne. Det kan ændre på, hvordan din enhed fungerer.\n\nAktuelle funktioner:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nDu kan ændre de valgte funktioner i Indstillinger &gt; Hjælpefunktioner."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Vil du aktivere <xliff:g id="SERVICE">%1$s</xliff:g>-genvejen?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Hvis du holder begge lydstyrkeknapperne nede i et par sekunder, aktiveres hjælpefunktionen <xliff:g id="SERVICE">%1$s</xliff:g>. Det kan ændre på, hvordan din enhed fungerer.\n\nDu kan ændre denne genvej til en anden funktion i Indstillinger &gt; Hjælpefunktioner."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktivér"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 4b1c544..831a66b 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Verwende deinen Fingerabdruck oder deine Display-Entsperrmethode, um fortzufahren"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerabdruck-Symbol"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Entsperrung per Gesichtserkennung"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem bei der Entsperrung per Gesichtserkennung"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Verwende die Gesichtserkennung oder deine Display-Entsperrmethode, um fortzufahren"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Gesichtssymbol"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"Synchronisierungseinstellungen lesen"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Ermöglicht der App, die Synchronisierungseinstellungen eines Kontos zu lesen. Beispielsweise kann damit festgestellt werden, ob Kontakte mit einem Konto synchronisiert werden."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Wenn die Verknüpfung aktiviert ist, kannst du die beiden Lautstärketasten drei Sekunden lang gedrückt halten, um eine Bedienungshilfe zu starten."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Verknüpfung für Bedienungshilfen aktivieren?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Wenn du beide Lautstärketasten einige Sekunden lang gedrückt hältst, aktivierst du die Bedienungshilfen. Dadurch kann sich die Funktionsweise deines Geräts ändern.\n\nAktuelle Funktionen:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nDu kannst ausgewählte Funktionen unter \"Einstellungen\" &gt; \"Bedienungshilfen\" ändern."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Verknüpfung für <xliff:g id="SERVICE">%1$s</xliff:g> aktivieren?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Wenn du beide Lautstärketasten einige Sekunden lang gedrückt hältst, aktivierst du die Bedienungshilfe \"<xliff:g id="SERVICE">%1$s</xliff:g>\". Dadurch kann sich die Funktionsweise deines Geräts ändern.\n\nUnter \"Einstellungen &gt; \"Bedienungshilfen\" kannst du dieser Verknüpfung eine andere Funktion zuweisen."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktivieren"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 6fe7d63..beffc46 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Χρησιμοποιήστε το δακτυλικό σας αποτύπωμα ή το κλείδωμα οθόνης για να συνεχίσετε"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Εικονίδιο δακτυλικών αποτυπωμάτων"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ξεκλείδωμα με το πρόσωπο"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Πρόβλημα με το Ξεκλείδωμα με το πρόσωπο"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Χρησιμοποιήστε το πρόσωπό σας ή το κλείδωμα οθόνης για συνέχεια"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Εικ. προσ."</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"διαβάζει τις ρυθμίσεις συγχρονισμού"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Επιτρέπει στην εφαρμογή την ανάγνωση των ρυθμίσεων συγχρονισμού για έναν λογαριασμό. Για παράδειγμα, αυτό μπορεί να καθορίσει εάν η εφαρμογή \"Άτομα\" είναι συγχρονισμένη με έναν λογαριασμό."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Όταν η συντόμευση είναι ενεργοποιημένη, το πάτημα και των δύο κουμπιών έντασης ήχου για 3 δευτερόλεπτα θα ξεκινήσει μια λειτουργία προσβασιμότητας."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Ενεργοποίηση συντόμευσης για λειτουργίες προσβασιμότητας;"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Για να ενεργοποιήσετε τις λειτουργίες προσβασιμότητας, πατήστε παρατεταμένα τα δύο πλήκτρα έντασης για μερικά δευτερόλεπτα. Αυτό ενδέχεται να αλλάξει τον τρόπο λειτουργίας της συσκευής σας.\n\nΤρέχουσες λειτουργίες:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nΜπορείτε να αλλάξετε τις επιλεγμένες λειτουργίες στις Ρυθμίσεις &gt; Προσβασιμότητα."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Ενεργοποίηση συντόμευσης <xliff:g id="SERVICE">%1$s</xliff:g>;"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Μπορείτε να ενεργοποιήσετε τη λειτουργία <xliff:g id="SERVICE">%1$s</xliff:g>, η οποία είναι μία από τις λειτουργίες προσβασιμότητας, πατώντας παρατεταμένα ταυτόχρονα τα δύο πλήκτρα έντασης ήχου για μερικά δευτερόλεπτα. Αυτό ενδέχεται να αλλάξει τον τρόπο λειτουργίας της συσκευής σας.\n\nΜπορείτε να αλλάξετε αυτή τη συντόμευση σε μια άλλη λειτουργία στις Ρυθμίσεις &gt; Προσβασιμότητα."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Ενεργοποίηση"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 13725de..0b02d69 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -609,6 +609,7 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Use your fingerprint or screen lock to continue"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Something went wrong. Try again."</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Face Unlock"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Issue with Face Unlock"</string>
@@ -661,6 +662,7 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use your face or screen lock to continue"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Something went wrong. Try again."</string>
     <string name="face_icon_content_description" msgid="465030547475916280">"Face icon"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"read sync settings"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Allows the app to read the sync settings for an account. For example, this can determine whether the People app is synced with an account."</string>
@@ -1692,7 +1694,7 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"When the shortcut is on, pressing both volume buttons for three seconds will start an accessibility feature."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Turn on shortcut for accessibility features?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Holding down both volume keys for a few seconds turns on accessibility features. This may change how your device works.\n\nCurrent features:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nYou can change selected features in Settings &gt; Accessibility."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Turn on <xliff:g id="SERVICE">%1$s</xliff:g> shortcut?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Holding down both volume keys for a few seconds turns on <xliff:g id="SERVICE">%1$s</xliff:g>, an accessibility feature. This may change how your device works.\n\nYou can change this shortcut to another feature in Settings &gt; Accessibility."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Turn on"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 9205763..c916761 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -609,6 +609,7 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Use your fingerprint or screen lock to continue"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Something went wrong. Try again."</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Face Unlock"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Issue with Face Unlock"</string>
@@ -661,6 +662,7 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use your face or screen lock to continue"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Something went wrong. Try again."</string>
     <string name="face_icon_content_description" msgid="465030547475916280">"Face icon"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"read sync settings"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Allows the app to read the sync settings for an account. For example, this can determine whether the People app is synced with an account."</string>
@@ -1692,7 +1694,7 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"When the shortcut is on, pressing both volume buttons for three seconds will start an accessibility feature."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Turn on shortcut for accessibility features?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Holding down both volume keys for a few seconds turns on accessibility features. This may change how your device works.\n\nCurrent features:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nYou can change selected features in Settings &gt; Accessibility."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Turn on <xliff:g id="SERVICE">%1$s</xliff:g> shortcut?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Holding down both volume keys for a few seconds turns on <xliff:g id="SERVICE">%1$s</xliff:g>, an accessibility feature. This may change how your device works.\n\nYou can change this shortcut to another feature in Settings &gt; Accessibility."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Turn on"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 45709f0..34eeff4 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -609,6 +609,7 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Use your fingerprint or screen lock to continue"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Something went wrong. Try again."</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Face Unlock"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Issue with Face Unlock"</string>
@@ -661,6 +662,7 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use your face or screen lock to continue"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Something went wrong. Try again."</string>
     <string name="face_icon_content_description" msgid="465030547475916280">"Face icon"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"read sync settings"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Allows the app to read the sync settings for an account. For example, this can determine whether the People app is synced with an account."</string>
@@ -1692,7 +1694,7 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"When the shortcut is on, pressing both volume buttons for three seconds will start an accessibility feature."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Turn on shortcut for accessibility features?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Holding down both volume keys for a few seconds turns on accessibility features. This may change how your device works.\n\nCurrent features:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nYou can change selected features in Settings &gt; Accessibility."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Turn on <xliff:g id="SERVICE">%1$s</xliff:g> shortcut?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Holding down both volume keys for a few seconds turns on <xliff:g id="SERVICE">%1$s</xliff:g>, an accessibility feature. This may change how your device works.\n\nYou can change this shortcut to another feature in Settings &gt; Accessibility."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Turn on"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 8749d05..ef7924e 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -609,6 +609,7 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Use your fingerprint or screen lock to continue"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Something went wrong. Try again."</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerprint icon"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Face Unlock"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Issue with Face Unlock"</string>
@@ -661,6 +662,7 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use your face or screen lock to continue"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Something went wrong. Try again."</string>
     <string name="face_icon_content_description" msgid="465030547475916280">"Face icon"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"read sync settings"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Allows the app to read the sync settings for an account. For example, this can determine whether the People app is synced with an account."</string>
@@ -1692,7 +1694,7 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"When the shortcut is on, pressing both volume buttons for three seconds will start an accessibility feature."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Turn on shortcut for accessibility features?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Holding down both volume keys for a few seconds turns on accessibility features. This may change how your device works.\n\nCurrent features:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nYou can change selected features in Settings &gt; Accessibility."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Turn on <xliff:g id="SERVICE">%1$s</xliff:g> shortcut?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Holding down both volume keys for a few seconds turns on <xliff:g id="SERVICE">%1$s</xliff:g>, an accessibility feature. This may change how your device works.\n\nYou can change this shortcut to another feature in Settings &gt; Accessibility."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Turn on"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 996a332..7aa9f44 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -609,6 +609,7 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‏‏‎‏‏‎‎‏‏‏‎‎‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‎‏‎‎‎‎‏‎‎‎‎Use your fingerprint or screen lock to continue‎‏‎‎‏‎"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‏‏‏‎‏‏‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‎‎‎‎‎‎‎‎‎‎‏‏‏‏‎‎‏‏‎‏‏‏‎‎‏‎Something went wrong. Try again.‎‏‎‎‏‎"</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‎‏‎‎‏‎‏‏‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‏‏‎‏‎‎‏‎‎‎‏‎Fingerprint icon‎‏‎‎‏‎"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‏‎‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‏‎‏‎‎‎‎‎‎‎‏‏‏‎‎Face Unlock‎‏‎‎‏‎"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‎‏‎‎‏‏‏‎‏‏‏‎‎‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‎‏‎‎‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‎Issue with Face Unlock‎‏‎‎‏‎"</string>
@@ -661,6 +662,7 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎Use your face or screen lock to continue‎‏‎‎‏‎"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‏‎‎‎‎‏‏‏‎‏‎‎‏‏‏‎‏‎‏‏‎‏‏‎‎Something went wrong. Try again.‎‏‎‎‏‎"</string>
     <string name="face_icon_content_description" msgid="465030547475916280">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‎‎‎‎‏‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎‎‎Face icon‎‏‎‎‏‎"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎‏‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‏‎read sync settings‎‏‎‎‏‎"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‎‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‏‎‎‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‏‏‏‎‏‏‏‎‏‏‎‏‎‎‎‏‎‎Allows the app to read the sync settings for an account. For example, this can determine whether the People app is synced with an account.‎‏‎‎‏‎"</string>
@@ -1692,7 +1694,7 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‎‎When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‎‏‎‎‏‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‏‎‎Turn on shortcut for accessibility features?‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‏‎‎‎‎‏‏‏‏‏‎Holding down both volume keys for a few seconds turns on accessibility features. This may change how your device works.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Current features:‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="SERVICE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎You can change selected features in Settings &gt; Accessibility.‎‏‎‎‏‎"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‎‎‎‎‏‎‎‎‏‎‏‎‎‏‏‎‎‏‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‏‎‎‏‏‏‎‏‎‎‏‎‏‏‎‏‏‎	• ‎‏‎‎‏‏‎<xliff:g id="SERVICE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" ‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‏‎‏‎‎‏‎‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‏‎‏‎‎‎‏‎‏‎‏‎‏‎‏‎‎‏‎‎ • ‎‏‎‎‏‏‎<xliff:g id="SERVICE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‎‏‏‎‎‏‎‎Turn on ‎‏‎‎‏‏‎<xliff:g id="SERVICE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ shortcut?‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‏‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‏‏‎‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‎‎‎‎‏‎Holding down both volume keys for a few seconds turns on ‎‏‎‎‏‏‎<xliff:g id="SERVICE">%1$s</xliff:g>‎‏‎‎‏‏‏‎, an accessibility feature. This may change how your device works.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎You can change this shortcut to another feature in Settings &gt; Accessibility.‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‏‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎Turn on‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 569cfcf..3de374d 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Usa tu huella dactilar o bloqueo de pantalla para continuar"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícono de huella dactilar"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueo facial"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema con el Desbloqueo facial"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Usa tu rostro o bloqueo de pantalla para continuar"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Ícono cara"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"leer la configuración de sincronización"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Este permiso permite que la aplicación consulte la configuración de sincronización de una cuenta. Esto permite, por ejemplo, determinar si la aplicación Personas está sincronizada con una cuenta."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Cuando la combinación de teclas está activada, puedes presionar los botones de volumen durante 3 segundos para iniciar una función de accesibilidad."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"¿Quieres activar la combinación de teclas para las funciones de accesibilidad?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Si mantienes presionadas las dos teclas de volumen durante unos segundos, se activarán las funciones de accesibilidad. Esto puede cambiar el funcionamiento de tu dispositivo.\n\nFunciones actuales:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPuedes cambiar las funciones seleccionadas en Configuración &gt; Accesibilidad."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"¿Quieres activar el acceso directo de <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Si mantienes presionadas ambas teclas de volumen durante unos segundos, se activará la función de accesibilidad <xliff:g id="SERVICE">%1$s</xliff:g>. Esto podría cambiar la forma en que funciona tu dispositivo.\n\nPuedes cambiar este acceso directo a otra función en Configuración &gt; Accesibilidad."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Activar"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 716b2c8..68e90f1 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -609,6 +609,7 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Usa tu huella digital o tu bloqueo de pantalla para continuar"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Se ha producido un error. Inténtalo de nuevo."</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icono de huella digital"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueo facial"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema con Desbloqueo facial"</string>
@@ -661,6 +662,7 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Usa tu cara o tu bloqueo de pantalla para continuar"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Se ha producido un error. Inténtalo de nuevo."</string>
     <string name="face_icon_content_description" msgid="465030547475916280">"Icono cara"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"leer la configuración de sincronización"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permite que la aplicación consulte la configuración de sincronización de una cuenta. La aplicación puede utilizar este permiso, por ejemplo, para determinar si la aplicación Contactos está sincronizada con una cuenta."</string>
@@ -1692,7 +1694,7 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Si el acceso directo está activado, pulsa los dos botones de volumen durante 3 segundos para iniciar una función de accesibilidad."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"¿Quieres activar el acceso directo a las funciones de accesibilidad?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Al mantener pulsadas las dos teclas de volumen durante unos segundos, se activan las funciones de accesibilidad, que pueden cambiar el funcionamiento del dispositivo.\n\nFunciones actuales:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPuedes cambiar las funciones seleccionadas en Ajustes &gt; Accesibilidad."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"¿Quieres activar el acceso directo a <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Al mantener pulsadas ambas teclas de volumen durante unos segundos se activa <xliff:g id="SERVICE">%1$s</xliff:g>, una función de accesibilidad. Esta función puede modificar el funcionamiento del dispositivo.\n\nPuedes asignar este acceso directo a otra función en Ajustes &gt; Accesibilidad."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Activar"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 6153a83..e549d45 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Jätkamiseks kasutage oma sõrmejälge või ekraanilukku"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Sõrmejälje ikoon"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Näoga avamine"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Probleem funktsiooniga Näoga avamine"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Jätkamiseks kasutage oma nägu või ekraanilukku"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Näoikoon"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"loe sünkroonimisseadeid"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Võimaldab rakendusel lugeda konto sünkroonimisseadeid. Näiteks võib see määrata, kas rakendus Inimesed on kontoga sünkroonitud."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kui otsetee on sisse lülitatud, käivitab mõlema helitugevuse nupu kolm sekundit all hoidmine juurdepääsetavuse funktsiooni."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Kas lülitada juurdepääsufunktsioonide otsetee sisse?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Hoidke juurdepääsufunktsioonide sisselülitamiseks mõlemat helitugevuse klahvi mõni sekund all. See võib teie seadme tööviisi muuta.\n\nPraegused funktsioonid:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nValitud funktsioone saab muuta jaotises Seaded &gt; Juurdepääsetavus."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Kas lülitada teenuse <xliff:g id="SERVICE">%1$s</xliff:g> otsetee sisse?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Kui hoiate mõlemat helitugevuse klahvi mõni sekund all, lülitatakse juurdepääsufunktsioon <xliff:g id="SERVICE">%1$s</xliff:g> sisse. See võib teie seadme tööviisi muuta.\n\nSelle otsetee saab asendada muu otseteega jaotises Seaded &gt; Juurdepääsetavus."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Lülita sisse"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index a56d19a..01d191d 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Aurrera egiteko, erabili hatz-marka edo pantailaren blokeoa"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Hatz-markaren ikonoa"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Aurpegi bidez desblokeatzeko eginbidea"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Arazoak ditugu aurpegi bidez desblokeatzeko eginbidearekin"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Aurrera egiteko, erabili aurpegia edo pantailaren blokeoa"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Aurpegiaren ikonoa"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"irakurri sinkronizazio-ezarpenak"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Kontu baten sinkronizazio-ezarpenak irakurtzeko baimena ematen die aplikazioei. Adibidez, Jendea aplikazioa konturen batekin sinkronizatuta dagoen zehatz dezake."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Lasterbidea aktibatuta dagoenean, bi bolumen-botoiak hiru segundoz sakatuta abiaraziko da erabilerraztasun-eginbidea."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Erabilerraztasun-eginbideetarako lasterbidea aktibatu nahi duzu?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Eduki sakatuta bolumen-botoiak segundo batzuez erabilerraztasun-eginbideak aktibatzeko. Hori eginez gero, baliteke zure mugikorraren funtzionamendua aldatzea.\n\nEginbideak:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nHautatutako eginbideak aldatzeko, joan Ezarpenak &gt; Erabilerraztasuna atalera."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> zerbitzuaren lasterbidea aktibatu nahi duzu?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Eduki sakatuta bolumen-botoiak segundo batzuez <xliff:g id="SERVICE">%1$s</xliff:g> izeneko erabilerraztasun-eginbidea aktibatzeko. Honen bidez, baliteke zure mugikorraren funtzionamendua aldatzea.\n\nLasterbide hau beste eginbide batengatik aldatzeko, joan Ezarpenak &gt; Erabilerraztasuna atalera."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktibatu"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index b0bc2c2..393382a 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"برای ادامه، از اثر انگشت یا قفل صفحه استفاده کنید"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"نماد اثر انگشت"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"قفل‌گشایی با چهره"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"مشکل در «قفل‌گشایی با چهره»"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"برای ادامه، از تشخیص چهره یا قفل صفحه استفاده کنید"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"نماد چهره"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"خواندن تنظیمات همگام‌سازی"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"به برنامه اجازه می‌دهد تنظیمات را برای یک حساب بخواند. به‌عنوان مثال، این ویژگی می‌تواند تعیین کند آیا حساب «افراد» شما با یک حساب همگام‌سازی شده است."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"وقتی میان‌بر روشن باشد، با فشار دادن هردو دکمه صدا به‌مدت ۳ ثانیه ویژگی دسترس‌پذیری فعال می‌شود."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"میان‌بر برای ویژگی‌های دسترس‌پذیری روشن شود؟"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"با پایین نگه داشتن هردو کلید میزان صدا به‌مدت چند ثانیه، ویژگی‌های دسترس‌پذیری روشن می‌شود. با این کار نحوه عملکرد دستگاهتان تغییر می‌کند.\n\nویژگی‌های فعلی:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nمی‌توانید ویژگی‌های انتخابی را در «تنظیمات &gt; دسترس‌پذیری» تغییر دهید."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"میان‌بر <xliff:g id="SERVICE">%1$s</xliff:g> روشن شود؟"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"با پایین نگه داشتن هردو کلید میزان صدا به‌مدت چند ثانیه، <xliff:g id="SERVICE">%1$s</xliff:g> (یکی از ویژگی‌های دسترس‌پذیری) روشن می‌شود. با این کار نحوه عملکرد دستگاهتان تغییر می‌کند.\n\nمی‌توانید در «تنظیمات &gt; دسترس‌پذیری»،‌این میان‌بر را به ویژگی دیگری تغییر دهید."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"روشن شود"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 5c7b4a7..4ce9a323 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Jatka sormenjäljen tai näytön lukituksen avulla"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Sormenjälkikuvake"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Kasvojentunnistusavaus"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Face Unlockiin liittyvä ongelma"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Jatka kasvojentunnistuksen tai näytön lukituksen avulla"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Kasvokuvake"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lue synkronointiasetuksia"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Antaa sovelluksen lukea tilien synkronointiasetuksia. Sovellus voi esimerkiksi määrittää, onko Henkilöt-sovellus synkronoitu tilin kanssa."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kun pikanäppäin on käytössä, voit käynnistää esteettömyystoiminnon pitämällä molempia äänenvoimakkuuspainikkeita painettuna kolmen sekunnin ajan."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Laitetaanko esteettömyysominaisuuksien pikavalinta päälle?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Molempien äänenvoimakkuuspainikkeiden painaminen muutaman sekunnin ajan laittaa esteettömyysominaisuudet päälle. Tämä voi muuttaa laitteesi toimintaa.\n\nNykyiset ominaisuudet:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nVoit muuttaa valittuja ominaisuuksia kohdassa Asetukset &gt; Esteettömyys."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Laitetaanko pikavalinta (<xliff:g id="SERVICE">%1$s</xliff:g>) päälle?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Molempien äänenvoimakkuuspainikkeiden pitkään painaminen laittaa päälle esteettömyysominaisuuden <xliff:g id="SERVICE">%1$s</xliff:g>. Tämä voi muuttaa laitteesi toimintaa.\n\nVoit muuttaa tätä pikanäppäintä kohdassa Asetukset &gt; Esteettömyys."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Laita päälle"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 83a9ac2..9b16ba7 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Utilisez votre empreinte digitale ou le verrouillage de l\'écran pour continuer"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icône d\'empreinte digitale"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Déverrouillage par reconnaissance faciale"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problème avec la fonctionnalité de déverrouillage par reconnaissance faciale"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Utilisez votre visage ou le verrouillage de l\'écran pour continuer"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Icône visage"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lire les paramètres de synchronisation"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permet à l\'application d\'accéder aux paramètres de synchronisation d\'un compte. Par exemple, cette autorisation peut permettre de déterminer si l\'application Contacts est synchronisée avec un compte ou non."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quand le raccourci est activé, appuyez sur les deux boutons de volume pendant trois secondes pour lancer une fonctionnalité d\'accessibilité."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Activer le raccourci pour les fonctionnalités d\'accessibilité?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Si vous maintenez enfoncées les deux touches de volume pendant quelques secondes, vous activez les fonctionnalités d\'accessibilité. Cela peut modifier le fonctionnement de votre appareil.\n\nFonctionnalités actuellement utilisées :\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPour les modifier, sélectionnez Paramètres &gt; Accessibilité."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Activer le raccourci pour <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Si vous maintenez enfoncées les deux touches de volume pendant quelques secondes, vous activez la fonctionnalité d\'accessibilité <xliff:g id="SERVICE">%1$s</xliff:g>. Cela peut modifier le fonctionnement de votre appareil.\n\nPour attribuer ce raccourci à une autre fonctionnalité, sélectionnez Paramètres &gt; Accessibilité."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Activer"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 4fec45b..08394ad 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Utilisez votre empreinte digitale ou le verrouillage de l\'écran pour continuer"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icône d\'empreinte digitale"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Déverrouillage par reconnaissance faciale"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problème lié au déverrouillage par reconnaissance faciale"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Utilisez la reconnaissance faciale ou le verrouillage de l\'écran pour continuer"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Icône visage"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lire les paramètres de synchronisation"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permet à l\'application d\'accéder aux paramètres de synchronisation d\'un compte. Par exemple, cette autorisation peut permettre de déterminer si l\'application Contacts est synchronisée avec un compte ou non."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quand le raccourci est activé, appuyez sur les deux boutons de volume pendant trois secondes pour démarrer une fonctionnalité d\'accessibilité."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Activer le raccourci pour accéder aux fonctionnalités d\'accessibilité ?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Si vous appuyez sur les deux touches de volume pendant quelques secondes, vous activez des fonctionnalités d\'accessibilité. Cela peut affecter le fonctionnement de votre appareil.\n\nFonctionnalités actuellement utilisées :\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPour les modifier, accédez à Paramètres &gt; Accessibilité."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Activer le raccourci <xliff:g id="SERVICE">%1$s</xliff:g> ?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Si vous appuyez sur les deux touches de volume pendant quelques secondes, vous activez la fonctionnalité d\'accessibilité <xliff:g id="SERVICE">%1$s</xliff:g>. Cela peut affecter le fonctionnement de votre appareil.\n\nPour attribuer ce raccourci à une autre fonctionnalité, accédez à Paramètres &gt; Accessibilité."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Activer"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index cdbe604..47ca329 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Para continuar, utiliza a impresión dixital ou o bloqueo de pantalla"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icona de impresión dixital"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueo facial"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Produciuse un problema co desbloqueo facial"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Para continuar, utiliza o desbloqueo facial ou a credencial do dispositivo"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Icona cara"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ler a configuración de vinculación"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permite á aplicación ler a configuración de vinculación dunha conta. Por exemplo, esta acción pode determinar se a aplicación Contactos se vincula cunha conta."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Cando o atallo está activado, podes premer os dous botóns de volume durante 3 segundos para iniciar unha función de accesibilidade."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Queres activar as funcións de accesibilidade?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ao manter as dúas teclas de volume premidas durante uns segundos actívanse as funcións de accesibilidade. Esta acción pode cambiar o funcionamento do dispositivo.\n\nFuncións activadas actualmente:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPodes cambiar as funcións seleccionadas en Configuración &gt; Accesibilidade."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Queres activar o atallo a <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ao manter as dúas teclas de volume premidas durante uns segundos actívase <xliff:g id="SERVICE">%1$s</xliff:g>, unha función de accesibilidade. Esta acción pode cambiar o funcionamento do dispositivo.\n\nPodes cambiar o uso deste atallo para outra función en Configuración &gt; Accesibilidade."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Activar"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 540e7bd..133d144 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ચાલુ રાખવા માટે તમારા ફિંગરપ્રિન્ટ અથવા સ્ક્રીન લૉકનો ઉપયોગ કરો"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ફિંગરપ્રિન્ટ આયકન"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ફેસ અનલૉક"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ફેસ અનલૉકની સુવિધામાં સમસ્યા"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ચાલુ રાખવા માટે તમારા ફેસ લૉક અથવા સ્ક્રીન લૉકનો ઉપયોગ કરો"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"ચહેરા આઇકન"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"સિંક સેટિંગ વાંચો"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ઍપને એકાઉન્ટ માટે સિંક સેટિંગને વાંચવાની મંજૂરી આપે છે. ઉદાહરણ તરીકે, આ એકાઉન્ટ સાથે લોકો ઍપ સિંક થઈ છે કે કેમ તે નિર્ધારિત કરી શકે છે."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"જ્યારે શૉર્ટકટ ચાલુ હોય, ત્યારે બન્ને વૉલ્યૂમ બટનને 3 સેકન્ડ સુધી દબાવી રાખવાથી ઍક્સેસિબિલિટી સુવિધા શરૂ થઈ જશે."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ઍક્સેસિબિલિટી સુવિધાઓ માટે શૉર્ટકટ ચાલુ કરીએ?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"બન્ને વૉલ્યૂમ કીને થોડી સેકન્ડ સુધી દબાવી રાખવાથી ઍક્સેસિબિલિટી સુવિધાઓ ચાલુ થઈ જાય છે. આનાથી તમારા ડિવાઇસની કામ કરવાની રીત બદલાઈ શકે છે.\n\nવર્તમાન સુવિધાઓ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nતમે સેટિંગ &gt; ઍક્સેસિબિલિટીમાં જઈને પસંદ કરેલી સુવિધાઓને બદલી શકો છો."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> શૉર્ટકટ ચાલુ કરીએ?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"બન્ને વૉલ્યૂમ કીને થોડી સેકન્ડ સુધી દબાવી રાખવાથી ઍક્સેસિબિલિટી સુવિધા એવી <xliff:g id="SERVICE">%1$s</xliff:g> ચાલુ થઈ જાય છે. આનાથી તમારા ડિવાઇસની કામ કરવાની રીત બદલાઈ શકે છે.\n\nતમે સેટિંગ &gt; ઍક્સેસિબિલિટીમાં જઈને આ શૉર્ટકટને બીજી સુવિધામાં બદલી શકો છો."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ચાલુ કરો"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index b5261e0..c678650 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -326,7 +326,7 @@
     <string name="permgroupdesc_phone" msgid="270048070781478204">"फ़ोन कॉल करने और उन्हें प्रबंधित करने की अनुमति दें"</string>
     <string name="permgrouplab_sensors" msgid="9134046949784064495">"बॉडी सेंसर"</string>
     <string name="permgroupdesc_sensors" msgid="2610631290633747752">"अपने महत्वपूर्ण संकेतों के बारे में सेंसर डेटा को ऐक्सेस करें"</string>
-    <string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"विंडो की सामग्री वापस पाएं"</string>
+    <string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"विंडो का कॉन्टेंट वापस पाएं"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"उस विंडो की सामग्री की जाँच करें, जिसका आप इस्तेमाल कर रहे हैं."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"छूकर, किसी चीज़ से जुड़ी जानकारी सुनने की सुविधा चालू करें"</string>
     <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"जिन चीज़ों पर आप टैप करेंगे उन्हें ज़ोर से बोला जाएगा और स्क्रीन को जेस्चर के ज़रिए एक्सप्लोर किया जा सकेगा."</string>
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"जारी रखने के लिए, फ़िंगरप्रिंट या स्क्रीन लॉक क्रेडेंशियल डालकर पुष्टि करें"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"फ़िंगरप्रिंट आइकॉन"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"फ़ेस अनलॉक"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"फ़ेस अनलॉक से जुड़ी समस्या"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"जारी रखने के लिए, अपना चेहरा दिखाकर या स्क्रीन लॉक क्रेडेंशियल डालकर पुष्टि करें"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"चेहरे का आइकॉन"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"समन्वयन सेटिंग पढ़ें"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ऐप्स  को किसी खाते की समन्वयन सेटिंग पढ़ने देता है. उदाहरण के लिए, इससे यह तय किया जा सकता है कि लोग ऐप्स  किसी खाते के साथ समन्‍वयित है या नहीं."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"शॉर्टकट के चालू होने पर, दाेनाें वॉल्यूम बटन (आवाज़ कम या ज़्यादा करने वाले बटन) को तीन सेकंड तक दबाने से, सुलभता सुविधा शुरू हाे जाएगी."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"क्या आप सुलभता सुविधाओं के लिए शॉर्टकट चालू करना चाहते हैं?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"आवाज़ कम और ज़्यादा करने वाले दोनों बटन को कुछ सेकंड तक दबाकर रखने से सुलभता सुविधाएं चालू हो जाती हैं. ऐसा करने से आपके डिवाइस के काम करने के तरीके में बदलाव हो सकता है.\n\nमौजूदा सुविधाएं:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nआप सेटिंग और सुलभता में जाकर चुनी हुई सुविधाएं बदल सकते हैं."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"क्या आप <xliff:g id="SERVICE">%1$s</xliff:g> शॉर्टकट चालू करना चाहते हैं?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"आवाज़ कम और ज़्यादा करने वाले दोनों बटन को कुछ सेकंड तक दबाकर रखने से <xliff:g id="SERVICE">%1$s</xliff:g> चालू हो जाती है, जो एक सुलभता सुविधा है. ऐसा करने से आपके डिवाइस के काम करने के तरीके में बदलाव हो सकता है.\n\nआप सेटिंग और सुलभता में जाकर इस शॉर्टकट को किसी दूसरी सुविधा के लिए बदल सकते हैं."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"चालू करें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 281cf85..35cd2f5 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -612,6 +612,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Za nastavak se identificirajte otiskom prsta ili vjerodajnicom zaključavanja zaslona"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona otiska prsta"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Otključavanje licem"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Poteškoće s otključavanjem licem"</string>
@@ -664,6 +666,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Za nastavak se identificirajte licem ili vjerodajnicom zaključavanja zaslona"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Ikona lica"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"čitanje postavki sinkronizacije"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Aplikaciji omogućuje čitanje postavki sinkronizacije za račun. Time se, primjerice, može utvrditi je li aplikacija Osobe sinkronizirana s računom."</string>
@@ -1714,7 +1718,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kad je taj prečac uključen, pritiskom na obje tipke za glasnoću na tri sekunde pokrenut će se značajka pristupačnosti."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Želite li uključiti prečac za značajke pristupačnosti?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Značajke pristupačnosti uključuju se ako na nekoliko sekundi pritisnete obje tipke za glasnoću. Time se može promijeniti način na koji vaš uređaj radi.\n\nTrenutačne značajke:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nOdabrane značajke možete promijeniti u odjeljku Postavke &gt; Pristupačnost."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Želite li uključiti prečac za uslugu <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ako na nekoliko sekundi pritisnete obje tipke za glasnoću, uključuje se značajka pristupačnosti <xliff:g id="SERVICE">%1$s</xliff:g>. Time se može promijeniti način na koji vaš uređaj radi.\n\nZnačajku na koju se taj prečac odnosi možete promijeniti u odjeljku Postavke &gt; Pristupačnost."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Uključi"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 9e0232d..2e383ec 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"A folytatás ujjlenyomattal vagy a képernyőzár feloldásával lehetséges"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ujjlenyomat ikon"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Arcalapú feloldás"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Arcalapú feloldással kapcsolatos problémák"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"A folytatás arcalapú feloldással vagy a képernyőzár feloldásával lehetséges"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Arcikon"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"szinkronizálási beállítások olvasása"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Lehetővé teszi az alkalmazás számára egy fiók szinkronizálási beállításainak beolvasását. Például ellenőrizheti, hogy a Személyek alkalmazás szinkronizálva van-e egy fiókkal."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Ha a gyorsparancs aktív, akkor a két hangerőgomb három másodpercig tartó együttes lenyomásával kisegítő funkciót indíthat el."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Bekapcsol gyorsparancsot a kisegítő lehetőségekhez?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"A kisegítő lehetőségek bekapcsolásához tartsa nyomva néhány másodpercig mindkét hangerőgombot. Ez hatással lehet az eszköz működésére.\n\nJelenlegi funkciók:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nA kiválasztott funkciókat a Beállítások &gt; Kisegítő lehetőségek pontban módosíthatja."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Bekapcsolja a(z) <xliff:g id="SERVICE">%1$s</xliff:g> szolgáltatás gyorsparancsát?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"A(z) <xliff:g id="SERVICE">%1$s</xliff:g> kisegítő lehetőség bekapcsolásához tartsa nyomva néhány másodpercig mindkét hangerőgombot. Ez hatással lehet az eszköz működésére.\n\nEzt a gyorsparancsot a Beállítások &gt; Kisegítő lehetőségek pontban módosíthatja másik funkció használatára."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Bekapcsolom"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 6fdf577..f4c0316 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Շարունակելու համար օգտագործեք ձեր մատնահետքը կամ էկրանի կողպումը"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Մատնահետքի պատկերակ"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Դեմքով ապակողպում"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Դեմքով ապակողպման հետ կապված խնդիր"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Շարունակելու համար օգտագործեք ձեր դեմքը կամ էկրանի կողպումը"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Դեմքի պատկերակ"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"կարդալ համաժամացման կարգավորումները"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Թույլ է տալիս հավելվածին կարդալ համաժամացման կարգավորումները հաշվի համար: Օրինակ՝ այն կարող է որոշել, արդյոք Մարդիկ հավելվածը համաժամացված է հաշվի հետ:"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Հատուկ գործառույթն օգտագործելու համար սեղմեք և 3 վայրկյան սեղմած պահեք ձայնի ուժգնության երկու կոճակները, երբ գործառույթը միացված է:"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Միացնե՞լ հատուկ գործառույթների դյուրանցումը"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ձայնի կարգավորման երկու կոճակները մի քանի վայրկյան սեղմած պահելով կմիացնեք հատուկ գործառույթները։ Դրա արդյունքում սարքի աշխատաեղանակը կարող է փոխվել։\n\nԸնթացիկ գործառույթներ՝\n<xliff:g id="SERVICE">%1$s</xliff:g>\nԸնտրված գործառույթները փոխելու համար անցեք Կարգավորումներ &gt; Հատուկ գործառույթներ։"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Միացնե՞լ <xliff:g id="SERVICE">%1$s</xliff:g>-ի դյուրանցումը"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ձայնի կարգավորման երկու կոճակները մի քանի վայրկյան սեղմած պահելով կմիացնեք <xliff:g id="SERVICE">%1$s</xliff:g> ծառայությունը, որը հատուկ գործառույթ է։ Դրա արդյունքում սարքի աշխատաեղանակը կարող է փոխվել։\n\nԱյս դյուրանցումը մեկ այլ գործառույթով փոխելու համար անցեք Կարգավորումներ &gt; Հատուկ գործառույթներ։"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Միացնել"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 1988b40..47dd2a2 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -58,8 +58,8 @@
     <string name="meid" msgid="3291227361605924674">"MEID"</string>
     <string name="ClipMmi" msgid="4110549342447630629">"Nomor Penelepon Masuk"</string>
     <string name="ClirMmi" msgid="6752346475055446417">"Menyembunyikan ID Penelepon untuk Panggilan Keluar"</string>
-    <string name="ColpMmi" msgid="4736462893284419302">"ID Saluran yang Tersambung"</string>
-    <string name="ColrMmi" msgid="5889782479745764278">"Batasan ID Saluran yang Tersambung"</string>
+    <string name="ColpMmi" msgid="4736462893284419302">"ID Saluran yang Terhubung"</string>
+    <string name="ColrMmi" msgid="5889782479745764278">"Batasan ID Saluran yang Terhubung"</string>
     <string name="CfMmi" msgid="8390012691099787178">"Penerusan panggilan"</string>
     <string name="CwMmi" msgid="3164609577675404761">"Nada tunggu"</string>
     <string name="BaMmi" msgid="7205614070543372167">"Pemblokiran panggilan"</string>
@@ -162,7 +162,7 @@
     <string name="httpErrorUnsupportedAuthScheme" msgid="3976195595501606787">"Skema autentikasi situs tidak didukung."</string>
     <string name="httpErrorAuth" msgid="469553140922938968">"Tidak dapat mengautentikasi."</string>
     <string name="httpErrorProxyAuth" msgid="7229662162030113406">"Autentikasi via proxy server gagal."</string>
-    <string name="httpErrorConnect" msgid="3295081579893205617">"Tidak dapat tersambung ke server."</string>
+    <string name="httpErrorConnect" msgid="3295081579893205617">"Tidak dapat terhubung ke server."</string>
     <string name="httpErrorIO" msgid="3860318696166314490">"Tidak dapat berkomunikasi dengan server. Coba lagi nanti."</string>
     <string name="httpErrorTimeout" msgid="7446272815190334204">"Koneksi ke server terputus."</string>
     <string name="httpErrorRedirectLoop" msgid="8455757777509512098">"Halaman ini berisi terlalu banyak pengalihan server."</string>
@@ -468,7 +468,7 @@
     <string name="permlab_accessImsCallService" msgid="442192920714863782">"akses layanan panggilan IMS"</string>
     <string name="permdesc_accessImsCallService" msgid="6328551241649687162">"Memungkinkan aplikasi menggunakan layanan IMS untuk melakukan panggilan tanpa campur tangan Anda."</string>
     <string name="permlab_readPhoneState" msgid="8138526903259297969">"baca identitas dan status ponsel"</string>
-    <string name="permdesc_readPhoneState" msgid="7229063553502788058">"Memungkinkan aplikasi mengakses fitur telepon perangkat. Izin ini memungkinkan aplikasi menentukan nomor telepon dan ID perangkat, apakah suatu panggilan aktif atau tidak, dan nomor jarak jauh yang tersambung oleh sebuah panggilan."</string>
+    <string name="permdesc_readPhoneState" msgid="7229063553502788058">"Memungkinkan aplikasi mengakses fitur telepon perangkat. Izin ini memungkinkan aplikasi menentukan nomor telepon dan ID perangkat, apakah suatu panggilan aktif atau tidak, dan nomor jarak jauh yang terhubung oleh sebuah panggilan."</string>
     <string name="permlab_manageOwnCalls" msgid="9033349060307561370">"sambungkan panggilan telepon melalui sistem"</string>
     <string name="permdesc_manageOwnCalls" msgid="4431178362202142574">"Mengizinkan aplikasi menyambungkan panggilan telepon melalui sistem untuk menyempurnakan pengalaman menelepon."</string>
     <string name="permlab_callCompanionApp" msgid="3654373653014126884">"melihat dan mengontrol panggilan melalui sistem."</string>
@@ -504,7 +504,7 @@
     <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"Mengizinkan aplikasi mendapatkan daftar akun yang dikenal oleh perangkat Android TV. Ini mungkin mencakup akun yang dibuat oleh aplikasi yang telah Anda instal."</string>
     <string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"Memungkinkan aplikasi mendapatkan daftar akun yang dikenal oleh ponsel. Ini mungkin termasuk akun yang dibuat oleh aplikasi yang telah Anda instal."</string>
     <string name="permlab_accessNetworkState" msgid="2349126720783633918">"lihat koneksi jaringan"</string>
-    <string name="permdesc_accessNetworkState" msgid="4394564702881662849">"Memungkinkan aplikasi melihat informasi tentang koneksi jaringan, misalnya jaringan yang ada dan tersambung."</string>
+    <string name="permdesc_accessNetworkState" msgid="4394564702881662849">"Memungkinkan aplikasi melihat informasi tentang koneksi jaringan, misalnya jaringan yang ada dan terhubung."</string>
     <string name="permlab_createNetworkSockets" msgid="3224420491603590541">"dapatkan akses jaringan penuh"</string>
     <string name="permdesc_createNetworkSockets" msgid="7722020828749535988">"Memungkinkan aplikasi membuat soket jaringan dan menggunakan protokol jaringan khusus. Browser dan aplikasi lain menyediakan sarana untuk mengirim data ke internet sehingga izin ini tidak diperlukan untuk mengirim data ke internet."</string>
     <string name="permlab_changeNetworkState" msgid="8945711637530425586">"ubah konektivitas jaringan"</string>
@@ -512,7 +512,7 @@
     <string name="permlab_changeTetherState" msgid="9079611809931863861">"mengubah konektivitas yang tertambat"</string>
     <string name="permdesc_changeTetherState" msgid="3025129606422533085">"Mengizinkan apl mengubah status konektivitas jaringan yang tertambat."</string>
     <string name="permlab_accessWifiState" msgid="5552488500317911052">"lihat sambungan Wi-Fi"</string>
-    <string name="permdesc_accessWifiState" msgid="6913641669259483363">"Memungkinkan aplikasi melihat informasi tentang jaringan Wi-Fi, misalnya apakah Wi-Fi diaktifkan dan nama perangkat Wi-Fi yang tersambung."</string>
+    <string name="permdesc_accessWifiState" msgid="6913641669259483363">"Memungkinkan aplikasi melihat informasi tentang jaringan Wi-Fi, misalnya apakah Wi-Fi diaktifkan dan nama perangkat Wi-Fi yang terhubung."</string>
     <string name="permlab_changeWifiState" msgid="7947824109713181554">"sambung dan putuskan Wi-Fi"</string>
     <string name="permdesc_changeWifiState" msgid="7170350070554505384">"Memungkinkan aplikasi menyambung ke dan memutus dari titik akses Wi-Fi, dan mengubah konfigurasi perangkat untuk jaringan Wi-Fi."</string>
     <string name="permlab_changeWifiMulticastState" msgid="285626875870754696">"Izinkan penerimaan Wi-Fi Multicast"</string>
@@ -524,14 +524,14 @@
     <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"Mengizinkan aplikasi mengonfigurasi Bluetooth di perangkat Android TV, serta menemukan dan menyambungkan dengan perangkat jarak jauh."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"Mengizinkan apl mengonfigurasi ponsel Bluetooth lokal, dan menemukan serta menyandingkan dengan perangkat jarak jauh."</string>
     <string name="permlab_accessWimaxState" msgid="7029563339012437434">"sambungkan dan putuskan dari WiMAX"</string>
-    <string name="permdesc_accessWimaxState" msgid="5372734776802067708">"Memungkinkan aplikasi menentukan apakah WiMAX diaktifkan dan informasi tentang jaringan WiMAX apa saja yang tersambung."</string>
+    <string name="permdesc_accessWimaxState" msgid="5372734776802067708">"Memungkinkan aplikasi menentukan apakah WiMAX diaktifkan dan informasi tentang jaringan WiMAX apa saja yang terhubung."</string>
     <string name="permlab_changeWimaxState" msgid="6223305780806267462">"Ganti status WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="4011097664859480108">"Memungkinkan aplikasi menyambungkan tablet ke dan memutus tablet dari jaringan WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="tv" msgid="5373274458799425276">"Mengizinkan aplikasi menghubungkan perangkat Android TV ke, dan memutuskan hubungan perangkat Android TV dari, jaringan WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="1551666203780202101">"Memungkinkan aplikasi menyambungkan ponsel ke dan memutus ponsel dari jaringan WiMAX."</string>
     <string name="permlab_bluetooth" msgid="586333280736937209">"sambungkan dengan perangkat Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Memungkinkan aplikasi melihat konfigurasi Bluetooth di tablet, dan membuat serta menerima sambungan dengan perangkat yang disandingkan."</string>
-    <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Mengizinkan aplikasi melihat konfigurasi Bluetooth di perangkat Android TV, serta melakukan dan menerima sambungan dengan perangkat yang tersambung."</string>
+    <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Mengizinkan aplikasi melihat konfigurasi Bluetooth di perangkat Android TV, serta melakukan dan menerima sambungan dengan perangkat yang terhubung."</string>
     <string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Memungkinkan aplikasi melihat konfigurasi Bluetooth di ponsel, dan membuat serta menerima sambungan dengan perangkat yang disandingkan."</string>
     <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"temukan &amp; sambungkan perangkat Bluetooth di sekitar"</string>
     <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Mengizinkan aplikasi menemukan dan menyambungkan perangkat Bluetooth di sekitar"</string>
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Gunakan sidik jari atau kunci layar untuk melanjutkan"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon sidik jari"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Face Unlock"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Masalah pada Face Unlock"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gunakan face lock atau kunci layar untuk melanjutkan"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Ikon wajah"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"baca setelan sinkronisasi"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Memungkinkan aplikasi membaca setelan sinkronisasi untuk sebuah akun. Misalnya, izin ini dapat menentukan apakah aplikasi Orang disinkronkan dengan sebuah akun."</string>
@@ -1366,7 +1370,7 @@
     <string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP via USB diaktifkan"</string>
     <string name="usb_tether_notification_title" msgid="8828527870612663771">"Tethering USB diaktifkan"</string>
     <string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI via USB diaktifkan"</string>
-    <string name="usb_accessory_notification_title" msgid="1385394660861956980">"Aksesori USB tersambung"</string>
+    <string name="usb_accessory_notification_title" msgid="1385394660861956980">"Aksesori USB terhubung"</string>
     <string name="usb_notification_message" msgid="4715163067192110676">"Ketuk untuk opsi lainnya."</string>
     <string name="usb_power_notification_message" msgid="7284765627437897702">"Mengisi daya perangkat yang terhubung. Ketuk untuk opsi lainnya."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Aksesori audio analog terdeteksi"</string>
@@ -1498,9 +1502,9 @@
     <string name="vpn_title" msgid="5906991595291514182">"VPN diaktifkan"</string>
     <string name="vpn_title_long" msgid="6834144390504619998">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="2275388920267251078">"Ketuk untuk mengelola jaringan."</string>
-    <string name="vpn_text_long" msgid="278540576806169831">"Tersambung ke <xliff:g id="SESSION">%s</xliff:g>. Ketuk untuk mengelola jaringan."</string>
+    <string name="vpn_text_long" msgid="278540576806169831">"Terhubung ke <xliff:g id="SESSION">%s</xliff:g>. Ketuk untuk mengelola jaringan."</string>
     <string name="vpn_lockdown_connecting" msgid="6096725311950342607">"Menyambungkan VPN selalu aktif..."</string>
-    <string name="vpn_lockdown_connected" msgid="2853127976590658469">"VPN selalu aktif tersambung"</string>
+    <string name="vpn_lockdown_connected" msgid="2853127976590658469">"VPN selalu aktif terhubung"</string>
     <string name="vpn_lockdown_disconnected" msgid="5573611651300764955">"Terputus dari VPN yang selalu aktif"</string>
     <string name="vpn_lockdown_error" msgid="4453048646854247947">"Tidak dapat terhubung ke VPN yang selalu aktif"</string>
     <string name="vpn_lockdown_config" msgid="8331697329868252169">"Ubah setelan jaringan atau VPN"</string>
@@ -1635,7 +1639,7 @@
     <string name="media_route_chooser_extended_settings" msgid="2506352159381327741">"Setelan"</string>
     <string name="media_route_controller_disconnect" msgid="7362617572732576959">"Putuskan koneksi"</string>
     <string name="media_route_status_scanning" msgid="8045156315309594482">"Memindai..."</string>
-    <string name="media_route_status_connecting" msgid="5845597961412010540">"Menyambung..."</string>
+    <string name="media_route_status_connecting" msgid="5845597961412010540">"Menghubungkan..."</string>
     <string name="media_route_status_available" msgid="1477537663492007608">"Tersedia"</string>
     <string name="media_route_status_not_available" msgid="480912417977515261">"Tidak tersedia"</string>
     <string name="media_route_status_in_use" msgid="6684112905244944724">"Sedang digunakan"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Saat pintasan aktif, menekan kedua tombol volume selama 3 detik akan memulai fitur aksesibilitas."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Aktifkan pintasan untuk fitur aksesibilitas?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Menahan kedua tombol volume selama beberapa detik akan mengaktifkan fitur aksesibilitas. Tindakan ini dapat mengubah cara kerja perangkat Anda.\n\nFitur saat ini:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nAnda dapat mengubah fitur yang dipilih di Setelan &gt; Aksesibilitas."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Aktifkan pintasan <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Menahan kedua tombol volume selama beberapa detik akan mengaktifkan <xliff:g id="SERVICE">%1$s</xliff:g>, yang merupakan fitur aksesibilitas. Tindakan ini dapat mengubah cara kerja perangkat Anda.\n\nAnda dapat mengubah pintasan ini ke fitur lain di Setelan &gt; Aksesibilitas."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktifkan"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index abd7735..59d0e4b 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Notaðu fingrafar eða skjálás til að halda áfram"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingrafaratákn"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Andlitskenni"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Vandamál varðandi andlitskenni"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Notaðu andlitið eða skjálás til að halda áfram"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Andlitstákn"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lesa samstillingar"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Leyfir forriti að lesa kosti samstillingar fyrir reikning. Þetta er til dæmis hægt að nota til að komast að því hvort forritið Fólk er samstillt við reikning."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Þegar flýtileiðin er virk er kveikt á aðgengiseiginleikanum með því að halda báðum hljóðstyrkshnöppunum inni í þrjár sekúndur."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Kveikja á flýtileið fyrir aðgangseiginleika?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Kveikt er á aðgengiseiginleikum þegar báðum hljóðstyrkstökkunum er haldið inni í nokkrar sekúndur. Þetta getur breytt því hvernig tækið virkar.\n\nNúverandi eiginleikar:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nÞú getur breytt völdum eiginleikum í Stillingar &gt; Aðgengi."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Kveikja á flýtileið <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ef báðum hljóðstyrkstökkunum er haldið inni í nokkrar sekúndur er kveikt á aðgengiseiginleikanum <xliff:g id="SERVICE">%1$s</xliff:g>. Þetta getur breytt því hvernig tækið virkar.\n\nÞú getur breytt þessari flýtileið í annan eiginleika í Stillingar &gt; Aðgengi."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Kveikja"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index d44dcdf..62f87a9 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -609,6 +609,7 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Per continuare devi usare la tua impronta o il tuo blocco schermo"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Si è verificato un errore. Riprova."</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icona dell\'impronta"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Sblocco con il volto"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema con Sblocco con il volto"</string>
@@ -661,6 +662,7 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Per continuare devi usare il tuo volto o il tuo blocco schermo"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Si è verificato un errore. Riprova."</string>
     <string name="face_icon_content_description" msgid="465030547475916280">"Icona volto"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lettura impostazioni di sincronizz."</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Consente all\'applicazione di leggere le impostazioni di sincronizzazione per un account. Ad esempio, questa autorizzazione può determinare se l\'applicazione Persone è sincronizzata con un account."</string>
@@ -1692,7 +1694,7 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quando la scorciatoia è attiva, puoi premere entrambi i pulsanti del volume per tre secondi per avviare una funzione di accessibilità."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vuoi attivare la scorciatoia per le funzioni di accessibilità?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Se tieni premuti entrambi i tasti del volume per qualche secondo, vengono attivate le funzioni di accessibilità. Questa operazione potrebbe modificare il funzionamento del dispositivo.\n\nFunzioni correnti:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPuoi modificare le funzioni selezionate in Impostazioni &gt; Accessibilità."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Vuoi attivare la scorciatoia per <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Se tieni premuti entrambi i tasti del volume per qualche secondo verrà attivata la funzione di accessibilità <xliff:g id="SERVICE">%1$s</xliff:g>. Questa operazione potrebbe modificare il funzionamento del dispositivo.\n\nPuoi associare questa scorciatoia a un\'altra funzionalità in Impostazioni &gt; Accessibilità."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Attiva"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 2daf5b1..7ccec0f 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -615,6 +615,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"יש להשתמש בטביעת האצבע או בנעילת המסך כדי להמשיך"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"סמל טביעת אצבע"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"פתיחה ע\"י זיהוי הפנים"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"בעיה בפתיחה ע\"י זיהוי הפנים"</string>
@@ -667,6 +669,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"יש להשתמש בזיהוי הפנים או בנעילת המסך כדי להמשיך"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"סמל הפנים"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"קריאת הגדרות הסנכרון"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"מאפשרת לאפליקציה לקרוא את הגדרות הסנכרון של חשבון. לדוגמה, כך אפשר לדעת אם האפליקציה \'אנשים\' מסונכרנת עם חשבון כלשהו."</string>
@@ -1736,7 +1740,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"כשקיצור הדרך מופעל, לחיצה על שני לחצני עוצמת הקול למשך שלוש שניות מפעילה את תכונת הנגישות."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"האם להפעיל את מקש הקיצור לתכונות הנגישות?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"לחיצה ארוכה על שני לחצני עוצמת הקול למשך מספר שניות מפעילה את תכונות הנגישות. בעקבות זאת, ייתכן שאופן הפעולה של המכשיר ישתנה.\n\nהתכונות הנוכחיות:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nניתן לשנות את התכונות שנבחרו ב\'הגדרות\' &gt; \'נגישות\'."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"האם להפעיל את מקש הקיצור של <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"לחיצה על שני מקשי עוצמת הקול למשך מספר שניות מפעילה את תכונת הנגישות <xliff:g id="SERVICE">%1$s</xliff:g>. ייתכן שאופן הפעולה של המכשיר ישתנה בעקבות זאת.\n\nאפשר לשנות את מקשי הקיצור האלה לתכונה אחרת ב\'הגדרות\' &gt; \'נגישות\'."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"אני רוצה להפעיל"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 1f9f4ab..93fd395 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"続行するには、指紋認証または画面ロックを使用してください"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"指紋アイコン"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"顔認証"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"顔認証に関する問題"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"続行するには、顔認証または画面ロックを使用してください"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"顔アイコン"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"同期設定の読み取り"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"アカウントの同期設定の読み取りをアプリに許可します。たとえば、連絡帳アプリがアカウントと同期しているかどうかをアプリから特定できるようになります。"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ショートカットが ON の場合、両方の音量ボタンを 3 秒ほど長押しするとユーザー補助機能が起動します。"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ユーザー補助機能のショートカットを ON にしますか?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"音量大と音量小の両方のボタンを数秒ほど長押しすると、ユーザー補助機能が ON になります。この機能が ON になると、デバイスの動作が変わることがあります。\n\n現在の機能:\n<xliff:g id="SERVICE">%1$s</xliff:g>\n選択した機能は [設定] &gt; [ユーザー補助] で変更できます。"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> のショートカットを ON にしますか?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"音量大と音量小の両方のボタンを数秒ほど長押しすると、ユーザー補助機能の <xliff:g id="SERVICE">%1$s</xliff:g> が ON になります。この機能が ON になると、デバイスの動作が変わることがあります。\n\nこのショートカットは [設定] &gt; [ユーザー補助] で別の機能に変更できます。"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ON にする"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index fb17c51..3648788 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"გასაგრძელებლად გამოიყენეთ თქვენი თითის ანაბეჭდი ან ეკრანის განბლოკვის ნიმუში"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"თითის ანაბეჭდის ხატულა"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"განბლოკვა სახით"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"პრობლემა სახით განბლოკვასთან დაკავშირებით"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"გასაგრძელებლად გამოიყენეთ თქვენი სახე ან ეკრანის განბლოკვის ნიმუში"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"სახის ხატულა"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"სინქრონიზაციის პარამეტრების წაკითხვა"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"აპს შეეძლება, წაიკითხოს ანგარიშის სინქრონიზაციის პარამეტრები. მაგალითად, მას შეეძლება განსაზღვროს, არის თუ არა People აპი სინქრონიზებული ანგარიშთან."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"თუ მალსახმობი ჩართულია, ხმის ორივე ღილაკზე 3 წამის განმავლობაში დაჭერით მარტივი წვდომის ფუნქცია ჩაირთვება."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ჩაირთოს მარტივი წვდომის ფუნქციების მალსახმობი?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ხმის ორივე ღილაკზე ხანგრძლივად დაჭერა რამდენიმე წამის განმავლობაში ჩართავს მარტივი წვდომის ფუნქციებს. ამ ქმედებამ შეიძლება შეცვალოს თქვენი მოწყობილობის მუშაობის პრინციპი.\n\nამჟამინდელი ფუნქციები:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nარჩეული ფუნქციების შეცვლა შესაძლებელია აქ: პარამეტრები &gt; მარტივი წვდომა."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"ჩაირთოს <xliff:g id="SERVICE">%1$s</xliff:g>-ის მალსახმობი?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ხმის ორივე ღილაკზე რამდენიმე წამის განმავლობაში დაჭერით ჩაირთვება <xliff:g id="SERVICE">%1$s</xliff:g>, რომელიც მარტივი წვდომის ფუნქციაა. ამან შეიძლება შეცვალოს თქვენი მოწყობილობის მუშაობის პრინციპი.\n\nამ მალსახმობის შეცვლა სხვა ფუნქციით შეგიძლიათ აქ: პარამეტრები &gt; აპები."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ჩართვა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index d9fde8f..c42e849 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Жалғастыру үшін саусақ ізін немесе экран құлпын пайдаланыңыз."</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Саусақ ізі белгішесі"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Бет тану"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Бет тану функциясына қатысты мәселе шықты"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Жалғастыру үшін бетті анықтау функциясын немесе экран құлпын пайдаланыңыз."</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Бет белгішесі"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"синх параметрлерін оқу"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Қолданбаға есептік жазба синхрондау параметрлерін оқу мүмкіндігін береді. Мысалы, бұл арқылы People қолданбасының есептік жазбамен сихрондалғаны анықталуы мүмкін."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Түймелер тіркесімі қосулы кезде, екі дыбыс түймесін 3 секунд басып тұрсаңыз, \"Арнайы мүмкіндіктер\" функциясы іске қосылады."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Арнайы мүмкіндіктердің жылдам пәрмені іске қосылсын ба?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Дыбыс деңгейі пернелерін бірнеше секунд басып тұрсаңыз, арнайы мүмкіндіктер іске қосылады. Бұл – құрылғының жұмысына әсер етуі мүмкін.\n\nҚазіргі функциялар:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТаңдалған функцияларды \"Параметрлер &gt; Арнайы мүмкіндіктер\" бөлімінен өзгерте аласыз."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> жылдам пәрмені іске қосылсын ба?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Дыбыс деңгейі пернелерін бірнеше секунд басып тұрсаңыз, <xliff:g id="SERVICE">%1$s</xliff:g> арнайы қызметі іске қосылады. Бұл – құрылғының жүмысына әсер етуі мүмкін.\n\nБұл таңбашаны басқа функцияға \"Параметрлер &gt; Арнайы мүмкіндіктер\" бөлімінен өзгерте аласыз."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Қосылсын"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 716e810..6418a6e 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ប្រើការចាក់សោអេក្រង់ ឬស្នាមម្រាមដៃរបស់អ្នក ដើម្បីបន្ត"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"រូបស្នាមម្រាមដៃ"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ដោះ​សោ​តាម​​ទម្រង់​មុខ"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"មានបញ្ហា​ពាក់ព័ន្ធនឹង​មុខងារ​ដោះសោ​តាមទម្រង់មុខ"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ប្រើការចាក់សោអេក្រង់ ឬមុខរបស់អ្នក ដើម្បីបន្ត"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"រូប​ផ្ទៃមុខ"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"អាន​ការ​កំណត់​ធ្វើ​សម​កាល​កម្ម"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ឲ្យ​កម្មវិធី​អាន​ការ​កំណត់​ធ្វើ​សម​កាល​កម្ម​សម្រាប់​គណនី។ ឧទាហរណ៍ វា​អាច​កំណត់​ថា​តើ​​​កម្មវិធី​ត្រូវ​បាន​បើក​ជា​មួយ​គណនី​ដែរ​ឬទេ។"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"នៅពេលបើក​ផ្លូវកាត់ ការចុច​ប៊ូតុង​កម្រិតសំឡេង​ទាំងពីរ​រយៈពេល 3 វិនាទី​នឹង​ចាប់ផ្តើម​មុខងារ​ភាពងាយប្រើ។"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"បើក​ផ្លូវកាត់​សម្រាប់មុខងារ​ភាពងាយស្រួលឬ?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ការសង្កត់​គ្រាប់ចុច​កម្រិតសំឡេង​ទាំងពីរ​ឱ្យជាប់​រយៈពេល​ពីរបីវិនាទី​នឹងបើក​មុខងារ​ភាពងាយប្រើ។ ការធ្វើ​បែបនេះ​អាចផ្លាស់ប្ដូរ​របៀបដែល​ឧបករណ៍​របស់អ្នក​ដំណើរការ។\n\nមុខងារ​បច្ចុប្បន្ន៖\n<xliff:g id="SERVICE">%1$s</xliff:g>\nអ្នកអាច​ប្ដូរ​មុខងារ​ដែលបាន​ជ្រើសរើស​នៅក្នុង​ការកំណត់ &gt; ភាពងាយស្រួល។"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"បើក​ផ្លូវកាត់ <xliff:g id="SERVICE">%1$s</xliff:g> ឬ?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ការសង្កត់​គ្រាប់ចុច​កម្រិតសំឡេង​ទាំងពីរ​ឱ្យជាប់​រយៈពេល​ពីរបីវិនាទី​នឹងបើក <xliff:g id="SERVICE">%1$s</xliff:g> ដែលជា​មុខងារ​ភាពងាយប្រើ។ ការធ្វើ​បែបនេះ​អាចផ្លាស់ប្ដូរ​របៀបដែល​ឧបករណ៍​របស់អ្នក​ដំណើរការ។\n\nអ្នកអាច​ប្ដូរផ្លូវកាត់​នេះទៅ​មុខងារ​ផ្សេងទៀត​នៅក្នុង​ការកំណត់ &gt; ភាពងាយស្រួល។"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"បើក"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index c6ae32a..6c21e3e 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ಮುಂದುವರಿಸಲು ಫಿಂಗರ್ ಪ್ರಿಂಟ್ ಅಥವಾ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಬಳಸಿ"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಐಕಾನ್"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ಫೇಸ್ ಅನ್‌ಲಾಕ್"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ಫೇಸ್ ಅನ್‌ಲಾಕ್ ಕುರಿತು ಸಮಸ್ಯೆ ಇದೆ"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ಮುಂದುವರಿಸಲು ನಿಮ್ಮ ಮುಖ ಅಥವಾ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಬಳಸಿ"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"ಮುಖದ ಐಕಾನ್‌"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ಸಿಂಕ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ರೀಡ್‌ ಮಾಡು"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ಒಂದು ಖಾತೆಯ ಸಿಂಕ್ ಸೆಟ್ಟಿಂಗ್‍‍ಗಳನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಉದಾಹರಣೆಗೆ, ಖಾತೆಯೊಂದಿಗೆ ಜನರ ಅಪ್ಲಿಕೇಶನ್ ಸಿಂಕ್ ಮಾಡಲಾಗಿದೆಯೇ ಎಂಬುದನ್ನು ಇದು ನಿರ್ಧರಿಸಬಹುದು."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ಶಾರ್ಟ್‌ಕಟ್ ಆನ್ ಆಗಿರುವಾಗ, ಎರಡೂ ವಾಲ್ಯೂಮ್ ಬಟನ್‌ಗಳನ್ನು 3 ಸೆಕೆಂಡುಗಳ ಕಾಲ ಒತ್ತಿದರೆ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯವೊಂದು ಪ್ರಾರಂಭವಾಗುತ್ತದೆ."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯಗಳಿಗಾಗಿ ಶಾರ್ಟ್‌ಕಟ್ ಆನ್ ಮಾಡಬೇಕೇ?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ಎರಡೂ ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಕೆಲವು ಸೆಕೆಂಡುಗಳ ಕಾಲ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳುವುದರಿಂದ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯಗಳು ಆನ್ ಆಗುತ್ತವೆ. ಇದು ನಿಮ್ಮ ಸಾಧನವು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ಬದಲಾಯಿಸಬಹುದು.\n\n ಪ್ರಸ್ತುತ ವೈಶಿಷ್ಟ್ಯಗಳು:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿಯಲ್ಲಿ ಆಯ್ದ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ನೀವು ಬದಲಾಯಿಸಬಹುದು."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"ಶಾರ್ಟ್‌ಕಟ್ <xliff:g id="SERVICE">%1$s</xliff:g>ಆನ್‌ ಮಾಡಬೇಕೇ?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ಎರಡೂ ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಕೆಲವು ಸೆಕೆಂಡುಗಳ ಕಾಲ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳುವುದರಿಂದ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯವಾದ <xliff:g id="SERVICE">%1$s</xliff:g> ಆನ್ ಆಗುತ್ತದೆ. ಇದು ನಿಮ್ಮ ಸಾಧನವು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ಬದಲಾಯಿಸಬಹುದು.\n\nನೀವು ಈ ಶಾರ್ಟ್‌ಕಟ್ ಅನ್ನು ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಅಕ್ಸೆಸಿಬಿಲಿಟಿಯಲ್ಲಿನ ಮತ್ತೊಂದು ವೈಶಿಷ್ಟ್ಯಕ್ಕೆ ಬದಲಾಯಿಸಬಹುದು."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ಆನ್ ಮಾಡಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index a0054c0..4657d52 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"계속하려면 지문이나 화면 잠금을 사용하세요"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"지문 아이콘"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"얼굴 인식 잠금 해제"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"얼굴 인식 잠금 해제 문제"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"계속하려면 얼굴 또는 화면 잠금을 사용하세요"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"얼굴 아이콘"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"동기화 설정 읽기"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"앱이 계정의 동기화 설정을 읽을 수 있도록 허용합니다. 예를 들어, 계정에서 주소록 앱을 동기화할지 여부를 확인할 수 있습니다."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"단축키가 사용 설정된 경우 볼륨 버튼 두 개를 동시에 3초간 누르면 접근성 기능이 시작됩니다."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"접근성 기능 바로가기를 사용 설정하시겠습니까?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"볼륨 키 2개를 몇 초 동안 길게 누르면 접근성 기능이 사용 설정됩니다. 이때 기기 작동 방식이 달라질 수 있습니다.\n\n현재 기능:\n<xliff:g id="SERVICE">%1$s</xliff:g>\n설정 &gt; 접근성에서 선택한 기능을 변경할 수 있습니다."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> 바로가기를 사용 설정하시겠습니까?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"볼륨 키 2개를 몇 초 동안 길게 누르면 <xliff:g id="SERVICE">%1$s</xliff:g> 접근성 기능이 사용 설정됩니다. 이렇게 되면 기기 작동 방식이 달라질 수 있습니다.\n\n설정 &gt; 접근성에서 이 단축키를 다른 기능으로 변경할 수 있습니다."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"사용"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 45624a4..2458e11 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Улантуу үчүн манжа изин же экрандын кулпусун колдонуңуз"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Манжа изинин сүрөтчөсү"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Жүзүнөн таанып ачуу"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Жүзүнөн таанып ачуу функциясында маселе келип чыкты"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Улантуу үчүн жүзүңүздү же экрандын кулпусун колдонуңуз"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Жүздүн сүрөтчөсү"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"шайкештирүү жөндөөлөрүн окуу"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Колдонмого эсеп менен синхрондошуу тууралоолорун окуганга уруксат берет. Мисалы, Кишилер колдонмосу эсеп менен синхрондошкондугун аныктай алат."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Атайын мүмкүнчүлүктөр функциясын пайдалануу үчүн ал күйгүзүлгөндө, үндү катуулатып/акырындаткан эки баскычты тең 3 секунддай коё бербей басып туруңуз."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Атайын мүмкүнчүлүктөрдүн ыкчам баскычын иштетесизби?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Атайын мүмкүнчүлүктөр функциясын иштетүү үчүн үндү чоңойтуп/кичирейтүү баскычтарын бир нече секунд коё бербей басып туруңуз. Ушуну менен, түзмөгүңүз бир аз башкача иштеп калышы мүмкүн.\n\nУчурдагы функциялар:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТандалган функцияларды өзгөртүү үчүн Жөндөөлөр &gt; Атайын мүмкүнчүлүктөр бөлүмүнө өтүңүз."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> ыкчам баскычын иштетесизби?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"<xliff:g id="SERVICE">%1$s</xliff:g> кызматын иштетүү үчүн үндү чоңойтуп/кичирейтүү баскычтарын бир нече секунд коё бербей басып туруңуз. Ушуну менен, түзмөгүңүз бир аз башкача иштеп калышы мүмкүн.\n\nБаскычтардын ушул айкалышын башка функцияга дайындоо үчүн, Жөндөөлөр &gt; Атайын мүмкүнчүлүктөр бөлүмүнө өтүңүз."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Ооба"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 7544c39..935df5a 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ໃຊ້ລາຍນິ້ວມື ຫຼື ການລັອກໜ້າຈໍຂອງທ່ານເພື່ອດຳເນີນການຕໍ່"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ໄອຄອນລາຍນິ້ວມື"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ປົດລັອກດ້ວຍໜ້າ"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ເກີດບັນຫາກັບການປົດລັອກດ້ວຍໜ້າ"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ໃຊ້ໃບໜ້າ ຫຼື ການລັອກໜ້າຈໍຂອງທ່ານເພື່ອດຳເນີນການຕໍ່"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"ໄອຄອນໃບໜ້າ"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ອ່ານການຕັ້ງຄ່າຊິ້ງຂໍ້ມູນ"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ອະນຸຍາດໃຫ້ແອັບຯ ອ່ານການຕັ້ງຄ່າການຊິ້ງຂໍ້ມູນຂອງບັນຊີໄດ້. ຕົວຢ່າງເຊັ່ນ: ມັນຈະສາມາດກວດສອບໄດ້ແອັບຯ People ຖືກຊິ້ງຂໍ້ມູນກັບບັນຊີໃດນຶ່ງແລ້ວຫຼືຍັງ."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ເມື່ອເປີດໃຊ້ທາງລັດແລ້ວ, ການກົດປຸ່ມລະດັບສຽງທັງສອງຄ້າງໄວ້ 3 ວິນາທີຈະເປັນການເລີ່ມຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງ."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ເປີດໃຊ້ທາງລັດສຳລັບຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງບໍ?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ກົດປຸ່ມລະດັບສຽງທັງສອງຄ້າງໄວ້ສອງສາມວິນາທີເພື່ອເປີດໃຊ້ຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງ. ນີ້ອາດປ່ຽນວິທີການເຮັດວຽກຂອງອຸປະກອນທ່ານ.\n\nຄຸນສົມບັດປັດຈຸບັນ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nທ່ານສາມາດປ່ຽນຄຸນສົມບັດທີ່ເລືອກໄດ້ໃນການຕັ້ງຄ່າ &gt; ການຊ່ວຍເຂົ້າເຖິງ."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"ເປີດໃຊ້ທາງລັດ <xliff:g id="SERVICE">%1$s</xliff:g> ບໍ?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ກົດປຸ່ມລະດັບສຽງທັງສອງຄ້າງໄວ້ສອງສາມວິນາທີເພື່ອເປີດໃຊ້ <xliff:g id="SERVICE">%1$s</xliff:g>, ຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງ. ນີ້ອາດປ່ຽນວິທີການເຮັດວຽກຂອງອຸປະກອນທ່ານ.\n\nທ່ານສາມາດປ່ຽນທາງລັດນີ້ເປັນຄຸນສົມບັດອື່ນໄດ້ໃນການຕັ້ງຄ່າ &gt; ການຊ່ວຍເຂົ້າເຖິງ."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ເປີດໃຊ້"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 18ac1b1..7317f5f 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -615,6 +615,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Jei norite tęsti, naudokite kontrolinį kodą arba ekrano užraktą"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Piršto antspaudo piktograma"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Atrakinimas pagal veidą"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Su atrakinimu pagal veidą susijusi problema"</string>
@@ -667,6 +669,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Jei norite tęsti, naudokite veido atpažinimo funkciją arba ekrano užraktą"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Veido pkt."</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"skaityti sinchronizavimo nustatymus"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Leidžiama programai skaityti ir sinchronizuoti paskyros nustatymus. Pvz., taip gali būti nustatoma, ar su paskyra sinchronizuota Žmonių programa."</string>
@@ -1736,7 +1740,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kai spartusis klavišas įjungtas, paspaudus abu garsumo mygtukus ir palaikius 3 sekundes bus įjungta pritaikymo neįgaliesiems funkcija."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Įjungti pritaikymo neįgaliesiems funkcijų spartųjį klavišą?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Paspaudus abu garsumo klavišus ir palaikius kelias sekundes įjungiamos pritaikymo neįgaliesiems funkcijos. Tai gali pakeisti įrenginio veikimą.\n\nDabartinės funkcijos:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPasirinktas funkcijas galite pakeisti skiltyje „Nustatymai“ &gt; „Pritaikomumas“."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Įjungti „<xliff:g id="SERVICE">%1$s</xliff:g>“ spartųjį klavišą?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Paspaudus abu garsumo klavišus ir palaikius kelias sekundes įjungiama pritaikymo neįgaliesiems funkcija „<xliff:g id="SERVICE">%1$s</xliff:g>“. Tai gali pakeisti įrenginio veikimą.\n\nGalite pakeisti šį spartųjį klavišą į kitą funkciją skiltyje „Nustatymai“ &gt; „Pritaikomumas“."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Įjungti"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 1799e38..db4587e 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -612,6 +612,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Izmantojiet pirksta nospiedumu vai ekrāna bloķēšanas opciju, lai turpinātu"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Pirksta nospieduma ikona"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Autorizācija pēc sejas"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problēma ar autorizāciju pēc sejas"</string>
@@ -664,6 +666,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Izmantojiet autorizāciju pēc sejas vai ekrāna bloķēšanas opciju, lai turpinātu"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Sejas ikona"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lasīt sinhronizācijas iestatījumus"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Ļauj lietotnei lasīt konta sinhronizācijas iestatījumus. Piemēram, šādi var noteikt, vai lietotne Personas ir sinhronizēta ar kontu."</string>
@@ -1714,7 +1718,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kad īsinājumtaustiņš ir ieslēgts, nospiežot abas skaļuma pogas un 3 sekundes turot tās, tiks aktivizēta pieejamības funkcija."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vai ieslēgt pieejamības funkciju saīsni?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Turot nospiestus abus skaļuma taustiņus dažas sekundes, tiek ieslēgtas pieejamības funkcijas. Tas var mainīt ierīces darbību.\n\nPašreizējās funkcijas:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nAtlasītās funkcijas varat mainīt šeit: Iestatījumi &gt; Pieejamība."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Vai ieslēgt <xliff:g id="SERVICE">%1$s</xliff:g> saīsni?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Turot nospiestus abus skaļuma taustiņus dažas sekundes, tiek ieslēgta pieejamības funkcija <xliff:g id="SERVICE">%1$s</xliff:g>. Tas var mainīt ierīces darbību.\n\nŠo saīsni uz citu funkciju varat mainīt šeit: Iestatījumi &gt; Pieejamība."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Ieslēgt"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 39c3b8a..09f6230 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Користете го вашиот отпечаток или заклучување екран за да продолжите"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Икона за отпечатоци"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Отклучување со лик"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Проблем со „Отклучување со лик“"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Користете отклучување со лик или заклучување екран за да продолжите"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Икона"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"чита поставки за синхронизација"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Овозможува апликацијата да ги чита поставките за синхронизирање на сметка. На пример, така може да се утврди дали апликацијата „Луѓе“ е синхронизирана со сметка."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Кога е вклучена кратенката, ако ги притиснете двете копчиња за јачина на звук во времетраење од 3 секунди, ќе се стартува функција за пристапност."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Да се вклучи кратенка за функциите за пристапност?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ако ги задржите притиснати двете копчиња за јачина на звук неколку секунди, ќе се вклучат функциите за пристапност. Ова може да го промени начинот на функционирање на уредот.\n\nТековни функции:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nМоже да ги промените избраните функции во „Поставки &gt; Пристапност“."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Да се вклучи кратенка за <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ако ги задржите притиснати двете копчиња за јачина на звук неколку секунди, ќе се вклучи функцијата за пристапност <xliff:g id="SERVICE">%1$s</xliff:g>. Ова може да го промени начинот на функционирање на уредот.\n\nМоже да ја измените кратенкава да биде за друга функција во „Поставки &gt; Пристапност“."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Вклучи"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 5e8b1f1..f36e02f 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"തുടരാൻ നിങ്ങളുടെ ഫിംഗർപ്രിന്റ്‌ അല്ലെങ്കിൽ സ്‌ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ഫിംഗർപ്രിന്റ് ഐക്കൺ"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ഫെയ്‌സ് അൺലോക്ക്"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ഫെയ്‌സ് അൺലോക്കുമായി ബന്ധപ്പെട്ട പ്രശ്നം"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"തുടരാൻ നിങ്ങളുടെ മുഖം‌ അല്ലെങ്കിൽ സ്‌ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"മുഖത്തിന്റെ ഐക്കൺ"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"സമന്വയ ക്രമീകരണങ്ങൾ റീഡുചെയ്യുക"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ഒരു അക്കൗണ്ടിനായി സമന്വയ ക്രമീകരണങ്ങൾ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഉദാഹരണത്തിന്, ആളുകൾ അപ്ലിക്കേഷൻ ഒരു അക്കൗണ്ടിൽ സമന്വയിപ്പിച്ചിട്ടുണ്ടോയെന്നത് നിർണ്ണയിക്കാൻ ഇതിനാകും."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"കുറുക്കുവഴി ഓണായിരിക്കുമ്പോൾ, രണ്ട് വോളിയം ബട്ടണുകളും 3 സെക്കൻഡ് നേരത്തേക്ക് അമർത്തുന്നത് ഉപയോഗസഹായി ഫീച്ചർ ആരംഭിക്കും."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ഉപയോഗസഹായി ഫീച്ചറുകൾക്കുള്ള കുറുക്കുവഴി ഓണാക്കണോ?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"രണ്ട് വോളിയം കീകളും അൽപ്പ നേരത്തേക്ക് അമർത്തിപ്പിടിക്കുന്നത്, ഉപയോഗസഹായി ഫീച്ചറുകൾ ഓണാക്കുന്നു. നിങ്ങളുടെ ഉപകരണം പ്രവർത്തിക്കുന്ന രീതിയെ ഇത് മാറ്റിയേക്കാം.\n\nനിലവിലുള്ള ഫീച്ചറുകൾ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nതിരഞ്ഞെടുത്ത ഫീച്ചറുകൾ ക്രമീകരണം &gt; ഉപയോഗസഹായി എന്നതിൽ മാറ്റാനാവും."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> കുറുക്കുവഴി ഓണാക്കണോ?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"രണ്ട് വോളിയം കീകളും അൽപ്പ നേരത്തേക്ക് അമർത്തിപ്പിടിക്കുന്നത് ഉപയോഗസഹായി ഫീച്ചറായ <xliff:g id="SERVICE">%1$s</xliff:g> എന്നതിനെ ഓണാക്കുന്നു. നിങ്ങളുടെ ഉപകരണം പ്രവർത്തിക്കുന്ന വിധം ഇത് മാറ്റിയേക്കാം.\n\nക്രമീകരണം &gt; ഉപയോഗസഹായി എന്നതിലെ മറ്റൊരു ഫീച്ചറിലേക്ക് നിങ്ങൾക്ക് ഈ കുറുക്കുവഴി മാറ്റാനാവും."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ഓണാക്കുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index e17b884..e35571f 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Үргэлжлүүлэхийн тулд хурууны хээ эсвэл дэлгэцийн түгжээгээ ашиглана уу"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Хурууны хээний дүрс"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Царайгаар түгжээ тайлах"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Царайгаар түгжээ тайлахтай холбоотой асуудал"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Үргэлжлүүлэхийн тулд царай эсвэл дэлгэцийн түгжээгээ ашиглана уу"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Царайны дүрс тэмдэг"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"синк тохиргоог унших"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Апп нь бүртгэлийн синк тохиргоог унших боломжтой. Жишээ нь энэ нь Хүмүүс апп бүртгэлтэй синк хийгдсэн эсэхийг тодорхойлох боломжтой."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Товчлол асаалттай үед дууны түвшний хоёр товчлуурыг хамтад нь 3 секунд дарснаар хандалтын онцлогийг эхлүүлнэ."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Хандалтын онцлогуудын товчлолыг асаах уу?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Дууны түвшний түлхүүрийг хэдэн секундийн турш зэрэг дарснаар хандалтын онцлогууд асна. Энэ нь таны төхөөрөмжийн ажиллах зарчмыг өөрчилж болзошгүй.\n\nОдоогийн онцлогууд:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТа сонгосон онцлогуудыг Тохиргоо &gt; Хандалт хэсэгт өөрчлөх боломжтой."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g>-н товчлолыг асаах уу?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Дууны түвшний түлхүүрийг хэдэн секундийн турш зэрэг дарах нь хандалтын онцлог болох <xliff:g id="SERVICE">%1$s</xliff:g>-г асаадаг. Энэ нь таны төхөөрөмжийн ажиллах зарчмыг өөрчилж болзошгүй.\n\nТа Тохиргоо &gt; Хандалт хэсэгт энэ товчлолыг өөр онцлогт оноож өөрчлөх боломжтой."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Асаах"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 424a521..45762cd 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"पुढे सुरू ठेवण्यासाठी तुमचे फिंगरप्रिंट किंवा स्क्रीन लॉक वापरा"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"फिंगरप्रिंट आयकन"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"फेस अनलॉक"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"फेस अनलॉकसंबंधित समस्या"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"पुढे सुरू ठेवण्यासाठी तुमचा चेहरा किंवा स्क्रीन लॉक वापरा"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"चेहरा आयकन"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"सिंक सेटिंग्‍ज वाचा"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"खात्याच्या सिंक सेटिंग्ज वाचण्यासाठी अ‍ॅप ला अनुमती देते. उदाहरणार्थ, हे खात्यासह लोकांचा अ‍ॅप संकालित केला आहे किंवा नाही हे निर्धारित करू शकते."</string>
@@ -1040,7 +1044,7 @@
     <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"हटवा"</string>
     <string name="search_go" msgid="2141477624421347086">"Search"</string>
     <string name="search_hint" msgid="455364685740251925">"शोधा…"</string>
-    <string name="searchview_description_search" msgid="1045552007537359343">"Search"</string>
+    <string name="searchview_description_search" msgid="1045552007537359343">"शोधा"</string>
     <string name="searchview_description_query" msgid="7430242366971716338">"शोध क्वेरी"</string>
     <string name="searchview_description_clear" msgid="1989371719192982900">"क्‍वेरी साफ करा"</string>
     <string name="searchview_description_submit" msgid="6771060386117334686">"क्वेरी सबमिट करा"</string>
@@ -1468,7 +1472,7 @@
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"झूम नियंत्रणासाठी दोनदा टॅप करा"</string>
     <string name="gadget_host_error_inflating" msgid="2449961590495198720">"विजेट जोडू शकलो नाही."</string>
     <string name="ime_action_go" msgid="5536744546326495436">"जा"</string>
-    <string name="ime_action_search" msgid="4501435960587287668">"Search"</string>
+    <string name="ime_action_search" msgid="4501435960587287668">"शोधा"</string>
     <string name="ime_action_send" msgid="8456843745664334138">"पाठवा"</string>
     <string name="ime_action_next" msgid="4169702997635728543">"पुढे"</string>
     <string name="ime_action_done" msgid="6299921014822891569">"पूर्ण झाले"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"शॉर्टकट सुरू असताना, दोन्ही व्‍हॉल्‍यूम बटणे तीन सेकंदांसाठी दाबून ठेवल्याने अ‍ॅक्सेसिबिलिटी वैशिष्ट्य सुरू होईल."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"अ‍ॅक्सेसिबिलिटी वैशिष्ट्यांसाठी शॉर्टकट सुरू करायचा आहे का?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"दोन्ही व्हॉल्यूम की काही सेकंद धरून ठेवल्याने अ‍ॅक्सेसिबिलिटी वैशिष्ट्ये सुरू होतात. यामुळे तुमचे डिव्हाइस कसे काम करते हे पूर्णपणे बदलते.\n\nसध्याची वैशिष्ट्ये:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nतुम्ही हा शॉर्टकट सेटिंग्ज &gt; अ‍ॅक्सेसिबिलिटी मध्ये बदलू शकता."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> शॉर्टकट सुरू करायचा आहे का?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"दोन्ही व्हॉल्यूम की काही सेकंद धरून ठेवल्याने <xliff:g id="SERVICE">%1$s</xliff:g>, एक अ‍ॅक्सेसिबिलिटी वैशिष्ट्य सुरू होते. यामुळे तुमचे डिव्हाइस कसे काम करते हे पूर्णपणे बदलते.\n\nतुम्ही हा शॉर्टकट सेटिंग्ज &gt; अ‍ॅक्सेसिबिलिटी मध्ये बदलू शकता."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"सुरू करा"</string>
@@ -1973,7 +1978,7 @@
     <string name="language_picker_section_suggested" msgid="6556199184638990447">"सुचवलेल्या भाषा"</string>
     <string name="language_picker_section_all" msgid="1985809075777564284">"सर्व भाषा"</string>
     <string name="region_picker_section_all" msgid="756441309928774155">"सर्व प्रदेश"</string>
-    <string name="locale_search_menu" msgid="6258090710176422934">"Search"</string>
+    <string name="locale_search_menu" msgid="6258090710176422934">"शोध"</string>
     <string name="app_suspended_title" msgid="888873445010322650">"अ‍ॅप उपलब्ध नाही"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> आत्ता उपलब्ध नाही. हे <xliff:g id="APP_NAME_1">%2$s</xliff:g> कडून व्यवस्थापित केले जाते."</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"अधिक जाणून घ्या"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 76d52a9..f6cf330 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Gunakan cap jari atau kunci skrin anda untuk meneruskan"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon cap jari"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Buka Kunci Wajah"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Isu dengan Buka Kunci Wajah"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gunakan wajah atau kunci skrin anda untuk meneruskan"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Ikon wajah"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"membaca tetapan penyegerakan"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Membenarkan apl membaca tetapan segerak untuk akaun. Sebagai contoh, ini boleh menentukan sama ada apl Orang disegerakkan dengan akaun."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Apabila pintasan dihidupkan, tindakan menekan kedua-dua butang kelantangan selama 3 saat akan memulakan ciri kebolehaksesan."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Hidupkan pintasan untuk ciri kebolehaksesan?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Tindakan menahan kedua-dua kekunci kelantangan selama beberapa saat akan menghidupkan ciri kebolehaksesan. Hal ini mungkin mengubah cara peranti anda berfungsi.\n\nCiri semasa:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nAnda boleh menukar ciri yang dipilih dalam Tetapan &gt; Kebolehaksesan."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Hidupkan pintasan <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Tindakan menahan kedua-dua kekunci kelantangan selama beberapa saat akan menghidupkan <xliff:g id="SERVICE">%1$s</xliff:g>, iaitu satu ciri kebolehaksesan. Ini mungkin mengubah cara peranti anda berfungsi.\n\nAnda boleh menukar pintasan ini kepada ciri lain dalam Tetapan &gt; Kebolehaksesan."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Hidupkan"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 74ecc1d..f0216d6 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -609,6 +609,7 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ရှေ့ဆက်ရန် သင်၏ လက်ဗွေ (သို့) ဖန်သားပြင်လော့ခ်ကို သုံးပါ"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"တစ်ခုခုမှားသွားသည်။ ထပ်စမ်းကြည့်ပါ။"</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"လက်ဗွေ သင်္ကေတ"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"မျက်နှာပြ လော့ခ်ဖွင့်ခြင်း"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"‘မျက်နှာပြ လော့ခ်ဖွင့်ခြင်း’ ဆိုင်ရာ ပြဿနာ"</string>
@@ -661,6 +662,7 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ရှေ့ဆက်ရန် သင်၏ မျက်နှာ (သို့) ဖန်သားပြင်လော့ခ်ကို သုံးပါ"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"တစ်ခုခုမှားသွားသည်။ ထပ်စမ်းကြည့်ပါ။"</string>
     <string name="face_icon_content_description" msgid="465030547475916280">"မျက်နှာသင်္ကေတ"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ထပ်တူပြုအဆင်အပြင်အားဖတ်ခြင်း"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"အပလီကေးရှင်းအား အကောင့်တစ်ခုအတွက် ထပ်တူညီအောင် လုပ်ဆောင်မှု ဆက်တင်အား ကြည့်ခွင့် ပြုပါ။ ဥပမာ People အက်ပ်က အကောင့်တစ်ခုနဲ့ ထပ်တူညီအောင် လုပ်ရန် ဆက်သွယ်ထားမှု ရှိမရှိ သိရှိနိုင်ခြင်း"</string>
@@ -1692,7 +1694,7 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ဖြတ်လမ်းလင့်ခ်ကို ဖွင့်ထားစဉ် အသံထိန်းခလုတ် နှစ်ခုစလုံးကို ၃ စက္ကန့်ခန့် ဖိထားခြင်းဖြင့် အများသုံးစွဲနိုင်မှုဆိုင်ရာ ဝန်ဆောင်မှုကို ဖွင့်နိုင်သည်။"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"အများသုံးစွဲနိုင်မှုဆိုင်ရာ ဝန်ဆောင်မှုများအတွက် ဖြတ်လမ်းကို ဖွင့်မလား။"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"အသံခလုတ်နှစ်ခုလုံးကို စက္ကန့်အနည်းငယ် ဖိထားခြင်းက အများသုံးစွဲနိုင်မှုဆိုင်ရာ ဝန်ဆောင်မှုများ ဖွင့်ပေးသည်။ ဤလုပ်ဆောင်ချက်က သင့်စက်အလုပ်လုပ်ပုံကို ပြောင်းလဲနိုင်သည်။\n\nလက်ရှိ ဝန်ဆောင်မှုများ-\n<xliff:g id="SERVICE">%1$s</xliff:g>\n\'ဆက်တင်များ &gt; အများသုံးစွဲနိုင်မှု\' တွင် ရွေးထားသည့် ဝန်ဆောင်မှုများကို ပြောင်းနိုင်သည်။"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> ဖြတ်လမ်းကို ဖွင့်မလား။"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"အသံခလုတ်နှစ်ခုလုံးကို စက္ကန့်အနည်းငယ် ဖိထားခြင်းက အများသုံးစွဲနိုင်မှုဆိုင်ရာ ဝန်ဆောင်မှုဖြစ်သော <xliff:g id="SERVICE">%1$s</xliff:g> ကို ဖွင့်ပေးသည်။ ဤလုပ်ဆောင်ချက်က သင့်စက်အလုပ်လုပ်ပုံကို ပြောင်းလဲနိုင်သည်။\n\nဤဖြတ်လမ်းလင့်ခ်ကို \'ဆက်တင်များ &gt; အများသုံးစွဲနိုင်မှု\' တွင် နောက်ဝန်ဆောင်မှုတစ်ခုသို့ ပြောင်းနိုင်သည်။"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ဖွင့်ရန်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 4394e49..ac523f9 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Bruk fingeravtrykket eller skjermlåsen for å fortsette"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon for fingeravtrykk"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ansiktslås"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem med ansiktslås"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Bruk ansikts- eller skjermlåsen for å fortsette"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Ansiktikon"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lese synkroniseringsinnstillinger"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Lar appen lese synkroniseringsinnstillingene for en konto. For eksempel kan den finne ut om Personer-appen er synkronisert med en konto."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Når snarveien er på, starter en tilgjengelighetsfunksjon når du trykker inn begge volumknappene i tre sekunder."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vil du slå på snarveien for tilgjengelighetsfunksjoner?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Hvis du holder inne volumtastene i noen sekunder, slås tilgjengelighetsfunksjoner på. Dette kan endre hvordan enheten din fungerer.\n\nNåværende funksjoner:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nDu kan endre valgte funksjoner i Innstillinger &gt; Tilgjengelighet."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Vil du slå på <xliff:g id="SERVICE">%1$s</xliff:g>-snarveien?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Hvis du holder inne begge volumtastene i noen sekunder, slår du på <xliff:g id="SERVICE">%1$s</xliff:g>, en tilgjengelighetsfunksjon. Dette kan endre hvordan enheten din fungerer.\n\nDu kan endre denne snarveien til en annen funksjon i Innstillinger &gt; Tilgjengelighet."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Slå på"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 2d8b565..0751379 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"जारी राख्न आफ्नो फिंगरप्रिन्ट वा स्क्रिन लक प्रयोग गरी पुष्टि गर्नुहोस्"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"फिंगरप्रिन्ट आइकन"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"फेस अनलक"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"फेस अनलक सुविधामा अनुहार दर्ता गर्ने क्रममा त्रुटि भयो"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"जारी राख्न आफ्नो फेस वा स्क्रिन लक प्रयोग गरी पुष्टि गर्नुहोस्"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"अनुहारको आइकन"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"समीकरण सेटिङहरू पढ्नुहोस्"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"एपलाई खाताको लागि सिंक सेटिङहरू पढ्न अनुमति दिन्छ। उदाहरणको लागि यसले व्यक्तिहरको एप खातासँग सिंक भएको नभएको निर्धारण गर्न सक्दछ।"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"यो सर्टकट सक्रिय हुँदा, ३ सेकेन्डसम्म दुवै भोल्युम बटन थिच्नुले पहुँचसम्बन्धी कुनै सुविधा सुरु गर्ने छ।"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"एक्सेसिबिलिटीसम्बन्धी सुविधा  प्रयोग गर्न सर्टकट अन गर्ने हो?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"केही सेकेन्डसम्म दुवै भोल्युम की थिचिराख्नुभयो भने पहुँचसम्बन्धी सुविधाहरू सक्रिय हुन्छ। यसले तपाईंको यन्त्रले काम गर्ने तरिका परिवर्तन गर्न सक्छ।\n\nहालका सुविधाहरू:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nतपाईं सेटिङ &gt; पहुँचमा गएर चयन गरिएका सुविधाहरू परिवर्तन गर्न सक्नुहुन्छ।"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> प्रयोग गर्न सर्टकट अन गर्ने हो?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"केही सेकेन्डसम्म दुवै भोल्युम की थिचिराख्नुले <xliff:g id="SERVICE">%1$s</xliff:g> नामक पहुँचसम्बन्धी सुविधा  सक्रिय गर्छ। यसले तपाईंको यन्त्रले काम गर्ने तरिका परिवर्तन गर्न सक्छ।\n\nतपाईं सेटिङ &gt; पहुँचमा गई यो सर्टकटमार्फत अर्को सुविधा खुल्ने बनाउन सक्नुहुन्छ।"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"सक्रिय गरियोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 0c61054..8c4021d 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Gebruik je vingerafdruk of schermvergrendeling om door te gaan"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Vingerafdruk-icoon"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ontgrendelen via gezichtsherkenning"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Probleem met Ontgrendelen via gezichtsherkenning"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gebruik je gezicht of schermvergrendeling om door te gaan"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Gezichtspictogram"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"synchronisatie-instellingen lezen"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Hiermee kan de app de synchronisatie-instellingen voor een account lezen. Dit kan bijvoorbeeld bepalen of de app Personen wordt gesynchroniseerd met een account."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Als de snelkoppeling aanstaat, houd je beide volumeknoppen 3 seconden ingedrukt om een toegankelijkheidsfunctie te starten."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Snelkoppeling voor toegankelijkheidsfuncties aanzetten?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Als je beide volumetoetsen een paar seconden ingedrukt houdt, zet je de toegankelijkheidsfuncties aan. Hierdoor kan de manier veranderen waarop je apparaat werkt.\n\nHuidige functies:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nJe kunt de geselecteerde functies wijzigen via Instellingen &gt; Toegankelijkheid."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Snelkoppeling voor <xliff:g id="SERVICE">%1$s</xliff:g> aanzetten?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Als je beide volumetoetsen een paar seconden ingedrukt houdt, wordt de toegankelijkheidsfunctie <xliff:g id="SERVICE">%1$s</xliff:g> aangezet. Hierdoor kan de manier veranderen waarop je apparaat werkt.\n\nJe kunt deze sneltoets op een andere functie instellen via Instellingen &gt; Toegankelijkheid."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aanzetten"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 9d42402..14ca2e5 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ଜାରି ରଖିବାକୁ ଆପଣଙ୍କ ଟିପଚିହ୍ନ କିମ୍ବା ସ୍କ୍ରିନ୍ ଲକ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ଟିପଚିହ୍ନ ଆଇକନ୍"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ଫେସ୍ ଅନଲକ୍"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ଫେସ୍ ଅନଲକ୍ ସହ ସମସ୍ୟା"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ଜାରି ରଖିବାକୁ ଆପଣଙ୍କ ଚେହେରା କିମ୍ବା ସ୍କ୍ରିନ୍ ଲକ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"ଫେସ୍ ଆଇକନ୍"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ସିଙ୍କ ସେଟିଙ୍ଗକୁ ପଢ଼ନ୍ତୁ"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ଏକ ଆକାଉଣ୍ଟ ପାଇଁ ସିଙ୍କ ସେଟିଙ୍ଗ ପଢ଼ିବାକୁ ଆପ୍‍ଟିକୁ ଅନୁମତି ଦିଏ। ଉଦାହରଣସ୍ୱରୂପ, ଲୋକଙ୍କ ଆପ୍‍ ଏକ ଆକାଉଣ୍ଟରେ ସିଙ୍କ ହୋଇଛି କି ନାହିଁ ଏହା ଜାଣିପାରେ।"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ସର୍ଟକଟ୍ ଚାଲୁ ଥିବା ବେଳେ, ଉଭୟ ଭଲ୍ୟୁମ୍ ବଟନ୍ 3 ସେକେଣ୍ଡ ପାଇଁ ଦବାଇବା ଦ୍ୱାରା ଏକ ଆକ୍ସେସବିଲିଟି ଫିଚର୍ ଆରମ୍ଭ ହେବ।"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ଆକ୍ସେସିବିଲିଟୀ ଫିଚରଗୁଡ଼ିକ ପାଇଁ ସର୍ଟକଟ୍ ଚାଲୁ କରିବେ?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"କିଛି ସେକେଣ୍ଡ ପାଇଁ ଉଭୟ ଭଲ୍ୟୁମ୍ କୀ’କୁ ଧରି ରଖିବା ଫଳରେ ଆକ୍ସେସିବିଲିଟୀ ଫିଚରଗୁଡ଼ିକ ଚାଲୁ ହୁଏ। ଏହା ଆପଣଙ୍କ ଡିଭାଇସ୍ କିପରି କାମ କରେ ତାହା ପରିବର୍ତ୍ତନ କରିପାରେ।\n\nବର୍ତ୍ତମାନର ଫିଚରଗୁଡ଼ିକ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\n ଆପଣ ସେଟିଂସ୍ &amp;gt ଆକ୍ସେସିବିଲିଟୀରେ ଚୟନିତ ଫିଚରଗୁଡ଼ିକୁ ପରିବର୍ତ୍ତନ କରିପାରିବେ।"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> ସର୍ଟକଟ୍ ଚାଲୁ କରିବେ?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"କିଛି ସେକେଣ୍ଡ ପାଇଁ ଉଭୟ ଭଲ୍ୟୁମ୍ କୀ’କୁ ଧରି ରଖିବା ଫଳରେ ଏକ ଆକ୍ସେସିବିଲିଟୀ ଫିଚର୍ <xliff:g id="SERVICE">%1$s</xliff:g> ଚାଲୁ ହୁଏ। ଏହା ଆପଣଙ୍କ ଡିଭାଇସ୍ କିପରି କାମ କରେ ତାହା ପରିବର୍ତ୍ତନ କରିପାରେ।\n\nଆପଣ ସେଟିଂସ୍ &amp;gt ଆକ୍ସେସିବିଲିଟୀରେ ଏହି ସର୍ଚକଟକୁ ଅନ୍ୟ ଏକ ଫିଚରରେ ପରିବର୍ତ୍ତନ କରିପାରିବେ।"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ଚାଲୁ କରନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 7577457..b9e2a0b 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਜਾਂ ਸਕ੍ਰੀਨ ਲਾਕ ਵਰਤੋ"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਪ੍ਰਤੀਕ"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ਫ਼ੇਸ ਅਣਲਾਕ"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ਫ਼ੇਸ ਅਣਲਾਕ ਨਾਲ ਸਮੱਸਿਆ"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣਾ ਚਿਹਰਾ ਜਾਂ ਸਕ੍ਰੀਨ ਲਾਕ ਵਰਤੋ"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"ਚਿਹਰਾ ਪ੍ਰਤੀਕ"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ਸਿੰਕ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹੋ"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ਐਪ ਨੂੰ ਕਿਸੇ ਖਾਤੇ ਲਈ ਸਮਕਾਲੀਕਰਨ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹਨ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਹ ਪਤਾ ਕਰ ਸਕਦਾ ਹੈ ਕਿ People ਐਪ ਦਾ ਕਿਸੇ ਖਾਤੇ ਨਾਲ ਸਮਕਾਲੀਕਿਰਤ ਕੀਤਾ ਗਿਆ ਹੈ ਜਾਂ ਨਹੀਂ।"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ਸ਼ਾਰਟਕੱਟ ਚਾਲੂ ਹੋਣ \'ਤੇ, ਕਿਸੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ ਬਟਨਾਂ ਨੂੰ 3 ਸਕਿੰਟ ਲਈ ਦਬਾ ਕੇ ਰੱਖੋ।"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ਕੀ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਲਈ ਸ਼ਾਰਟਕੱਟ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ਕੁਝ ਸਕਿੰਟਾਂ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਨੂੰ ਦਬਾਈ ਰੱਖਣਾ, ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਚਾਲੂ ਕਰ ਦਿੰਦਾ ਹੈ। ਇਹ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਕੰਮ ਕਰਨ ਦੇ ਤਰੀਕੇ ਨੂੰ ਬਦਲ ਸਕਦਾ ਹੈ।\n\nਮੌਜੂਦਾ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nਸੈਟਿੰਗਾਂ ਅਤੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿੱਚ ਤੁਸੀਂ ਚੁਣੀਆਂ ਗਈਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹੋ।"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"ਕੀ <xliff:g id="SERVICE">%1$s</xliff:g> ਸ਼ਾਰਟਕੱਟ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ਕੁਝ ਸਕਿੰਟਾਂ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਨੂੰ ਦਬਾਈ ਰੱਖਣਾ <xliff:g id="SERVICE">%1$s</xliff:g>, ਇੱਕ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਚਾਲੂ ਕਰ ਦਿੰਦਾ ਹੈ। ਇਹ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਕੰਮ ਕਰਨ ਦੇ ਤਰੀਕੇ ਨੂੰ ਬਦਲ ਸਕਦਾ ਹੈ।\n\nਸੈਟਿੰਗਾਂ ਅਤੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿੱਚ ਤੁਸੀਂ ਇਸ ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਕਿਸੇ ਹੋਰ ਵਿਸ਼ੇਸ਼ਤਾ ਵਿੱਚ ਬਦਲ ਸਕਦੇ ਹੋ।"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ਚਾਲੂ ਕਰੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 31172f6..c3c30da 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -615,6 +615,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Aby kontynuować, użyj odcisku palca lub blokady ekranu"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona odcisku palca"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Rozpoznawanie twarzy"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem z rozpoznawaniem twarzy"</string>
@@ -667,6 +669,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Aby kontynuować, użyj rozpoznawania twarzy lub blokady ekranu"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Ikona twarzy"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"czytanie ustawień synchronizacji"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Zezwala aplikacji na odczyt ustawień synchronizacji konta. Pozwala to na przykład określić, czy aplikacja Ludzie jest zsynchronizowana z kontem."</string>
@@ -1736,7 +1740,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Gdy skrót jest włączony, jednoczesne naciskanie przez trzy sekundy obu przycisków głośności uruchamia funkcję ułatwień dostępu."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Włączyć skrót ułatwień dostępu?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Przytrzymanie obu klawiszy głośności przez kilka sekund włącza ułatwienia dostępu. Może to zmienić sposób działania urządzenia.\n\nBieżące funkcje:\n<xliff:g id="SERVICE">%1$s</xliff:g>\naby zmienić wybrane funkcje, kliknij Ustawienia &gt; Ułatwienia dostępu."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Włączyć skrót <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Przytrzymanie obu klawiszy głośności przez kilka sekund włącza usługę <xliff:g id="SERVICE">%1$s</xliff:g>, stanowiącą ułatwienie dostępu. Może to zmienić sposób działania urządzenia.\n\nAby zmienić ten skrót i wskazać inną funkcję, kliknij Ustawienia &gt; Ułatwienia dostępu."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Włącz"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index ab5f176..e5eb61d 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -609,6 +609,7 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Use sua impressão digital ou o bloqueio de tela para continuar"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Algo deu errado. Tente de novo."</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícone de impressão digital"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueio facial"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema com o Desbloqueio facial"</string>
@@ -661,6 +662,7 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use seu rosto ou o bloqueio de tela para continuar"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Algo deu errado. Tente de novo."</string>
     <string name="face_icon_content_description" msgid="465030547475916280">"Ícone facial"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ler as configurações de sincronização"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permite que o app leia as configurações de sincronização de uma conta. Por exemplo, pode determinar se o app People está sincronizado com uma conta."</string>
@@ -1692,7 +1694,7 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quando o atalho estiver ativado, pressione os dois botões de volume por três segundos para iniciar um recurso de acessibilidade."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Ativar atalho para recursos de acessibilidade?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Manter as duas teclas de volume pressionadas por alguns segundos ativa os recursos de acessibilidade. Isso pode mudar a forma como seu dispositivo funciona.\n\nRecursos atuais:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nÉ possível mudar os recursos selecionados em \"Config. &gt; Acessibilidade\"."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Ativar atalho para <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Manter as duas teclas de volume pressionadas por alguns segundos ativa o serviço <xliff:g id="SERVICE">%1$s</xliff:g>, um recurso de acessibilidade. Isso pode mudar a forma como seu dispositivo funciona.\n\nÉ possível trocar o uso desse atalho para outro recurso em \"Config. &gt; Acessibilidade\"."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Ativar"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 6455af0..cd4adb0 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -609,6 +609,7 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Utilize a impressão digital ou o bloqueio de ecrã para continuar"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Algo correu mal. Tente novamente."</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícone de impressão digital"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueio facial"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema com o Desbloqueio facial"</string>
@@ -661,6 +662,7 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Utilize o rosto ou o bloqueio de ecrã para continuar"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Algo correu mal. Tente novamente."</string>
     <string name="face_icon_content_description" msgid="465030547475916280">"Ícone de rosto"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ler definições de sincronização"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permite que a app leia as definições de sincronização de uma conta. Por exemplo, pode determinar se a app Pessoas está sincronizada com uma conta."</string>
@@ -1692,7 +1694,7 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quando o atalho está ativado, premir ambos os botões de volume durante 3 segundos inicia uma funcionalidade de acessibilidade."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Pretende ativar o atalho das funcionalidades de acessibilidade?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Manter premidas ambas as teclas de volume durante alguns segundos ativa as funcionalidades de acessibilidade. Estas podem alterar a forma como o seu dispositivo funciona.\n\nFuncionalidades atuais:\n<xliff:g id="SERVICE">%1$s</xliff:g>\npode alterar as funcionalidades selecionadas em Definições &gt; Acessibilidade."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Pretende ativar o atalho do serviço <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Manter premidas ambas as teclas de volume durante alguns segundos ativa o serviço <xliff:g id="SERVICE">%1$s</xliff:g>, uma funcionalidade de acessibilidade. Esta pode alterar a forma como o seu dispositivo funciona.\n\nPode alterar este atalho para outra funcionalidade em Definições &gt; Acessibilidade."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Ativar"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index ab5f176..e5eb61d 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -609,6 +609,7 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Use sua impressão digital ou o bloqueio de tela para continuar"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Algo deu errado. Tente de novo."</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícone de impressão digital"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueio facial"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema com o Desbloqueio facial"</string>
@@ -661,6 +662,7 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Use seu rosto ou o bloqueio de tela para continuar"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Algo deu errado. Tente de novo."</string>
     <string name="face_icon_content_description" msgid="465030547475916280">"Ícone facial"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ler as configurações de sincronização"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permite que o app leia as configurações de sincronização de uma conta. Por exemplo, pode determinar se o app People está sincronizado com uma conta."</string>
@@ -1692,7 +1694,7 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quando o atalho estiver ativado, pressione os dois botões de volume por três segundos para iniciar um recurso de acessibilidade."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Ativar atalho para recursos de acessibilidade?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Manter as duas teclas de volume pressionadas por alguns segundos ativa os recursos de acessibilidade. Isso pode mudar a forma como seu dispositivo funciona.\n\nRecursos atuais:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nÉ possível mudar os recursos selecionados em \"Config. &gt; Acessibilidade\"."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Ativar atalho para <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Manter as duas teclas de volume pressionadas por alguns segundos ativa o serviço <xliff:g id="SERVICE">%1$s</xliff:g>, um recurso de acessibilidade. Isso pode mudar a forma como seu dispositivo funciona.\n\nÉ possível trocar o uso desse atalho para outro recurso em \"Config. &gt; Acessibilidade\"."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Ativar"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index c20a590..71e338f 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -612,6 +612,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Folosiți amprenta sau blocarea ecranului pentru a continua"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Pictograma amprentă"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Deblocare facială"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problemă cu Deblocarea facială"</string>
@@ -664,6 +666,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Folosiți-vă chipul sau blocarea ecranului pentru a continua"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Pictograma chip"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"citire setări sincronizare"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permite aplicației să citească setările de sincronizare ale unui cont. De exemplu, cu această permisiune aplicația poate determina dacă aplicația Persoane este sincronizată cu un anumit cont."</string>
@@ -1714,7 +1718,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Atunci când comanda rapidă este activată, dacă apăsați ambele butoane de volum timp de trei secunde, veți lansa o funcție de accesibilitate."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Activați comanda rapidă pentru funcțiile de accesibilitate?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Dacă apăsați ambele taste de volum câteva secunde, activați funcțiile de accesibilitate. Acest lucru poate schimba funcționarea dispozitivului.\n\nFuncțiile actuale:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPuteți schimba funcțiile selectate din Setări &gt; Accesibilitate."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Activați comanda rapidă <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Dacă apăsați ambele taste de volum câteva secunde, activați funcția de accesibilitate <xliff:g id="SERVICE">%1$s</xliff:g>. Acest lucru poate schimba funcționarea dispozitivului.\n\nPuteți alege altă funcție pentru această comandă în Setări &gt; Accesibilitate."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Activați"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 9c961ba..88d06f8 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -615,6 +615,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Чтобы продолжить, используйте отпечаток пальца или данные для разблокировки экрана."</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Значок отпечатка пальца"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Фейсконтроль"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Ошибка фейсконтроля"</string>
@@ -667,6 +669,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Чтобы продолжить, посмотрите на экран или используйте данные для разблокировки."</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Значок лица"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"Просмотр настроек синхронизации"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Приложение сможет просматривать настройки синхронизации аккаунта, например определять, включена ли синхронизация для приложения \"Контакты\"."</string>
@@ -1736,7 +1740,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Чтобы использовать функцию специальных возможностей, когда она включена, нажмите и удерживайте обе кнопки регулировки громкости в течение трех секунд."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Использовать быстрое включение?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Чтобы включить специальные возможности, нажмите обе кнопки регулировки громкости и удерживайте несколько секунд. Обратите внимание, что в работе устройства могут произойти изменения.\n\nТекущие функции:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nЧтобы изменить выбранные функции, перейдите в настройки и нажмите \"Специальные возможности\"."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Использовать быстрое включение сервиса \"<xliff:g id="SERVICE">%1$s</xliff:g>\"?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Чтобы включить функцию \"<xliff:g id="SERVICE">%1$s</xliff:g>\", нажмите обе кнопки регулировки громкости на несколько секунд. Обратите внимание, что в работе устройства могут произойти изменения.\n\nЧтобы назначить это сочетание клавиш другой функции, перейдите в настройки и выберите \"Специальные возможности\"."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Включить"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 2b20e66..1b7973d 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ඉදිරියට යාමට ඔබගේ ඇඟිලි සලකුණ හෝ තිර අගුල භාවිත කරන්න"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ඇඟිලි සලකුණු නිරූපකය"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"මුහුණෙන් අගුළු හැරීම"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"මුහුණෙන් අගුලු හැරීම සම්බන්ධව ගැටලුවකි"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ඉදිරියට යාමට ඔබගේ මුහුණු හෝ තිර අගුල භාවිත කරන්න"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"මුහුණ නිරූපකය"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"සමමුහුර්ත සැකසීම් කියවන්න"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ගිණුම සඳහා සමමුහුර්ත සැකසීම් කියවීමට යෙදුමට අවසර දෙන්න. උදාහරණයක් ලෙස, ගිණුමක් සමඟ පුද්ගල යෙදුම සමමුහුර්ත දැයි මෙයට හඳුනා ගත හැක."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"කෙටිමග ක්‍රියාත්මක විට, හඬ පරිමා බොත්තම් දෙකම තත්පර 3ක් තිස්සේ එබීමෙන් ප්‍රවේශ්‍යතා විශේෂාංගය ආරම්භ වනු ඇත."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ප්‍රවේශ්‍යතා විශේෂාංග සඳහා කෙටි මග ක්‍රියාත්මක කරන්නද?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"හඬ පරිමා යතුරු දෙකම තත්පර කීපයකට පහළට අල්ලාගෙන සිටීම ප්‍රවේශ්‍යතා විශේෂාංග ක්‍රියාත්මක කරයි. මෙය ඔබේ උපාංගය ක්‍රියා කරන ආකාරය වෙනස් කළ හැකිය.\n\nවත්මන් විශේෂාංග:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nඔබට තේරූ විශේෂාංග සැකසීම් &gt; ප්‍රවේශ්‍යතාව හි වෙනස් කළ හැකිය."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> කෙටි මග ක්‍රියාත්මක කරන්නද?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"හඬ පරිමා යතුරු දෙකම තත්පර කීපයකට පහළට අල්ලාගෙන සිටීම ප්‍රවේශ්‍යතා විශේෂාංගයක් වන <xliff:g id="SERVICE">%1$s</xliff:g> ක්‍රියාත්මක කරයි. මෙය ඔබේ උපාංගය ක්‍රියා කරන ආකාරය වෙනස් කළ හැකිය.\n\nඔබට මෙම කෙටිමග සැකසීම් &gt; ප්‍රවේශ්‍යතාව හි තවත් විශේෂාංගයකට වෙනස් කළ හැකිය."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ක්‍රියාත්මක කරන්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 80f55c6..33ea9c9 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -615,6 +615,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Pokračujte použitím odtlačku prsta alebo zámky obrazovky"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona odtlačku prsta"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Odomknutie tvárou"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problém s odomknutím tvárou"</string>
@@ -667,6 +669,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Pokračujte použitím tváre alebo zámky obrazovky"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Ikona tváre"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"čítať nastavenia synchronizácie"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Umožňuje aplikácii čítať nastavenia synchronizácie v účte. Môže napríklad určiť, či je s účtom synchronizovaná aplikácia Ľudia."</string>
@@ -1736,7 +1740,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Keď je skratka zapnutá, stlačením obidvoch tlačidiel hlasitosti na tri sekundy spustíte funkciu dostupnosti."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Chcete zapnúť skratku pre funkcie dostupnosti?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Pridržaním oboch tlačidiel hlasitosti na niekoľko sekúnd zapnete funkcie dostupnosti. Môže sa tým zmeniť spôsob fungovania vášho zariadenia.\n\nAktuálne funkcie:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nVybrané funkcie môžete zmeniť v časti Nastavenia &gt; Dostupnosť."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Chcete zapnúť skratku na službu <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Pridržaním oboch klávesov hlasitosti na niekoľko sekúnd zapnete funkciu dostupnosti <xliff:g id="SERVICE">%1$s</xliff:g>. Môže sa tým zmeniť spôsob fungovania vášho zariadenia.\n\nTúto skratku môžete zmeniť na inú funkciu v časti Nastavenia &gt; Dostupnosť."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Zapnúť"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 414d0bd..f53d847b 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -615,6 +615,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Za nadaljevanje uporabite prstni odtis ali odklepanje s poverilnico."</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona prstnih odtisov"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Odklepanje z obrazom"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Težava z odklepanjem z obrazom"</string>
@@ -667,6 +669,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Za nadaljevanje uporabite obraz ali odklepanje s poverilnico."</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Ikona obraza"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"branje nastavitev sinhronizacije"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Aplikaciji omogoča branje nastavitev sinhronizacije za račun. S tem lahko aplikacija na primer ugotovi, ali je aplikacija Ljudje sinhronizirana z računom."</string>
@@ -1736,7 +1740,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Ko je bližnjica vklopljena, pritisnite gumba za glasnost in ju pridržite tri sekunde, če želite zagnati funkcijo za ljudi s posebnimi potrebami."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Želite vklopiti bližnjico za funkcije za ljudi s posebnimi potrebami?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Če za nekaj sekund pridržite obe tipki za glasnost, boste vklopili funkcije za ljudi s posebnimi potrebami. To lahko spremeni način delovanja naprave.\n\nTrenutne funkcije:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nIzbrane funkcije lahko spremenite v meniju »Nastavitve« &gt; »Funkcije za ljudi s posebnimi potrebami«."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Želite vklopiti bližnjico za <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Če za nekaj sekund pridržite obe tipki za glasnost, boste vklopili storitev <xliff:g id="SERVICE">%1$s</xliff:g>, ki je funkcija za ljudi s posebnimi potrebami. To lahko spremeni način delovanja naprave.\n\nTo bližnjico lahko v meniju »Nastavitve« &gt; »Funkcije za ljudi s posebnimi potrebami« spremenite, da bo uporabljena za drugo funkcijo."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Vklopi"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 16edb81..9cbc916 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Përdor gjurmën tënde të gishtit ose kyçjen e ekranit për të vazhduar"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona e gjurmës së gishtit"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Shkyçja me fytyrë"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem me \"Shkyçjen me fytyrë\""</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Përdor fytyrën tënde ose kyçjen e ekranit për të vazhduar"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Ikona e fytyrës"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"lexo cilësimet e sinkronizimit"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Lejon aplikacionin të lexojë cilësimet e sinkronizimit për një llogari. Për shembull, kjo mund të përcaktojë nëse aplikacioni \"Kontaktet\" është i sinkronizuar me një llogari."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kur shkurtorja është e aktivizuar, shtypja e të dy butonave për 3 sekonda do të nisë një funksion qasshmërie."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Të aktivizohet shkurtorja për veçoritë e qasshmërisë?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Mbajtja shtypur e dy tasteve të volumit për pak sekonda aktivizon veçoritë e qasshmërisë. Kjo mund të ndryshojë mënyrën se si funksionon pajisja jote.\n\nVeçoritë aktuale:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nKe ndryshuar veçoritë e zgjedhura te Cilësimet &gt; Qasshmëria."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Të aktivizohet shkurtorja për <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Mbajtja shtypur e dy tasteve të volumit për pak sekonda aktivizon <xliff:g id="SERVICE">%1$s</xliff:g>, një veçori të qasshmërisë. Kjo mund të ndryshojë mënyrën se si funksionon pajisja jote.\n\nMund të ndryshosh këtë shkurtore te një veçori tjetër te Cilësimet &gt; Qasshmëria."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktivizo"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 5261bd3..561f5a3 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -612,6 +612,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Користите отисак прста или закључавање екрана да бисте наставили"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Икона отиска прста"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Откључавање лицем"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Проблем са откључавање лицем"</string>
@@ -664,6 +666,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Користите лице или закључавање екрана да бисте наставили"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Икона лица"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"читање подешавања синхронизације"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Дозвољава апликацији да чита подешавања синхронизације за налог. На пример, овако може да се утврди да ли је апликација Људи синхронизована са налогом."</string>
@@ -1714,7 +1718,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Када је пречица укључена, притисните оба дугмета за јачину звука да бисте покренули функцију приступачности."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Желите да укључите пречицу за функције приступачности?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ако задржите оба тастера за јачину звука пар секунди, укључиће се функције приступачности. То може да промени начин рада уређаја.\n\nПостојеће функције:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nМожете да промените изабране функције у одељку Подешавања &gt; Приступачност."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Желите да укључите пречицу за услугу <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ако задржите оба тастера за јачину звука пар секунди, укључује се <xliff:g id="SERVICE">%1$s</xliff:g>, функција приступачности. То може да промени начин рада уређаја.\n\nМожете да промените функцију на коју се односи ова пречица у одељку Подешавања &gt; Приступачност."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Укључи"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index e494ef0..72c8ccc 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Fortsätt med hjälp av ditt fingeravtryck eller skärmlåset"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon för fingeravtryck"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ansiktslås"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem med ansiktslås"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Fortsätt med hjälp av ditt ansikte eller skärmlåset"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Ansikte"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"läsa synkroniseringsinställningar"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Tillåter att appen läser synkroniseringsinställningarna för ett konto. Detta kan användas till exempel för att avgöra om appen Personer är synkroniserad med ett konto."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"När kortkommandot har aktiverats startar du en tillgänglighetsfunktion genom att trycka ned båda volymknapparna i tre sekunder."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vill du aktivera genvägen till tillgänglighetsfunktioner?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Om du trycker ned båda volymknapparna i ett par sekunder aktiveras tillgänglighetsfunktionerna. Det kan få enheten ett fungera annorlunda.\n\nAktuella funktioner:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nDu kan ändra vilka funktioner som aktiveras under Inställningar &gt; Tillgänglighet."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Vill du aktivera genvägen till <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Om du trycker ned båda volymknapparna i ett par sekunder aktiveras <xliff:g id="SERVICE">%1$s</xliff:g>, en tillgänglighetsfunktion. Det kan leda till att enheten fungerar annorlunda.\n\nDu kan ändra vilken funktion som ska aktiveras med genvägen under Inställningar &gt; Tillgänglighet."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktivera"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 4166478..90bdf85 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Tumia alama ya kidole au mbinu yako ya kufunga skrini ili uendelee"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Aikoni ya alama ya kidole"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Kufungua kwa Uso"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Hitilafu imetokea kwenye kipengele cha Kufungua kwa Uso"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Tumia uso au mbinu yako ya kufunga skrini ili uendelee"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Aikoni ya uso"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"kusoma mipangilio ya usawazishaji"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Inaruhusu programu kusoma mipangilio ya upatanishi wa akaunti. Kwa mfano, huku kunaweza kuamua kama programu ya Watu imepatanishwa na akaunti."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Unapowasha kipengele cha njia ya mkato, hatua ya kubonyeza vitufe vyote viwili vya sauti kwa sekunde tatu itafungua kipengele cha ufikivu."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Ungependa kuwasha njia ya mkato ya vipengele vya ufikivu?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Hatua ya kushikilia chini vitufe vyote viwili vya sauti kwa sekunde chache huwasha vipengele vya ufikivu. Huenda hatua hii ikabadilisha jinsi kifaa chako kinavyofanya kazi.\n\nVipengele vya sasa:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nUnaweza kubadilisha vipengele ulivyochagua katika Mipangilio &gt; Ufikivu."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Ungependa kuwasha njia ya mkato ya <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Hatua ya kushikilia chini vitufe vyote viwili vya sauti kwa sekunde chache huwasha <xliff:g id="SERVICE">%1$s</xliff:g>, kipengele cha ufikivu. Huenda hatua hii ikabadilisha jinsi kifaa chako kinavyofanya kazi.\n\nUnaweza kubadilisha njia hii ya mkato iwe kipengele kingine katika Mipangilio &gt; Ufikivu."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Washa"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index c6b6b77..62fb2a0 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"தொடர, உங்கள் கைரேகையையோ திரைப் பூட்டையோ பயன்படுத்துங்கள்"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"கைரேகை ஐகான்"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"முகம் காட்டித் திறத்தல்"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"முகம் காட்டித் திறத்தல் அம்சத்தில் சிக்கல்"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"தொடர, உங்கள் முகத்தையோ திரைப் பூட்டையோ பயன்படுத்துங்கள்"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"முக ஐகான்"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"ஒத்திசைவு அமைப்புகளைப் படித்தல்"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"கணக்கிற்கான ஒத்திசைவு அமைப்புகளைப் படிக்க ஆப்ஸை அனுமதிக்கிறது. எடுத்துக்காட்டாக, பீப்பிள் ஆப்ஸ் கணக்குடன் ஒத்திசைக்கப்பட்டுள்ளதா என்பதை இது தீர்மானிக்கலாம்."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ஷார்ட்கட் இயக்கத்தில் இருக்கும்போது ஒலியளவு பட்டன்கள் இரண்டையும் 3 வினாடிகளுக்கு அழுத்தினால் அணுகல்தன்மை அம்சம் இயக்கப்படும்."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"அணுகல்தன்மை அம்சங்களுக்கான ஷார்ட்கட்டை ஆன் செய்யவா?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"இரண்டு ஒலியளவு விசைகளையும் சில விநாடிகள் பிடித்திருந்தால் அணுகல்தன்மை அம்சங்கள் ஆன் செய்யப்படும். இதனால் உங்கள் சாதனம் வேலை செய்யும் முறை மாறக்கூடும்.\n\nதற்போதைய அம்சங்கள்:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nதேர்ந்தெடுத்த அம்சங்களை அமைப்புகள் &gt; அணுகல்தன்மைக்குச் சென்று உங்களால் மாற்ற முடியும்."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> அம்சத்துக்கான ஷார்ட்கட்டை ஆன் செய்யவா?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"இரண்டு ஒலியளவு விசைகளையும் சில விநாடிகள் பிடித்திருப்பதால் அணுகல்தன்மை அம்சமான <xliff:g id="SERVICE">%1$s</xliff:g> ஆன் ஆகும். இதனால் உங்கள் சாதனம் வேலை செய்யும் முறை மாறக்கூடும்.\n\nஅமைப்புகள் &gt; அணுகல்தன்மைக்குச் சென்று இந்த ஷார்ட்கட்டை வேறு அம்சத்திற்கு மாற்ற முடியும்."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ஆன் செய்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 478886a..ef5c621 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -305,7 +305,7 @@
     <string name="permgrouplab_contacts" msgid="4254143639307316920">"కాంటాక్ట్‌లు"</string>
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"మీ కాంటాక్ట్‌లను యాక్సెస్ చేయడానికి"</string>
     <string name="permgrouplab_location" msgid="1858277002233964394">"లొకేషన్"</string>
-    <string name="permgroupdesc_location" msgid="1995955142118450685">"ఈ పరికర స్థానాన్ని యాక్సెస్ చేయడానికి"</string>
+    <string name="permgroupdesc_location" msgid="1995955142118450685">"ఈ పరికర లొకేషన్‌ను యాక్సెస్ చేయడానికి"</string>
     <string name="permgrouplab_calendar" msgid="6426860926123033230">"క్యాలెండర్"</string>
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"మీ క్యాలెండర్‌ను యాక్సెస్ చేయడానికి"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
@@ -410,11 +410,11 @@
     <string name="permdesc_broadcastSticky" product="tablet" msgid="5058486069846384013">"ప్రసారం ముగిసిన తర్వాత భద్రపరచబడే ప్రసారాలను పంపడానికి యాప్‌ను అనుమతిస్తుంది. అత్యధిక వినియోగం వలన టాబ్లెట్ నెమ్మదిగా పని చేయవచ్చు లేదా అధిక పరిమాణంలో మెమరీని ఉపయోగించడం వలన అస్థిరంగా మారవచ్చు."</string>
     <string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"ప్రసారం ముగిసిన తర్వాత భద్రపరచబడే ప్రసారాలను పంపడానికి యాప్‌ని అనుమతిస్తుంది. ఎక్కువగా వినియోగిస్తే అధిక పరిమాణంలో మెమరీని ఉపయోగించడం వలన టీవీ నెమ్మదిగా పని చేయవచ్చు లేదా అస్థిరంగా మారవచ్చు."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"ప్రసారం ముగిసిన తర్వాత భద్రపరచబడే ప్రసారాలను పంపడానికి యాప్‌ను అనుమతిస్తుంది. అత్యధిక వినియోగం వలన ఫోన్ నెమ్మదిగా పని చేయవచ్చు లేదా అధిక పరిమాణంలో మెమరీని ఉపయోగించడం వలన అస్థిరంగా మారవచ్చు."</string>
-    <string name="permlab_readContacts" msgid="8776395111787429099">"మీ పరిచయాలను చదవడం"</string>
+    <string name="permlab_readContacts" msgid="8776395111787429099">"మీ కాంటాక్ట్‌లను చదవడం"</string>
     <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"టాబ్లెట్‌లో నిల్వ చేసిన మీ కాంటాక్ట్‌లకు సంబంధించిన డేటాను చదవడానికి యాప్‌ను అనుమతిస్తుంది. కాంటాక్ట్‌లను సృష్టించిన మీ టాబ్లెట్‌లోని ఖాతాలకు కూడా యాప్‌లకు యాక్సెస్ ఉంటుంది. ఇందులో మీరు ఇన్‌స్టాల్ చేసిన యాప్‌ల ద్వారా సృష్టించబడిన ఖాతాలు ఉండవచ్చు. ఈ అనుమతి, మీ కాంటాక్ట్ డేటాను సేవ్ చేయడానికి యాప్‌లను అనుమతిస్తుంది, హానికరమైన యాప్‌లు మీకు తెలియకుండానే కాంటాక్ట్ డేటాను షేర్ చేయవచ్చు."</string>
     <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"మీ Android TV పరికరంలో నిల్వ చేసిన కాంటాక్ట్‌లకు సంబంధించిన డేటాను చదవడానికి యాప్‌ను అనుమతిస్తుంది. కాంటాక్ట్‌లను సృష్టించిన మీ Android TV పరికరంలోని ఖాతాలకు కూడా యాప్‌లకు యాక్సెస్ ఉంటుంది. ఇందులో మీరు ఇన్‌స్టాల్ చేసిన యాప్‌ల ద్వారా సృష్టించబడిన ఖాతాలు ఉండవచ్చు. ఈ అనుమతి, మీ కాంటాక్ట్ డేటాను సేవ్ చేయడానికి యాప్‌లను అనుమతిస్తుంది, హానికరమైన యాప్‌లు మీకు తెలియకుండానే కాంటాక్ట్ డేటాను షేర్ చేయవచ్చు."</string>
     <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"ఫోన్‌లో నిల్వ చేసిన మీ కాంటాక్ట్‌లకు సంబంధించిన డేటాను చదవడానికి యాప్‌ను అనుమతిస్తుంది. కాంటాక్ట్‌లను సృష్టించిన మీ ఫోన్‌లోని ఖాతాలను కూడా యాప్‌లు యాక్సెస్ చేయగలవు. ఇందులో మీరు ఇన్‌స్టాల్ చేసిన యాప్‌ల ద్వారా సృష్టించబడిన ఖాతాలు ఉండవచ్చు. ఈ అనుమతి, మీ కాంటాక్ట్ డేటాను సేవ్ చేయడానికి యాప్‌లను అనుమతిస్తుంది, హానికరమైన యాప్‌లు మీకు తెలియకుండానే కాంటాక్ట్ డేటాను షేర్ చేయవచ్చు."</string>
-    <string name="permlab_writeContacts" msgid="8919430536404830430">"మీ పరిచయాలను సవరించడం"</string>
+    <string name="permlab_writeContacts" msgid="8919430536404830430">"మీ కాంటాక్ట్‌లను సవరించడం"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"మీ టాబ్లెట్‌లో నిల్వ చేసి ఉన్న కాంటాక్ట్‌లకు సంబంధించిన డేటాను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. ఈ అనుమతి, కాంటాక్ట్ డేటాను తొలగించడానికి యాప్‌లను అనుమతిస్తుంది."</string>
     <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"మీ Android TV పరికరంలో నిల్వ చేసి ఉన్న కాంటాక్ట్‌లకు సంబంధించిన డేటాను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. ఈ అనుమతి, కాంటాక్ట్ డేటాను తొలగించడానికి యాప్‌లను అనుమతిస్తుంది."</string>
     <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"మీ ఫోన్‌లో నిల్వ చేసి ఉన్న కాంటాక్ట్‌లకు సంబంధించిన డేటాను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. ఈ అనుమతి, కాంటాక్ట్ డేటాను తొలగించడానికి యాప్‌లను అనుమతిస్తుంది."</string>
@@ -434,13 +434,13 @@
     <string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"ఈ యాప్ మీ టాబ్లెట్‌లో క్యాలెండర్ ఈవెంట్‌లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ యజమానుల నుండి వచ్చినట్లుగా మెసేజ్‌లను పంపగలదు లేదా ఈవెంట్‌లను వాటి యజమానులకు తెలియకుండానే మార్చగలదు."</string>
     <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"ఈ యాప్ మీ Android TV పరికరంలో క్యాలెండర్ ఈవెంట్‌లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ యజమానుల నుండి వచ్చినట్లుగా మెసేజ్‌లను పంపగలదు లేదా ఈవెంట్‌లను వాటి యజమానులకు తెలియకుండానే మార్చగలదు."</string>
     <string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"ఈ యాప్ మీ ఫోన్‌లో క్యాలెండర్ ఈవెంట్‌లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ యజమానుల నుండి వచ్చినట్లుగా మెసేజ్‌లను పంపగలదు లేదా ఈవెంట్‌లను వాటి యజమానులకు తెలియకుండానే మార్చగలదు."</string>
-    <string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"అదనపు స్థాన ప్రదాత ఆదేశాలను యాక్సెస్ చేయడం"</string>
+    <string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"అదనపు లొకేషన్ ప్రొవైడర్ కమాండ్‌లను యాక్సెస్ చేయడం"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"అదనపు లొకేషన్ ప్రొవైడర్ కమాండ్లను యాక్సెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. ఇది GPS లేదా ఇతర లొకేషన్ సోర్స్‌ల నిర్వహణలో యాప్‌ ప్రమేయం ఉండేలా అనుమతించవచ్చు."</string>
     <string name="permlab_accessFineLocation" msgid="6426318438195622966">"స్క్రీన్‌పై ఉన్నప్పుడు మాత్రమే ఖచ్చితమైన లొకేషన్‌ను యాక్సెస్ చేయండి"</string>
     <string name="permdesc_accessFineLocation" msgid="6732174080240016335">"యాప్ ఉపయోగంలో ఉన్నప్పుడు మాత్రమే ఈ యాప్ మీ ఖచ్చితమైన లొకేషన్‌ను లొకేషన్ సర్వీస్‌ల ద్వారా తెలుసుకోగలదు. లొకేషన్‌ను యాప్ పొందాలంటే, దాని కోసం మీ పరికరం యొక్క లొకేషన్ సర్వీస్‌లను తప్పనిసరిగా ఆన్ చేయాలి. ఇది బ్యాటరీ వినియోగాన్ని పెంచవచ్చు."</string>
     <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"స్క్రీన్‌పై ఉన్నప్పుడు మాత్రమే సుమారు లొకేషన్‌ను యాక్సెస్ చేయండి"</string>
     <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"యాప్ ఉపయోగంలో ఉన్నప్పుడు మాత్రమే ఈ యాప్ మీ ఇంచుమించు లొకేషన్‌ను లొకేషన్ సర్వీస్‌ల నుండి తెలుసుకోగలదు. లొకేషన్‌ను యాప్ పొందాలంటే, దాని కోసం మీ పరికరం యొక్క లొకేషన్ సర్వీస్‌లను తప్పనిసరిగా ఆన్ చేయాలి."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"నేపథ్యంలో స్థానాన్ని యాక్సెస్ చేయి"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"బ్యాక్‌గ్రౌండ్‌లో లొకేషన్‌ను యాక్సెస్ చేయి"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"యాప్ ఉపయోగంలో లేనప్పటికీ కూడా, ఈ యాప్, లొకేషన్‌ను ఎప్పుడైనా యాక్సెస్ చేయగలదు."</string>
     <string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"మీ ఆడియో సెట్టింగ్‌లను మార్చడం"</string>
     <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"వాల్యూమ్ మరియు అవుట్‌పుట్ కోసం ఉపయోగించాల్సిన స్పీకర్ వంటి సార్వజనీన ఆడియో సెట్టింగ్‌లను సవరించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"కొనసాగించడానికి మీ వేలిముద్ర లేదా స్క్రీన్ లాక్‌ను ఉపయోగించండి"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"వేలిముద్ర చిహ్నం"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ఫేస్ అన్‌లాక్"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ఫేస్ అన్‌లాక్‌తో సమస్య"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"కొనసాగించడానికి మీ ముఖం లేదా స్క్రీన్ లాక్‌ను ఉపయోగించండి"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"ముఖ చిహ్నం"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"సింక్ సెట్టింగ్‌లను చదవగలగడం"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ఖాతా యొక్క సింక్‌ సెట్టింగ్‌లను చదవడానికి యాప్‌ను అనుమతిస్తుంది. ఉదాహరణకు, వ్యక్తుల యాప్‌ ఖాతాతో సమకాలీకరించబడాలా లేదా అనే విషయాన్ని ఇది నిశ్చయించవచ్చు."</string>
@@ -1006,7 +1010,7 @@
     <string name="permlab_readHistoryBookmarks" msgid="9102293913842539697">"మీ వెబ్ బుక్‌మార్క్‌లు మరియు చరిత్రను చదవడం"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="2323799501008967852">"బ్రౌజర్ సందర్శించిన అన్ని URLల చరిత్ర గురించి మరియు అన్ని బ్రౌజర్ బుక్‌మార్క్‌ల గురించి చదవడానికి యాప్‌ను అనుమతిస్తుంది. గమనిక: ఈ అనుమతి మూడవ పక్షం బ్రౌజర్‌లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర యాప్‌ల ద్వారా అమలు చేయబడకపోవచ్చు."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="6090259925187986937">"వెబ్ బుక్‌మార్క్‌లు మరియు చరిత్రను వ్రాయడం"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"మీ టాబ్లెట్‌లో నిల్వ చేయబడిన బ్రౌజర్ చరిత్రను లేదా బుక్‌మార్క్‌లను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. ఇది బ్రౌజర్ డేటాను ఎరేజ్ చేయడానికి లేదా సవరించడానికి యాప్‌ను అనుమతించవచ్చు. గమనిక: ఈ అనుమతి మూడవ పక్షం బ్రౌజర్‌లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర యాప్‌ల ద్వారా అమలు చేయబడకపోవచ్చు."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"మీ టాబ్లెట్‌లో నిల్వ చేయబడిన బ్రౌజర్ హిస్టరీని, బుక్‌మార్క్‌లను ఎడిట్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. ఇది బ్రౌజర్ డేటాను ఎరేజ్ చేయడానికి లేదా ఎడిట్ చేయడానికి యాప్‌ను అనుమతించవచ్చు. గమనిక: ఈ అనుమతిని థర్డ్ పార్టీ బ్రౌజర్‌లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర యాప్‌లు అమలు చేయకపోవచ్చు."</string>
     <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"మీ Android TV పరికరంలో నిల్వ చేసిన బ్రౌజర్ చరిత్ర లేదా బుక్‌మార్క్‌లను సవరించడానికి యాప్‌ని అనుమతిస్తుంది. ఇది బ్రౌజర్ డేటాను తీసివేయడానికి లేదా సవరించడానికి యాప్‌ని అనుమతించవచ్చు. గమనిక: ఈ అనుమతి మూడవ-పక్ష బ్రౌజర్‌లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర యాప్‌ల ద్వారా అమలు కాకపోవచ్చు."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"మీ ఫోన్‌లో నిల్వ చేయబడిన బ్రౌజర్ చరిత్రను లేదా బుక్‌మార్క్‌లను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. ఇది బ్రౌజర్ డేటాను ఎరేజ్ చేయడానికి లేదా సవరించడానికి యాప్‌ను అనుమతించవచ్చు. గమనిక: ఈ అనుమతి మూడవ పక్షం బ్రౌజర్‌లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర యాప్‌ల ద్వారా అమలు చేయబడకపోవచ్చు."</string>
     <string name="permlab_setAlarm" msgid="1158001610254173567">"అలారం సెట్ చేయడం"</string>
@@ -1387,8 +1391,8 @@
     <string name="usb_contaminant_not_detected_message" msgid="892863190942660462">"ఫోన్ ఇకపై ద్రవ లేదా వ్యర్థ పదార్థాలను గుర్తించదు."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="1582531382166919850">"బగ్ రిపోర్ట్‌ను తీస్తోంది…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="6708897723753334999">"బగ్ రిపోర్ట్‌ను షేర్ చేయాలా?"</string>
-    <string name="sharing_remote_bugreport_notification_title" msgid="3077385149217638550">"బగ్ రిపోర్ట్‌ను భాగస్వామ్యం చేస్తోంది..."</string>
-    <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"మీ నిర్వాహకులు ఈ పరికరం సమస్యకు పరిష్కారాన్ని కనుగొనడంలో సహాయం కోసం బగ్ రిపోర్ట్‌ను అభ్యర్థించారు. యాప్‌లు మరియు డేటా భాగస్వామ్యం చేయబడవచ్చు."</string>
+    <string name="sharing_remote_bugreport_notification_title" msgid="3077385149217638550">"బగ్ రిపోర్ట్‌ను షేర్ చేస్తోంది..."</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"మీ అడ్మిన్ ఈ పరికరం సమస్యకు పరిష్కారాన్ని కనుగొనడంలో సహాయం కోసం బగ్ రిపోర్ట్‌ను రిక్వెస్ట్ చేశారు. యాప్‌లు మరియు డేటా షేర్ చేయబడవచ్చు."</string>
     <string name="share_remote_bugreport_action" msgid="7630880678785123682">"షేర్ చేయి"</string>
     <string name="decline_remote_bugreport_action" msgid="4040894777519784346">"తిరస్కరిస్తున్నాను"</string>
     <string name="select_input_method" msgid="3971267998568587025">"ఇన్‌పుట్ పద్ధతిని ఎంచుకోండి"</string>
@@ -1420,7 +1424,7 @@
     <string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"మీరు పరికరాన్ని తిరిగి ఫార్మాట్ చేయాల్సి ఉంటుంది. తొలగించడానికి ట్యాప్ చేయండి"</string>
     <string name="ext_media_unsupported_notification_title" msgid="4358280700537030333">"<xliff:g id="NAME">%s</xliff:g>కి మద్దతు లేదు"</string>
     <string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> పని చేయటం లేదు"</string>
-    <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ఈ పరికరం ఈ <xliff:g id="NAME">%s</xliff:g>కి మద్దతు ఇవ్వదు. మద్దతు కలిగిన ఆకృతిలో సెటప్ చేయడానికి నొక్కండి."</string>
+    <string name="ext_media_unsupported_notification_message" msgid="917738524888367560">"ఈ పరికరం ఈ <xliff:g id="NAME">%s</xliff:g>‌కు సపోర్ట్‌ ఇవ్వదు. సపోర్ట్‌ ఉన్న ఫార్మాట్‌లో సెటప్ చేయడానికి నొక్కండి."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"సపోర్ట్ చేసే ఫార్మాట్‌లో <xliff:g id="NAME">%s</xliff:g>ను సెటప్ చేయడానికి ఎంచుకోండి."</string>
     <string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"మీరు పరికరాన్ని తిరిగి ఫార్మాట్ చేయాల్సి ఉంటుంది"</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> ఊహించని విధంగా తీసివేయబడింది"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"షార్ట్‌కట్ ఆన్ చేసి ఉన్నప్పుడు, రెండు వాల్యూమ్ బటన్‌లను 3 సెకన్ల పాటు నొక్కి ఉంచితే యాక్సెస్ సౌలభ్య ఫీచర్ ప్రారంభం అవుతుంది."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"యాక్సెస్ సౌలభ్య ఫీచర్‌ల కోసం షార్ట్‌కట్‌ను ఆన్ చేయాలా?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"రెండు వాల్యూమ్ కీలను కొంత సేపు నొక్కి పట్టుకుంటే యాక్సెసిబిలిటీ ఫీచ‌ర్‌లు ఆన్ అవుతాయి. ఇది మీ పరికరం పని చేసే విధానాన్ని మార్చవచ్చు.\n\nప్రస్తుత ఫీచర్లు:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nఎంపిక చేసిన ఫీచర్లను మీరు సెట్టింగ్‌లు&gt;యాక్సెసిబిలిటీలో మార్చవచ్చు."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> షార్ట్‌కట్‌ను ఆన్ చేయాలా?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"రెండు వాల్యూమ్ కీలను కొన్ని సెకన్ల పాటు నొక్కి పట్టుకోవడం ద్వారా యాక్సెసిబిలిటీ అయిన <xliff:g id="SERVICE">%1$s</xliff:g> ఆన్ అవుతుంది. ఇది మీ పరికరం పని చేసే విధానాన్ని మార్చవచ్చు.\n\nసెట్టింగ్‌లు &gt; యాక్సెసిబిలిటీలో, వేరొక ఫీచర్‌ను ప్రారంభించేలా ఈ షార్ట్ కట్‌ను మీరు మార్చవచ్చు."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"ఆన్ చేయి"</string>
@@ -2140,7 +2145,7 @@
     <string name="accessibility_system_action_back_label" msgid="4205361367345537608">"వెనుకకు"</string>
     <string name="accessibility_system_action_recents_label" msgid="4782875610281649728">"ఇటీవలి యాప్‌లు"</string>
     <string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"నోటిఫికేషన్‌లు"</string>
-    <string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"శీఘ్ర సెట్టింగ్‌లు"</string>
+    <string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"క్విక్ సెట్టింగ్‌లు"</string>
     <string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"పవర్ డైలాగ్‌ను తెరువు"</string>
     <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"స్క్రీన్‌ను లాక్ చేయి"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"స్క్రీన్‌షాట్"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 44516d7..7452ad1 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ใช้ลายนิ้วมือหรือการล็อกหน้าจอเพื่อดำเนินการต่อ"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ไอคอนลายนิ้วมือ"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"การปลดล็อกด้วยใบหน้า"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"มีปัญหาเกี่ยวกับฟีเจอร์ปลดล็อกด้วยใบหน้า"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ใช้ใบหน้าหรือการล็อกหน้าจอเพื่อดำเนินการต่อ"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"ไอคอนใบหน้า"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"อ่านการตั้งค่าการซิงค์"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"อนุญาตให้แอปพลิเคชันอ่านการตั้งค่าการซิงค์ของบัญชี ตัวอย่างเช่น การอนุญาตนี้สามารถระบุได้ว่าแอปพลิเคชัน People ซิงค์กับบัญชีหรือไม่"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"เมื่อทางลัดเปิดอยู่ การกดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มนาน 3 วินาทีจะเริ่มฟีเจอร์การช่วยเหลือพิเศษ"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"เปิดใช้ทางลัดสำหรับฟีเจอร์การช่วยเหลือพิเศษใช่ไหม"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"การกดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มค้างไว้ 2-3 วินาทีจะเปิดฟีเจอร์การช่วยเหลือพิเศษ การดำเนินการนี้อาจเปลี่ยนแปลงลักษณะการทำงานของอุปกรณ์\n\nฟีเจอร์ปัจจุบัน:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nคุณจะเปลี่ยนฟีเจอร์ที่เลือกไว้ได้ในการตั้งค่า &gt; การช่วยเหลือพิเศษ"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"เปิดใช้ทางลัด <xliff:g id="SERVICE">%1$s</xliff:g> ใช่ไหม"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"การกดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มค้างไว้ 2-3 วินาทีจะเปิด <xliff:g id="SERVICE">%1$s</xliff:g> ซึ่งเป็นฟีเจอร์การช่วยเหลือพิเศษ การดำเนินการนี้อาจเปลี่ยนแปลงลักษณะการทำงานของอุปกรณ์\n\nคุณแก้ไขทางลัดนี้ให้เปิดฟีเจอร์อื่นได้ในการตั้งค่า &gt; การช่วยเหลือพิเศษ"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"เปิด"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index a21c4f0..78fcafb 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Gamitin ang iyong fingerprint o lock ng screen para magpatuloy"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icon ng fingerprint"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Pag-unlock Gamit ang Mukha"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Isyu sa Pag-unlock Gamit ang Mukha"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gamitin ang iyong mukha o lock ng screen para magpatuloy"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Face icon"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"basahin ang mga setting ng sync"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Pinapayagan ang app na basahin ang mga setting ng pag-sync para sa isang account. Halimbawa, matutukoy nito kung naka-sync ang app na Mga Tao sa isang account."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kapag naka-on ang shortcut, magsisimula ang isang feature ng pagiging naa-access kapag pinindot ang parehong button ng volume."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"I-on ang shortcut para sa mga feature ng pagiging naa-access?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Mao-on ang mga feature ng accessibility kapag pinindot nang matagal ang parehong volume key nang ilang segundo. Posibleng mabago nito ang paggana ng iyong device.\n\nMga kasalukuyang feature:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPuwede mong baguhin ang mga napiling feature sa Mga Setting &gt; Accessibility."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"I-on ang shortcut ng <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Mao-on ang feature ng accessibility na <xliff:g id="SERVICE">%1$s</xliff:g> kapag pinindot nang matagal ang parehong volume key nang ilang segundo. Posibleng mabago nito ang paggana ng iyong device.\n\nPuwede mong palitan ng ibang feature ang shortcut na ito sa Mga Setting &gt; Accessibility."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"I-on"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index deda317..92aeea1 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Devam etmek için parmak izi veya ekran kilidinizi kullanın"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Parmak izi simgesi"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Yüz Tanıma Kilidi"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Yüz Tanıma Kilidi sorunu"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Devam etmek için yüz veya ekran kilidinizi kullanın"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Yüz simgesi"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"senk. ayarlarını okuma"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Uygulamaya bir hesaba ait senkronizasyon ayarlarını okuma izni verir. Örneğin, bu izne sahip bir uygulama Kişiler uygulamasının bir hesapla senkronize olup olmadığını belirleyebilir."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kısayol açıkken ses düğmelerinin ikisini birden 3 saniyeliğine basılı tutmanız bir erişilebilirlik özelliğini başlatır."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Erişilebilirlik özellikleri için kısayol açılsın mı?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ses tuşlarının ikisini birden birkaç saniyeliğine basılı tutmak, erişilebilirlik özelliklerini açar. Bu, cihazınızın çalışma şeklini değiştirebilir.\n\nGeçerli özellikler:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nSeçilen özellikleri Ayarlar &gt; Erişilebilirlik\'te değiştirebilirsiniz."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> kısayolu açılsın mı?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ses tuşlarının ikisini birden birkaç saniyeliğine basılı tutmak <xliff:g id="SERVICE">%1$s</xliff:g> erişilebilirlik özelliğini etkinleştirir. Bu, cihazınızın çalışma şeklini değiştirebilir.\n\nBu kısayolu, Ayarlar &gt; Erişilebilirlik\'te başka bir özellikle değiştirebilirsiniz."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Etkinleştir"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index fe64d9d..a503272 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -615,6 +615,7 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Щоб продовжити, скористайтеся відбитком пальця або даними для розблокування екрана"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Сталася помилка. Повторіть спробу."</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Значок відбитка пальця"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Фейсконтроль"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Сталася помилка з фейсконтролем"</string>
@@ -667,6 +668,7 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Щоб продовжити, скористайтеся фейсконтролем або даними для розблокування екрана"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Сталася помилка. Повторіть спробу."</string>
     <string name="face_icon_content_description" msgid="465030547475916280">"Значок обличчя"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"читати налаштування синхронізації"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Дозволяє програмі читати налаштування синхронізації для облікового запису, наприклад, визначати, чи програма Люди синхронізується з обліковим записом."</string>
@@ -1736,7 +1738,7 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Якщо цей засіб увімкнено, ви можете активувати спеціальні можливості, утримуючи обидві кнопки гучності протягом трьох секунд."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Увімкнути засіб спеціальних можливостей?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Якщо втримувати обидві клавіші гучності впродовж кількох секунд, вмикаються спеціальні можливості. Це впливає на роботу пристрою.\n\nПоточні функції:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nВибрані функції можна змінити в налаштуваннях у меню спеціальних можливостей."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Увімкнути засіб швидкого доступу до сервісу <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Якщо втримувати обидві клавіші гучності впродовж кількох секунд, буде ввімкнено спеціальні можливості – <xliff:g id="SERVICE">%1$s</xliff:g>. Це може вплинути на роботу пристрою.\n\nДля цієї комбінації клавіш можна вибрати іншу функцію в меню \"Налаштування &gt; Спеціальні можливості\"."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Увімкнути"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index de5a301..d450667 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"جاری رکھنے کے لیے اپنے فنگر پرنٹ یا اسکرین لاک کا استعمال کریں"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"فنگر پرنٹ آئیکن"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"فیس اَنلاک"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"فیس اَنلاک میں مسئلہ"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"جاری رکھنے کے لیے اپنے چہرے یا اسکرین لاک کا استعمال کریں"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"چہرے کا آئیکن"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"مطابقت پذیری کی ترتیبات پڑھیں"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"‏ایپ کو کسی اکاؤنٹ کیلئے مطابقت پذیری کی ترتیبات پڑھنے کی اجازت دیتا ہے۔ مثلا، یہ تعین کرسکتا ہے کہ آیا People ایپ کسی اکاؤنٹ کے ساتھ مطابقت پذیر ہے۔"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"شارٹ کٹ آن ہونے پر، 3 سیکنڈ تک دونوں والیوم بٹنز کو دبانے سے ایک ایکسیسبیلٹی خصوصیت شروع ہو جائے گی۔"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ایکسیسبیلٹی خصوصیات کے لیے شارٹ کٹ آن کریں؟"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"دونوں والیوم کی کلیدوں کو کچھ سیکنڈز تک دبائیں رکھنے سے ایکسیسبیلٹی خصوصیات آن ہو جاتی ہیں۔ اس سے آپ کے آلے کے کام کرنے کا طریقہ تبدیل ہو سکتا ہے۔\n\nموجودہ خصوصیات:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nآپ ترتیبات اور ایکسیسبیلٹی میں منتخب کردہ خصوصیات کو تبدیل کر سکتے ہیں۔"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> شارٹ کٹ آن کریں؟"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"والیوم کی دونوں کلیدوں کو کچھ سیکنڈز تک دبائے رکھنے سے <xliff:g id="SERVICE">%1$s</xliff:g> ایکسیسبیلٹی خصوصیت آن ہو جاتی ہے۔ اس سے آپ کے آلے کے کام کرنے کا طریقہ تبدیل ہو سکتا ہے۔\n\nآپ ترتیبات اور ایکسیسبیلٹی میں دیگر خصوصیت کے لیے اس شارٹ کٹ کو تبدیل کر سکتے ہیں۔"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"آن کریں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index ecc5f52..f5a8fed2 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Davom etish uchun barmoq izi yoki ekran qulfidan foydalaning"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Barmoq izi belgisi"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Yuz bilan ochish"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Yuz bilan ochishda muammo bor"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Davom etish uchun yuz tekshiruvi yoki ekran qulfidan foydalaning"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Yuz belgisi"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"sinx-sh sozlamalarini o‘qish"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Ilovaga hisobning sinxronlash sozlamalarini o‘qish uchun ruxsat beradi. Masalan, bu \"Odamlar\" ilovasi hisob bilan sinxronlangan yoki aksini aniqlay oladi."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Maxsus imkoniyatlar funksiyasidan foydalanish uchun u yoniqligida ikkala tovush tugmasini 3 soniya bosib turing."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Maxsus imkoniyatlar uchun tezkor tugma yoqilsinmi?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Maxsus imkoniyatlarni yoqish uchun ikkala tovush tugmalarini bir necha soniya bosib turing. Qurilmangiz ishlashida oʻzgarish yuz berishi mumkin.\n\nJoriy funksiyalar:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nTanlangan funksiyalarni Sozlamalar ichidagi Maxsus imkoniyatlar ustiga bosib oʻzgartirishingiz mumkin."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> tezkor tugmasi yoqilsinmi?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"<xliff:g id="SERVICE">%1$s</xliff:g> funksiyasini yoqish uchun ikkala tovush tugmalarini bir necha soniya bosib turing. Qurilmangiz ishlashida oʻzgarish yuz berishi mumkin.\n\nBu tezkor tugmalarni boshqa funksiyaga Sozlamalar ichidagi Maxsus imkoniyatlar orqali tayinlash mumkin."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Yoqilsin"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 38a424b..31a2605 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Dùng vân tay của bạn hoặc phương thức khóa màn hình để tiếp tục"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Biểu tượng vân tay"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Mở khóa bằng khuôn mặt"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Vấn đề với tính năng Mở khóa bằng khuôn mặt"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Dùng khuôn mặt của bạn hoặc phương thức khóa màn hình để tiếp tục"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Biểu tượng khuôn mặt"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"đọc cài đặt đồng bộ hóa"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Cho phép ứng dụng đọc cài đặt đồng bộ hóa cho tài khoản. Ví dụ: việc này có thể xác định liệu ứng dụng Mọi người đã được đồng bộ hóa với tài khoản chưa."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Khi phím tắt này đang bật, thao tác nhấn cả hai nút âm lượng trong 3 giây sẽ mở tính năng hỗ trợ tiếp cận."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Bật phím tắt cho các tính năng hỗ trợ tiếp cận?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Thao tác nhấn và giữ cả hai phím âm lượng trong vài giây sẽ bật các tính năng hỗ trợ tiếp cận. Việc bật các tính năng này có thể thay đổi cách thiết bị của bạn hoạt động.\n\nCác tính năng hiện tại:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nBạn có thể thay đổi những tính năng đã chọn trong phần Cài đặt &gt; Hỗ trợ tiếp cận."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Bật phím tắt cho <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Thao tác nhấn và giữ cả hai phím âm lượng trong vài giây sẽ bật <xliff:g id="SERVICE">%1$s</xliff:g>, một tính năng hỗ trợ tiếp cận. Việc bật tính năng này có thể thay đổi cách thiết bị của bạn hoạt động.\n\nBạn có thể chuyển phím tắt này thành một tính năng khác trong phần Cài đặt &gt; Hỗ trợ tiếp cận."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Bật"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 4b6dda5..26c2b25 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"使用指纹解锁或屏幕锁定凭据验证身份,才能继续操作"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"指纹图标"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"人脸解锁"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"人脸解锁存在问题"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"使用人脸解锁或屏幕锁定凭据验证身份,才能继续操作"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"面孔图标"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"读取同步设置"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"允许该应用读取某个帐号的同步设置。例如,此权限可确定“联系人”应用是否与某个帐号同步。"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"启用这项快捷方式后,同时按下两个音量按钮 3 秒钟即可启动无障碍功能。"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"要开启无障碍功能快捷方式吗?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"同时按住两个音量键几秒钟,即可开启无障碍功能。这样做可能会改变您设备的工作方式。\n\n当前功能:\n<xliff:g id="SERVICE">%1$s</xliff:g>\n您可以在“设置”&gt;“无障碍”中更改所选功能。"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"要开启<xliff:g id="SERVICE">%1$s</xliff:g>快捷方式吗?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"同时按住两个音量键几秒钟,即可开启<xliff:g id="SERVICE">%1$s</xliff:g>无障碍功能。这样做可能会改变您设备的工作方式。\n\n您可以在“设置”&gt;“无障碍”中将此快捷方式更改为开启另一项功能。"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"开启"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index ccfb026..b87d7c0 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -609,6 +609,7 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"請使用指紋解鎖或螢幕鎖定功能驗證身分,才能繼續操作"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"發生錯誤,請再試一次。"</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"指紋圖示"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"面孔解鎖"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"「面孔解鎖」功能發生問題"</string>
@@ -661,6 +662,7 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"請使用面孔解鎖或螢幕鎖定功能驗證身分,才能繼續操作"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"發生錯誤,請再試一次。"</string>
     <string name="face_icon_content_description" msgid="465030547475916280">"臉孔圖示"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"讀取同步處理設定"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"允許應用程式讀取帳戶的同步設定,例如確定「通訊錄」應用程式是否和某個帳戶保持同步。"</string>
@@ -1692,7 +1694,7 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"啟用快速鍵後,同時按住音量按鈕 3 秒便可啟用無障礙功能。"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"要開啟無障礙功能捷徑嗎?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"同時按下兩個音量鍵幾秒,以開啟無障礙功能。這可能會變更裝置的運作。\n\n目前功能:\n<xliff:g id="SERVICE">%1$s</xliff:g>\n您可在「設定」&gt;「無障礙功能」中變更所選功能。"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"要開啟 <xliff:g id="SERVICE">%1$s</xliff:g> 捷徑嗎?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"同時按下兩個音量鍵幾秒,以開啟 <xliff:g id="SERVICE">%1$s</xliff:g> 無障礙功能。這可能會變更裝置的運作。\n\n您可在「設定」&gt;「無障礙功能」中變更此快速鍵。"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"開啟"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 107f115..4fb2225 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"請使用指紋解鎖或螢幕鎖定功能驗證身分,才能繼續操作"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"指紋圖示"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"人臉解鎖"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"人臉解鎖功能發生問題"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"請使用人臉解鎖或螢幕鎖定功能驗證身分,才能繼續操作"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"臉孔圖示"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"讀取同步處理設定"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"允許應用程式讀取帳戶的同步處理設定,例如判斷「使用者」應用程式是否和某個帳戶進行同步處理。"</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"啟用捷徑功能,只要同時按下兩個音量按鈕 3 秒,就能啟動無障礙功能。"</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"要開啟無障礙功能快速鍵嗎?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"同時按住音量調高鍵和調低鍵數秒,即可開啟無障礙功能。這麼做可能會改變裝置的運作方式。\n\n目前的功能:\n<xliff:g id="SERVICE">%1$s</xliff:g>\n你可以在 [設定] &gt; [無障礙設定] 中變更選取的功能。"</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"要開啟「<xliff:g id="SERVICE">%1$s</xliff:g>」快速鍵嗎?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"同時按住音量調高鍵和調低鍵數秒,即可開啟「<xliff:g id="SERVICE">%1$s</xliff:g>」無障礙功能。這麼做可能會改變裝置的運作方式。\n\n你可以在 [設定] &gt; [無障礙設定] 中變更這個快速鍵觸發的功能。"</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"開啟"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 9c9d68a..ae0cbe2 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -609,6 +609,8 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Sebenzisa izigxivizo zakho zomunwe noma ukukhiya isikrini ukuze uqhubeke"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
+    <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
+    <skip />
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Isithonjana sezigxivizo zeminwe"</string>
     <string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ukuvula ubuso"</string>
     <string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Inkinga Ngokuvula ngobuso"</string>
@@ -661,6 +663,8 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Sebenzisa ubuso bakho noma ukukhiya isikrini ukuze uqhubeke"</string>
   <string-array name="face_error_vendor">
   </string-array>
+    <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
+    <skip />
     <string name="face_icon_content_description" msgid="465030547475916280">"Isithonjana sobuso"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"funda izilungiselelo zokuvumelanisa"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Ivumela uhlelo lokusebenza ukufunda izilungiselelo zokuvumelanisa ze-akhawunti. Isibonelo, lokhu kungacacisa ukuthi noma ngabe uhlelo lokusebenza le-People livumelanisiwe ne-akhawunti."</string>
@@ -1692,7 +1696,8 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Uma isinqamuleli sivuliwe, ukucindezela zombili izinkinobho zevolumu amasekhondi angu-3 kuzoqalisa isici sokufinyelela."</string>
     <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vula isinqamuleli sezici zokufinyeleleka?"</string>
     <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ukubambela phansi bobabili okhiye bevolumu amasekhondi ambalwa kuvula izici zokufinyelela. Lokhu kungashintsha indlela idivayisi yakho esebenza ngayo.\n\nIzici zamanje:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nUngashintsha izici ezikhethiwe Kuzilungiselelo &gt; Ukufinyeleleka."</string>
-    <string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">"	• <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
+    <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
+    <skip />
     <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Vula isinqamuleli se-<xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
     <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ukubambela phansi bobabili okhiye bevolumu amasekhondi ambalwa kuvula i-<xliff:g id="SERVICE">%1$s</xliff:g>, eyisici sokufinyelela Lokhu kungashintsha indlela idivayisi yakho esebenza ngayo.\n\nUngashintshela lesi sinqamuleli kwesinye isici Kuzilungiselelo &gt; Ukufinyeleleka."</string>
     <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Vula"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a5f5051..a56ed14 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8658,6 +8658,8 @@
         <attr name="successColor" format="color|reference"/>
         <!-- The dot color -->
         <attr name="dotColor" format="color|reference"/>
+        <!-- Color of the dot when it's activated -->
+        <attr name="dotActivatedColor" format="color|reference"/>
 
     </declare-styleable>
 
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index c9df3ff..fc9b55f 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1226,18 +1226,18 @@
 
     <!-- List of split types required by this APK to be present in order to function properly,
          separated by commas. The platform will reject installation of an app that is missing
-         any required split types. Each split type is an arbitrary string that has no specific
-         meaning to the platform, and is only used for matching <code>splitTypes</code> and
-         <code>requiredSplitTypes</code>. As an example, if a split requires strings, drawables,
-         and native code this value could be "language,density,abi". Default value is null to
-         indicate no split types are required. -->
+         any required split types. Each split type is a string, and is only used for matching
+         <code>requiredSplitTypes</code> and <code>splitTypes</code>. As an example, if this
+         APK requires localized string resources, screen density resources, and native code
+         this value could be "language,density,abi". Default value is null to indicate no split
+         types are required. -->
     <attr name="requiredSplitTypes" format="string" />
 
-    <!-- List of split types offered by this APK, separated by commas. Each split type is an
-         arbitrary string that has no specific meaning to the platform, and is only used for
-         matching <code>splitTypes</code> and <code>requiredSplitTypes</code>. As an example,
-         if a split offers strings and drawables the value could be "language,density". Default
-         value is null to indicate no split types are offered. -->
+    <!-- List of split types offered by this APK, separated by commas. Each split type is a
+         string, and is only used for matching <code>requiredSplitTypes</code> and
+         <code>splitTypes</code>. As an example, if this split offers localized string resources,
+         and screen density resources the value could be "language,density". Default value is
+         null to indicate no split types are offered. -->
     <attr name="splitTypes" format="string" />
 
     <!-- Flag to specify if this app wants to run the dex within its APK but not extracted or
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8813c43..d11c3f7 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1080,34 +1080,27 @@
     <!-- Vibrator pattern for feedback about a long screen/key press -->
     <integer-array name="config_longPressVibePattern">
         <item>0</item>
-        <item>1</item>
-        <item>20</item>
-        <item>21</item>
+        <item>30</item>
     </integer-array>
 
     <!-- Vibrator pattern for feedback about touching a virtual key -->
     <integer-array name="config_virtualKeyVibePattern">
         <item>0</item>
-        <item>10</item>
         <item>20</item>
-        <item>30</item>
     </integer-array>
 
-    <!-- Vibrator pattern for a very short but reliable vibration for soft keyboard tap -->
-    <integer-array name="config_keyboardTapVibePattern">
-        <item>40</item>
+    <!-- Vibrator pattern for feedback that simulates a double click effect -->
+    <integer-array name="config_doubleClickVibePattern">
+        <item>0</item>
+        <item>30</item>
+        <item>100</item>
+        <item>30</item>
     </integer-array>
 
     <!-- Vibrator pattern for feedback when selecting an hour/minute tick of a Clock -->
     <integer-array name="config_clockTickVibePattern">
-        <item>125</item>
-        <item>30</item>
-    </integer-array>
-
-    <!-- Vibrator pattern for feedback when selecting a day/month/year date of a Calendar -->
-    <integer-array name="config_calendarDateVibePattern">
-        <item>125</item>
-        <item>30</item>
+        <item>0</item>
+        <item>10</item>
     </integer-array>
 
     <!-- Vibrator pattern for feedback about booting with safe mode enabled -->
@@ -1120,14 +1113,6 @@
         <item>600</item>
     </integer-array>
 
-    <!-- Vibrator pattern for feedback about hitting a scroll barrier -->
-    <integer-array name="config_scrollBarrierVibePattern">
-        <item>0</item>
-        <item>15</item>
-        <item>10</item>
-        <item>10</item>
-    </integer-array>
-
     <!-- The URI to associate with each ringtone effect constant, intended to be used with the
          android.os.VibrationEffect#get(Uri, Context) API.
          The position of the string in the string-array determines which ringtone effect is chosen.
@@ -5137,6 +5122,14 @@
            - config_fillBuiltInDisplayCutoutArray
            - config_maskBuiltInDisplayCutoutArray
            - config_waterfallCutoutArray
+           - config_roundedCornerRadiusArray
+           - config_roundedCornerTopRadiusArray
+           - config_roundedCornerBottomRadiusArray
+           - config_builtInDisplayIsRoundArray (config in SystemUI resource)
+           - config_roundedCornerMultipleRadiusArray (config in SystemUI resource)
+           - config_roundedCornerDrawableArray (config in SystemUI resource)
+           - config_roundedCornerTopDrawableArray (config in SystemUI resource)
+           - config_roundedCornerBottomDrawableArray (config in SystemUI resource)
 
          Leave this array empty for single display device and the system will load the default main
          built-in related configs.
@@ -5204,4 +5197,48 @@
 
     <!-- Wear OS: the name of the main activity of the device's sysui. -->
     <string name="config_wearSysUiMainActivity" translatable="false"/>
+
+    <bool name="config_secondaryBuiltInDisplayIsRound">@bool/config_windowIsRound</bool>
+
+    <!-- The display round config for each display in a multi-display device. -->
+    <array name="config_builtInDisplayIsRoundArray" translatable="false">
+        <item>@bool/config_mainBuiltInDisplayIsRound</item>
+        <item>@bool/config_secondaryBuiltInDisplayIsRound</item>
+    </array>
+
+    <!-- The rounded corner radius for each display in a multi-display device. -->
+    <array name="config_roundedCornerRadiusArray" translatable="false">
+        <item>@dimen/rounded_corner_radius</item>
+        <item>@dimen/secondary_rounded_corner_radius</item>
+    </array>
+
+    <!-- The top rounded corner radius for each display in a multi-display device. -->
+    <array name="config_roundedCornerTopRadiusArray" translatable="false">
+        <item>@dimen/rounded_corner_radius_top</item>
+        <item>@dimen/secondary_rounded_corner_radius_top</item>
+    </array>
+
+    <!-- The bottom rounded corner radius for each display in a multi-display device. -->
+    <array name="config_roundedCornerBottomRadiusArray" translatable="false">
+        <item>@dimen/rounded_corner_radius_bottom</item>
+        <item>@dimen/secondary_rounded_corner_radius_bottom</item>
+    </array>
+
+    <!-- The rounded corner radius adjustment for each display in a multi-display device. -->
+    <array name="config_roundedCornerRadiusAdjustmentArray" translatable="false">
+        <item>@dimen/rounded_corner_radius_adjustment</item>
+        <item>@dimen/secondary_rounded_corner_radius_adjustment</item>
+    </array>
+
+    <!-- The rounded corner radius top adjustment for each display in a multi-display device. -->
+    <array name="config_roundedCornerTopRadiusAdjustmentArray" translatable="false">
+        <item>@dimen/rounded_corner_radius_top_adjustment</item>
+        <item>@dimen/secondary_rounded_corner_radius_top_adjustment</item>
+    </array>
+
+    <!-- The rounded corner radius bottom adjustment for each display in a multi-display device. -->
+    <array name="config_roundedCornerBottomRadiusAdjustmentArray" translatable="false">
+        <item>@dimen/rounded_corner_radius_bottom_adjustment</item>
+        <item>@dimen/secondary_rounded_corner_radius_bottom_adjustment</item>
+    </array>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index e8bb606..a4151c7 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -55,6 +55,8 @@
     <dimen name="navigation_bar_height_landscape">48dp</dimen>
     <!-- Width of the navigation bar when it is placed vertically on the screen -->
     <dimen name="navigation_bar_width">48dp</dimen>
+    <!-- Height of the bottom taskbar not including decorations like rounded corners. -->
+    <dimen name="taskbar_frame_height">60dp</dimen>
     <!-- How much we expand the touchable region of the status bar below the notch to catch touches
          that just start below the notch. -->
     <dimen name="display_cutout_touchable_region_size">12dp</dimen>
@@ -641,6 +643,8 @@
     <dimen name="lock_pattern_dot_line_width">22dp</dimen>
     <dimen name="lock_pattern_dot_size">14dp</dimen>
     <dimen name="lock_pattern_dot_size_activated">30dp</dimen>
+    <!-- Width of a gradient applied to a lock pattern line while its disappearing animation. -->
+    <dimen name="lock_pattern_fade_away_gradient_width">8dp</dimen>
 
     <dimen name="text_handle_min_size">40dp</dimen>
 
@@ -678,9 +682,6 @@
     <dimen name="default_magnifier_horizontal_offset">0dp</dimen>
     <item type="dimen" format="float" name="default_magnifier_zoom">1.25</item>
 
-    <!-- Spacing around the background change frome service to non-service -->
-    <dimen name="chooser_service_spacing">8dp</dimen>
-
     <item type="dimen" name="aerr_padding_list_top">15dp</item>
     <item type="dimen" name="aerr_padding_list_bottom">8dp</item>
 
@@ -952,4 +953,12 @@
     <dimen name="secondary_waterfall_display_top_edge_size">0px</dimen>
     <dimen name="secondary_waterfall_display_right_edge_size">0px</dimen>
     <dimen name="secondary_waterfall_display_bottom_edge_size">0px</dimen>
+
+    <!-- Rounded corner settings for secondary built-in display -->
+    <dimen name="secondary_rounded_corner_radius">0px</dimen>
+    <dimen name="secondary_rounded_corner_radius_top">0px</dimen>
+    <dimen name="secondary_rounded_corner_radius_bottom">0px</dimen>
+    <dimen name="secondary_rounded_corner_radius_adjustment">0px</dimen>
+    <dimen name="secondary_rounded_corner_radius_top_adjustment">0px</dimen>
+    <dimen name="secondary_rounded_corner_radius_bottom_adjustment">0px</dimen>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6a1152b..5df7a97 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1318,6 +1318,7 @@
   <java-symbol type="dimen" name="lock_pattern_dot_line_width" />
   <java-symbol type="dimen" name="lock_pattern_dot_size" />
   <java-symbol type="dimen" name="lock_pattern_dot_size_activated" />
+  <java-symbol type="dimen" name="lock_pattern_fade_away_gradient_width" />
   <java-symbol type="drawable" name="clock_dial" />
   <java-symbol type="drawable" name="clock_hand_hour" />
   <java-symbol type="drawable" name="clock_hand_minute" />
@@ -1694,10 +1695,10 @@
   <java-symbol type="anim" name="activity_close_exit" />
 
   <java-symbol type="array" name="config_autoRotationTiltTolerance" />
-  <java-symbol type="array" name="config_keyboardTapVibePattern" />
   <java-symbol type="array" name="config_longPressVibePattern" />
-  <java-symbol type="array" name="config_safeModeEnabledVibePattern" />
   <java-symbol type="array" name="config_virtualKeyVibePattern" />
+  <java-symbol type="array" name="config_doubleClickVibePattern" />
+  <java-symbol type="array" name="config_safeModeEnabledVibePattern" />
   <java-symbol type="attr" name="actionModePopupWindowStyle" />
   <java-symbol type="attr" name="dialogCustomTitleDecorLayout" />
   <java-symbol type="attr" name="dialogTitleDecorLayout" />
@@ -1742,6 +1743,7 @@
   <java-symbol type="dimen" name="navigation_bar_height_car_mode" />
   <java-symbol type="dimen" name="navigation_bar_height_landscape_car_mode" />
   <java-symbol type="dimen" name="navigation_bar_width_car_mode" />
+  <java-symbol type="dimen" name="taskbar_frame_height" />
   <java-symbol type="dimen" name="status_bar_height" />
   <java-symbol type="dimen" name="display_cutout_touchable_region_size" />
   <java-symbol type="dimen" name="quick_qs_offset_height" />
@@ -2500,7 +2502,6 @@
   <java-symbol type="dimen" name="datepicker_year_label_height" />
 
   <java-symbol type="array" name="config_clockTickVibePattern" />
-  <java-symbol type="array" name="config_calendarDateVibePattern" />
 
   <!-- From KeyguardServiceDelegate -->
   <java-symbol type="string" name="config_keyguardComponent" />
@@ -3685,7 +3686,6 @@
   <java-symbol type="string" name="popup_window_default_title" />
   <java-symbol type="bool" name="config_showAreaUpdateInfoSettings" />
   <java-symbol type="layout" name="shutdown_dialog" />
-  <java-symbol type="dimen" name="chooser_service_spacing" />
   <java-symbol type="bool" name="config_showSysuiShutdown" />
   <java-symbol type="drawable" name="chooser_file_generic" />
 
@@ -4478,4 +4478,19 @@
 
   <java-symbol type="string" name="config_wearSysUiPackage"/>
   <java-symbol type="string" name="config_wearSysUiMainActivity"/>
+
+  <java-symbol type="dimen" name="secondary_rounded_corner_radius" />
+  <java-symbol type="dimen" name="secondary_rounded_corner_radius_top" />
+  <java-symbol type="dimen" name="secondary_rounded_corner_radius_bottom" />
+  <java-symbol type="dimen" name="secondary_rounded_corner_radius_adjustment" />
+  <java-symbol type="dimen" name="secondary_rounded_corner_radius_top_adjustment" />
+  <java-symbol type="dimen" name="secondary_rounded_corner_radius_bottom_adjustment" />
+  <java-symbol type="array" name="config_roundedCornerRadiusArray" />
+  <java-symbol type="array" name="config_roundedCornerTopRadiusArray" />
+  <java-symbol type="array" name="config_roundedCornerBottomRadiusArray" />
+  <java-symbol type="array" name="config_roundedCornerRadiusAdjustmentArray" />
+  <java-symbol type="array" name="config_roundedCornerTopRadiusAdjustmentArray" />
+  <java-symbol type="array" name="config_roundedCornerBottomRadiusAdjustmentArray" />
+  <java-symbol type="bool" name="config_secondaryBuiltInDisplayIsRound" />
+  <java-symbol type="array" name="config_builtInDisplayIsRoundArray" />
 </resources>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 69d2c74..a65de91 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -265,7 +265,7 @@
 
     <!-- USA: 5-6 digits (premium codes from https://www.premiumsmsrefunds.com/ShortCodes.htm),
          visual voicemail code for T-Mobile: 122 -->
-    <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" standard="44567|244444" free="122|87902|21696|24614|28003|30356|33669|40196|41064|41270|43753|44034|46645|52413|56139|57969|61785|66975|75136|76227|81398|83952|85140|86566|86799|95737|96684|99245" />
+    <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" standard="44567|244444" free="122|87902|21696|24614|28003|30356|33669|40196|41064|41270|43753|44034|46645|52413|56139|57969|61785|66975|75136|76227|81398|83952|85140|86566|86799|95737|96684|99245|611611" />
 
     <!-- Vietnam: 1-5 digits (standard system default, not country specific) -->
     <shortcode country="vn" pattern="\\d{1,5}" free="5001|9055" />
diff --git a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
index 7f9d618..7ff76df 100644
--- a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
+++ b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
@@ -234,8 +234,8 @@
         final BatteryUsageStats.Builder builder =
                 new BatteryUsageStats.Builder(new String[0]);
         // If not truncated, this BatteryUsageStats object would generate a proto buffer
-        // larger than 70 Kb
-        for (int i = 0; i < 20000; i++) {
+        // significantly larger than 50 Kb
+        for (int i = 0; i < 3000; i++) {
             BatteryStatsImpl.Uid mockUid = mock(BatteryStatsImpl.Uid.class);
             when(mockUid.getUid()).thenReturn(i);
             builder.getOrCreateUidBatteryConsumerBuilder(mockUid)
@@ -246,7 +246,7 @@
         }
 
         // Add a UID with much larger battery footprint
-        final int largeConsumerUid = 20001;
+        final int largeConsumerUid = 3001;
         BatteryStatsImpl.Uid largeConsumerMockUid = mock(BatteryStatsImpl.Uid.class);
         when(largeConsumerMockUid.getUid()).thenReturn(largeConsumerUid);
         builder.getOrCreateUidBatteryConsumerBuilder(largeConsumerMockUid)
@@ -256,7 +256,7 @@
                 .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 400);
 
         // Add a UID with much larger usage duration
-        final int highUsageUid = 20002;
+        final int highUsageUid = 3002;
         BatteryStatsImpl.Uid highUsageMockUid = mock(BatteryStatsImpl.Uid.class);
         when(highUsageMockUid.getUid()).thenReturn(highUsageUid);
         builder.getOrCreateUidBatteryConsumerBuilder(highUsageMockUid)
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index 685671b..34c1763 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -16,9 +16,11 @@
 
 package android.app;
 
-import static androidx.core.graphics.ColorUtils.calculateContrast;
+import static android.app.Notification.Builder.ensureColorSpanContrast;
 
 import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.internal.util.ContrastColorUtilTest.assertContrastIsAtLeast;
+import static com.android.internal.util.ContrastColorUtilTest.assertContrastIsWithinRange;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -35,6 +37,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.LocusId;
+import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.graphics.BitmapFactory;
 import android.graphics.Color;
@@ -42,12 +45,21 @@
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.TextAppearanceSpan;
 import android.widget.RemoteViews;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.R;
+import com.android.internal.util.ContrastColorUtil;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -334,6 +346,163 @@
     }
 
     @Test
+    public void testBuilder_getFullLengthSpanColor_returnsNullForString() {
+        assertThat(Notification.Builder.getFullLengthSpanColor("String")).isNull();
+    }
+
+    @Test
+    public void testBuilder_getFullLengthSpanColor_returnsNullWithPartialSpan() {
+        CharSequence text = new SpannableStringBuilder()
+                .append("text with ")
+                .append("some red", new ForegroundColorSpan(Color.RED),
+                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        assertThat(Notification.Builder.getFullLengthSpanColor(text)).isNull();
+    }
+
+    @Test
+    public void testBuilder_getFullLengthSpanColor_worksWithSingleSpan() {
+        CharSequence text = new SpannableStringBuilder()
+                .append("text that is all red", new ForegroundColorSpan(Color.RED),
+                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        assertThat(Notification.Builder.getFullLengthSpanColor(text)).isEqualTo(Color.RED);
+    }
+
+    @Test
+    public void testBuilder_getFullLengthSpanColor_worksWithFullAndPartialSpans() {
+        Spannable text = new SpannableString("blue text with yellow and green");
+        text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21,
+                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        text.setSpan(new ForegroundColorSpan(Color.BLUE), 0, text.length(),
+                Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+        text.setSpan(new ForegroundColorSpan(Color.GREEN), 26, 31,
+                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        assertThat(Notification.Builder.getFullLengthSpanColor(text)).isEqualTo(Color.BLUE);
+    }
+
+    @Test
+    public void testBuilder_getFullLengthSpanColor_worksWithTextAppearance() {
+        Spannable text = new SpannableString("title text with yellow and green");
+        text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21,
+                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        TextAppearanceSpan textAppearanceSpan = new TextAppearanceSpan(mContext,
+                R.style.TextAppearance_DeviceDefault_Notification_Title);
+        int expectedTextColor = textAppearanceSpan.getTextColor().getDefaultColor();
+        text.setSpan(textAppearanceSpan, 0, text.length(),
+                Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+        text.setSpan(new ForegroundColorSpan(Color.GREEN), 26, 31,
+                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        assertThat(Notification.Builder.getFullLengthSpanColor(text)).isEqualTo(expectedTextColor);
+    }
+
+    @Test
+    public void testBuilder_ensureColorSpanContrast_removesAllFullLengthColorSpans() {
+        Spannable text = new SpannableString("blue text with yellow and green");
+        text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21,
+                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        text.setSpan(new ForegroundColorSpan(Color.BLUE), 0, text.length(),
+                Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+        TextAppearanceSpan taSpan = new TextAppearanceSpan(mContext,
+                R.style.TextAppearance_DeviceDefault_Notification_Title);
+        assertThat(taSpan.getTextColor()).isNotNull();  // it must be set to prove it is cleared.
+        text.setSpan(taSpan, 0, text.length(),
+                Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+        text.setSpan(new ForegroundColorSpan(Color.GREEN), 26, 31,
+                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        Spannable result = (Spannable) ensureColorSpanContrast(text, Color.BLACK);
+        Object[] spans = result.getSpans(0, result.length(), Object.class);
+        assertThat(spans).hasLength(3);
+
+        assertThat(result.getSpanStart(spans[0])).isEqualTo(15);
+        assertThat(result.getSpanEnd(spans[0])).isEqualTo(21);
+        assertThat(((ForegroundColorSpan) spans[0]).getForegroundColor()).isEqualTo(Color.YELLOW);
+
+        assertThat(result.getSpanStart(spans[1])).isEqualTo(0);
+        assertThat(result.getSpanEnd(spans[1])).isEqualTo(31);
+        assertThat(spans[1]).isNotSameInstanceAs(taSpan);  // don't mutate the existing span
+        assertThat(((TextAppearanceSpan) spans[1]).getFamily()).isEqualTo(taSpan.getFamily());
+        assertThat(((TextAppearanceSpan) spans[1]).getTextColor()).isNull();
+
+        assertThat(result.getSpanStart(spans[2])).isEqualTo(26);
+        assertThat(result.getSpanEnd(spans[2])).isEqualTo(31);
+        assertThat(((ForegroundColorSpan) spans[2]).getForegroundColor()).isEqualTo(Color.GREEN);
+    }
+
+    @Test
+    public void testBuilder_ensureColorSpanContrast_partialLength_adjusted() {
+        int background = 0xFFFF0101;  // Slightly lighter red
+        CharSequence text = new SpannableStringBuilder()
+                .append("text with ")
+                .append("some red", new ForegroundColorSpan(Color.RED),
+                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        CharSequence result = ensureColorSpanContrast(text, background);
+
+        // ensure the span has been updated to have > 1.3:1 contrast ratio with fill color
+        Object[] spans = ((Spannable) result).getSpans(0, result.length(), Object.class);
+        assertThat(spans).hasLength(1);
+        int foregroundColor = ((ForegroundColorSpan) spans[0]).getForegroundColor();
+        assertContrastIsWithinRange(foregroundColor, background, 3, 3.2);
+    }
+
+    @Test
+    public void testBuilder_ensureColorSpanContrast_worksWithComplexInput() {
+        Spannable text = new SpannableString("blue text with yellow and green and cyan");
+        text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21,
+                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        text.setSpan(new ForegroundColorSpan(Color.BLUE), 0, text.length(),
+                Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+        // cyan TextAppearanceSpan
+        TextAppearanceSpan taSpan = new TextAppearanceSpan(mContext,
+                R.style.TextAppearance_DeviceDefault_Notification_Title);
+        taSpan = new TextAppearanceSpan(taSpan.getFamily(), taSpan.getTextStyle(),
+                taSpan.getTextSize(), ColorStateList.valueOf(Color.CYAN), null);
+        text.setSpan(taSpan, 36, 40,
+                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        text.setSpan(new ForegroundColorSpan(Color.GREEN), 26, 31,
+                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        Spannable result = (Spannable) ensureColorSpanContrast(text, Color.GRAY);
+        Object[] spans = result.getSpans(0, result.length(), Object.class);
+        assertThat(spans).hasLength(3);
+
+        assertThat(result.getSpanStart(spans[0])).isEqualTo(15);
+        assertThat(result.getSpanEnd(spans[0])).isEqualTo(21);
+        assertThat(((ForegroundColorSpan) spans[0]).getForegroundColor()).isEqualTo(Color.YELLOW);
+
+        assertThat(result.getSpanStart(spans[1])).isEqualTo(36);
+        assertThat(result.getSpanEnd(spans[1])).isEqualTo(40);
+        assertThat(spans[1]).isNotSameInstanceAs(taSpan);  // don't mutate the existing span
+        assertThat(((TextAppearanceSpan) spans[1]).getFamily()).isEqualTo(taSpan.getFamily());
+        ColorStateList newCyanList = ((TextAppearanceSpan) spans[1]).getTextColor();
+        assertThat(newCyanList).isNotNull();
+        assertContrastIsWithinRange(newCyanList.getDefaultColor(), Color.GRAY, 3, 3.2);
+
+        assertThat(result.getSpanStart(spans[2])).isEqualTo(26);
+        assertThat(result.getSpanEnd(spans[2])).isEqualTo(31);
+        int newGreen = ((ForegroundColorSpan) spans[2]).getForegroundColor();
+        assertThat(newGreen).isNotEqualTo(Color.GREEN);
+        assertContrastIsWithinRange(newGreen, Color.GRAY, 3, 3.2);
+    }
+
+    @Test
+    public void testBuilder_ensureButtonFillContrast_adjustsDarker() {
+        int background = Color.LTGRAY;
+        int foreground = Color.LTGRAY;
+        int result = Notification.Builder.ensureButtonFillContrast(foreground, background);
+        assertContrastIsWithinRange(result, background, 1.3, 1.5);
+        assertThat(ContrastColorUtil.calculateLuminance(result))
+                .isLessThan(ContrastColorUtil.calculateLuminance(background));
+    }
+
+    @Test
+    public void testBuilder_ensureButtonFillContrast_adjustsLighter() {
+        int background = Color.DKGRAY;
+        int foreground = Color.DKGRAY;
+        int result = Notification.Builder.ensureButtonFillContrast(foreground, background);
+        assertContrastIsWithinRange(result, background, 1.3, 1.5);
+        assertThat(ContrastColorUtil.calculateLuminance(result))
+                .isGreaterThan(ContrastColorUtil.calculateLuminance(background));
+    }
+
+    @Test
     public void testColors_ensureColors_dayMode_producesValidPalette() {
         Notification.Colors c = new Notification.Colors();
         boolean colorized = false;
@@ -437,16 +606,6 @@
         assertContrastIsAtLeast(c.getOnAccentTextColor(), c.getTertiaryAccentColor(), 4.5);
     }
 
-    private void assertContrastIsAtLeast(int foreground, int background, double minContrast) {
-        try {
-            assertThat(calculateContrast(foreground, background)).isAtLeast(minContrast);
-        } catch (AssertionError e) {
-            throw new AssertionError(
-                    String.format("Insufficient contrast: foreground=#%08x background=#%08x",
-                            foreground, background), e);
-        }
-    }
-
     private void resolveColorsInNightMode(boolean nightMode, Notification.Colors c, int rawColor,
             boolean colorized) {
         runInNightMode(nightMode,
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
index 97652a9..75d2025 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
@@ -384,10 +384,10 @@
         info = createPackageManagerMockedInfo(true);
         pg = new ResolveInfoPresentationGetter(
                 info.ctx, 0, info.resolveInfo);
-        assertThat("With override permission label should match resolve info label if set",
-                pg.getLabel().equals(info.setResolveInfoLabel));
-        assertThat("With override permission sublabel should be empty",
-                TextUtils.isEmpty(pg.getSubLabel()));
+        assertThat("With override permission label should match activity label if set",
+                pg.getLabel().equals(info.setActivityLabel));
+        assertThat("With override permission the sublabel should be the resolve info label",
+                pg.getSubLabel().equals(info.setResolveInfoLabel));
     }
 
     @Test
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
index c58df4e..b44de3b 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
@@ -70,18 +70,15 @@
     @Test
     public void testParcelability_smallNumberOfUids() {
         final BatteryUsageStats outBatteryUsageStats = buildBatteryUsageStats1(true).build();
-        final Parcel outParcel = Parcel.obtain();
-        outParcel.writeParcelable(outBatteryUsageStats, 0);
-        final byte[] bytes = outParcel.marshall();
-        outParcel.recycle();
+        final Parcel parcel = Parcel.obtain();
+        parcel.writeParcelable(outBatteryUsageStats, 0);
 
-        assertThat(bytes.length).isLessThan(2000);
+        assertThat(parcel.dataSize()).isLessThan(5000);
 
-        final Parcel inParcel = Parcel.obtain();
-        inParcel.unmarshall(bytes, 0, bytes.length);
-        inParcel.setDataPosition(0);
+        parcel.setDataPosition(0);
+
         final BatteryUsageStats inBatteryUsageStats =
-                inParcel.readParcelable(getClass().getClassLoader());
+                parcel.readParcelable(getClass().getClassLoader());
         assertThat(inBatteryUsageStats).isNotNull();
         assertBatteryUsageStats1(inBatteryUsageStats, true);
     }
@@ -91,7 +88,7 @@
         final BatteryUsageStats.Builder builder =
                 new BatteryUsageStats.Builder(new String[0]);
 
-        // Without the use of a blob, this BatteryUsageStats object would generate a Parcel
+        // Without the use of a CursorWindow, this BatteryUsageStats object would generate a Parcel
         // larger than 64 Kb
         final int uidCount = 200;
         for (int i = 0; i < uidCount; i++) {
@@ -108,8 +105,6 @@
 
         assertThat(parcel.dataSize()).isLessThan(2000);
 
-        // This parcel cannot be marshaled because it contains a file descriptor.
-        // Assuming that parcel marshaling works fine, let's just rewind the parcel.
         parcel.setDataPosition(0);
 
         final BatteryUsageStats inBatteryUsageStats =
diff --git a/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java b/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java
index 26296f1..2da9f57 100644
--- a/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java
@@ -46,5 +46,10 @@
         counter.getCounts(longArrayContainer, 1);
         longArrayContainer.getValues(result);
         assertThat(result).isEqualTo(new long[]{25, 50, 75, 100});
+
+        assertThat(counter.toString()).isEqualTo(
+                "currentState: 0 lastStateChangeTimestamp: 9000 lastUpdateTimestamp: 9000 states:"
+                        + " [0: time: 0 counter: { 75, 150, 225, 300}"
+                        + ", 1: time: 0 counter: { 25, 50, 75, 100}]");
     }
 }
diff --git a/core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java b/core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java
index 9da720c..cfe660c 100644
--- a/core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java
@@ -70,13 +70,13 @@
         assertContrastIsWithinRange(selfContrastColor, lightBg, 4.5, 4.75);
     }
 
-    private void assertContrastIsWithinRange(int foreground, int background,
+    public static void assertContrastIsWithinRange(int foreground, int background,
             double minContrast, double maxContrast) {
         assertContrastIsAtLeast(foreground, background, minContrast);
         assertContrastIsAtMost(foreground, background, maxContrast);
     }
 
-    private void assertContrastIsAtLeast(int foreground, int background, double minContrast) {
+    public static void assertContrastIsAtLeast(int foreground, int background, double minContrast) {
         try {
             assertThat(calculateContrast(foreground, background)).isAtLeast(minContrast);
         } catch (AssertionError e) {
@@ -86,7 +86,7 @@
         }
     }
 
-    private void assertContrastIsAtMost(int foreground, int background, double maxContrast) {
+    public static void assertContrastIsAtMost(int foreground, int background, double maxContrast) {
         try {
             assertThat(calculateContrast(foreground, background)).isAtMost(maxContrast);
         } catch (AssertionError e) {
diff --git a/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java b/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
index edf473e..b85cb9c 100644
--- a/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
@@ -542,83 +542,83 @@
     public void testStateMachineEnterExitTransitionToTest() throws Exception {
         //if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger();
 
-        StateMachineEnterExitTransitionToTest smEnterExitTranstionToTest =
-            new StateMachineEnterExitTransitionToTest("smEnterExitTranstionToTest");
-        smEnterExitTranstionToTest.start();
-        if (smEnterExitTranstionToTest.isDbg()) {
+        StateMachineEnterExitTransitionToTest smEnterExitTransitionToTest =
+                new StateMachineEnterExitTransitionToTest("smEnterExitTransitionToTest");
+        smEnterExitTransitionToTest.start();
+        if (smEnterExitTransitionToTest.isDbg()) {
             tlog("testStateMachineEnterExitTransitionToTest E");
         }
 
-        synchronized (smEnterExitTranstionToTest) {
-            smEnterExitTranstionToTest.sendMessage(TEST_CMD_1);
+        synchronized (smEnterExitTransitionToTest) {
+            smEnterExitTransitionToTest.sendMessage(TEST_CMD_1);
 
             try {
                 // wait for the messages to be handled
-                smEnterExitTranstionToTest.wait();
+                smEnterExitTransitionToTest.wait();
             } catch (InterruptedException e) {
                 tloge("testStateMachineEnterExitTransitionToTest: exception while waiting "
                     + e.getMessage());
             }
         }
 
-        dumpLogRecs(smEnterExitTranstionToTest);
+        dumpLogRecs(smEnterExitTransitionToTest);
 
-        assertEquals(9, smEnterExitTranstionToTest.getLogRecCount());
+        assertEquals(9, smEnterExitTransitionToTest.getLogRecCount());
         LogRec lr;
 
-        lr = smEnterExitTranstionToTest.getLogRec(0);
+        lr = smEnterExitTransitionToTest.getLogRec(0);
         assertEquals(ENTER, lr.getInfo());
-        assertEquals(smEnterExitTranstionToTest.mS1, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS1, lr.getState());
 
-        lr = smEnterExitTranstionToTest.getLogRec(1);
+        lr = smEnterExitTransitionToTest.getLogRec(1);
         assertEquals(EXIT, lr.getInfo());
-        assertEquals(smEnterExitTranstionToTest.mS1, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS1, lr.getState());
 
-        lr = smEnterExitTranstionToTest.getLogRec(2);
+        lr = smEnterExitTransitionToTest.getLogRec(2);
         assertEquals(ENTER, lr.getInfo());
-        assertEquals(smEnterExitTranstionToTest.mS2, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS2, lr.getState());
 
-        lr = smEnterExitTranstionToTest.getLogRec(3);
+        lr = smEnterExitTransitionToTest.getLogRec(3);
         assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(smEnterExitTranstionToTest.mS2, lr.getState());
-        assertEquals(smEnterExitTranstionToTest.mS2, lr.getOriginalState());
-        assertEquals(smEnterExitTranstionToTest.mS3, lr.getDestState());
+        assertEquals(smEnterExitTransitionToTest.mS2, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS2, lr.getOriginalState());
+        assertEquals(smEnterExitTransitionToTest.mS3, lr.getDestState());
 
-        lr = smEnterExitTranstionToTest.getLogRec(4);
+        lr = smEnterExitTransitionToTest.getLogRec(4);
         assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(smEnterExitTranstionToTest.mS2, lr.getState());
-        assertEquals(smEnterExitTranstionToTest.mS2, lr.getOriginalState());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
+        assertEquals(smEnterExitTransitionToTest.mS2, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS2, lr.getOriginalState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getDestState());
         assertEquals(EXIT, lr.getInfo());
 
-        lr = smEnterExitTranstionToTest.getLogRec(5);
+        lr = smEnterExitTransitionToTest.getLogRec(5);
         assertEquals(TEST_CMD_1, lr.getWhat());
         assertEquals(ENTER, lr.getInfo());
-        assertEquals(smEnterExitTranstionToTest.mS3, lr.getState());
-        assertEquals(smEnterExitTranstionToTest.mS3, lr.getOriginalState());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
+        assertEquals(smEnterExitTransitionToTest.mS3, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS3, lr.getOriginalState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getDestState());
 
-        lr = smEnterExitTranstionToTest.getLogRec(6);
+        lr = smEnterExitTransitionToTest.getLogRec(6);
         assertEquals(TEST_CMD_1, lr.getWhat());
         assertEquals(EXIT, lr.getInfo());
-        assertEquals(smEnterExitTranstionToTest.mS3, lr.getState());
-        assertEquals(smEnterExitTranstionToTest.mS3, lr.getOriginalState());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
+        assertEquals(smEnterExitTransitionToTest.mS3, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS3, lr.getOriginalState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getDestState());
 
-        lr = smEnterExitTranstionToTest.getLogRec(7);
+        lr = smEnterExitTransitionToTest.getLogRec(7);
         assertEquals(TEST_CMD_1, lr.getWhat());
         assertEquals(ENTER, lr.getInfo());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getState());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getOriginalState());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getOriginalState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getDestState());
 
-        lr = smEnterExitTranstionToTest.getLogRec(8);
+        lr = smEnterExitTransitionToTest.getLogRec(8);
         assertEquals(TEST_CMD_1, lr.getWhat());
         assertEquals(EXIT, lr.getInfo());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getState());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getOriginalState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getOriginalState());
 
-        if (smEnterExitTranstionToTest.isDbg()) {
+        if (smEnterExitTransitionToTest.isDbg()) {
             tlog("testStateMachineEnterExitTransitionToTest X");
         }
     }
diff --git a/data/etc/car/com.google.android.car.kitchensink.xml b/data/etc/car/com.google.android.car.kitchensink.xml
index 40dda65..42d80e5 100644
--- a/data/etc/car/com.google.android.car.kitchensink.xml
+++ b/data/etc/car/com.google.android.car.kitchensink.xml
@@ -91,5 +91,6 @@
         <permission name="android.car.permission.CONTROL_CAR_EVS_ACTIVITY" />
         <permission name="android.car.permission.USE_CAR_EVS_CAMERA" />
         <permission name="android.car.permission.MONITOR_CAR_EVS_STATUS" />
+        <permission name="android.car.permission.USE_CAR_TELEMETRY_SERVICE" />
     </privapp-permissions>
 </permissions>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 6a93761..0d7225b 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -211,6 +211,12 @@
       "group": "WM_DEBUG_SYNC_ENGINE",
       "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
     },
+    "-1898316768": {
+      "message": "Unable to retrieve window container to start layer mirroring for display %d",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_LAYER_MIRRORING",
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
     "-1895337367": {
       "message": "Delete root task display=%d winMode=%d",
       "level": "VERBOSE",
@@ -1093,6 +1099,12 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-904499590": {
+      "message": "Provided surface for layer mirroring on display %d is not present, so do not update the surface",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_LAYER_MIRRORING",
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
     "-883738232": {
       "message": "Adding more than one toast window for UID at a time.",
       "level": "WARN",
@@ -1303,6 +1315,12 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/RootWindowContainer.java"
     },
+    "-663411559": {
+      "message": "Going ahead with updating layer mirroring for display %d to new bounds %s and\/or orientation %d.",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_LAYER_MIRRORING",
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
     "-655104359": {
       "message": "Frontmost changed immersion: %s",
       "level": "DEBUG",
@@ -1561,6 +1579,12 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-384564722": {
+      "message": "Unable to start layer mirroring for display %d since the surface is not available.",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_LAYER_MIRRORING",
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
     "-381475323": {
       "message": "DisplayContent: boot is waiting for window of type %d to be drawn",
       "level": "DEBUG",
@@ -1633,6 +1657,12 @@
       "group": "WM_DEBUG_STATES",
       "at": "com\/android\/server\/wm\/TaskFragment.java"
     },
+    "-309399422": {
+      "message": "Display %d state is now (%d), so update layer mirroring?",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_LAYER_MIRRORING",
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
     "-302468788": {
       "message": "Expected target rootTask=%s to be top most but found rootTask=%s",
       "level": "WARN",
@@ -1699,6 +1729,12 @@
       "group": "WM_DEBUG_WINDOW_MOVEMENT",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-190034097": {
+      "message": "Unable to retrieve window container to update layer mirroring for display %d",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_LAYER_MIRRORING",
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
     "-177040661": {
       "message": "Start rotation animation. customAnim=%s, mCurRotation=%s, mOriginalRotation=%s",
       "level": "DEBUG",
@@ -1795,6 +1831,12 @@
       "group": "WM_DEBUG_STATES",
       "at": "com\/android\/server\/wm\/TaskFragment.java"
     },
+    "-79877120": {
+      "message": "Display %d has content (%b) so disable layer mirroring",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_LAYER_MIRRORING",
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
     "-70719599": {
       "message": "Unregister remote animations for organizer=%s uid=%d pid=%d",
       "level": "VERBOSE",
@@ -2347,6 +2389,12 @@
       "group": "WM_DEBUG_WINDOW_ORGANIZER",
       "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java"
     },
+    "504397469": {
+      "message": "Unable to update layer mirroring for display %d to new bounds %s and\/or orientation %d, since the surface is not available.",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_LAYER_MIRRORING",
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
     "508887531": {
       "message": "applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s",
       "level": "VERBOSE",
@@ -3103,6 +3151,12 @@
       "group": "WM_DEBUG_SCREEN_ON",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "1407569006": {
+      "message": "Display %d was already layer mirroring, so apply transformations if necessary",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_LAYER_MIRRORING",
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
     "1417601133": {
       "message": "Enqueueing ADD_STARTING",
       "level": "VERBOSE",
@@ -3349,6 +3403,12 @@
       "group": "WM_DEBUG_CONFIGURATION",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
+    "1687376052": {
+      "message": "Display %d has no content and is on, so start layer mirroring for state %d",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_LAYER_MIRRORING",
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
     "1689989893": {
       "message": "SyncGroup %d: Set ready",
       "level": "VERBOSE",
@@ -3753,6 +3813,9 @@
     "WM_DEBUG_KEEP_SCREEN_ON": {
       "tag": "WindowManager"
     },
+    "WM_DEBUG_LAYER_MIRRORING": {
+      "tag": "WindowManager"
+    },
     "WM_DEBUG_LOCKTASK": {
       "tag": "WindowManager"
     },
diff --git a/data/sounds/AllAudio.mk b/data/sounds/AllAudio.mk
index c6c7d3b..a349520 100644
--- a/data/sounds/AllAudio.mk
+++ b/data/sounds/AllAudio.mk
@@ -24,18 +24,13 @@
     $(LOCAL_PATH)/alarms/ogg/Argon.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Argon.ogg \
     $(LOCAL_PATH)/alarms/ogg/Barium.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Barium.ogg \
     $(LOCAL_PATH)/alarms/ogg/Carbon.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Carbon.ogg \
-    $(LOCAL_PATH)/alarms/ogg/Cesium.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Cesium.ogg \
-    $(LOCAL_PATH)/alarms/ogg/Fermium.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Fermium.ogg \
-    $(LOCAL_PATH)/alarms/ogg/Hassium.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Hassium.ogg \
     $(LOCAL_PATH)/alarms/ogg/Helium.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Helium.ogg \
     $(LOCAL_PATH)/alarms/ogg/Krypton.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Krypton.ogg \
     $(LOCAL_PATH)/alarms/ogg/Neon.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Neon.ogg \
     $(LOCAL_PATH)/alarms/ogg/Neptunium.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Neptunium.ogg \
-    $(LOCAL_PATH)/alarms/ogg/Nobelium.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Nobelium.ogg \
     $(LOCAL_PATH)/alarms/ogg/Osmium.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Osmium.ogg \
     $(LOCAL_PATH)/alarms/ogg/Oxygen.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Oxygen.ogg \
     $(LOCAL_PATH)/alarms/ogg/Platinum.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Platinum.ogg \
-    $(LOCAL_PATH)/alarms/ogg/Plutonium.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Plutonium.ogg \
     $(LOCAL_PATH)/alarms/ogg/Promethium.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Promethium.ogg \
     $(LOCAL_PATH)/alarms/ogg/Scandium.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Scandium.ogg \
     $(LOCAL_PATH)/notifications/ogg/Adara.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/notifications/Adara.ogg \
diff --git a/graphics/java/android/graphics/BLASTBufferQueue.java b/graphics/java/android/graphics/BLASTBufferQueue.java
index 36215ec..e369acc 100644
--- a/graphics/java/android/graphics/BLASTBufferQueue.java
+++ b/graphics/java/android/graphics/BLASTBufferQueue.java
@@ -34,11 +34,12 @@
     private static native void nativeSetNextTransaction(long ptr, long transactionPtr);
     private static native void nativeUpdate(long ptr, long surfaceControl, long width, long height,
             int format, long transactionPtr);
-    private static native void nativeFlushShadowQueue(long ptr);
     private static native void nativeMergeWithNextTransaction(long ptr, long transactionPtr,
                                                               long frameNumber);
     private static native void nativeSetTransactionCompleteCallback(long ptr, long frameNumber,
             TransactionCompleteCallback callback);
+    private static native long nativeGetLastAcquiredFrameNum(long ptr);
+    private static native void nativeApplyPendingTransactions(long ptr, long frameNumber);
 
     /**
      * Callback sent to {@link #setTransactionCompleteCallback(long, TransactionCompleteCallback)}
@@ -124,10 +125,6 @@
         }
     }
 
-    public void flushShadowQueue() {
-        nativeFlushShadowQueue(mNativeObject);
-    }
-
     /**
      * Merge the transaction passed in to the next transaction in BlastBufferQueue. The next
      * transaction will be applied or merged when the next frame with specified frame number
@@ -145,4 +142,18 @@
         nativeMergeWithNextTransaction(mNativeObject, nativeTransaction, frameNumber);
     }
 
+    /**
+     * Apply any transactions that were passed to {@link #mergeWithNextTransaction} with the
+     * specified frameNumber. This is intended to ensure transactions don't get stuck as pending
+     * if the specified frameNumber is never drawn.
+     *
+     * @param frameNumber The frameNumber used to determine which transactions to apply.
+     */
+    public void applyPendingTransactions(long frameNumber) {
+        nativeApplyPendingTransactions(mNativeObject, frameNumber);
+    }
+
+    public long getLastAcquiredFrameNum() {
+        return nativeGetLastAcquiredFrameNum(mNativeObject);
+    }
 }
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index 8894fa3..abdf1a2 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -388,7 +388,8 @@
          */
         public @NonNull FrameRenderRequest setFrameCommitCallback(@NonNull Executor executor,
                 @NonNull Runnable frameCommitCallback) {
-            setFrameCompleteCallback(frameNr -> executor.execute(frameCommitCallback));
+            nSetFrameCommitCallback(mNativeProxy,
+                    didProduceBuffer -> executor.execute(frameCommitCallback));
             return this;
         }
 
@@ -609,6 +610,11 @@
     }
 
     /** @hide */
+    public void setFrameCommitCallback(FrameCommitCallback callback) {
+        nSetFrameCommitCallback(mNativeProxy, callback);
+    }
+
+    /** @hide */
     public void setFrameCompleteCallback(FrameCompleteCallback callback) {
         nSetFrameCompleteCallback(mNativeProxy, callback);
     }
@@ -896,13 +902,27 @@
      *
      * @hide
      */
+    public interface FrameCommitCallback {
+        /**
+         * Invoked after a new frame was drawn
+         *
+         * @param didProduceBuffer The draw successfully produced a new buffer.
+         */
+        void onFrameCommit(boolean didProduceBuffer);
+    }
+
+    /**
+     * Interface used to be notified when RenderThread has finished an attempt to draw. This doesn't
+     * mean a new frame has drawn, specifically if there's nothing new to draw, but only that
+     * RenderThread had a chance to draw a frame.
+     *
+     * @hide
+     */
     public interface FrameCompleteCallback {
         /**
-         * Invoked after a frame draw
-         *
-         * @param frameNr The id of the frame that was drawn.
+         * Invoked after a frame draw was attempted.
          */
-        void onFrameComplete(long frameNr);
+        void onFrameComplete();
     }
 
     /**
@@ -1391,6 +1411,9 @@
 
     private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
 
+    private static native void nSetFrameCommitCallback(long nativeProxy,
+            FrameCommitCallback callback);
+
     private static native void nSetFrameCompleteCallback(long nativeProxy,
             FrameCompleteCallback callback);
 
diff --git a/graphics/java/android/graphics/drawable/RippleShader.java b/graphics/java/android/graphics/drawable/RippleShader.java
index 57b3223..272b840 100644
--- a/graphics/java/android/graphics/drawable/RippleShader.java
+++ b/graphics/java/android/graphics/drawable/RippleShader.java
@@ -119,7 +119,7 @@
             + "    vec4 waveColor = vec4(in_color.rgb * waveAlpha, waveAlpha);\n"
             + "    vec4 sparkleColor = vec4(in_sparkleColor.rgb * in_sparkleColor.a, "
             + "in_sparkleColor.a);\n"
-            + "    float mask = in_hasMask == 1. ? sample(in_shader, p).a > 0. ? 1. : 0. : 1.;\n"
+            + "    float mask = in_hasMask == 1. ? in_shader.eval(p).a > 0. ? 1. : 0. : 1.;\n"
             + "    return mix(waveColor, sparkleColor, sparkleAlpha) * mask;\n"
             + "}";
     private static final String SHADER = SHADER_UNIFORMS + SHADER_LIB + SHADER_MAIN;
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitContainer.java
index 4fd2126..a41557d 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitContainer.java
@@ -40,7 +40,15 @@
         mSplitRule = splitRule;
 
         if (shouldFinishPrimaryWithSecondary(splitRule)) {
-            mSecondaryContainer.addActivityToFinishOnExit(primaryActivity);
+            if (mPrimaryContainer.getRunningActivityCount() == 1
+                    && mPrimaryContainer.hasActivity(primaryActivity.getActivityToken())) {
+                mSecondaryContainer.addContainerToFinishOnExit(mPrimaryContainer);
+            } else {
+                // Only adding the activity to be finished vs. the entire TaskFragment while
+                // the secondary container exits because there are other unrelated activities in the
+                // primary TaskFragment.
+                mSecondaryContainer.addActivityToFinishOnExit(primaryActivity);
+            }
         }
         if (shouldFinishSecondaryWithPrimary(splitRule)) {
             mPrimaryContainer.addContainerToFinishOnExit(mSecondaryContainer);
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java
index 05c6792..a783fcd 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java
@@ -117,6 +117,10 @@
         }
 
         container.setInfo(taskFragmentAppearedInfo.getTaskFragmentInfo());
+        if (container.isFinished()) {
+            mPresenter.cleanupContainer(container, false /* shouldFinishDependent */);
+            updateCallbackIfNecessary();
+        }
     }
 
     @Override
@@ -130,7 +134,11 @@
         // Check if there are no running activities - consider the container empty if there are no
         // non-finishing activities left.
         if (!taskFragmentInfo.hasRunningActivity()) {
-            mPresenter.cleanupContainer(container, true /* shouldFinishDependent */);
+            // Do not finish the dependents if this TaskFragment was cleared due to launching
+            // activity in the Task.
+            final boolean shouldFinishDependent =
+                    !taskFragmentInfo.isTaskClearedForReuse();
+            mPresenter.cleanupContainer(container, shouldFinishDependent);
             updateCallbackIfNecessary();
         }
     }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java
index a4f5c75..8503b9f 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java
@@ -125,12 +125,20 @@
         return false;
     }
 
+    int getRunningActivityCount() {
+        int count = mPendingAppearedActivities.size();
+        if (mInfo != null) {
+            count += mInfo.getRunningActivityCount();
+        }
+        return count;
+    }
+
     @Nullable
     TaskFragmentInfo getInfo() {
         return mInfo;
     }
 
-    void setInfo(@Nullable TaskFragmentInfo info) {
+    void setInfo(@NonNull TaskFragmentInfo info) {
         mInfo = info;
         if (mInfo == null || mPendingAppearedActivities.isEmpty()) {
             return;
@@ -182,20 +190,30 @@
      */
     void finish(boolean shouldFinishDependent, @NonNull SplitPresenter presenter,
             @NonNull WindowContainerTransaction wct, @NonNull SplitController controller) {
-        if (mIsFinished) {
-            return;
+        if (!mIsFinished) {
+            mIsFinished = true;
+            finishActivities(shouldFinishDependent, presenter, wct, controller);
         }
-        mIsFinished = true;
 
-        // Finish own activities
-        for (Activity activity : collectActivities()) {
-            activity.finish();
+        if (mInfo == null) {
+            // Defer removal the container and wait until TaskFragment appeared.
+            return;
         }
 
         // Cleanup the visuals
         presenter.deleteTaskFragment(wct, getTaskFragmentToken());
         // Cleanup the records
         controller.removeContainer(this);
+        // Clean up task fragment information
+        mInfo = null;
+    }
+
+    private void finishActivities(boolean shouldFinishDependent, @NonNull SplitPresenter presenter,
+            @NonNull WindowContainerTransaction wct, @NonNull SplitController controller) {
+        // Finish own activities
+        for (Activity activity : collectActivities()) {
+            activity.finish();
+        }
 
         if (!shouldFinishDependent) {
             return;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 95b80df..9dafefe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -628,8 +628,11 @@
             mAddedToWindowManager = true;
             mBubbleData.getOverflow().initialize(this);
             mWindowManager.addView(mStackView, mWmLayoutParams);
-            // Position info is dependent on us being attached to a window
-            mBubblePositioner.update();
+            mStackView.setOnApplyWindowInsetsListener((view, windowInsets) -> {
+                mBubblePositioner.update();
+                mStackView.onDisplaySizeChanged();
+                return windowInsets;
+            });
         } catch (IllegalStateException e) {
             // This means the stack has already been added. This shouldn't happen...
             e.printStackTrace();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 5a51eed..5bc6128 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -1315,6 +1315,7 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
+        mPositioner.update();
         getViewTreeObserver().addOnComputeInternalInsetsListener(this);
         getViewTreeObserver().addOnDrawListener(mSystemGestureExcludeUpdater);
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index 826e2f5..f35c8e1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -58,16 +58,8 @@
     // TODO(b/191269755): use the value defined in InsetsController.
     private static final int ANIMATION_DURATION_RESIZE = 300;
 
-    /**
-     * The task bar height defined in launcher. Used to determine whether to insets divider bounds
-     * or not.
-     */
-    private static final int EXPANDED_TASK_BAR_HEIGHT_IN_DP = 60;
-
     /** The task bar expanded height. Used to determine whether to insets divider bounds or not. */
-    private final float mExpandedTaskBarHeight = TypedValue.applyDimension(
-            TypedValue.COMPLEX_UNIT_DIP, EXPANDED_TASK_BAR_HEIGHT_IN_DP,
-            getResources().getDisplayMetrics());
+    private float mExpandedTaskBarHeight;
 
     private final int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
 
@@ -167,6 +159,8 @@
         mDividerBar = findViewById(R.id.divider_bar);
         mHandle = findViewById(R.id.docked_divider_handle);
         mBackground = findViewById(R.id.docked_divider_background);
+        mExpandedTaskBarHeight = getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.taskbar_frame_height);
         mTouchElevation = getResources().getDimensionPixelSize(
                 R.dimen.docked_stack_divider_lift_elevation);
         mDoubleTapDetector = new GestureDetector(getContext(), new DoubleTapListener());
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 81cad5a..754b8da 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -305,6 +305,10 @@
         mDividePosition = mDividerSnapAlgorithm.getMiddleTarget().position;
         mSplitWindowManager.setResizingSplits(false);
         updateBounds(mDividePosition);
+        mWinToken1 = null;
+        mWinToken2 = null;
+        mWinBounds1.setEmpty();
+        mWinBounds2.setEmpty();
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
index 102b90f..fbf04d6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
@@ -304,7 +304,7 @@
          * Exits splitscreen, with an associated exit trigger from the SplitscreenUIChanged proto
          * for logging.
          */
-        void exitSplitScreen(int exitTrigger);
+        void exitSplitScreen(int toTopTaskId, int exitTrigger);
     }
 
     /**
@@ -357,7 +357,7 @@
         }
 
         @Override
-        public void exitSplitScreen(int exitTrigger) {
+        public void exitSplitScreen(int toTopTaskId, int exitTrigger) {
             throw new UnsupportedOperationException("exitSplitScreen not implemented by starter");
         }
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropOutlineDrawable.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropOutlineDrawable.java
index 64f7be5..73deea5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropOutlineDrawable.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropOutlineDrawable.java
@@ -86,7 +86,7 @@
     public DropOutlineDrawable(Context context) {
         super();
         // TODO(b/169894807): Use corner specific radii and maybe lower radius for non-edge corners
-        mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context.getResources());
+        mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context);
         mColor = context.getColor(R.color.drop_outline_background);
         mMaxAlpha = Color.alpha(mColor);
         // Initialize as hidden
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
index 6ec514b..3d3a630 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
@@ -22,7 +22,7 @@
 import android.os.UserHandle;
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationTarget;
-import android.window.IRemoteTransition;
+import android.window.RemoteTransition;
 
 import com.android.wm.shell.splitscreen.ISplitScreenListener;
 
@@ -52,9 +52,10 @@
     oneway void removeFromSideStage(int taskId) = 4;
 
     /**
-     * Removes the split-screen stages.
+     * Removes the split-screen stages and leaving indicated task to top. Passing INVALID_TASK_ID
+     * to indicate leaving no top task after leaving split-screen.
      */
-    oneway void exitSplitScreen() = 5;
+    oneway void exitSplitScreen(int toTopTaskId) = 5;
 
     /**
      * @param exitSplitScreenOnHide if to exit split-screen if both stages are not visible.
@@ -82,7 +83,7 @@
      * Starts tasks simultaneously in one transition.
      */
     oneway void startTasks(int mainTaskId, in Bundle mainOptions, int sideTaskId,
-            in Bundle sideOptions, int sidePosition, in IRemoteTransition remoteTransition) = 10;
+            in Bundle sideOptions, int sidePosition, in RemoteTransition remoteTransition) = 10;
 
     /**
      * Version of startTasks using legacy transition system.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 437b52a..6527cab 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -22,7 +22,6 @@
 import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
 import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
-import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN;
 
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
@@ -44,7 +43,7 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.WindowManager;
-import android.window.IRemoteTransition;
+import android.window.RemoteTransition;
 import android.window.WindowContainerTransaction;
 
 import androidx.annotation.BinderThread;
@@ -76,6 +75,7 @@
  * {@link SplitScreen}.
  * @see StageCoordinator
  */
+// TODO(b/198577848): Implement split screen flicker test to consolidate CUJ of split screen.
 public class SplitScreenController implements DragAndDropPolicy.Starter,
         RemoteCallable<SplitScreenController> {
     private static final String TAG = SplitScreenController.class.getSimpleName();
@@ -173,8 +173,8 @@
                 leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT);
     }
 
-    public void exitSplitScreen(int exitReason) {
-        mStageCoordinator.exitSplitScreen(exitReason);
+    public void exitSplitScreen(int toTopTaskId, int exitReason) {
+        mStageCoordinator.exitSplitScreen(toTopTaskId, exitReason);
     }
 
     public void onKeyguardOccludedChanged(boolean occluded) {
@@ -241,46 +241,34 @@
     private void startIntentLegacy(PendingIntent intent, Intent fillInIntent,
             @SplitScreen.StageType int stage, @SplitPosition int position,
             @Nullable Bundle options) {
-        final boolean wasInSplit = isSplitScreenVisible();
-
         LegacyTransitions.ILegacyTransition transition = new LegacyTransitions.ILegacyTransition() {
             @Override
             public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
                     RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
                     IRemoteAnimationFinishedCallback finishedCallback,
                     SurfaceControl.Transaction t) {
-                boolean cancelled = apps == null || apps.length == 0;
                 mStageCoordinator.updateSurfaceBounds(null /* layout */, t);
-                if (cancelled) {
-                    if (!wasInSplit) {
-                        final WindowContainerTransaction undoWct = new WindowContainerTransaction();
-                        mStageCoordinator.prepareExitSplitScreen(STAGE_TYPE_MAIN, undoWct);
-                        mSyncQueue.queue(undoWct);
-                        mSyncQueue.runInSync(undoT -> {
-                            // looks weird, but we want undoT to execute after t but still want the
-                            // rest of the syncQueue runnables to aggregate.
-                            t.merge(undoT);
-                            undoT.merge(t);
-                        });
-                        return;
-                    }
-                } else {
+
+                if (apps != null) {
                     for (int i = 0; i < apps.length; ++i) {
                         if (apps[i].mode == MODE_OPENING) {
                             t.show(apps[i].leash);
                         }
                     }
                 }
-                RemoteAnimationTarget divider = mStageCoordinator.getDividerBarLegacyTarget();
+
+                final RemoteAnimationTarget divider = mStageCoordinator.getDividerBarLegacyTarget();
                 if (divider.leash != null) {
                     t.show(divider.leash);
                 }
+
                 t.apply();
-                if (cancelled) return;
-                try {
-                    finishedCallback.onAnimationFinished();
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Error finishing legacy transition: ", e);
+                if (finishedCallback != null) {
+                    try {
+                        finishedCallback.onAnimationFinished();
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Error finishing legacy transition: ", e);
+                    }
                 }
             }
         };
@@ -511,11 +499,11 @@
         }
 
         @Override
-        public void exitSplitScreen() {
+        public void exitSplitScreen(int toTopTaskId) {
             executeRemoteCallWithTaskPermission(mController, "exitSplitScreen",
                     (controller) -> {
-                        controller.exitSplitScreen(
-                                FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
+                        controller.exitSplitScreen(toTopTaskId,
+                                FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__UNKNOWN_EXIT);
                     });
         }
 
@@ -565,7 +553,7 @@
         public void startTasks(int mainTaskId, @Nullable Bundle mainOptions,
                 int sideTaskId, @Nullable Bundle sideOptions,
                 @SplitPosition int sidePosition,
-                @Nullable IRemoteTransition remoteTransition) {
+                @Nullable RemoteTransition remoteTransition) {
             executeRemoteCallWithTaskPermission(mController, "startTasks",
                     (controller) -> controller.mStageCoordinator.startTasks(mainTaskId, mainOptions,
                             sideTaskId, sideOptions, sidePosition, remoteTransition));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
index 69d0be6..86e7b0e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
@@ -35,7 +35,7 @@
 import android.os.IBinder;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
-import android.window.IRemoteTransition;
+import android.window.RemoteTransition;
 import android.window.TransitionInfo;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
@@ -169,7 +169,7 @@
 
     /** Starts a transition to enter split with a remote transition animator. */
     IBinder startEnterTransition(@WindowManager.TransitionType int transitType,
-            @NonNull WindowContainerTransaction wct, @Nullable IRemoteTransition remoteTransition,
+            @NonNull WindowContainerTransaction wct, @Nullable RemoteTransition remoteTransition,
             @NonNull Transitions.TransitionHandler handler) {
         if (remoteTransition != null) {
             // Wrapping it for ease-of-use (OneShot handles all the binder linking/death stuff)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 9e6edd2..d9708f0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -72,7 +72,7 @@
 import android.view.SurfaceSession;
 import android.view.WindowManager;
 import android.window.DisplayAreaInfo;
-import android.window.IRemoteTransition;
+import android.window.RemoteTransition;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
 import android.window.WindowContainerToken;
@@ -263,7 +263,7 @@
     /** Starts 2 tasks in one transition. */
     void startTasks(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId,
             @Nullable Bundle sideOptions, @SplitPosition int sidePosition,
-            @Nullable IRemoteTransition remoteTransition) {
+            @Nullable RemoteTransition remoteTransition) {
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         mainOptions = mainOptions != null ? mainOptions : new Bundle();
         sideOptions = sideOptions != null ? sideOptions : new Bundle();
@@ -358,7 +358,7 @@
     public void startIntent(PendingIntent intent, Intent fillInIntent,
             @SplitScreen.StageType int stage, @SplitPosition int position,
             @androidx.annotation.Nullable Bundle options,
-            @Nullable IRemoteTransition remoteTransition) {
+            @Nullable RemoteTransition remoteTransition) {
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         options = resolveStartStage(stage, position, options, wct);
         wct.sendPendingIntent(intent, fillInIntent, options);
@@ -472,16 +472,32 @@
         }
     }
 
-    void exitSplitScreen(int exitReason) {
-        exitSplitScreen(null /* childrenToTop */, exitReason);
-    }
-
     void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) {
         mExitSplitScreenOnHide = exitSplitScreenOnHide;
     }
 
+    void exitSplitScreen(int toTopTaskId, int exitReason) {
+        StageTaskListener childrenToTop = null;
+        if (mMainStage.containsTask(toTopTaskId)) {
+            childrenToTop = mMainStage;
+        } else if (mSideStage.containsTask(toTopTaskId)) {
+            childrenToTop = mSideStage;
+        }
+
+        final WindowContainerTransaction wct = new WindowContainerTransaction();
+        if (childrenToTop != null) {
+            childrenToTop.reorderChild(toTopTaskId, true /* onTop */, wct);
+        }
+        applyExitSplitScreen(childrenToTop, wct, exitReason);
+    }
+
     private void exitSplitScreen(StageTaskListener childrenToTop, int exitReason) {
         final WindowContainerTransaction wct = new WindowContainerTransaction();
+        applyExitSplitScreen(childrenToTop, wct, exitReason);
+    }
+
+    private void applyExitSplitScreen(StageTaskListener childrenToTop,
+            WindowContainerTransaction wct, int exitReason) {
         mSideStage.removeAllTasks(wct, childrenToTop == mSideStage);
         mMainStage.deactivate(wct, childrenToTop == mMainStage);
         mTaskOrganizer.applyTransaction(wct);
@@ -627,7 +643,8 @@
             // Don't dismiss staged split when both stages are not visible due to sleeping display,
             // like the cases keyguard showing or screen off.
             || (!mMainStage.mRootTaskInfo.isSleeping && !mSideStage.mRootTaskInfo.isSleeping)) {
-                exitSplitScreen(SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
+                exitSplitScreen(null /* childrenToTop */,
+                        SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
             }
         } else if (mKeyguardOccluded) {
             // At least one of the stages is visible while keyguard occluded. Dismiss split because
@@ -1249,7 +1266,7 @@
         @Override
         public void onNoLongerSupportMultiWindow() {
             if (mMainStage.isActive()) {
-                StageCoordinator.this.exitSplitScreen(
+                StageCoordinator.this.exitSplitScreen(null /* childrenToTop */,
                         SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW);
             }
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 3512a0c..15b4ff9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -113,10 +113,20 @@
 
     /** @return {@code true} if this listener contains the currently focused task. */
     boolean isFocused() {
-        if (mRootTaskInfo.isFocused) return true;
-        for (int i = mChildrenTaskInfo.size() - 1; i >= 0; --i) {
-            if (mChildrenTaskInfo.valueAt(i).isFocused) return true;
+        if (mRootTaskInfo == null) {
+            return false;
         }
+
+        if (mRootTaskInfo.isFocused) {
+            return true;
+        }
+
+        for (int i = mChildrenTaskInfo.size() - 1; i >= 0; --i) {
+            if (mChildrenTaskInfo.valueAt(i).isFocused) {
+                return true;
+            }
+        }
+
         return false;
     }
 
@@ -214,6 +224,13 @@
         wct.setBounds(mRootTaskInfo.token, bounds);
     }
 
+    void reorderChild(int taskId, boolean onTop, WindowContainerTransaction wct) {
+        if (!containsTask(taskId)) {
+            return;
+        }
+        wct.reorder(mChildrenTaskInfo.get(taskId).token, onTop /* onTop */);
+    }
+
     void setVisibility(boolean visible, WindowContainerTransaction wct) {
         wct.reorder(mRootTaskInfo.token, visible /* onTop */);
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 2286598..8df7cbb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -50,6 +50,7 @@
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.Slog;
+import android.view.ContextThemeWrapper;
 import android.view.SurfaceControl;
 import android.view.View;
 import android.window.SplashScreenView;
@@ -137,12 +138,14 @@
      *                                 null if failed.
      */
     void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info,
-            int taskId, Consumer<SplashScreenView> splashScreenViewConsumer) {
+            int taskId, Consumer<SplashScreenView> splashScreenViewConsumer,
+            Consumer<Runnable> uiThreadInitConsumer) {
         mSplashscreenWorkerHandler.post(() -> {
             SplashScreenView contentView;
             try {
                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "makeSplashScreenContentView");
-                contentView = makeSplashScreenContentView(context, info, suggestType);
+                contentView = makeSplashScreenContentView(context, info, suggestType,
+                        uiThreadInitConsumer);
                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
             } catch (RuntimeException e) {
                 Slog.w(TAG, "failed creating starting window content at taskId: "
@@ -238,7 +241,7 @@
     }
 
     private SplashScreenView makeSplashScreenContentView(Context context, ActivityInfo ai,
-            @StartingWindowType int suggestType) {
+            @StartingWindowType int suggestType, Consumer<Runnable> uiThreadInitConsumer) {
         updateDensity();
 
         getWindowAttrs(context, mTmpAttrs);
@@ -253,6 +256,7 @@
                 .setWindowBGColor(themeBGColor)
                 .overlayDrawable(legacyDrawable)
                 .chooseStyle(suggestType)
+                .setUiThreadInitConsumer(uiThreadInitConsumer)
                 .build();
     }
 
@@ -299,6 +303,11 @@
         }
     }
 
+    /** Creates the wrapper with system theme to avoid unexpected styles from app. */
+    ContextThemeWrapper createViewContextWrapper(Context appContext) {
+        return new ContextThemeWrapper(appContext, mContext.getTheme());
+    }
+
     /** The configuration of the splash screen window. */
     public static class SplashScreenWindowAttrs {
         private int mWindowBgResId = 0;
@@ -318,6 +327,7 @@
         private int mThemeColor;
         private Drawable[] mFinalIconDrawables;
         private int mFinalIconSize = mIconSize;
+        private Consumer<Runnable> mUiThreadInitTask;
 
         StartingWindowViewBuilder(@NonNull Context context, @NonNull ActivityInfo aInfo) {
             mContext = context;
@@ -339,6 +349,11 @@
             return this;
         }
 
+        StartingWindowViewBuilder setUiThreadInitConsumer(Consumer<Runnable> uiThreadInitTask) {
+            mUiThreadInitTask = uiThreadInitTask;
+            return this;
+        }
+
         SplashScreenView build() {
             Drawable iconDrawable;
             final int animationDuration;
@@ -385,7 +400,8 @@
                 animationDuration = 0;
             }
 
-            return fillViewWithIcon(mFinalIconSize, mFinalIconDrawables, animationDuration);
+            return fillViewWithIcon(mFinalIconSize, mFinalIconDrawables, animationDuration,
+                    mUiThreadInitTask);
         }
 
         private class ShapeIconFactory extends BaseIconFactory {
@@ -463,7 +479,7 @@
         }
 
         private SplashScreenView fillViewWithIcon(int iconSize, @Nullable Drawable[] iconDrawable,
-                int animationDuration) {
+                int animationDuration, Consumer<Runnable> uiThreadInitTask) {
             Drawable foreground = null;
             Drawable background = null;
             if (iconDrawable != null) {
@@ -472,13 +488,15 @@
             }
 
             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "fillViewWithIcon");
-            final SplashScreenView.Builder builder = new SplashScreenView.Builder(mContext)
+            final ContextThemeWrapper wrapper = createViewContextWrapper(mContext);
+            final SplashScreenView.Builder builder = new SplashScreenView.Builder(wrapper)
                     .setBackgroundColor(mThemeColor)
                     .setOverlayDrawable(mOverlayDrawable)
                     .setIconSize(iconSize)
                     .setIconBackground(background)
                     .setCenterViewDrawable(foreground)
-                    .setAnimationDurationMillis(animationDuration);
+                    .setAnimationDurationMillis(animationDuration)
+                    .setUiThreadInitConsumer(uiThreadInitTask);
 
             if (mSuggestType == STARTING_WINDOW_TYPE_SPLASH_SCREEN
                     && mTmpAttrs.mBrandingImage != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
index 951b97e..f0685a8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
@@ -304,6 +304,13 @@
             return true;
         }
 
+        @Override
+        public void stopAnimation() {
+            if (mIconAnimator != null) {
+                mIconAnimator.end();
+            }
+        }
+
         private final Callback mCallback = new Callback() {
             @Override
             public void invalidateDrawable(@NonNull Drawable who) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index 6c60bad..debe6d5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -146,7 +146,7 @@
         return mDisplayManager.getDisplay(displayId);
     }
 
-    private int getSplashScreenTheme(int splashScreenThemeResId, ActivityInfo activityInfo) {
+    int getSplashScreenTheme(int splashScreenThemeResId, ActivityInfo activityInfo) {
         return splashScreenThemeResId != 0
                 ? splashScreenThemeResId
                 : activityInfo.getThemeResource() != 0 ? activityInfo.getThemeResource()
@@ -174,7 +174,7 @@
 
         final int displayId = taskInfo.displayId;
         final int taskId = taskInfo.taskId;
-        Context context = mContext;
+
         // replace with the default theme if the application didn't set
         final int theme = getSplashScreenTheme(windowInfo.splashScreenThemeResId, activityInfo);
         if (DEBUG_SPLASH_SCREEN) {
@@ -182,12 +182,16 @@
                     + " theme=" + Integer.toHexString(theme) + " task=" + taskInfo.taskId
                     + " suggestType=" + suggestType);
         }
-
         final Display display = getDisplay(displayId);
         if (display == null) {
             // Can't show splash screen on requested display, so skip showing at all.
             return;
         }
+        Context context = displayId == DEFAULT_DISPLAY
+                ? mContext : mContext.createDisplayContext(display);
+        if (context == null) {
+            return;
+        }
         if (theme != context.getThemeResId()) {
             try {
                 context = context.createPackageContextAsUser(activityInfo.packageName,
@@ -298,7 +302,8 @@
         // Record whether create splash screen view success, notify to current thread after
         // create splash screen view finished.
         final SplashScreenViewSupplier viewSupplier = new SplashScreenViewSupplier();
-        final FrameLayout rootLayout = new FrameLayout(context);
+        final FrameLayout rootLayout = new FrameLayout(
+                mSplashscreenContentDrawer.createViewContextWrapper(context));
         rootLayout.setPadding(0, 0, 0, 0);
         rootLayout.setFitsSystemWindows(false);
         final Runnable setViewSynchronized = () -> {
@@ -327,7 +332,7 @@
             mSysuiProxy.requestTopUi(true, TAG);
         }
         mSplashscreenContentDrawer.createContentView(context, suggestType, activityInfo, taskId,
-                viewSupplier::setView);
+                viewSupplier::setView, viewSupplier::setUiThreadInitTask);
         try {
             if (addWindow(taskId, appToken, rootLayout, display, params, suggestType)) {
                 // We use the splash screen worker thread to create SplashScreenView while adding
@@ -362,6 +367,7 @@
     private static class SplashScreenViewSupplier implements Supplier<SplashScreenView> {
         private SplashScreenView mView;
         private boolean mIsViewSet;
+        private Runnable mUiThreadInitTask;
         void setView(SplashScreenView view) {
             synchronized (this) {
                 mView = view;
@@ -370,6 +376,12 @@
             }
         }
 
+        void setUiThreadInitTask(Runnable initTask) {
+            synchronized (this) {
+                mUiThreadInitTask = initTask;
+            }
+        }
+
         @Override
         public @Nullable SplashScreenView get() {
             synchronized (this) {
@@ -379,6 +391,10 @@
                     } catch (InterruptedException ignored) {
                     }
                 }
+                if (mUiThreadInitTask != null) {
+                    mUiThreadInitTask.run();
+                    mUiThreadInitTask = null;
+                }
                 return mView;
             }
         }
@@ -501,7 +517,7 @@
             Slog.v(TAG, reason + "the splash screen. Releasing SurfaceControlViewHost for task:"
                     + taskId);
         }
-        viewHost.getView().post(viewHost::release);
+        SplashScreenView.releaseIconHost(viewHost);
     }
 
     protected boolean addWindow(int taskId, IBinder appToken, View view, Display display,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index 16fddb0..cdc0795 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -364,6 +364,7 @@
 
         // In case window manager leaks us, make sure we don't retain the snapshot.
         mSnapshot = null;
+        mSurfaceControl.release();
     }
 
     private void drawSizeMatchSnapshot() {
@@ -431,6 +432,7 @@
             mTransaction.setBuffer(mSurfaceControl, background);
         }
         mTransaction.apply();
+        childSurfaceControl.release();
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl
index dffc700..bdcdb63 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl
@@ -16,7 +16,7 @@
 
 package com.android.wm.shell.transition;
 
-import android.window.IRemoteTransition;
+import android.window.RemoteTransition;
 import android.window.TransitionFilter;
 
 /**
@@ -28,10 +28,10 @@
      * Registers a remote transition handler.
      */
     oneway void registerRemote(in TransitionFilter filter,
-            in IRemoteTransition remoteTransition) = 1;
+            in RemoteTransition remoteTransition) = 1;
 
     /**
      * Unregisters a remote transition handler.
      */
-    oneway void unregisterRemote(in IRemoteTransition remoteTransition) = 2;
+    oneway void unregisterRemote(in RemoteTransition remoteTransition) = 2;
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
index 6bd8053..3be896e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
@@ -24,6 +24,7 @@
 import android.view.SurfaceControl;
 import android.window.IRemoteTransition;
 import android.window.IRemoteTransitionFinishedCallback;
+import android.window.RemoteTransition;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
 import android.window.WindowContainerTransaction;
@@ -43,10 +44,10 @@
     private IBinder mTransition = null;
 
     /** The remote to delegate animation to */
-    private final IRemoteTransition mRemote;
+    private final RemoteTransition mRemote;
 
     public OneShotRemoteHandler(@NonNull ShellExecutor mainExecutor,
-            @NonNull IRemoteTransition remote) {
+            @NonNull RemoteTransition remote) {
         mMainExecutor = mainExecutor;
         mRemote = remote;
     }
@@ -88,7 +89,7 @@
             if (mRemote.asBinder() != null) {
                 mRemote.asBinder().linkToDeath(remoteDied, 0 /* flags */);
             }
-            mRemote.startAnimation(transition, info, startTransaction, cb);
+            mRemote.getRemoteTransition().startAnimation(transition, info, startTransaction, cb);
         } catch (RemoteException e) {
             Log.e(Transitions.TAG, "Error running remote transition.", e);
             if (mRemote.asBinder() != null) {
@@ -115,7 +116,7 @@
             }
         };
         try {
-            mRemote.mergeAnimation(transition, info, t, mergeTarget, cb);
+            mRemote.getRemoteTransition().mergeAnimation(transition, info, t, mergeTarget, cb);
         } catch (RemoteException e) {
             Log.e(Transitions.TAG, "Error merging remote transition.", e);
         }
@@ -125,8 +126,9 @@
     @Nullable
     public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
             @Nullable TransitionRequestInfo request) {
-        IRemoteTransition remote = request.getRemoteTransition();
-        if (remote != mRemote) return null;
+        RemoteTransition remote = request.getRemoteTransition();
+        IRemoteTransition iRemote = remote != null ? remote.getRemoteTransition() : null;
+        if (iRemote != mRemote.getRemoteTransition()) return null;
         mTransition = transition;
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "RemoteTransition directly requested"
                 + " for %s: %s", transition, remote);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
index bda884c..ac612a7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
@@ -27,6 +27,7 @@
 import android.view.SurfaceControl;
 import android.window.IRemoteTransition;
 import android.window.IRemoteTransitionFinishedCallback;
+import android.window.RemoteTransition;
 import android.window.TransitionFilter;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
@@ -50,10 +51,10 @@
     private final ShellExecutor mMainExecutor;
 
     /** Includes remotes explicitly requested by, eg, ActivityOptions */
-    private final ArrayMap<IBinder, IRemoteTransition> mRequestedRemotes = new ArrayMap<>();
+    private final ArrayMap<IBinder, RemoteTransition> mRequestedRemotes = new ArrayMap<>();
 
     /** Ordered by specificity. Last filters will be checked first */
-    private final ArrayList<Pair<TransitionFilter, IRemoteTransition>> mFilters =
+    private final ArrayList<Pair<TransitionFilter, RemoteTransition>> mFilters =
             new ArrayList<>();
 
     private final ArrayMap<IBinder, RemoteDeathHandler> mDeathHandlers = new ArrayMap<>();
@@ -62,19 +63,12 @@
         mMainExecutor = mainExecutor;
     }
 
-    void addFiltered(TransitionFilter filter, IRemoteTransition remote) {
-        try {
-            RemoteDeathHandler handler = new RemoteDeathHandler(remote.asBinder());
-            remote.asBinder().linkToDeath(handler, 0 /* flags */);
-            mDeathHandlers.put(remote.asBinder(), handler);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Failed to link to death");
-            return;
-        }
+    void addFiltered(TransitionFilter filter, RemoteTransition remote) {
+        handleDeath(remote.asBinder(), null /* finishCallback */);
         mFilters.add(new Pair<>(filter, remote));
     }
 
-    void removeFiltered(IRemoteTransition remote) {
+    void removeFiltered(RemoteTransition remote) {
         boolean removed = false;
         for (int i = mFilters.size() - 1; i >= 0; --i) {
             if (mFilters.get(i).second == remote) {
@@ -83,8 +77,7 @@
             }
         }
         if (removed) {
-            RemoteDeathHandler handler = mDeathHandlers.remove(remote.asBinder());
-            remote.asBinder().unlinkToDeath(handler, 0 /* flags */);
+            unhandleDeath(remote.asBinder(), null /* finishCallback */);
         }
     }
 
@@ -98,7 +91,7 @@
             @NonNull SurfaceControl.Transaction startTransaction,
             @NonNull SurfaceControl.Transaction finishTransaction,
             @NonNull Transitions.TransitionFinishCallback finishCallback) {
-        IRemoteTransition pendingRemote = mRequestedRemotes.get(transition);
+        RemoteTransition pendingRemote = mRequestedRemotes.get(transition);
         if (pendingRemote == null) {
             ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition %s doesn't have "
                     + "explicit remote, search filters for match for %s", transition, info);
@@ -120,21 +113,12 @@
 
         if (pendingRemote == null) return false;
 
-        final IRemoteTransition remote = pendingRemote;
-        final IBinder.DeathRecipient remoteDied = () -> {
-            Log.e(Transitions.TAG, "Remote transition died, finishing");
-            mMainExecutor.execute(() -> {
-                mRequestedRemotes.remove(transition);
-                finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */);
-            });
-        };
+        final RemoteTransition remote = pendingRemote;
         IRemoteTransitionFinishedCallback cb = new IRemoteTransitionFinishedCallback.Stub() {
             @Override
             public void onTransitionFinished(WindowContainerTransaction wct,
                     SurfaceControl.Transaction sct) {
-                if (remote.asBinder() != null) {
-                    remote.asBinder().unlinkToDeath(remoteDied, 0 /* flags */);
-                }
+                unhandleDeath(remote.asBinder(), finishCallback);
                 mMainExecutor.execute(() -> {
                     if (sct != null) {
                         finishTransaction.merge(sct);
@@ -145,15 +129,11 @@
             }
         };
         try {
-            if (remote.asBinder() != null) {
-                remote.asBinder().linkToDeath(remoteDied, 0 /* flags */);
-            }
-            remote.startAnimation(transition, info, startTransaction, cb);
+            handleDeath(remote.asBinder(), finishCallback);
+            remote.getRemoteTransition().startAnimation(transition, info, startTransaction, cb);
         } catch (RemoteException e) {
             Log.e(Transitions.TAG, "Error running remote transition.", e);
-            if (remote.asBinder() != null) {
-                remote.asBinder().unlinkToDeath(remoteDied, 0 /* flags */);
-            }
+            unhandleDeath(remote.asBinder(), finishCallback);
             mRequestedRemotes.remove(transition);
             mMainExecutor.execute(
                     () -> finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */));
@@ -165,7 +145,7 @@
     public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
             @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
             @NonNull Transitions.TransitionFinishCallback finishCallback) {
-        final IRemoteTransition remote = mRequestedRemotes.get(mergeTarget);
+        final IRemoteTransition remote = mRequestedRemotes.get(mergeTarget).getRemoteTransition();
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Attempt merge %s into %s",
                 transition, remote);
         if (remote == null) return;
@@ -196,7 +176,7 @@
     @Nullable
     public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
             @Nullable TransitionRequestInfo request) {
-        IRemoteTransition remote = request.getRemoteTransition();
+        RemoteTransition remote = request.getRemoteTransition();
         if (remote == null) return null;
         mRequestedRemotes.put(transition, remote);
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "RemoteTransition directly requested"
@@ -204,14 +184,70 @@
         return new WindowContainerTransaction();
     }
 
+    private void handleDeath(@NonNull IBinder remote,
+            @Nullable Transitions.TransitionFinishCallback finishCallback) {
+        synchronized (mDeathHandlers) {
+            RemoteDeathHandler deathHandler = mDeathHandlers.get(remote);
+            if (deathHandler == null) {
+                deathHandler = new RemoteDeathHandler(remote);
+                try {
+                    remote.linkToDeath(deathHandler, 0 /* flags */);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to link to death");
+                    return;
+                }
+                mDeathHandlers.put(remote, deathHandler);
+            }
+            deathHandler.addUser(finishCallback);
+        }
+    }
+
+    private void unhandleDeath(@NonNull IBinder remote,
+            @Nullable Transitions.TransitionFinishCallback finishCallback) {
+        synchronized (mDeathHandlers) {
+            RemoteDeathHandler deathHandler = mDeathHandlers.get(remote);
+            if (deathHandler == null) return;
+            deathHandler.removeUser(finishCallback);
+            if (deathHandler.getUserCount() == 0) {
+                if (!deathHandler.mPendingFinishCallbacks.isEmpty()) {
+                    throw new IllegalStateException("Unhandling death for binder that still has"
+                            + " pending finishCallback(s).");
+                }
+                remote.unlinkToDeath(deathHandler, 0 /* flags */);
+                mDeathHandlers.remove(remote);
+            }
+        }
+    }
+
     /** NOTE: binder deaths can alter the filter order */
     private class RemoteDeathHandler implements IBinder.DeathRecipient {
         private final IBinder mRemote;
+        private final ArrayList<Transitions.TransitionFinishCallback> mPendingFinishCallbacks =
+                new ArrayList<>();
+        private int mUsers = 0;
 
         RemoteDeathHandler(IBinder remote) {
             mRemote = remote;
         }
 
+        void addUser(@Nullable Transitions.TransitionFinishCallback finishCallback) {
+            if (finishCallback != null) {
+                mPendingFinishCallbacks.add(finishCallback);
+            }
+            ++mUsers;
+        }
+
+        void removeUser(@Nullable Transitions.TransitionFinishCallback finishCallback) {
+            if (finishCallback != null) {
+                mPendingFinishCallbacks.remove(finishCallback);
+            }
+            --mUsers;
+        }
+
+        int getUserCount() {
+            return mUsers;
+        }
+
         @Override
         @BinderThread
         public void binderDied() {
@@ -221,6 +257,16 @@
                         mFilters.remove(i);
                     }
                 }
+                for (int i = mRequestedRemotes.size() - 1; i >= 0; --i) {
+                    if (mRemote.equals(mRequestedRemotes.valueAt(i).asBinder())) {
+                        mRequestedRemotes.removeAt(i);
+                    }
+                }
+                for (int i = mPendingFinishCallbacks.size() - 1; i >= 0; --i) {
+                    mPendingFinishCallbacks.get(i).onTransitionFinished(
+                            null /* wct */, null /* wctCB */);
+                }
+                mPendingFinishCallbacks.clear();
             });
         }
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java
index bc42c6e..802d25f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java
@@ -17,7 +17,7 @@
 package com.android.wm.shell.transition;
 
 import android.annotation.NonNull;
-import android.window.IRemoteTransition;
+import android.window.RemoteTransition;
 import android.window.TransitionFilter;
 
 import com.android.wm.shell.common.annotations.ExternalThread;
@@ -39,10 +39,10 @@
      * Registers a remote transition.
      */
     void registerRemote(@NonNull TransitionFilter filter,
-            @NonNull IRemoteTransition remoteTransition);
+            @NonNull RemoteTransition remoteTransition);
 
     /**
      * Unregisters a remote transition.
      */
-    void unregisterRemote(@NonNull IRemoteTransition remoteTransition);
+    void unregisterRemote(@NonNull RemoteTransition remoteTransition);
 }
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 8d21ce2..2720157 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
@@ -40,8 +40,8 @@
 import android.util.Log;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
-import android.window.IRemoteTransition;
 import android.window.ITransitionPlayer;
+import android.window.RemoteTransition;
 import android.window.TransitionFilter;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
@@ -176,13 +176,13 @@
         return new ShellTransitions() {
             @Override
             public void registerRemote(@androidx.annotation.NonNull TransitionFilter filter,
-                    @androidx.annotation.NonNull IRemoteTransition remoteTransition) {
+                    @androidx.annotation.NonNull RemoteTransition remoteTransition) {
                 // Do nothing
             }
 
             @Override
             public void unregisterRemote(
-                    @androidx.annotation.NonNull IRemoteTransition remoteTransition) {
+                    @androidx.annotation.NonNull RemoteTransition remoteTransition) {
                 // Do nothing
             }
         };
@@ -218,12 +218,12 @@
 
     /** Register a remote transition to be used when `filter` matches an incoming transition */
     public void registerRemote(@NonNull TransitionFilter filter,
-            @NonNull IRemoteTransition remoteTransition) {
+            @NonNull RemoteTransition remoteTransition) {
         mRemoteTransitionHandler.addFiltered(filter, remoteTransition);
     }
 
     /** Unregisters a remote transition and all associated filters */
-    public void unregisterRemote(@NonNull IRemoteTransition remoteTransition) {
+    public void unregisterRemote(@NonNull RemoteTransition remoteTransition) {
         mRemoteTransitionHandler.removeFiltered(remoteTransition);
     }
 
@@ -704,14 +704,14 @@
 
         @Override
         public void registerRemote(@NonNull TransitionFilter filter,
-                @NonNull IRemoteTransition remoteTransition) {
+                @NonNull RemoteTransition remoteTransition) {
             mMainExecutor.execute(() -> {
                 mRemoteTransitionHandler.addFiltered(filter, remoteTransition);
             });
         }
 
         @Override
-        public void unregisterRemote(@NonNull IRemoteTransition remoteTransition) {
+        public void unregisterRemote(@NonNull RemoteTransition remoteTransition) {
             mMainExecutor.execute(() -> {
                 mRemoteTransitionHandler.removeFiltered(remoteTransition);
             });
@@ -738,7 +738,7 @@
 
         @Override
         public void registerRemote(@NonNull TransitionFilter filter,
-                @NonNull IRemoteTransition remoteTransition) {
+                @NonNull RemoteTransition remoteTransition) {
             executeRemoteCallWithTaskPermission(mTransitions, "registerRemote",
                     (transitions) -> {
                         transitions.mRemoteTransitionHandler.addFiltered(filter, remoteTransition);
@@ -746,7 +746,7 @@
         }
 
         @Override
-        public void unregisterRemote(@NonNull IRemoteTransition remoteTransition) {
+        public void unregisterRemote(@NonNull RemoteTransition remoteTransition) {
             executeRemoteCallWithTaskPermission(mTransitions, "unregisterRemote",
                     (transitions) -> {
                         transitions.mRemoteTransitionHandler.removeFiltered(remoteTransition);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index a53d2e8..d357e77 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -46,6 +46,7 @@
 import android.view.SurfaceSession;
 import android.window.IRemoteTransition;
 import android.window.IRemoteTransitionFinishedCallback;
+import android.window.RemoteTransition;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
 import android.window.WindowContainerTransaction;
@@ -130,8 +131,8 @@
         TestRemoteTransition testRemote = new TestRemoteTransition();
 
         IBinder transition = mSplitScreenTransitions.startEnterTransition(
-                TRANSIT_SPLIT_SCREEN_PAIR_OPEN, new WindowContainerTransaction(), testRemote,
-                mStageCoordinator);
+                TRANSIT_SPLIT_SCREEN_PAIR_OPEN, new WindowContainerTransaction(),
+                new RemoteTransition(testRemote), mStageCoordinator);
         mMainStage.onTaskAppeared(mMainChild, createMockSurface());
         mSideStage.onTaskAppeared(mSideChild, createMockSurface());
         boolean accepted = mStageCoordinator.startAnimation(transition, info,
@@ -304,7 +305,7 @@
         TransitionInfo enterInfo = createEnterPairInfo();
         IBinder enterTransit = mSplitScreenTransitions.startEnterTransition(
                 TRANSIT_SPLIT_SCREEN_PAIR_OPEN, new WindowContainerTransaction(),
-                new TestRemoteTransition(), mStageCoordinator);
+                new RemoteTransition(new TestRemoteTransition()), mStageCoordinator);
         mMainStage.onTaskAppeared(mMainChild, createMockSurface());
         mSideStage.onTaskAppeared(mSideChild, createMockSurface());
         mStageCoordinator.startAnimation(enterTransit, enterInfo,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index 6cce0ab..d930d4ca 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -16,14 +16,17 @@
 
 package com.android.wm.shell.splitscreen;
 
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME;
 import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
 import android.graphics.Rect;
@@ -94,4 +97,38 @@
         verify(mSideStage).removeTask(
                 eq(task.taskId), any(), any(WindowContainerTransaction.class));
     }
+
+    @Test
+    public void testExitSplitScreen() {
+        mStageCoordinator.exitSplitScreen(INVALID_TASK_ID,
+                SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
+        verify(mSideStage).removeAllTasks(any(WindowContainerTransaction.class), eq(false));
+        verify(mMainStage).deactivate(any(WindowContainerTransaction.class), eq(false));
+    }
+
+    @Test
+    public void testExitSplitScreenToMainStage() {
+        final int testTaskId = 12345;
+        when(mMainStage.containsTask(eq(testTaskId))).thenReturn(true);
+        when(mSideStage.containsTask(eq(testTaskId))).thenReturn(false);
+        mStageCoordinator.exitSplitScreen(testTaskId,
+                SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
+        verify(mMainStage).reorderChild(eq(testTaskId), eq(true),
+                any(WindowContainerTransaction.class));
+        verify(mSideStage).removeAllTasks(any(WindowContainerTransaction.class), eq(false));
+        verify(mMainStage).deactivate(any(WindowContainerTransaction.class), eq(true));
+    }
+
+    @Test
+    public void testExitSplitScreenToSideStage() {
+        final int testTaskId = 12345;
+        when(mMainStage.containsTask(eq(testTaskId))).thenReturn(false);
+        when(mSideStage.containsTask(eq(testTaskId))).thenReturn(true);
+        mStageCoordinator.exitSplitScreen(testTaskId,
+                SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
+        verify(mSideStage).reorderChild(eq(testTaskId), eq(true),
+                any(WindowContainerTransaction.class));
+        verify(mSideStage).removeAllTasks(any(WindowContainerTransaction.class), eq(true));
+        verify(mMainStage).deactivate(any(WindowContainerTransaction.class), eq(false));
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index 160b367..2994e71 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -25,6 +25,7 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.verify;
 
 import android.app.ActivityManager;
@@ -85,7 +86,6 @@
 
     static final class TestStartingSurfaceDrawer extends StartingSurfaceDrawer{
         int mAddWindowForTask = 0;
-        int mViewThemeResId;
 
         TestStartingSurfaceDrawer(Context context, ShellExecutor splashScreenExecutor,
                 TransactionPool pool) {
@@ -97,7 +97,6 @@
                 WindowManager.LayoutParams params, int suggestType) {
             // listen for addView
             mAddWindowForTask = taskId;
-            mViewThemeResId = view.getContext().getThemeResId();
             // Do not wait for background color
             return false;
         }
@@ -167,12 +166,15 @@
         final int taskId = 1;
         final StartingWindowInfo windowInfo =
                 createWindowInfo(taskId, 0);
+        final int[] theme = new int[1];
+        doAnswer(invocation -> theme[0] = (Integer) invocation.callRealMethod())
+                .when(mStartingSurfaceDrawer).getSplashScreenTheme(eq(0), any());
+
         mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
                 STARTING_WINDOW_TYPE_SPLASH_SCREEN);
         waitHandlerIdle(mTestHandler);
-        verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any(),
-                eq(STARTING_WINDOW_TYPE_SPLASH_SCREEN));
-        assertNotEquals(mStartingSurfaceDrawer.mViewThemeResId, 0);
+        verify(mStartingSurfaceDrawer).getSplashScreenTheme(eq(0), any());
+        assertNotEquals(theme[0], 0);
     }
 
     @Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
index b4ef5bf..b0f0d71 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -63,6 +63,7 @@
 import android.view.WindowManager;
 import android.window.IRemoteTransition;
 import android.window.IRemoteTransitionFinishedCallback;
+import android.window.RemoteTransition;
 import android.window.TransitionFilter;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
@@ -238,7 +239,8 @@
         };
         IBinder transitToken = new Binder();
         transitions.requestStartTransition(transitToken,
-                new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, testRemote));
+                new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */,
+                        new RemoteTransition(testRemote)));
         verify(mOrganizer, times(1)).startTransition(eq(TRANSIT_OPEN), eq(transitToken), any());
         TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN)
                 .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
@@ -383,7 +385,7 @@
                 new TransitionFilter.Requirement[]{new TransitionFilter.Requirement()};
         filter.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
 
-        transitions.registerRemote(filter, testRemote);
+        transitions.registerRemote(filter, new RemoteTransition(testRemote));
         mMainExecutor.flushAll();
 
         IBinder transitToken = new Binder();
@@ -426,11 +428,12 @@
 
         final int transitType = TRANSIT_FIRST_CUSTOM + 1;
 
-        OneShotRemoteHandler oneShot = new OneShotRemoteHandler(mMainExecutor, testRemote);
+        OneShotRemoteHandler oneShot = new OneShotRemoteHandler(mMainExecutor,
+                new RemoteTransition(testRemote));
         // Verify that it responds to the remote but not other things.
         IBinder transitToken = new Binder();
         assertNotNull(oneShot.handleRequest(transitToken,
-                new TransitionRequestInfo(transitType, null, testRemote)));
+                new TransitionRequestInfo(transitType, null, new RemoteTransition(testRemote))));
         assertNull(oneShot.handleRequest(transitToken,
                 new TransitionRequestInfo(transitType, null, null)));
 
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 2c299fa..b931d03 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -587,6 +587,7 @@
                 "HardwareBitmapUploader.cpp",
                 "HWUIProperties.sysprop",
                 "JankTracker.cpp",
+                "FrameMetricsReporter.cpp",
                 "Layer.cpp",
                 "LayerUpdateQueue.cpp",
                 "ProfileData.cpp",
@@ -691,6 +692,7 @@
         "tests/unit/FatVectorTests.cpp",
         "tests/unit/GraphicsStatsServiceTests.cpp",
         "tests/unit/JankTrackerTests.cpp",
+        "tests/unit/FrameMetricsReporterTests.cpp",
         "tests/unit/LayerUpdateQueueTests.cpp",
         "tests/unit/LinearAllocatorTests.cpp",
         "tests/unit/MatrixTests.cpp",
diff --git a/libs/hwui/FrameMetricsObserver.h b/libs/hwui/FrameMetricsObserver.h
index ef1f5aa..498ec57 100644
--- a/libs/hwui/FrameMetricsObserver.h
+++ b/libs/hwui/FrameMetricsObserver.h
@@ -26,6 +26,13 @@
     virtual void notify(const int64_t* buffer) = 0;
     bool waitForPresentTime() const { return mWaitForPresentTime; };
 
+    void reportMetricsFrom(uint64_t frameNumber, int32_t surfaceControlId) {
+        mAttachedFrameNumber = frameNumber;
+        mSurfaceControlId = surfaceControlId;
+    };
+    uint64_t attachedFrameNumber() const { return mAttachedFrameNumber; };
+    int32_t attachedSurfaceControlId() const { return mSurfaceControlId; };
+
     /**
      * Create a new metrics observer. An observer that watches present time gets notified at a
      * different time than the observer that doesn't.
@@ -42,6 +49,22 @@
 
 private:
     const bool mWaitForPresentTime;
+
+    // The id of the surface control (mSurfaceControlGenerationId in CanvasContext)
+    // for which the mAttachedFrameNumber applies to. We rely on this value being
+    // an increasing counter. We will report metrics:
+    // - for all frames if the frame comes from a surface with a surfaceControlId
+    //   that is strictly greater than mSurfaceControlId.
+    // - for all frames with a frame number greater than or equal to mAttachedFrameNumber
+    //   if the frame comes from a surface with a surfaceControlId that is equal to the
+    //   mSurfaceControlId.
+    // We will never report metrics if the frame comes from a surface with a surfaceControlId
+    // that is strictly smaller than mSurfaceControlId.
+    int32_t mSurfaceControlId;
+
+    // The frame number the metrics observer was attached on. Metrics will be sent from this frame
+    // number (inclusive) onwards in the case that the surface id is equal to mSurfaceControlId.
+    uint64_t mAttachedFrameNumber;
 };
 
 }  // namespace uirenderer
diff --git a/libs/hwui/FrameMetricsReporter.cpp b/libs/hwui/FrameMetricsReporter.cpp
new file mode 100644
index 0000000..ee32ea1
--- /dev/null
+++ b/libs/hwui/FrameMetricsReporter.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FrameMetricsReporter.h"
+
+namespace android {
+namespace uirenderer {
+
+void FrameMetricsReporter::reportFrameMetrics(const int64_t* stats, bool hasPresentTime,
+                                              uint64_t frameNumber, int32_t surfaceControlId) {
+    FatVector<sp<FrameMetricsObserver>, 10> copy;
+    {
+        std::lock_guard lock(mObserversLock);
+        copy.reserve(mObservers.size());
+        for (size_t i = 0; i < mObservers.size(); i++) {
+            auto observer = mObservers[i];
+
+            if (CC_UNLIKELY(surfaceControlId < observer->attachedSurfaceControlId())) {
+                // Don't notify if the metrics are from a frame that was run on an old
+                // surface (one from before the observer was attached).
+                ALOGV("skipped reporting metrics from old surface %d", surfaceControlId);
+                continue;
+            } else if (CC_UNLIKELY(surfaceControlId == observer->attachedSurfaceControlId() &&
+                                   frameNumber < observer->attachedFrameNumber())) {
+                // Don't notify if the metrics are from a frame that was queued by the
+                // BufferQueueProducer on the render thread before the observer was attached.
+                ALOGV("skipped reporting metrics from old frame %ld", (long)frameNumber);
+                continue;
+            }
+
+            const bool wantsPresentTime = observer->waitForPresentTime();
+            if (hasPresentTime == wantsPresentTime) {
+                copy.push_back(observer);
+            }
+        }
+    }
+    for (size_t i = 0; i < copy.size(); i++) {
+        copy[i]->notify(stats);
+    }
+}
+
+}  // namespace uirenderer
+}  // namespace android
diff --git a/libs/hwui/FrameMetricsReporter.h b/libs/hwui/FrameMetricsReporter.h
index 0ac025f..7e51df7c 100644
--- a/libs/hwui/FrameMetricsReporter.h
+++ b/libs/hwui/FrameMetricsReporter.h
@@ -63,23 +63,14 @@
      * If an observer does not want present time, only notify when 'hasPresentTime' is false.
      * Never notify both types of observers from the same callback, because the callback with
      * 'hasPresentTime' is sent at a different time than the one without.
+     *
+     * The 'frameNumber' and 'surfaceControlId' associated to the frame whose's stats are being
+     * reported are used to determine whether or not the stats should be reported. We won't report
+     * stats of frames that are from "old" surfaces (i.e. with surfaceControlIds older than the one
+     * the observer was attached on) nor those that are from "old" frame numbers.
      */
-    void reportFrameMetrics(const int64_t* stats, bool hasPresentTime) {
-        FatVector<sp<FrameMetricsObserver>, 10> copy;
-        {
-            std::lock_guard lock(mObserversLock);
-            copy.reserve(mObservers.size());
-            for (size_t i = 0; i < mObservers.size(); i++) {
-                const bool wantsPresentTime = mObservers[i]->waitForPresentTime();
-                if (hasPresentTime == wantsPresentTime) {
-                    copy.push_back(mObservers[i]);
-                }
-            }
-        }
-        for (size_t i = 0; i < copy.size(); i++) {
-            copy[i]->notify(stats);
-        }
-    }
+    void reportFrameMetrics(const int64_t* stats, bool hasPresentTime, uint64_t frameNumber,
+                            int32_t surfaceControlId);
 
 private:
     FatVector<sp<FrameMetricsObserver>, 10> mObservers GUARDED_BY(mObserversLock);
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index 34e5577..3e5cbb5 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -164,7 +164,8 @@
             - lastFrameOffset + mFrameIntervalLegacy;
 }
 
-void JankTracker::finishFrame(FrameInfo& frame, std::unique_ptr<FrameMetricsReporter>& reporter) {
+void JankTracker::finishFrame(FrameInfo& frame, std::unique_ptr<FrameMetricsReporter>& reporter,
+                              int64_t frameNumber, int32_t surfaceControlId) {
     std::lock_guard lock(mDataMutex);
 
     calculateLegacyJank(frame);
@@ -253,7 +254,8 @@
     }
 
     if (CC_UNLIKELY(reporter.get() != nullptr)) {
-        reporter->reportFrameMetrics(frame.data(), false /* hasPresentTime */);
+        reporter->reportFrameMetrics(frame.data(), false /* hasPresentTime */, frameNumber,
+                                     surfaceControlId);
     }
 }
 
diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h
index bdb784d..bcd031e 100644
--- a/libs/hwui/JankTracker.h
+++ b/libs/hwui/JankTracker.h
@@ -57,7 +57,8 @@
     }
 
     FrameInfo* startFrame() { return &mFrames.next(); }
-    void finishFrame(FrameInfo& frame, std::unique_ptr<FrameMetricsReporter>& reporter);
+    void finishFrame(FrameInfo& frame, std::unique_ptr<FrameMetricsReporter>& reporter,
+                     int64_t frameNumber, int32_t surfaceId);
 
     // Calculates the 'legacy' jank information, i.e. with outdated refresh rate information and
     // without GPU completion or deadlined information.
diff --git a/libs/hwui/effects/StretchEffect.cpp b/libs/hwui/effects/StretchEffect.cpp
index 17cd3ce..8cb4515 100644
--- a/libs/hwui/effects/StretchEffect.cpp
+++ b/libs/hwui/effects/StretchEffect.cpp
@@ -181,7 +181,7 @@
         );
         coord.x = outU;
         coord.y = outV;
-        return sample(uContentTexture, coord);
+        return uContentTexture.eval(coord);
     })");
 
 static const float ZERO = 0.f;
diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp
index 9018443..1b38920 100644
--- a/libs/hwui/jni/Shader.cpp
+++ b/libs/hwui/jni/Shader.cpp
@@ -295,7 +295,7 @@
     SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
 
     SkRuntimeShaderBuilder::BuilderChild child = builder->child(name.c_str());
-    if (child.fIndex == -1) {
+    if (child.fChild == nullptr) {
         ThrowIAEFmt(env, "unable to find shader named %s", name.c_str());
         return;
     }
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 1ca4ce9..e536950 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -73,6 +73,10 @@
 } gFrameDrawingCallback;
 
 struct {
+    jmethodID onFrameCommit;
+} gFrameCommitCallback;
+
+struct {
     jmethodID onFrameComplete;
 } gFrameCompleteCallback;
 
@@ -101,22 +105,21 @@
     JavaVM* mVm;
 };
 
-class FrameCompleteWrapper : public LightRefBase<FrameCompleteWrapper> {
+class FrameCommitWrapper : public LightRefBase<FrameCommitWrapper> {
 public:
-    explicit FrameCompleteWrapper(JNIEnv* env, jobject jobject) {
+    explicit FrameCommitWrapper(JNIEnv* env, jobject jobject) {
         env->GetJavaVM(&mVm);
         mObject = env->NewGlobalRef(jobject);
         LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref");
     }
 
-    ~FrameCompleteWrapper() {
-        releaseObject();
-    }
+    ~FrameCommitWrapper() { releaseObject(); }
 
-    void onFrameComplete(int64_t frameNr) {
+    void onFrameCommit(bool didProduceBuffer) {
         if (mObject) {
-            ATRACE_FORMAT("frameComplete %" PRId64, frameNr);
-            getenv(mVm)->CallVoidMethod(mObject, gFrameCompleteCallback.onFrameComplete, frameNr);
+            ATRACE_FORMAT("frameCommit success=%d", didProduceBuffer);
+            getenv(mVm)->CallVoidMethod(mObject, gFrameCommitCallback.onFrameCommit,
+                                        didProduceBuffer);
             releaseObject();
         }
     }
@@ -607,15 +610,33 @@
     }
 }
 
+static void android_view_ThreadedRenderer_setFrameCommitCallback(JNIEnv* env, jobject clazz,
+                                                                 jlong proxyPtr, jobject callback) {
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    if (!callback) {
+        proxy->setFrameCommitCallback(nullptr);
+    } else {
+        sp<FrameCommitWrapper> wrapper = new FrameCommitWrapper{env, callback};
+        proxy->setFrameCommitCallback(
+                [wrapper](bool didProduceBuffer) { wrapper->onFrameCommit(didProduceBuffer); });
+    }
+}
+
 static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env,
         jobject clazz, jlong proxyPtr, jobject callback) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
     if (!callback) {
         proxy->setFrameCompleteCallback(nullptr);
     } else {
-        sp<FrameCompleteWrapper> wrapper = new FrameCompleteWrapper{env, callback};
-        proxy->setFrameCompleteCallback([wrapper](int64_t frameNr) {
-            wrapper->onFrameComplete(frameNr);
+        RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+        JavaVM* vm = nullptr;
+        LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
+        auto globalCallbackRef =
+                std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(callback));
+        proxy->setFrameCompleteCallback([globalCallbackRef]() {
+            JNIEnv* env = getenv(globalCallbackRef->vm());
+            env->CallVoidMethod(globalCallbackRef->object(),
+                                gFrameCompleteCallback.onFrameComplete);
         });
     }
 }
@@ -907,6 +928,8 @@
          (void*)android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback},
         {"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V",
          (void*)android_view_ThreadedRenderer_setFrameCallback},
+        {"nSetFrameCommitCallback", "(JLandroid/graphics/HardwareRenderer$FrameCommitCallback;)V",
+         (void*)android_view_ThreadedRenderer_setFrameCommitCallback},
         {"nSetFrameCompleteCallback",
          "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V",
          (void*)android_view_ThreadedRenderer_setFrameCompleteCallback},
@@ -974,10 +997,15 @@
     gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
             "onFrameDraw", "(J)V");
 
+    jclass frameCommitClass =
+            FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameCommitCallback");
+    gFrameCommitCallback.onFrameCommit =
+            GetMethodIDOrDie(env, frameCommitClass, "onFrameCommit", "(Z)V");
+
     jclass frameCompleteClass = FindClassOrDie(env,
             "android/graphics/HardwareRenderer$FrameCompleteCallback");
-    gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass,
-            "onFrameComplete", "(J)V");
+    gFrameCompleteCallback.onFrameComplete =
+            GetMethodIDOrDie(env, frameCompleteClass, "onFrameComplete", "()V");
 
     void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
     fromSurface = (ANW_fromSurface)dlsym(handle_, "ANativeWindow_fromSurface");
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index bb0b135..5fa0922 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -203,9 +203,10 @@
     mSurfaceControl = surfaceControl;
     mSurfaceControlGenerationId++;
     mExpectSurfaceStats = surfaceControl != nullptr;
-    if (mSurfaceControl != nullptr) {
+    if (mExpectSurfaceStats) {
         funcs.acquireFunc(mSurfaceControl);
-        funcs.registerListenerFunc(surfaceControl, this, &onSurfaceStatsAvailable);
+        funcs.registerListenerFunc(surfaceControl, mSurfaceControlGenerationId, this,
+                                   &onSurfaceStatsAvailable);
     }
 }
 
@@ -218,7 +219,7 @@
 
     }
 
-    mFrameNumber = -1;
+    mFrameNumber = 0;
 
     if (mNativeSurface != nullptr && hasSurface) {
         mHaveNewSurface = true;
@@ -492,10 +493,10 @@
         // Notify the callbacks, even if there's nothing to draw so they aren't waiting
         // indefinitely
         waitOnFences();
-        for (auto& func : mFrameCompleteCallbacks) {
-            std::invoke(func, mFrameNumber);
+        for (auto& func : mFrameCommitCallbacks) {
+            std::invoke(func, false /* didProduceBuffer */);
         }
-        mFrameCompleteCallbacks.clear();
+        mFrameCommitCallbacks.clear();
         return 0;
     }
 
@@ -512,7 +513,7 @@
                                       mContentDrawBounds, mOpaque, mLightInfo, mRenderNodes,
                                       &(profiler()));
 
-    int64_t frameCompleteNr = getFrameNumber();
+    uint64_t frameCompleteNr = getFrameNumber();
 
     waitOnFences();
 
@@ -580,7 +581,7 @@
         mCurrentFrameInfo->set(FrameInfoIndex::DequeueBufferDuration) = swap.dequeueDuration;
         mCurrentFrameInfo->set(FrameInfoIndex::QueueBufferDuration) = swap.queueDuration;
         mHaveNewSurface = false;
-        mFrameNumber = -1;
+        mFrameNumber = 0;
     } else {
         mCurrentFrameInfo->set(FrameInfoIndex::DequeueBufferDuration) = 0;
         mCurrentFrameInfo->set(FrameInfoIndex::QueueBufferDuration) = 0;
@@ -604,25 +605,29 @@
 #endif
 
     if (didSwap) {
-        for (auto& func : mFrameCompleteCallbacks) {
-            std::invoke(func, frameCompleteNr);
+        for (auto& func : mFrameCommitCallbacks) {
+            std::invoke(func, true /* didProduceBuffer */);
         }
-        mFrameCompleteCallbacks.clear();
+        mFrameCommitCallbacks.clear();
     }
 
     if (requireSwap) {
         if (mExpectSurfaceStats) {
             reportMetricsWithPresentTime();
-            std::lock_guard lock(mLast4FrameInfosMutex);
-            std::pair<FrameInfo*, int64_t>& next = mLast4FrameInfos.next();
-            next.first = mCurrentFrameInfo;
-            next.second = frameCompleteNr;
+            {  // acquire lock
+                std::lock_guard lock(mLast4FrameMetricsInfosMutex);
+                FrameMetricsInfo& next = mLast4FrameMetricsInfos.next();
+                next.frameInfo = mCurrentFrameInfo;
+                next.frameNumber = frameCompleteNr;
+                next.surfaceId = mSurfaceControlGenerationId;
+            }  // release lock
         } else {
             mCurrentFrameInfo->markFrameCompleted();
             mCurrentFrameInfo->set(FrameInfoIndex::GpuCompleted)
                     = mCurrentFrameInfo->get(FrameInfoIndex::FrameCompleted);
             std::scoped_lock lock(mFrameMetricsReporterMutex);
-            mJankTracker.finishFrame(*mCurrentFrameInfo, mFrameMetricsReporter);
+            mJankTracker.finishFrame(*mCurrentFrameInfo, mFrameMetricsReporter, frameCompleteNr,
+                                     mSurfaceControlGenerationId);
         }
     }
 
@@ -658,14 +663,18 @@
     ATRACE_CALL();
     FrameInfo* forthBehind;
     int64_t frameNumber;
+    int32_t surfaceControlId;
+
     {  // acquire lock
-        std::scoped_lock lock(mLast4FrameInfosMutex);
-        if (mLast4FrameInfos.size() != mLast4FrameInfos.capacity()) {
+        std::scoped_lock lock(mLast4FrameMetricsInfosMutex);
+        if (mLast4FrameMetricsInfos.size() != mLast4FrameMetricsInfos.capacity()) {
             // Not enough frames yet
             return;
         }
-        // Surface object keeps stats for the last 8 frames.
-        std::tie(forthBehind, frameNumber) = mLast4FrameInfos.front();
+        auto frameMetricsInfo = mLast4FrameMetricsInfos.front();
+        forthBehind = frameMetricsInfo.frameInfo;
+        frameNumber = frameMetricsInfo.frameNumber;
+        surfaceControlId = frameMetricsInfo.surfaceId;
     }  // release lock
 
     nsecs_t presentTime = 0;
@@ -680,25 +689,51 @@
     {  // acquire lock
         std::scoped_lock lock(mFrameMetricsReporterMutex);
         if (mFrameMetricsReporter != nullptr) {
-            mFrameMetricsReporter->reportFrameMetrics(forthBehind->data(), true /*hasPresentTime*/);
+            mFrameMetricsReporter->reportFrameMetrics(forthBehind->data(), true /*hasPresentTime*/,
+                                                      frameNumber, surfaceControlId);
         }
     }  // release lock
 }
 
-FrameInfo* CanvasContext::getFrameInfoFromLast4(uint64_t frameNumber) {
-    std::scoped_lock lock(mLast4FrameInfosMutex);
-    for (size_t i = 0; i < mLast4FrameInfos.size(); i++) {
-        if (mLast4FrameInfos[i].second == frameNumber) {
-            return mLast4FrameInfos[i].first;
+void CanvasContext::addFrameMetricsObserver(FrameMetricsObserver* observer) {
+    std::scoped_lock lock(mFrameMetricsReporterMutex);
+    if (mFrameMetricsReporter.get() == nullptr) {
+        mFrameMetricsReporter.reset(new FrameMetricsReporter());
+    }
+
+    // We want to make sure we aren't reporting frames that have already been queued by the
+    // BufferQueueProducer on the rendner thread but are still pending the callback to report their
+    // their frame metrics.
+    uint64_t nextFrameNumber = getFrameNumber();
+    observer->reportMetricsFrom(nextFrameNumber, mSurfaceControlGenerationId);
+    mFrameMetricsReporter->addObserver(observer);
+}
+
+void CanvasContext::removeFrameMetricsObserver(FrameMetricsObserver* observer) {
+    std::scoped_lock lock(mFrameMetricsReporterMutex);
+    if (mFrameMetricsReporter.get() != nullptr) {
+        mFrameMetricsReporter->removeObserver(observer);
+        if (!mFrameMetricsReporter->hasObservers()) {
+            mFrameMetricsReporter.reset(nullptr);
         }
     }
+}
+
+FrameInfo* CanvasContext::getFrameInfoFromLast4(uint64_t frameNumber, uint32_t surfaceControlId) {
+    std::scoped_lock lock(mLast4FrameMetricsInfosMutex);
+    for (size_t i = 0; i < mLast4FrameMetricsInfos.size(); i++) {
+        if (mLast4FrameMetricsInfos[i].frameNumber == frameNumber &&
+            mLast4FrameMetricsInfos[i].surfaceId == surfaceControlId) {
+            return mLast4FrameMetricsInfos[i].frameInfo;
+        }
+    }
+
     return nullptr;
 }
 
-void CanvasContext::onSurfaceStatsAvailable(void* context, ASurfaceControl* control,
-            ASurfaceControlStats* stats) {
-
-    CanvasContext* instance = static_cast<CanvasContext*>(context);
+void CanvasContext::onSurfaceStatsAvailable(void* context, int32_t surfaceControlId,
+                                            ASurfaceControlStats* stats) {
+    auto* instance = static_cast<CanvasContext*>(context);
 
     const ASurfaceControlFunctions& functions =
             instance->mRenderThread.getASurfaceControlFunctions();
@@ -706,14 +741,15 @@
     nsecs_t gpuCompleteTime = functions.getAcquireTimeFunc(stats);
     uint64_t frameNumber = functions.getFrameNumberFunc(stats);
 
-    FrameInfo* frameInfo = instance->getFrameInfoFromLast4(frameNumber);
+    FrameInfo* frameInfo = instance->getFrameInfoFromLast4(frameNumber, surfaceControlId);
 
     if (frameInfo != nullptr) {
         frameInfo->set(FrameInfoIndex::FrameCompleted) = std::max(gpuCompleteTime,
                 frameInfo->get(FrameInfoIndex::SwapBuffersCompleted));
         frameInfo->set(FrameInfoIndex::GpuCompleted) = gpuCompleteTime;
         std::scoped_lock lock(instance->mFrameMetricsReporterMutex);
-        instance->mJankTracker.finishFrame(*frameInfo, instance->mFrameMetricsReporter);
+        instance->mJankTracker.finishFrame(*frameInfo, instance->mFrameMetricsReporter, frameNumber,
+                                           surfaceControlId);
     }
 }
 
@@ -854,9 +890,9 @@
     mFrameFences.push_back(CommonPool::async(std::move(func)));
 }
 
-int64_t CanvasContext::getFrameNumber() {
-    // mFrameNumber is reset to -1 when the surface changes or we swap buffers
-    if (mFrameNumber == -1 && mNativeSurface.get()) {
+uint64_t CanvasContext::getFrameNumber() {
+    // mFrameNumber is reset to 0 when the surface changes or we swap buffers
+    if (mFrameNumber == 0 && mNativeSurface.get()) {
         mFrameNumber = ANativeWindow_getNextFrameId(mNativeSurface->getNativeWindow());
     }
     return mFrameNumber;
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2fed468..0caf76a 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -167,36 +167,20 @@
 
     void setContentDrawBounds(const Rect& bounds) { mContentDrawBounds = bounds; }
 
-    void addFrameMetricsObserver(FrameMetricsObserver* observer) {
-        std::scoped_lock lock(mFrameMetricsReporterMutex);
-        if (mFrameMetricsReporter.get() == nullptr) {
-            mFrameMetricsReporter.reset(new FrameMetricsReporter());
-        }
-
-        mFrameMetricsReporter->addObserver(observer);
-    }
-
-    void removeFrameMetricsObserver(FrameMetricsObserver* observer) {
-        std::scoped_lock lock(mFrameMetricsReporterMutex);
-        if (mFrameMetricsReporter.get() != nullptr) {
-            mFrameMetricsReporter->removeObserver(observer);
-            if (!mFrameMetricsReporter->hasObservers()) {
-                mFrameMetricsReporter.reset(nullptr);
-            }
-        }
-    }
+    void addFrameMetricsObserver(FrameMetricsObserver* observer);
+    void removeFrameMetricsObserver(FrameMetricsObserver* observer);
 
     // Used to queue up work that needs to be completed before this frame completes
     void enqueueFrameWork(std::function<void()>&& func);
 
-    int64_t getFrameNumber();
+    uint64_t getFrameNumber();
 
     void waitOnFences();
 
     IRenderPipeline* getRenderPipeline() { return mRenderPipeline.get(); }
 
-    void addFrameCompleteListener(std::function<void(int64_t)>&& func) {
-        mFrameCompleteCallbacks.push_back(std::move(func));
+    void addFrameCommitListener(std::function<void(bool)>&& func) {
+        mFrameCommitCallbacks.push_back(std::move(func));
     }
 
     void setPictureCapturedCallback(const std::function<void(sk_sp<SkPicture>&&)>& callback) {
@@ -212,8 +196,8 @@
     SkISize getNextFrameSize() const;
 
     // Called when SurfaceStats are available.
-    static void onSurfaceStatsAvailable(void* context, ASurfaceControl* control,
-            ASurfaceControlStats* stats);
+    static void onSurfaceStatsAvailable(void* context, int32_t surfaceControlId,
+                                        ASurfaceControlStats* stats);
 
     void setASurfaceTransactionCallback(
             const std::function<bool(int64_t, int64_t, int64_t)>& callback) {
@@ -254,7 +238,13 @@
      */
     void reportMetricsWithPresentTime();
 
-    FrameInfo* getFrameInfoFromLast4(uint64_t frameNumber);
+    struct FrameMetricsInfo {
+        FrameInfo* frameInfo;
+        int64_t frameNumber;
+        int32_t surfaceId;
+    };
+
+    FrameInfo* getFrameInfoFromLast4(uint64_t frameNumber, uint32_t surfaceControlId);
 
     // The same type as Frame.mWidth and Frame.mHeight
     int32_t mLastFrameWidth = 0;
@@ -266,7 +256,10 @@
     // NULL to remove the reference
     ASurfaceControl* mSurfaceControl = nullptr;
     // id to track surface control changes and WebViewFunctor uses it to determine
-    // whether reparenting is needed
+    // whether reparenting is needed also used by FrameMetricsReporter to determine
+    // if a frame is from an "old" surface (i.e. one that existed before the
+    // observer was attched) and therefore shouldn't be reported.
+    // NOTE: It is important that this is an increasing counter.
     int32_t mSurfaceControlGenerationId = 0;
     // stopped indicates the CanvasContext will reject actual redraw operations,
     // and defer repaint until it is un-stopped
@@ -288,7 +281,8 @@
 
     // Need at least 4 because we do quad buffer. Add a 5th for good measure.
     RingBuffer<SwapHistory, 5> mSwapHistory;
-    int64_t mFrameNumber = -1;
+    // Frame numbers start at 1, 0 means uninitialized
+    uint64_t mFrameNumber = 0;
     int64_t mDamageId = 0;
 
     // last vsync for a dropped frame due to stuffed queue
@@ -308,10 +302,11 @@
 
     FrameInfo* mCurrentFrameInfo = nullptr;
 
-    // List of frames that are awaiting GPU completion reporting
-    RingBuffer<std::pair<FrameInfo*, int64_t>, 4> mLast4FrameInfos
-            GUARDED_BY(mLast4FrameInfosMutex);
-    std::mutex mLast4FrameInfosMutex;
+    // List of data of frames that are awaiting GPU completion reporting. Used to compute frame
+    // metrics and determine whether or not to report the metrics.
+    RingBuffer<FrameMetricsInfo, 4> mLast4FrameMetricsInfos
+            GUARDED_BY(mLast4FrameMetricsInfosMutex);
+    std::mutex mLast4FrameMetricsInfosMutex;
 
     std::string mName;
     JankTracker mJankTracker;
@@ -328,7 +323,7 @@
     std::vector<std::future<void>> mFrameFences;
     std::unique_ptr<IRenderPipeline> mRenderPipeline;
 
-    std::vector<std::function<void(int64_t)>> mFrameCompleteCallbacks;
+    std::vector<std::function<void(bool)>> mFrameCommitCallbacks;
 
     // If set to true, we expect that callbacks into onSurfaceStatsAvailable
     bool mExpectSurfaceStats = false;
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index e7081df..94aedd0 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -150,16 +150,18 @@
         canUnblockUiThread = syncFrameState(info);
         canDrawThisFrame = info.out.canDrawThisFrame;
 
-        if (mFrameCompleteCallback) {
-            mContext->addFrameCompleteListener(std::move(mFrameCompleteCallback));
-            mFrameCompleteCallback = nullptr;
+        if (mFrameCommitCallback) {
+            mContext->addFrameCommitListener(std::move(mFrameCommitCallback));
+            mFrameCommitCallback = nullptr;
         }
     }
 
     // Grab a copy of everything we need
     CanvasContext* context = mContext;
-    std::function<void(int64_t)> callback = std::move(mFrameCallback);
+    std::function<void(int64_t)> frameCallback = std::move(mFrameCallback);
+    std::function<void()> frameCompleteCallback = std::move(mFrameCompleteCallback);
     mFrameCallback = nullptr;
+    mFrameCompleteCallback = nullptr;
     int64_t intendedVsync = mFrameInfo[static_cast<int>(FrameInfoIndex::IntendedVsync)];
     int64_t frameDeadline = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameDeadline)];
     int64_t frameStartTime = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameStartTime)];
@@ -170,9 +172,9 @@
     }
 
     // Even if we aren't drawing this vsync pulse the next frame number will still be accurate
-    if (CC_UNLIKELY(callback)) {
+    if (CC_UNLIKELY(frameCallback)) {
         context->enqueueFrameWork(
-                [callback, frameNr = context->getFrameNumber()]() { callback(frameNr); });
+                [frameCallback, frameNr = context->getFrameNumber()]() { frameCallback(frameNr); });
     }
 
     nsecs_t dequeueBufferDuration = 0;
@@ -189,6 +191,10 @@
         context->waitOnFences();
     }
 
+    if (CC_UNLIKELY(frameCompleteCallback)) {
+        std::invoke(frameCompleteCallback);
+    }
+
     if (!canUnblockUiThread) {
         unblockUiThread();
     }
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 6a61a2b..e3ea802 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -81,7 +81,11 @@
         mFrameCallback = std::move(callback);
     }
 
-    void setFrameCompleteCallback(std::function<void(int64_t)>&& callback) {
+    void setFrameCommitCallback(std::function<void(bool)>&& callback) {
+        mFrameCommitCallback = std::move(callback);
+    }
+
+    void setFrameCompleteCallback(std::function<void()>&& callback) {
         mFrameCompleteCallback = std::move(callback);
     }
 
@@ -123,7 +127,8 @@
     int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
 
     std::function<void(int64_t)> mFrameCallback;
-    std::function<void(int64_t)> mFrameCompleteCallback;
+    std::function<void(bool)> mFrameCommitCallback;
+    std::function<void()> mFrameCompleteCallback;
 
     nsecs_t mLastDequeueBufferDuration = 0;
     nsecs_t mLastTargetWorkDuration = 0;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index c485ce2..72d4ac5 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -326,7 +326,11 @@
     mDrawFrameTask.setFrameCallback(std::move(callback));
 }
 
-void RenderProxy::setFrameCompleteCallback(std::function<void(int64_t)>&& callback) {
+void RenderProxy::setFrameCommitCallback(std::function<void(bool)>&& callback) {
+    mDrawFrameTask.setFrameCommitCallback(std::move(callback));
+}
+
+void RenderProxy::setFrameCompleteCallback(std::function<void()>&& callback) {
     mDrawFrameTask.setFrameCompleteCallback(std::move(callback));
 }
 
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 2b5405c..6417b38 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -124,7 +124,8 @@
             const std::function<bool(int64_t, int64_t, int64_t)>& callback);
     void setPrepareSurfaceControlForWebviewCallback(const std::function<void()>& callback);
     void setFrameCallback(std::function<void(int64_t)>&& callback);
-    void setFrameCompleteCallback(std::function<void(int64_t)>&& callback);
+    void setFrameCommitCallback(std::function<void(bool)>&& callback);
+    void setFrameCompleteCallback(std::function<void()>&& callback);
 
     void addFrameMetricsObserver(FrameMetricsObserver* observer);
     void removeFrameMetricsObserver(FrameMetricsObserver* observer);
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 05d225b..0b81fc04 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -83,8 +83,9 @@
 typedef void (*ASC_acquire)(ASurfaceControl* control);
 typedef void (*ASC_release)(ASurfaceControl* control);
 
-typedef void (*ASC_registerSurfaceStatsListener)(ASurfaceControl* control, void* context,
-        ASurfaceControl_SurfaceStatsListener func);
+typedef void (*ASC_registerSurfaceStatsListener)(ASurfaceControl* control, int32_t id,
+                                                 void* context,
+                                                 ASurfaceControl_SurfaceStatsListener func);
 typedef void (*ASC_unregisterSurfaceStatsListener)(void* context,
                                                    ASurfaceControl_SurfaceStatsListener func);
 
diff --git a/libs/hwui/tests/unit/FrameMetricsReporterTests.cpp b/libs/hwui/tests/unit/FrameMetricsReporterTests.cpp
new file mode 100644
index 0000000..fb04700
--- /dev/null
+++ b/libs/hwui/tests/unit/FrameMetricsReporterTests.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <FrameMetricsObserver.h>
+#include <FrameMetricsReporter.h>
+#include <utils/TimeUtils.h>
+
+using namespace android;
+using namespace android::uirenderer;
+
+using ::testing::NotNull;
+
+class TestFrameMetricsObserver : public FrameMetricsObserver {
+public:
+    explicit TestFrameMetricsObserver(bool waitForPresentTime)
+            : FrameMetricsObserver(waitForPresentTime){};
+
+    MOCK_METHOD(void, notify, (const int64_t* buffer), (override));
+};
+
+TEST(FrameMetricsReporter, reportsAllFramesIfNoFromFrameIsSpecified) {
+    auto reporter = std::make_shared<FrameMetricsReporter>();
+
+    auto observer = sp<TestFrameMetricsObserver>::make(false /*waitForPresentTime*/);
+    EXPECT_CALL(*observer, notify).Times(4);
+
+    reporter->addObserver(observer.get());
+
+    const int64_t* stats;
+    bool hasPresentTime = false;
+    uint64_t frameNumber = 1;
+    int32_t surfaceControlId = 0;
+    reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber, surfaceControlId);
+
+    frameNumber = 10;
+    surfaceControlId = 0;
+    reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber, surfaceControlId);
+
+    frameNumber = 0;
+    surfaceControlId = 2;
+    reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber, surfaceControlId);
+
+    frameNumber = 10;
+    surfaceControlId = 2;
+    reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber, surfaceControlId);
+}
+
+TEST(FrameMetricsReporter, respectsWaitForPresentTimeUnset) {
+    auto reporter = std::make_shared<FrameMetricsReporter>();
+
+    auto observer = sp<TestFrameMetricsObserver>::make(false /*waitForPresentTime*/);
+    reporter->addObserver(observer.get());
+
+    const int64_t* stats;
+    bool hasPresentTime = false;
+    uint64_t frameNumber = 3;
+    int32_t surfaceControlId = 0;
+
+    EXPECT_CALL(*observer, notify).Times(1);
+    reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber, surfaceControlId);
+
+    EXPECT_CALL(*observer, notify).Times(0);
+    hasPresentTime = true;
+    reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber, surfaceControlId);
+}
+
+TEST(FrameMetricsReporter, respectsWaitForPresentTimeSet) {
+    auto reporter = std::make_shared<FrameMetricsReporter>();
+
+    auto observer = sp<TestFrameMetricsObserver>::make(true /*waitForPresentTime*/);
+    reporter->addObserver(observer.get());
+
+    const int64_t* stats;
+    bool hasPresentTime = false;
+    uint64_t frameNumber = 3;
+    int32_t surfaceControlId = 0;
+
+    EXPECT_CALL(*observer, notify).Times(0);
+    reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber, surfaceControlId);
+
+    EXPECT_CALL(*observer, notify).Times(1);
+    hasPresentTime = true;
+    reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber, surfaceControlId);
+}
+
+TEST(FrameMetricsReporter, reportsAllFramesAfterSpecifiedFromFrame) {
+    const int64_t* stats;
+    bool hasPresentTime = false;
+
+    std::vector<uint64_t> frameNumbers{0, 1, 10};
+    std::vector<int32_t> surfaceControlIds{0, 1, 10};
+    for (uint64_t frameNumber : frameNumbers) {
+        for (int32_t surfaceControlId : surfaceControlIds) {
+            auto reporter = std::make_shared<FrameMetricsReporter>();
+
+            auto observer =
+                    sp<TestFrameMetricsObserver>::make(hasPresentTime /*waitForPresentTime*/);
+            observer->reportMetricsFrom(frameNumber, surfaceControlId);
+            reporter->addObserver(observer.get());
+
+            EXPECT_CALL(*observer, notify).Times(8);
+            reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber, surfaceControlId);
+            reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber + 1, surfaceControlId);
+            reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber + 10, surfaceControlId);
+            reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber, surfaceControlId + 1);
+            reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber - 1,
+                                         surfaceControlId + 1);
+            reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber + 1,
+                                         surfaceControlId + 1);
+            reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber + 10,
+                                         surfaceControlId + 1);
+            reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber + 10,
+                                         surfaceControlId + 10);
+        }
+    }
+}
+
+TEST(FrameMetricsReporter, doesNotReportsFramesBeforeSpecifiedFromFrame) {
+    const int64_t* stats;
+    bool hasPresentTime = false;
+
+    std::vector<uint64_t> frameNumbers{1, 10};
+    std::vector<int32_t> surfaceControlIds{0, 1, 10};
+    for (uint64_t frameNumber : frameNumbers) {
+        for (int32_t surfaceControlId : surfaceControlIds) {
+            auto reporter = std::make_shared<FrameMetricsReporter>();
+
+            auto observer =
+                    sp<TestFrameMetricsObserver>::make(hasPresentTime /*waitForPresentTime*/);
+            observer->reportMetricsFrom(frameNumber, surfaceControlId);
+            reporter->addObserver(observer.get());
+
+            EXPECT_CALL(*observer, notify).Times(0);
+            reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber - 1, surfaceControlId);
+            if (surfaceControlId > 0) {
+                reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber,
+                                             surfaceControlId - 1);
+                reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber - 1,
+                                             surfaceControlId - 1);
+            }
+        }
+    }
+}
+
+TEST(FrameMetricsReporter, canRemoveObservers) {
+    const int64_t* stats;
+    bool hasPresentTime = false;
+    uint64_t frameNumber = 3;
+    int32_t surfaceControlId = 0;
+
+    auto reporter = std::make_shared<FrameMetricsReporter>();
+
+    auto observer = sp<TestFrameMetricsObserver>::make(hasPresentTime /*waitForPresentTime*/);
+
+    observer->reportMetricsFrom(frameNumber, surfaceControlId);
+    reporter->addObserver(observer.get());
+
+    EXPECT_CALL(*observer, notify).Times(1);
+    reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber, surfaceControlId);
+
+    ASSERT_TRUE(reporter->removeObserver(observer.get()));
+
+    EXPECT_CALL(*observer, notify).Times(0);
+    reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber, surfaceControlId);
+}
+
+TEST(FrameMetricsReporter, canSupportMultipleObservers) {
+    const int64_t* stats;
+    bool hasPresentTime = false;
+    uint64_t frameNumber = 3;
+    int32_t surfaceControlId = 0;
+
+    auto reporter = std::make_shared<FrameMetricsReporter>();
+
+    auto observer1 = sp<TestFrameMetricsObserver>::make(hasPresentTime /*waitForPresentTime*/);
+    auto observer2 = sp<TestFrameMetricsObserver>::make(hasPresentTime /*waitForPresentTime*/);
+    observer1->reportMetricsFrom(frameNumber, surfaceControlId);
+    observer2->reportMetricsFrom(frameNumber + 10, surfaceControlId + 1);
+    reporter->addObserver(observer1.get());
+    reporter->addObserver(observer2.get());
+
+    EXPECT_CALL(*observer1, notify).Times(1);
+    EXPECT_CALL(*observer2, notify).Times(0);
+    reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber, surfaceControlId);
+
+    EXPECT_CALL(*observer1, notify).Times(1);
+    EXPECT_CALL(*observer2, notify).Times(1);
+    reporter->reportFrameMetrics(stats, hasPresentTime, frameNumber + 10, surfaceControlId + 1);
+}
diff --git a/libs/hwui/tests/unit/JankTrackerTests.cpp b/libs/hwui/tests/unit/JankTrackerTests.cpp
index f467ebf..5b397de 100644
--- a/libs/hwui/tests/unit/JankTrackerTests.cpp
+++ b/libs/hwui/tests/unit/JankTrackerTests.cpp
@@ -34,6 +34,9 @@
     JankTracker jankTracker(&container);
     std::unique_ptr<FrameMetricsReporter> reporter = std::make_unique<FrameMetricsReporter>();
 
+    uint64_t frameNumber = 0;
+    uint32_t surfaceId = 0;
+
     FrameInfo* info = jankTracker.startFrame();
     info->set(FrameInfoIndex::IntendedVsync) = 100_ms;
     info->set(FrameInfoIndex::Vsync) = 101_ms;
@@ -42,7 +45,7 @@
     info->set(FrameInfoIndex::FrameCompleted) = 115_ms;
     info->set(FrameInfoIndex::FrameInterval) = 16_ms;
     info->set(FrameInfoIndex::FrameDeadline) = 120_ms;
-    jankTracker.finishFrame(*info, reporter);
+    jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
 
     info = jankTracker.startFrame();
     info->set(FrameInfoIndex::IntendedVsync) = 116_ms;
@@ -52,7 +55,7 @@
     info->set(FrameInfoIndex::FrameCompleted) = 131_ms;
     info->set(FrameInfoIndex::FrameInterval) = 16_ms;
     info->set(FrameInfoIndex::FrameDeadline) = 136_ms;
-    jankTracker.finishFrame(*info, reporter);
+    jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
 
     ASSERT_EQ(2, container.get()->totalFrameCount());
     ASSERT_EQ(0, container.get()->jankFrameCount());
@@ -65,6 +68,9 @@
     JankTracker jankTracker(&container);
     std::unique_ptr<FrameMetricsReporter> reporter = std::make_unique<FrameMetricsReporter>();
 
+    uint64_t frameNumber = 0;
+    uint32_t surfaceId = 0;
+
     FrameInfo* info = jankTracker.startFrame();
     info->set(FrameInfoIndex::IntendedVsync) = 100_ms;
     info->set(FrameInfoIndex::Vsync) = 101_ms;
@@ -73,7 +79,7 @@
     info->set(FrameInfoIndex::FrameCompleted) = 121_ms;
     info->set(FrameInfoIndex::FrameInterval) = 16_ms;
     info->set(FrameInfoIndex::FrameDeadline) = 120_ms;
-    jankTracker.finishFrame(*info, reporter);
+    jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
 
     ASSERT_EQ(1, container.get()->totalFrameCount());
     ASSERT_EQ(1, container.get()->jankFrameCount());
@@ -85,6 +91,9 @@
     JankTracker jankTracker(&container);
     std::unique_ptr<FrameMetricsReporter> reporter = std::make_unique<FrameMetricsReporter>();
 
+    uint64_t frameNumber = 0;
+    uint32_t surfaceId = 0;
+
     FrameInfo* info = jankTracker.startFrame();
     info->set(FrameInfoIndex::IntendedVsync) = 100_ms;
     info->set(FrameInfoIndex::Vsync) = 101_ms;
@@ -93,7 +102,7 @@
     info->set(FrameInfoIndex::FrameCompleted) = 118_ms;
     info->set(FrameInfoIndex::FrameInterval) = 16_ms;
     info->set(FrameInfoIndex::FrameDeadline) = 120_ms;
-    jankTracker.finishFrame(*info, reporter);
+    jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
 
     ASSERT_EQ(1, container.get()->totalFrameCount());
     ASSERT_EQ(0, container.get()->jankFrameCount());
@@ -106,6 +115,9 @@
     JankTracker jankTracker(&container);
     std::unique_ptr<FrameMetricsReporter> reporter = std::make_unique<FrameMetricsReporter>();
 
+    uint64_t frameNumber = 0;
+    uint32_t surfaceId = 0;
+
     // First frame janks
     FrameInfo* info = jankTracker.startFrame();
     info->set(FrameInfoIndex::IntendedVsync) = 100_ms;
@@ -115,7 +127,7 @@
     info->set(FrameInfoIndex::FrameCompleted) = 121_ms;
     info->set(FrameInfoIndex::FrameInterval) = 16_ms;
     info->set(FrameInfoIndex::FrameDeadline) = 120_ms;
-    jankTracker.finishFrame(*info, reporter);
+    jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
 
     ASSERT_EQ(1, container.get()->jankFrameCount());
 
@@ -128,7 +140,7 @@
     info->set(FrameInfoIndex::FrameCompleted) = 137_ms;
     info->set(FrameInfoIndex::FrameInterval) = 16_ms;
     info->set(FrameInfoIndex::FrameDeadline) = 136_ms;
-    jankTracker.finishFrame(*info, reporter);
+    jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
 
     ASSERT_EQ(2, container.get()->totalFrameCount());
     ASSERT_EQ(1, container.get()->jankFrameCount());
@@ -140,6 +152,9 @@
     JankTracker jankTracker(&container);
     std::unique_ptr<FrameMetricsReporter> reporter = std::make_unique<FrameMetricsReporter>();
 
+    uint64_t frameNumber = 0;
+    uint32_t surfaceId = 0;
+
     // First frame janks
     FrameInfo* info = jankTracker.startFrame();
     info->set(FrameInfoIndex::IntendedVsync) = 100_ms;
@@ -149,7 +164,7 @@
     info->set(FrameInfoIndex::FrameCompleted) = 121_ms;
     info->set(FrameInfoIndex::FrameInterval) = 16_ms;
     info->set(FrameInfoIndex::FrameDeadline) = 120_ms;
-    jankTracker.finishFrame(*info, reporter);
+    jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
 
     ASSERT_EQ(1, container.get()->jankFrameCount());
 
@@ -162,7 +177,7 @@
     info->set(FrameInfoIndex::FrameCompleted) = 137_ms;
     info->set(FrameInfoIndex::FrameInterval) = 16_ms;
     info->set(FrameInfoIndex::FrameDeadline) = 136_ms;
-    jankTracker.finishFrame(*info, reporter);
+    jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
 
     ASSERT_EQ(1, container.get()->jankFrameCount());
 
@@ -175,8 +190,8 @@
     info->set(FrameInfoIndex::FrameCompleted) = 169_ms;
     info->set(FrameInfoIndex::FrameInterval) = 16_ms;
     info->set(FrameInfoIndex::FrameDeadline) = 168_ms;
-    jankTracker.finishFrame(*info, reporter);
+    jankTracker.finishFrame(*info, reporter, frameNumber, surfaceId);
 
     ASSERT_EQ(3, container.get()->totalFrameCount());
     ASSERT_EQ(2, container.get()->jankFrameCount());
-}
\ No newline at end of file
+}
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index dbf2621..637f905 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -358,7 +358,7 @@
     }
 
     /**
-     * Gets the data of the reported GPS message.
+     * Gets the data of the reported GNSS message.
      *
      * <p>The bytes (or words) specified using big endian format (MSB first).
      *
diff --git a/media/Android.bp b/media/Android.bp
index ce62b03..7592c15 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -55,12 +55,18 @@
         "aidl/android/media/audio/common/AudioChannelLayout.aidl",
         "aidl/android/media/audio/common/AudioConfig.aidl",
         "aidl/android/media/audio/common/AudioConfigBase.aidl",
+        "aidl/android/media/audio/common/AudioContentType.aidl",
+        "aidl/android/media/audio/common/AudioEncapsulationMetadataType.aidl",
         "aidl/android/media/audio/common/AudioEncapsulationMode.aidl",
+        "aidl/android/media/audio/common/AudioEncapsulationType.aidl",
         "aidl/android/media/audio/common/AudioFormatDescription.aidl",
         "aidl/android/media/audio/common/AudioFormatType.aidl",
+        "aidl/android/media/audio/common/AudioMode.aidl",
         "aidl/android/media/audio/common/AudioOffloadInfo.aidl",
+        "aidl/android/media/audio/common/AudioSource.aidl",
         "aidl/android/media/audio/common/AudioStreamType.aidl",
         "aidl/android/media/audio/common/AudioUsage.aidl",
+        "aidl/android/media/audio/common/AudioUuid.aidl",
         "aidl/android/media/audio/common/PcmType.aidl",
     ],
     stability: "vintf",
diff --git a/media/aidl/android/media/audio/common/AudioChannelLayout.aidl b/media/aidl/android/media/audio/common/AudioChannelLayout.aidl
index 4f34372..311bd59 100644
--- a/media/aidl/android/media/audio/common/AudioChannelLayout.aidl
+++ b/media/aidl/android/media/audio/common/AudioChannelLayout.aidl
@@ -40,7 +40,7 @@
  *
  * {@hide}
  */
-@JavaDerive(equals = true, toString = true)
+@JavaDerive(equals=true, toString=true)
 @VintfStability
 union AudioChannelLayout {
     /**
@@ -114,95 +114,60 @@
      * to be from the LSB to MSB for all the bits set to '1'.
      */
     const int LAYOUT_MONO = CHANNEL_FRONT_LEFT;
-    const int LAYOUT_STEREO =
-            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT;
-    const int LAYOUT_2POINT1 =
-            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_LOW_FREQUENCY;
-    const int LAYOUT_TRI =
-            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER;
-    const int LAYOUT_TRI_BACK =
-            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_BACK_CENTER;
+    const int LAYOUT_STEREO = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT;
+    const int LAYOUT_2POINT1 = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_LOW_FREQUENCY;
+    const int LAYOUT_TRI = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER;
+    const int LAYOUT_TRI_BACK = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_BACK_CENTER;
     const int LAYOUT_3POINT1 =
-            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER |
-            CHANNEL_LOW_FREQUENCY;
-    const int LAYOUT_2POINT0POINT2 =
-            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
-            CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT;
-    const int LAYOUT_2POINT1POINT2 =
-            LAYOUT_2POINT0POINT2 | CHANNEL_LOW_FREQUENCY;
-    const int LAYOUT_3POINT0POINT2 =
-            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
-            CHANNEL_FRONT_CENTER |
-            CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT;
-    const int LAYOUT_3POINT1POINT2 =
-            LAYOUT_3POINT0POINT2 | CHANNEL_LOW_FREQUENCY;
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY;
+    const int LAYOUT_2POINT0POINT2 = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT
+            | CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT;
+    const int LAYOUT_2POINT1POINT2 = LAYOUT_2POINT0POINT2 | CHANNEL_LOW_FREQUENCY;
+    const int LAYOUT_3POINT0POINT2 = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER
+            | CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT;
+    const int LAYOUT_3POINT1POINT2 = LAYOUT_3POINT0POINT2 | CHANNEL_LOW_FREQUENCY;
     const int LAYOUT_QUAD =
-            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
-            CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT;
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT;
     const int LAYOUT_QUAD_SIDE =
-            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
-            CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT;
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT;
     const int LAYOUT_SURROUND =
-            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
-            CHANNEL_FRONT_CENTER | CHANNEL_BACK_CENTER;
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER | CHANNEL_BACK_CENTER;
     const int LAYOUT_PENTA = LAYOUT_QUAD | CHANNEL_FRONT_CENTER;
-    const int LAYOUT_5POINT1 =
-            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
-            CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY |
-            CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT;
-    const int LAYOUT_5POINT1_SIDE =
-            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
-            CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY |
-            CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT;
-    const int LAYOUT_5POINT1POINT2 = LAYOUT_5POINT1 |
-            CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT;
-    const int LAYOUT_5POINT1POINT4 = LAYOUT_5POINT1 |
-            CHANNEL_TOP_FRONT_LEFT | CHANNEL_TOP_FRONT_RIGHT |
-            CHANNEL_TOP_BACK_LEFT | CHANNEL_TOP_BACK_RIGHT;
-    const int LAYOUT_6POINT1 =
-            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
-            CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY |
-            CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT | CHANNEL_BACK_CENTER;
-    const int LAYOUT_7POINT1 = LAYOUT_5POINT1 |
-            CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT;
-    const int LAYOUT_7POINT1POINT2 = LAYOUT_7POINT1 |
-            CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT;
-    const int LAYOUT_7POINT1POINT4 = LAYOUT_7POINT1 |
-            CHANNEL_TOP_FRONT_LEFT | CHANNEL_TOP_FRONT_RIGHT |
-            CHANNEL_TOP_BACK_LEFT | CHANNEL_TOP_BACK_RIGHT;
-    const int LAYOUT_9POINT1POINT4 = LAYOUT_7POINT1POINT4 |
-            CHANNEL_FRONT_WIDE_LEFT | CHANNEL_FRONT_WIDE_RIGHT;
-    const int LAYOUT_9POINT1POINT6 = LAYOUT_9POINT1POINT4 |
-            CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT;
-    const int LAYOUT_13POINT_360RA =
-            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
-            CHANNEL_FRONT_CENTER |
-            CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT |
-            CHANNEL_TOP_FRONT_LEFT | CHANNEL_TOP_FRONT_RIGHT |
-            CHANNEL_TOP_FRONT_CENTER |
-            CHANNEL_TOP_BACK_LEFT | CHANNEL_TOP_BACK_RIGHT |
-            CHANNEL_BOTTOM_FRONT_LEFT | CHANNEL_BOTTOM_FRONT_RIGHT |
-            CHANNEL_BOTTOM_FRONT_CENTER;
-    const int LAYOUT_22POINT2 = LAYOUT_7POINT1POINT4 |
-            CHANNEL_FRONT_LEFT_OF_CENTER | CHANNEL_FRONT_RIGHT_OF_CENTER |
-            CHANNEL_BACK_CENTER | CHANNEL_TOP_CENTER |
-            CHANNEL_TOP_FRONT_CENTER | CHANNEL_TOP_BACK_CENTER |
-            CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT |
-            CHANNEL_BOTTOM_FRONT_LEFT | CHANNEL_BOTTOM_FRONT_RIGHT |
-            CHANNEL_BOTTOM_FRONT_CENTER |
-            CHANNEL_LOW_FREQUENCY_2;
-    const int LAYOUT_MONO_HAPTIC_A =
-            LAYOUT_MONO | CHANNEL_HAPTIC_A;
-    const int LAYOUT_STEREO_HAPTIC_A =
-            LAYOUT_STEREO | CHANNEL_HAPTIC_A;
-    const int LAYOUT_HAPTIC_AB =
-            CHANNEL_HAPTIC_A | CHANNEL_HAPTIC_B;
-    const int LAYOUT_MONO_HAPTIC_AB =
-            LAYOUT_MONO | LAYOUT_HAPTIC_AB;
-    const int LAYOUT_STEREO_HAPTIC_AB =
-            LAYOUT_STEREO | LAYOUT_HAPTIC_AB;
-    const int LAYOUT_FRONT_BACK =
-            CHANNEL_FRONT_CENTER | CHANNEL_BACK_CENTER;
+    const int LAYOUT_5POINT1 = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER
+            | CHANNEL_LOW_FREQUENCY | CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT;
+    const int LAYOUT_5POINT1_SIDE = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER
+            | CHANNEL_LOW_FREQUENCY | CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT;
+    const int LAYOUT_5POINT1POINT2 =
+            LAYOUT_5POINT1 | CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT;
+    const int LAYOUT_5POINT1POINT4 = LAYOUT_5POINT1 | CHANNEL_TOP_FRONT_LEFT
+            | CHANNEL_TOP_FRONT_RIGHT | CHANNEL_TOP_BACK_LEFT | CHANNEL_TOP_BACK_RIGHT;
+    const int LAYOUT_6POINT1 = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER
+            | CHANNEL_LOW_FREQUENCY | CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT | CHANNEL_BACK_CENTER;
+    const int LAYOUT_7POINT1 = LAYOUT_5POINT1 | CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT;
+    const int LAYOUT_7POINT1POINT2 =
+            LAYOUT_7POINT1 | CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT;
+    const int LAYOUT_7POINT1POINT4 = LAYOUT_7POINT1 | CHANNEL_TOP_FRONT_LEFT
+            | CHANNEL_TOP_FRONT_RIGHT | CHANNEL_TOP_BACK_LEFT | CHANNEL_TOP_BACK_RIGHT;
+    const int LAYOUT_9POINT1POINT4 =
+            LAYOUT_7POINT1POINT4 | CHANNEL_FRONT_WIDE_LEFT | CHANNEL_FRONT_WIDE_RIGHT;
+    const int LAYOUT_9POINT1POINT6 =
+            LAYOUT_9POINT1POINT4 | CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT;
+    const int LAYOUT_13POINT_360RA = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER
+            | CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT | CHANNEL_TOP_FRONT_LEFT
+            | CHANNEL_TOP_FRONT_RIGHT | CHANNEL_TOP_FRONT_CENTER | CHANNEL_TOP_BACK_LEFT
+            | CHANNEL_TOP_BACK_RIGHT | CHANNEL_BOTTOM_FRONT_LEFT | CHANNEL_BOTTOM_FRONT_RIGHT
+            | CHANNEL_BOTTOM_FRONT_CENTER;
+    const int LAYOUT_22POINT2 = LAYOUT_7POINT1POINT4 | CHANNEL_FRONT_LEFT_OF_CENTER
+            | CHANNEL_FRONT_RIGHT_OF_CENTER | CHANNEL_BACK_CENTER | CHANNEL_TOP_CENTER
+            | CHANNEL_TOP_FRONT_CENTER | CHANNEL_TOP_BACK_CENTER | CHANNEL_TOP_SIDE_LEFT
+            | CHANNEL_TOP_SIDE_RIGHT | CHANNEL_BOTTOM_FRONT_LEFT | CHANNEL_BOTTOM_FRONT_RIGHT
+            | CHANNEL_BOTTOM_FRONT_CENTER | CHANNEL_LOW_FREQUENCY_2;
+    const int LAYOUT_MONO_HAPTIC_A = LAYOUT_MONO | CHANNEL_HAPTIC_A;
+    const int LAYOUT_STEREO_HAPTIC_A = LAYOUT_STEREO | CHANNEL_HAPTIC_A;
+    const int LAYOUT_HAPTIC_AB = CHANNEL_HAPTIC_A | CHANNEL_HAPTIC_B;
+    const int LAYOUT_MONO_HAPTIC_AB = LAYOUT_MONO | LAYOUT_HAPTIC_AB;
+    const int LAYOUT_STEREO_HAPTIC_AB = LAYOUT_STEREO | LAYOUT_HAPTIC_AB;
+    const int LAYOUT_FRONT_BACK = CHANNEL_FRONT_CENTER | CHANNEL_BACK_CENTER;
 
     /**
      * Expresses the convention when stereo audio samples are stored interleaved
diff --git a/media/aidl/android/media/audio/common/AudioConfig.aidl b/media/aidl/android/media/audio/common/AudioConfig.aidl
index 8d71e8d..ce2da4f 100644
--- a/media/aidl/android/media/audio/common/AudioConfig.aidl
+++ b/media/aidl/android/media/audio/common/AudioConfig.aidl
@@ -24,7 +24,7 @@
  *
  * {@hide}
  */
-@JavaDerive(equals = true, toString = true)
+@JavaDerive(equals=true, toString=true)
 @VintfStability
 parcelable AudioConfig {
     AudioConfigBase base;
diff --git a/media/aidl/android/media/audio/common/AudioConfigBase.aidl b/media/aidl/android/media/audio/common/AudioConfigBase.aidl
index 63f12f4..5210d0d 100644
--- a/media/aidl/android/media/audio/common/AudioConfigBase.aidl
+++ b/media/aidl/android/media/audio/common/AudioConfigBase.aidl
@@ -24,7 +24,7 @@
  *
  * {@hide}
  */
-@JavaDerive(equals = true, toString = true)
+@JavaDerive(equals=true, toString=true)
 @VintfStability
 parcelable AudioConfigBase {
     int sampleRate;
diff --git a/media/aidl/android/media/audio/common/AudioContentType.aidl b/media/aidl/android/media/audio/common/AudioContentType.aidl
new file mode 100644
index 0000000..50ac181
--- /dev/null
+++ b/media/aidl/android/media/audio/common/AudioContentType.aidl
@@ -0,0 +1,53 @@
+/*
+ * 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 android.media.audio.common;
+
+/**
+ * Content type specifies "what" is playing. The content type expresses the
+ * general category of the content: speech, music, movie audio, etc.
+ * This enum corresponds to AudioAttributes.CONTENT_TYPE_* constants in the SDK.
+ *
+ * {@hide}
+ */
+@Backing(type="int")
+@VintfStability
+enum AudioContentType {
+    /**
+     * Content type value to use when the content type is unknown, or other than
+     * the ones defined.
+     */
+    UNKNOWN = 0,
+    /**
+     * Content type value to use when the content type is speech.
+     */
+    SPEECH = 1,
+    /**
+     * Content type value to use when the content type is music.
+     */
+    MUSIC = 2,
+    /**
+     * Content type value to use when the content type is a soundtrack,
+     * typically accompanying a movie or TV program.
+     */
+    MOVIE = 3,
+    /**
+     * Content type value to use when the content type is a sound used to
+     * accompany a user action, such as a beep or sound effect expressing a key
+     * click, or event, such as the type of a sound for a bonus being received
+     * in a game. These sounds are mostly synthesized or short Foley sounds.
+     */
+    SONIFICATION = 4,
+}
diff --git a/media/aidl/android/media/audio/common/AudioEncapsulationMetadataType.aidl b/media/aidl/android/media/audio/common/AudioEncapsulationMetadataType.aidl
new file mode 100644
index 0000000..e0b272c
--- /dev/null
+++ b/media/aidl/android/media/audio/common/AudioEncapsulationMetadataType.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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 android.media.audio.common;
+
+/**
+ * Enumeration of metadata types permitted for use by encapsulation mode audio
+ * streams (see AudioEncapsulationMode). This type corresponds to
+ * AudioTrack.ENCAPSULATION_METADATA_TYPE_* constants in the SDK.
+ *
+ * {@hide}
+ */
+@Backing(type="int")
+@VintfStability
+enum AudioEncapsulationMetadataType {
+    /** Default value. */
+    NONE = 0,
+    /**
+     * Encapsulation metadata type for framework tuner information.
+     */
+    FRAMEWORK_TUNER = 1,
+    /**
+     * Encapsulation metadata type for DVB AD descriptor.
+     *
+     * This metadata is formatted per ETSI TS 101 154 Table E.1: AD_descriptor.
+     */
+    DVB_AD_DESCRIPTOR = 2,
+}
diff --git a/media/aidl/android/media/audio/common/AudioEncapsulationType.aidl b/media/aidl/android/media/audio/common/AudioEncapsulationType.aidl
new file mode 100644
index 0000000..9e80bd6
--- /dev/null
+++ b/media/aidl/android/media/audio/common/AudioEncapsulationType.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.audio.common;
+
+/**
+ * Audio encapsulation type is used to describe if the audio data should be sent
+ * with a particular encapsulation type or not. This enum corresponds to
+ * AudioProfile.AUDIO_ENCAPSULATION_* constants in the SDK.
+ *
+ * {@hide}
+ */
+@Backing(type="int")
+@VintfStability
+enum AudioEncapsulationType {
+    /** No encapsulation type is specified. */
+    NONE = 0,
+    /** Encapsulation used the format defined in the standard IEC 61937. */
+    IEC61937 = 1,
+}
diff --git a/media/aidl/android/media/audio/common/AudioFormatDescription.aidl b/media/aidl/android/media/audio/common/AudioFormatDescription.aidl
index 2aea8dd..57f2bdb 100644
--- a/media/aidl/android/media/audio/common/AudioFormatDescription.aidl
+++ b/media/aidl/android/media/audio/common/AudioFormatDescription.aidl
@@ -33,7 +33,7 @@
  *
  * {@hide}
  */
-@JavaDerive(equals = true, toString = true)
+@JavaDerive(equals=true, toString=true)
 @VintfStability
 parcelable AudioFormatDescription {
     /**
@@ -73,14 +73,6 @@
      *   - Otherwise, "x-" prefix is added, e.g. "audio/x-iec61937".
      *   - All MIME types not found in the IANA formats list have an associated
      *     comment.
-     *
-     * For PCM encapsulations with a known bitstream format, the latter
-     * is added to the encapsulation encoding as a suffix, after a "+" char.
-     * For example, an IEC61937 encapsulation of AC3 has the following
-     * representation:
-     *   type = NON_PCM,
-     *   pcm = PcmType.INT_16_BIT,
-     *   encoding = "audio/x-iec61937+audio/ac3"
      */
     @utf8InCpp String encoding;
 }
diff --git a/media/aidl/android/media/audio/common/AudioMode.aidl b/media/aidl/android/media/audio/common/AudioMode.aidl
new file mode 100644
index 0000000..cc03813
--- /dev/null
+++ b/media/aidl/android/media/audio/common/AudioMode.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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 android.media.audio.common;
+
+/**
+ * Major modes for a mobile device. The current mode setting affects audio
+ * routing.
+ *
+ * {@hide}
+ */
+@Backing(type="int")
+@VintfStability
+enum AudioMode {
+    /**
+     * Used as default value in parcelables to indicate that a value was not
+     * set. Should never be considered a valid setting, except for backward
+     * compatibility scenarios.
+     */
+    SYS_RESERVED_INVALID = -2,
+    /**
+     * Value reserved for system use only. HALs must never return this value to
+     * the system or accept it from the system.
+     */
+    SYS_RESERVED_CURRENT = -1,
+    /** Normal mode (no call in progress). */
+    NORMAL = 0,
+    /** Mobile device is receiving an incoming connection request. */
+    RINGTONE = 1,
+    /** Calls handled by the telephony stack (PSTN). */
+    IN_CALL = 2,
+    /** Calls handled by apps (VoIP). */
+    IN_COMMUNICATION = 3,
+    /** Call screening in progress. */
+    CALL_SCREEN = 4,
+}
diff --git a/media/aidl/android/media/audio/common/AudioOffloadInfo.aidl b/media/aidl/android/media/audio/common/AudioOffloadInfo.aidl
index 46496c3..d8da065 100644
--- a/media/aidl/android/media/audio/common/AudioOffloadInfo.aidl
+++ b/media/aidl/android/media/audio/common/AudioOffloadInfo.aidl
@@ -26,7 +26,7 @@
  *
  * {@hide}
  */
-@JavaDerive(equals = true, toString = true)
+@JavaDerive(equals=true, toString=true)
 @VintfStability
 parcelable AudioOffloadInfo {
     /** Base audio configuration. */
diff --git a/media/aidl/android/media/audio/common/AudioSource.aidl b/media/aidl/android/media/audio/common/AudioSource.aidl
new file mode 100644
index 0000000..527ee39
--- /dev/null
+++ b/media/aidl/android/media/audio/common/AudioSource.aidl
@@ -0,0 +1,90 @@
+/*
+ * 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 android.media.audio.common;
+
+/**
+ * Defines the audio source. An audio source defines both a default physical
+ * source of audio signal, and a recording configuration. This enum corresponds
+ * to MediaRecorder.AudioSource.* constants in the SDK.
+ *
+ * {@hide}
+ */
+@Backing(type="int")
+@VintfStability
+enum AudioSource {
+    /**
+     * Used as default value in parcelables to indicate that a value was not
+     * set. Should never be considered a valid setting, except for backward
+     * compatibility scenarios.
+     */
+    SYS_RESERVED_INVALID = -1,
+    /** Default audio source. */
+    DEFAULT = 0,
+    /** Microphone audio source. */
+    MIC = 1,
+    /** Voice call uplink (Tx) audio source. */
+    VOICE_UPLINK = 2,
+    /** Voice call downlink (Rx) audio source. */
+    VOICE_DOWNLINK = 3,
+    /** Voice call uplink + downlink (duplex) audio source. */
+    VOICE_CALL = 4,
+    /**
+     * Microphone audio source tuned for video recording, with the same
+     * orientation as the camera if available.
+     */
+    CAMCORDER = 5,
+    /** Microphone audio source tuned for voice recognition. */
+    VOICE_RECOGNITION = 6,
+    /**
+     * Microphone audio source tuned for voice communications such as VoIP. It
+     * will for instance take advantage of echo cancellation or automatic gain
+     * control if available.
+     */
+    VOICE_COMMUNICATION = 7,
+    /**
+     * Audio source for a submix of audio streams to be presented remotely. An
+     * application can use this audio source to capture a mix of audio streams
+     * that should be transmitted to a remote receiver such as a Wifi display.
+     * While recording is active, these audio streams are redirected to the
+     * remote submix instead of being played on the device speaker or headset.
+     */
+    REMOTE_SUBMIX = 8,
+    /**
+     * Microphone audio source tuned for unprocessed (raw) sound if available,
+     * behaves like DEFAULT otherwise.
+     */
+    UNPROCESSED = 9,
+    /**
+     * Source for capturing audio meant to be processed in real time and played
+     * back for live performance (e.g karaoke). The capture path will minimize
+     * latency and coupling with playback path.
+     */
+    VOICE_PERFORMANCE = 10,
+    /**
+     * Source for an echo canceller to capture the reference signal to be
+     * canceled. The echo reference signal will be captured as close as
+     * possible to the DAC in order to include all post processing applied to
+     * the playback path.
+     */
+    ECHO_REFERENCE = 1997,
+    /** Audio source for capturing broadcast FM tuner output. */
+    FM_TUNER = 1998,
+    /**
+     * A low-priority, preemptible audio source for for background software
+     * hotword detection. Same tuning as VOICE_RECOGNITION.
+     */
+    HOTWORD = 1999,
+}
diff --git a/media/aidl/android/media/audio/common/AudioStreamType.aidl b/media/aidl/android/media/audio/common/AudioStreamType.aidl
index 1fa3a9c..e7f2961 100644
--- a/media/aidl/android/media/audio/common/AudioStreamType.aidl
+++ b/media/aidl/android/media/audio/common/AudioStreamType.aidl
@@ -37,8 +37,11 @@
      * Indicates that the operation is applied to the "default" stream
      * in this context, e.g. MUSIC in normal device state, or RING if the
      * phone is ringing.
+     *
+     * Value reserved for system use only. HALs must never return this value to
+     * the system or accept it from the system.
      */
-    DEFAULT = -1,
+    SYS_RESERVED_DEFAULT = -1,
     /** Used to identify the volume of audio streams for phone calls. */
     VOICE_CALL = 0,
     /** Used to identify the volume of audio streams for system sounds. */
diff --git a/media/aidl/android/media/audio/common/AudioUuid.aidl b/media/aidl/android/media/audio/common/AudioUuid.aidl
new file mode 100644
index 0000000..f2715ff
--- /dev/null
+++ b/media/aidl/android/media/audio/common/AudioUuid.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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 android.media.audio.common;
+
+/**
+ * Commonly used structure for passing unique identifiers (UUID).
+ * For the definition of UUID, refer to ITU-T X.667 spec.
+ *
+ * {@hide}
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable AudioUuid {
+    int timeLow;
+    int timeMid;
+    int timeHiAndVersion;
+    int clockSeq;
+    byte[] node; // Length = 6
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioContentType.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioContentType.aidl
new file mode 100644
index 0000000..3798b82
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioContentType.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum AudioContentType {
+  UNKNOWN = 0,
+  SPEECH = 1,
+  MUSIC = 2,
+  MOVIE = 3,
+  SONIFICATION = 4,
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioEncapsulationMetadataType.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioEncapsulationMetadataType.aidl
new file mode 100644
index 0000000..0ee0dbb
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioEncapsulationMetadataType.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum AudioEncapsulationMetadataType {
+  NONE = 0,
+  FRAMEWORK_TUNER = 1,
+  DVB_AD_DESCRIPTOR = 2,
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioEncapsulationType.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioEncapsulationType.aidl
new file mode 100644
index 0000000..8a31fc4
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioEncapsulationType.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum AudioEncapsulationType {
+  NONE = 0,
+  IEC61937 = 1,
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioMode.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioMode.aidl
new file mode 100644
index 0000000..8ae1c10
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioMode.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum AudioMode {
+  SYS_RESERVED_INVALID = -2,
+  SYS_RESERVED_CURRENT = -1,
+  NORMAL = 0,
+  RINGTONE = 1,
+  IN_CALL = 2,
+  IN_COMMUNICATION = 3,
+  CALL_SCREEN = 4,
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioSource.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioSource.aidl
new file mode 100644
index 0000000..d1dfe41
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioSource.aidl
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum AudioSource {
+  SYS_RESERVED_INVALID = -1,
+  DEFAULT = 0,
+  MIC = 1,
+  VOICE_UPLINK = 2,
+  VOICE_DOWNLINK = 3,
+  VOICE_CALL = 4,
+  CAMCORDER = 5,
+  VOICE_RECOGNITION = 6,
+  VOICE_COMMUNICATION = 7,
+  REMOTE_SUBMIX = 8,
+  UNPROCESSED = 9,
+  VOICE_PERFORMANCE = 10,
+  ECHO_REFERENCE = 1997,
+  FM_TUNER = 1998,
+  HOTWORD = 1999,
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioStreamType.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioStreamType.aidl
index cbca6c5..bcfd374 100644
--- a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioStreamType.aidl
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioStreamType.aidl
@@ -36,7 +36,7 @@
 @Backing(type="int") @VintfStability
 enum AudioStreamType {
   INVALID = -2,
-  DEFAULT = -1,
+  SYS_RESERVED_DEFAULT = -1,
   VOICE_CALL = 0,
   SYSTEM = 1,
   RING = 2,
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioUuid.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioUuid.aidl
new file mode 100644
index 0000000..af307da
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioUuid.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable AudioUuid {
+  int timeLow;
+  int timeMid;
+  int timeHiAndVersion;
+  int clockSeq;
+  byte[] node;
+}
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index f263c28..54252b5 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -139,26 +139,26 @@
      */
     public final static int USAGE_NOTIFICATION_RINGTONE = 6;
     /**
-     * @deprecated Use {@link #USAGE_NOTIFICATION} which is handled
-     *             the same way as this usage by the audio framework
      * Usage value to use when the usage is a request to enter/end a
      * communication, such as a VoIP communication or video-conference.
+     * @deprecated Use {@link #USAGE_NOTIFICATION} which is handled
+     *             the same way as this usage by the audio framework
      */
     @Deprecated
     public final static int USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7;
     /**
-     * @deprecated Use {@link #USAGE_NOTIFICATION} which is handled
-     *             the same way as this usage by the audio framework
      * Usage value to use when the usage is notification for an "instant"
      * communication such as a chat, or SMS.
+     * @deprecated Use {@link #USAGE_NOTIFICATION} which is handled
+     *             the same way as this usage by the audio framework
      */
     @Deprecated
     public final static int USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8;
     /**
-     * @deprecated Use {@link #USAGE_NOTIFICATION} which is handled
-     *             the same way as this usage by the audio framework
      * Usage value to use when the usage is notification for a
      * non-immediate type of communication such as e-mail.
+     * @deprecated Use {@link #USAGE_NOTIFICATION} which is handled
+     *             the same way as this usage by the audio framework
      */
     @Deprecated
     public final static int USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 31ab09e..91834fb 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -5827,6 +5827,40 @@
         }
     }
 
+    /**
+    * Indicate Le Audio output device connection state change and eventually suppress
+    * the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
+    * @param device Bluetooth device connected/disconnected
+    * @param state new connection state (BluetoothProfile.STATE_xxx)
+    * @param suppressNoisyIntent if true the
+    * {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent.
+    * {@hide}
+    */
+    public void setBluetoothLeAudioOutDeviceConnectionState(BluetoothDevice device, int state,
+            boolean suppressNoisyIntent) {
+        final IAudioService service = getService();
+        try {
+            service.setBluetoothLeAudioOutDeviceConnectionState(device, state, suppressNoisyIntent);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+    * Indicate Le Audio input connection state change.
+    * @param device Bluetooth device connected/disconnected
+    * @param state new connection state (BluetoothProfile.STATE_xxx)
+    * {@hide}
+    */
+    public void setBluetoothLeAudioInDeviceConnectionState(BluetoothDevice device, int state) {
+        final IAudioService service = getService();
+        try {
+            service.setBluetoothLeAudioInDeviceConnectionState(device, state);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
      /**
      * Indicate A2DP source or sink connection state change and eventually suppress
      * the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 115fb74..5891a18 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -577,7 +577,7 @@
     // 3.1. PNG file signature
     private static final byte[] PNG_SIGNATURE = new byte[] {(byte) 0x89, (byte) 0x50, (byte) 0x4e,
             (byte) 0x47, (byte) 0x0d, (byte) 0x0a, (byte) 0x1a, (byte) 0x0a};
-    // See PNG (Portable Network Graphics) Specification, Version 1.2,
+    // See "Extensions to the PNG 1.2 Specification, Version 1.5.0",
     // 3.7. eXIf Exchangeable Image File (Exif) Profile
     private static final byte[] PNG_CHUNK_TYPE_EXIF = new byte[]{(byte) 0x65, (byte) 0x58,
             (byte) 0x49, (byte) 0x66};
@@ -2085,7 +2085,9 @@
      * <p>
      * For WebP format, the Exif data will be stored as an Extended File Format, and it may not be
      * supported for older readers.
-     * </p>
+     * <p>
+     * For PNG format, the Exif data will be stored as an "eXIf" chunk as per
+     * "Extensions to the PNG 1.2 Specification, Version 1.5.0".
      */
     public void saveAttributes() throws IOException {
         if (!isSupportedFormatForSavingAttributes()) {
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 12b06bf..f6eb0d5 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -279,6 +279,11 @@
     void setBluetoothHearingAidDeviceConnectionState(in BluetoothDevice device,
             int state, boolean suppressNoisyIntent, int musicDevice);
 
+    void setBluetoothLeAudioOutDeviceConnectionState(in BluetoothDevice device, int state,
+            boolean suppressNoisyIntent);
+
+    void setBluetoothLeAudioInDeviceConnectionState(in BluetoothDevice device, int state);
+
     void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(in BluetoothDevice device,
             int state, int profile, boolean suppressNoisyIntent, int a2dpVolume);
 
diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java
index 353556d..5259c4f 100644
--- a/media/java/android/media/projection/MediaProjection.java
+++ b/media/java/android/media/projection/MediaProjection.java
@@ -25,6 +25,7 @@
 import android.hardware.display.VirtualDisplay;
 import android.hardware.display.VirtualDisplayConfig;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -50,13 +51,6 @@
     private final Context mContext;
     private final Map<Callback, CallbackRecord> mCallbacks;
 
-    /**
-     * Store the WindowContext in a field. If it is a local variable, and it is garbage collected
-     * during a MediaProjection session, the WindowContainer listener no longer exists.
-     */
-    @Nullable
-    private Context mWindowContext;
-
     /** @hide */
     public MediaProjection(Context context, IMediaProjection impl) {
         mCallbacks = new ArrayMap<Callback, CallbackRecord>();
@@ -107,19 +101,22 @@
     public VirtualDisplay createVirtualDisplay(@NonNull String name,
             int width, int height, int dpi, boolean isSecure, @Nullable Surface surface,
             @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
-        DisplayManager dm = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
         int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR
                 | DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
         if (isSecure) {
             flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
         }
+        Context windowContext = mContext.createWindowContext(mContext.getDisplayNoVerify(),
+                TYPE_APPLICATION, null /* options */);
         final VirtualDisplayConfig.Builder builder = buildMirroredVirtualDisplay(name, width,
-                height, dpi);
+                height, dpi, windowContext.getWindowContextToken());
         builder.setFlags(flags);
         if (surface != null) {
             builder.setSurface(surface);
         }
-        return dm.createVirtualDisplay(this, builder.build(), callback, handler);
+        VirtualDisplay virtualDisplay = createVirtualDisplay(builder.build(), callback, handler,
+                windowContext);
+        return virtualDisplay;
     }
 
     /**
@@ -148,13 +145,17 @@
     public VirtualDisplay createVirtualDisplay(@NonNull String name,
             int width, int height, int dpi, int flags, @Nullable Surface surface,
             @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
+        Context windowContext = mContext.createWindowContext(mContext.getDisplayNoVerify(),
+                TYPE_APPLICATION, null /* options */);
         final VirtualDisplayConfig.Builder builder = buildMirroredVirtualDisplay(name, width,
-                height, dpi);
+                height, dpi, windowContext.getWindowContextToken());
         builder.setFlags(flags);
         if (surface != null) {
             builder.setSurface(surface);
         }
-        return createVirtualDisplay(builder.build(), callback, handler);
+        VirtualDisplay virtualDisplay = createVirtualDisplay(builder.build(), callback, handler,
+                windowContext);
+        return virtualDisplay;
     }
 
     /**
@@ -168,12 +169,10 @@
      * @return a config representing a VirtualDisplay
      */
     private VirtualDisplayConfig.Builder buildMirroredVirtualDisplay(@NonNull String name,
-            int width, int height, int dpi) {
-        mWindowContext = mContext.createWindowContext(mContext.getDisplayNoVerify(),
-                TYPE_APPLICATION, null /* options */);
+            int width, int height, int dpi, IBinder windowContextToken) {
         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
                 height, dpi);
-        builder.setWindowTokenClientToMirror(mWindowContext.getWindowContextToken());
+        builder.setWindowTokenClientToMirror(windowContextToken);
         return builder;
     }
 
@@ -183,20 +182,22 @@
      *
      * @param virtualDisplayConfig The arguments for the virtual display configuration. See
      * {@link VirtualDisplayConfig} for using it.
-     * @param callback Callback to call when the virtual display's state
-     * changes, or null if none.
-     * @param handler The {@link android.os.Handler} on which the callback should be
-     * invoked, or null if the callback should be invoked on the calling
-     * thread's main {@link android.os.Looper}.
+     * @param callback Callback to call when the virtual display's state changes, or null if none.
+     * @param handler The {@link android.os.Handler} on which the callback should be invoked, or
+     *                null if the callback should be invoked on the calling thread's main
+     *                {@link android.os.Looper}.
+     * @param windowContext the WindowContext associated with the caller.
      *
      * @see android.hardware.display.VirtualDisplay
      * @hide
      */
     @Nullable
     public VirtualDisplay createVirtualDisplay(@NonNull VirtualDisplayConfig virtualDisplayConfig,
-            @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
+            @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler,
+            Context windowContext) {
         DisplayManager dm = mContext.getSystemService(DisplayManager.class);
-        return dm.createVirtualDisplay(this, virtualDisplayConfig, callback, handler);
+        return dm.createVirtualDisplay(this, virtualDisplayConfig, callback, handler,
+                windowContext);
     }
 
     /**
diff --git a/mms/OWNERS b/mms/OWNERS
index 7f05a2a..2e419c1 100644
--- a/mms/OWNERS
+++ b/mms/OWNERS
@@ -9,10 +9,10 @@
 jminjie@google.com
 satk@google.com
 shuoq@google.com
-nazaninb@google.com
 sarahchin@google.com
 xiaotonj@google.com
 huiwang@google.com
 jayachandranc@google.com
 chinmayd@google.com
 amruthr@google.com
+sasindran@google.com
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index 693a027..7f74dd4 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -146,28 +146,24 @@
     uint64_t frameNumber;
 };
 
-void ASurfaceControl_registerSurfaceStatsListener(ASurfaceControl* control, void* context,
-        ASurfaceControl_SurfaceStatsListener func) {
-    SurfaceStatsCallback callback = [func](void* callback_context,
-                                                               nsecs_t,
-                                                               const sp<Fence>&,
-                                                               const SurfaceStats& surfaceStats) {
-
+void ASurfaceControl_registerSurfaceStatsListener(ASurfaceControl* control, int32_t id,
+                                                  void* context,
+                                                  ASurfaceControl_SurfaceStatsListener func) {
+    SurfaceStatsCallback callback = [func, id](void* callback_context, nsecs_t, const sp<Fence>&,
+                                               const SurfaceStats& surfaceStats) {
         ASurfaceControlStats aSurfaceControlStats;
 
-        ASurfaceControl* aSurfaceControl =
-                reinterpret_cast<ASurfaceControl*>(surfaceStats.surfaceControl.get());
         aSurfaceControlStats.acquireTime = surfaceStats.acquireTime;
         aSurfaceControlStats.previousReleaseFence = surfaceStats.previousReleaseFence;
         aSurfaceControlStats.frameNumber = surfaceStats.eventStats.frameNumber;
 
-        (*func)(callback_context, aSurfaceControl, &aSurfaceControlStats);
+        (*func)(callback_context, id, &aSurfaceControlStats);
     };
+
     TransactionCompletedListener::getInstance()->addSurfaceStatsListener(context,
             reinterpret_cast<void*>(func), ASurfaceControl_to_SurfaceControl(control), callback);
 }
 
-
 void ASurfaceControl_unregisterSurfaceStatsListener(void* context,
         ASurfaceControl_SurfaceStatsListener func) {
     TransactionCompletedListener::getInstance()->removeSurfaceStatsListener(context,
@@ -662,4 +658,4 @@
     Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
 
     transaction->addTransactionCommittedCallback(callback, context);
-}
\ No newline at end of file
+}
diff --git a/packages/CarrierDefaultApp/OWNERS b/packages/CarrierDefaultApp/OWNERS
index 0d23f05..a2352e2 100644
--- a/packages/CarrierDefaultApp/OWNERS
+++ b/packages/CarrierDefaultApp/OWNERS
@@ -8,11 +8,11 @@
 jminjie@google.com
 satk@google.com
 shuoq@google.com
-nazaninb@google.com
 sarahchin@google.com
 xiaotonj@google.com
 huiwang@google.com
 jayachandranc@google.com
 chinmayd@google.com
 amruthr@google.com
+sasindran@google.com
 
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java
index 5f107d6..34e7e3d 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java
@@ -84,8 +84,7 @@
      */
     public MDNSFilterPlugin(@NonNull Context context, @NonNull String name,
             @NonNull CharSequence packageName, @NonNull List<String> mDNSNames) {
-        mName = context.getResources().getIdentifier(name, null,
-                "com.android.printservice.recommendation");
+        mName = context.getResources().getIdentifier(name, null, context.getPackageName());
         mPackageName = packageName;
         mMDNSFilteredDiscovery = new MDNSFilteredDiscovery(context, PRINTER_SERVICE_TYPES,
                 new VendorNameFilter(new HashSet<>(mDNSNames)));
diff --git a/packages/SettingsLib/res/layout/preference_widget_primary_switch.xml b/packages/SettingsLib/res/layout/preference_widget_primary_switch.xml
new file mode 100644
index 0000000..5de268d
--- /dev/null
+++ b/packages/SettingsLib/res/layout/preference_widget_primary_switch.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<Switch
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/switchWidget"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:minWidth="@dimen/two_target_min_width"
+    android:gravity="center_vertical"
+    android:clickable="false" />
\ No newline at end of file
diff --git a/packages/SettingsLib/res/layout/restricted_preference_widget_primary_switch.xml b/packages/SettingsLib/res/layout/restricted_preference_widget_primary_switch.xml
new file mode 100644
index 0000000..69df751
--- /dev/null
+++ b/packages/SettingsLib/res/layout/restricted_preference_widget_primary_switch.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <include layout="@layout/restricted_icon"/>
+
+    <include layout="@layout/preference_widget_primary_switch"/>
+</merge>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 2dba96a..7b4c9b6 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -23,7 +23,7 @@
   <string-array name="wifi_status">
     <item msgid="1596683495752107015"></item>
     <item msgid="3288373008277313483">"Memindai..."</item>
-    <item msgid="6050951078202663628">"Menyambung…"</item>
+    <item msgid="6050951078202663628">"Menghubungkan…"</item>
     <item msgid="8356618438494652335">"Mengautentikasi…"</item>
     <item msgid="2837871868181677206">"Mendapatkan alamat IP…"</item>
     <item msgid="4613015005934755724">"Terhubung"</item>
@@ -37,7 +37,7 @@
   <string-array name="wifi_status_with_ssid">
     <item msgid="5969842512724979061"></item>
     <item msgid="1818677602615822316">"Memindai..."</item>
-    <item msgid="8339720953594087771">"Menyambung ke <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
+    <item msgid="8339720953594087771">"Menghubungkan ke <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
     <item msgid="3028983857109369308">"Mengautentikasi dengan <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
     <item msgid="4287401332778341890">"Mendapatkan alamat IP dari <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
     <item msgid="1043944043827424501">"Terhubung ke <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 89101be..9eacc6c 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -53,21 +53,21 @@
     <string name="wifi_disconnected" msgid="7054450256284661757">"Terputus"</string>
     <string name="wifi_disabled_generic" msgid="2651916945380294607">"Nonaktif"</string>
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Kegagalan Konfigurasi IP"</string>
-    <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Tidak tersambung karena jaringan berkualitas rendah"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Tidak terhubung karena jaringan berkualitas rendah"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Kegagalan Sambungan Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Masalah autentikasi"</string>
-    <string name="wifi_cant_connect" msgid="5718417542623056783">"Tidak dapat tersambung"</string>
-    <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Tidak dapat tersambung ke \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string>
+    <string name="wifi_cant_connect" msgid="5718417542623056783">"Tidak dapat terhubung"</string>
+    <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Tidak dapat terhubung ke \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Periksa sandi dan coba lagi"</string>
     <string name="wifi_not_in_range" msgid="1541760821805777772">"Tidak dalam jangkauan"</string>
-    <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"Tidak akan tersambung otomatis"</string>
+    <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"Tidak akan terhubung otomatis"</string>
     <string name="wifi_no_internet" msgid="1774198889176926299">"Tidak ada akses internet"</string>
     <string name="saved_network" msgid="7143698034077223645">"Disimpan oleh <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_to_metered_access_point" msgid="9179693207918156341">"Terhubung ke jaringan berbayar"</string>
-    <string name="connected_via_network_scorer" msgid="7665725527352893558">"Tersambung otomatis melalui %1$s"</string>
-    <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"Otomatis tersambung melalui penyedia rating jaringan"</string>
+    <string name="connected_via_network_scorer" msgid="7665725527352893558">"Terhubung otomatis melalui %1$s"</string>
+    <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"Otomatis terhubung melalui penyedia rating jaringan"</string>
     <string name="connected_via_passpoint" msgid="7735442932429075684">"Terhubung melalui %1$s"</string>
-    <string name="connected_via_app" msgid="3532267661404276584">"Tersambung melalui <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="connected_via_app" msgid="3532267661404276584">"Terhubung melalui <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="available_via_passpoint" msgid="1716000261192603682">"Tersedia melalui %1$s"</string>
     <string name="tap_to_sign_up" msgid="5356397741063740395">"Ketuk untuk mendaftar"</string>
     <string name="wifi_connected_no_internet" msgid="5087420713443350646">"Tidak ada internet"</string>
@@ -76,10 +76,10 @@
     <string name="wifi_status_no_internet" msgid="3799933875988829048">"Tidak ada internet"</string>
     <string name="wifi_status_sign_in_required" msgid="2236267500459526855">"Perlu login"</string>
     <string name="wifi_ap_unable_to_handle_new_sta" msgid="5885145407184194503">"Titik akses penuh untuk sementara"</string>
-    <string name="connected_via_carrier" msgid="1968057009076191514">"Tersambung melalui %1$s"</string>
+    <string name="connected_via_carrier" msgid="1968057009076191514">"Terhubung melalui %1$s"</string>
     <string name="available_via_carrier" msgid="465598683092718294">"Tersedia melalui %1$s"</string>
     <string name="osu_opening_provider" msgid="4318105381295178285">"Membuka <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string>
-    <string name="osu_connect_failed" msgid="9107873364807159193">"Tidak dapat tersambung"</string>
+    <string name="osu_connect_failed" msgid="9107873364807159193">"Tidak dapat terhubung"</string>
     <string name="osu_completing_sign_up" msgid="8412636665040390901">"Menyelesaikan pendaftaran…"</string>
     <string name="osu_sign_up_failed" msgid="5605453599586001793">"Tidak dapat menyelesaikan pendaftaran. Ketuk untuk mencoba lagi."</string>
     <string name="osu_sign_up_complete" msgid="7640183358878916847">"Pendaftaran selesai. Menyambungkan…"</string>
@@ -93,7 +93,7 @@
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Sambungan terputus"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Memutus sambungan..."</string>
-    <string name="bluetooth_connecting" msgid="5871702668260192755">"Menyambung…"</string>
+    <string name="bluetooth_connecting" msgid="5871702668260192755">"Menghubungkan…"</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"Terhubung<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="4269046942588193600">"Menyandingkan..."</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Terhubung (tanpa ponsel)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -123,12 +123,12 @@
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"Audio HD"</string>
     <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"Alat Bantu Dengar"</string>
     <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"Terhubung ke Alat Bantu Dengar"</string>
-    <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Tersambung ke media audio"</string>
-    <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Tersambung ke audio ponsel"</string>
+    <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"Terhubung ke media audio"</string>
+    <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"Terhubung ke audio ponsel"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"Sambungkan ke server transfer file"</string>
-    <string name="bluetooth_map_profile_summary_connected" msgid="4141725591784669181">"Tersambung ke peta"</string>
+    <string name="bluetooth_map_profile_summary_connected" msgid="4141725591784669181">"Terhubung ke peta"</string>
     <string name="bluetooth_sap_profile_summary_connected" msgid="1280297388033001037">"Terhubung ke SAP"</string>
-    <string name="bluetooth_opp_profile_summary_not_connected" msgid="3959741824627764954">"Tidak tersambung kepada server transfer file"</string>
+    <string name="bluetooth_opp_profile_summary_not_connected" msgid="3959741824627764954">"Tidak terhubung kepada server transfer file"</string>
     <string name="bluetooth_hid_profile_summary_connected" msgid="3923653977051684833">"Terhubung ke perangkat masukan"</string>
     <string name="bluetooth_pan_user_profile_summary_connected" msgid="380469653827505727">"Terhubung ke perangkat untuk akses internet"</string>
     <string name="bluetooth_pan_nap_profile_summary_connected" msgid="3744773111299503493">"Berbagi koneksi internet lokal dengan perangkat"</string>
@@ -143,7 +143,7 @@
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Sambungkan"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"SAMBUNGKAN"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Batal"</string>
-    <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Penyandingan memberi akses ke kontak dan histori panggilan saat tersambung"</string>
+    <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Penyandingan memberi akses ke kontak dan histori panggilan saat terhubung"</string>
     <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Tidak dapat menyambungkan ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Tidak dapat menyambungkan ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g> karena PIN atau kode sandi salah."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Tidak dapat berkomunikasi dengan <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
@@ -160,7 +160,7 @@
     <string name="bluetooth_hearingaid_left_battery_level" msgid="7375621694748104876">"Kiri - baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_hearingaid_right_battery_level" msgid="1850094448499089312">"Kanan - baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi tidak aktif."</string>
-    <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi tidak tersambung."</string>
+    <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi tidak terhubung."</string>
     <string name="accessibility_wifi_one_bar" msgid="6025652717281815212">"Wi-Fi satu baris."</string>
     <string name="accessibility_wifi_two_bars" msgid="687800024970972270">"Wi-Fi dua baris"</string>
     <string name="accessibility_wifi_three_bars" msgid="779895671061950234">"Wi-Fi tiga baris."</string>
@@ -232,7 +232,7 @@
     <string name="tethering_settings_not_available" msgid="266821736434699780">"Setelan Penambatan tidak tersedia untuk pengguna ini"</string>
     <string name="apn_settings_not_available" msgid="1147111671403342300">"Setelan Nama Titik Akses tidak tersedia untuk pengguna ini"</string>
     <string name="enable_adb" msgid="8072776357237289039">"Debugging USB"</string>
-    <string name="enable_adb_summary" msgid="3711526030096574316">"Mode debug ketika USB tersambung"</string>
+    <string name="enable_adb_summary" msgid="3711526030096574316">"Mode debug ketika USB terhubung"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Cabut otorisasi debug USB"</string>
     <string name="enable_adb_wireless" msgid="6973226350963971018">"Proses debug nirkabel"</string>
     <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Mode debug saat Wi-Fi terhubung"</string>
@@ -244,19 +244,19 @@
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Sambungkan perangkat dengan kode penyambungan"</string>
     <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Sambungkan perangkat baru menggunakan kode enam digit"</string>
     <string name="adb_paired_devices_title" msgid="5268997341526217362">"Perangkat disambungkan"</string>
-    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Saat ini tersambung"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Saat ini terhubung"</string>
     <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Detail perangkat"</string>
     <string name="adb_device_forget" msgid="193072400783068417">"Lupakan"</string>
     <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Sidik jari perangkat: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
     <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Sambungan gagal"</string>
-    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Pastikan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> tersambung ke jaringan yang tepat"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Pastikan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> terhubung ke jaringan yang tepat"</string>
     <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Sambungkan dengan perangkat"</string>
     <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Kode penyambungan Wi-Fi"</string>
     <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Penyambungan perangkat gagal"</string>
     <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Pastikan perangkat terhubung ke jaringan yang sama."</string>
     <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Sambungkan perangkat melalui Wi‑Fi dengan memindai Kode QR"</string>
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Menyambungkan perangkat…"</string>
-    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Gagal menyambungkan perangkat. Kode QR salah, atau perangkat tidak tersambung ke jaringan yang sama."</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Gagal menyambungkan perangkat. Kode QR salah, atau perangkat tidak terhubung ke jaringan yang sama."</string>
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Alamat IP &amp; Port"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Memindai kode QR"</string>
     <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Sambungkan perangkat melalui Wi‑Fi dengan memindai Kode QR"</string>
@@ -362,7 +362,7 @@
     <string name="pointer_location" msgid="7516929526199520173">"Lokasi penunjuk"</string>
     <string name="pointer_location_summary" msgid="957120116989798464">"Hamparan layar menampilkan data sentuhan saat ini"</string>
     <string name="show_touches" msgid="8437666942161289025">"Tampilkan ketukan"</string>
-    <string name="show_touches_summary" msgid="3692861665994502193">"Tampilkan masukan untuk ketukan"</string>
+    <string name="show_touches_summary" msgid="3692861665994502193">"Tampilkan efek visual untuk ketukan"</string>
     <string name="show_screen_updates" msgid="2078782895825535494">"Lihat pembaruan permukaan"</string>
     <string name="show_screen_updates_summary" msgid="2126932969682087406">"Sorot seluruh permukaan jendela saat diperbarui"</string>
     <string name="show_hw_screen_updates" msgid="2021286231267747506">"Tampilkan update tampilan"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 20c5edb..421a428 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -116,7 +116,7 @@
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"ఇంటర్నెట్ యాక్సెస్"</string>
     <string name="bluetooth_profile_pbap" msgid="7064307749579335765">"కాంటాక్ట్ షేరింగ్"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="2955819694801952056">"కాంటాక్ట్ షేరింగ్ కోసం ఉపయోగించండి"</string>
-    <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ఇంటర్నెట్ కనెక్షన్ భాగస్వామ్యం"</string>
+    <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ఇంటర్నెట్ కనెక్షన్ షేరింగ్"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"వచన మెసేజ్‌లు"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM యాక్సెస్"</string>
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD ఆడియో: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/PrimarySwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/PrimarySwitchPreference.java
new file mode 100644
index 0000000..246fc8dd
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/PrimarySwitchPreference.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Switch;
+
+import androidx.annotation.Keep;
+import androidx.annotation.Nullable;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+/**
+ * A custom preference that provides inline switch toggle. It has a mandatory field for title, and
+ * optional fields for icon and sub-text. And it can be restricted by admin state.
+ */
+public class PrimarySwitchPreference extends RestrictedPreference {
+
+    private Switch mSwitch;
+    private boolean mChecked;
+    private boolean mCheckedSet;
+    private boolean mEnableSwitch = true;
+
+    public PrimarySwitchPreference(Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    public PrimarySwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public PrimarySwitchPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public PrimarySwitchPreference(Context context) {
+        super(context);
+    }
+
+    @Override
+    protected int getSecondTargetResId() {
+        return R.layout.restricted_preference_widget_primary_switch;
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        final View switchWidget = holder.findViewById(R.id.switchWidget);
+        if (switchWidget != null) {
+            switchWidget.setVisibility(isDisabledByAdmin() ? View.GONE : View.VISIBLE);
+            switchWidget.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    if (mSwitch != null && !mSwitch.isEnabled()) {
+                        return;
+                    }
+                    setChecked(!mChecked);
+                    if (!callChangeListener(mChecked)) {
+                        setChecked(!mChecked);
+                    } else {
+                        persistBoolean(mChecked);
+                    }
+                }
+            });
+
+            // Consumes move events to ignore drag actions.
+            switchWidget.setOnTouchListener((v, event) -> {
+                return event.getActionMasked() == MotionEvent.ACTION_MOVE;
+            });
+        }
+
+        mSwitch = (Switch) holder.findViewById(R.id.switchWidget);
+        if (mSwitch != null) {
+            mSwitch.setContentDescription(getTitle());
+            mSwitch.setChecked(mChecked);
+            mSwitch.setEnabled(mEnableSwitch);
+        }
+    }
+
+    public boolean isChecked() {
+        return mSwitch != null && mChecked;
+    }
+
+    /**
+     * Used to validate the state of mChecked and mCheckedSet when testing, without requiring
+     * that a ViewHolder be bound to the object.
+     */
+    @Keep
+    @Nullable
+    public Boolean getCheckedState() {
+        return mCheckedSet ? mChecked : null;
+    }
+
+    /**
+     * Set the checked status to be {@code checked}.
+     *
+     * @param checked The new checked status
+     */
+    public void setChecked(boolean checked) {
+        // Always set checked the first time; don't assume the field's default of false.
+        final boolean changed = mChecked != checked;
+        if (changed || !mCheckedSet) {
+            mChecked = checked;
+            mCheckedSet = true;
+            if (mSwitch != null) {
+                mSwitch.setChecked(checked);
+            }
+        }
+    }
+
+    /**
+     * Set the Switch to be the status of {@code enabled}.
+     *
+     * @param enabled The new enabled status
+     */
+    public void setSwitchEnabled(boolean enabled) {
+        mEnableSwitch = enabled;
+        if (mSwitch != null) {
+            mSwitch.setEnabled(enabled);
+        }
+    }
+
+    /**
+     * If admin is not null, disables the switch.
+     * Otherwise, keep it enabled.
+     */
+    public void setDisabledByAdmin(EnforcedAdmin admin) {
+        super.setDisabledByAdmin(admin);
+        setSwitchEnabled(admin == null);
+    }
+
+    public Switch getSwitch() {
+        return mSwitch;
+    }
+
+    @Override
+    protected boolean shouldHideSecondTarget() {
+        return getSecondTargetResId() == 0;
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 63cb381..c47ce41 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -101,6 +101,7 @@
     private PbapServerProfile mPbapProfile;
     private HearingAidProfile mHearingAidProfile;
     private SapProfile mSapProfile;
+    private VolumeControlProfile mVolumeControlProfile;
 
     /**
      * Mapping from profile name, e.g. "HEADSET" to profile object.
@@ -220,6 +221,16 @@
             mSapProfile = new SapProfile(mContext, mDeviceManager, this);
             addProfile(mSapProfile, SapProfile.NAME, BluetoothSap.ACTION_CONNECTION_STATE_CHANGED);
         }
+        if (mVolumeControlProfile == null
+                && supportedList.contains(BluetoothProfile.VOLUME_CONTROL)) {
+            if (DEBUG) {
+                Log.d(TAG, "Adding local Volume Control profile");
+            }
+            mVolumeControlProfile = new VolumeControlProfile();
+            // Note: no event handler for VCP, only for being connectable.
+            mProfileNameMap.put(VolumeControlProfile.NAME, mVolumeControlProfile);
+        }
+
         mEventManager.registerProfileIntentReceiver();
     }
 
@@ -569,6 +580,12 @@
             removedProfiles.remove(mSapProfile);
         }
 
+        if (mVolumeControlProfile != null
+                && ArrayUtils.contains(uuids, BluetoothUuid.VOLUME_CONTROL)) {
+            profiles.add(mVolumeControlProfile);
+            removedProfiles.remove(mVolumeControlProfile);
+        }
+
         if (DEBUG) {
             Log.d(TAG,"New Profiles" + profiles.toString());
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/VolumeControlProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/VolumeControlProfile.java
new file mode 100644
index 0000000..511df28
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/VolumeControlProfile.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+
+/**
+ * VolumeControlProfile handles Bluetooth Volume Control Controller role
+ */
+public class VolumeControlProfile implements LocalBluetoothProfile {
+    private static final String TAG = "VolumeControlProfile";
+    static final String NAME = "VCP";
+    // Order of this profile in device profiles list
+    private static final int ORDINAL = 23;
+
+    @Override
+    public boolean accessProfileEnabled() {
+        return false;
+    }
+
+    @Override
+    public boolean isAutoConnectable() {
+        return true;
+    }
+
+    @Override
+    public int getConnectionStatus(BluetoothDevice device) {
+        return BluetoothProfile.STATE_DISCONNECTED; // Settings app doesn't handle VCP
+    }
+
+    @Override
+    public boolean isEnabled(BluetoothDevice device) {
+        return false;
+    }
+
+    @Override
+    public int getConnectionPolicy(BluetoothDevice device) {
+        return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; // Settings app doesn't handle VCP
+    }
+
+    @Override
+    public boolean setEnabled(BluetoothDevice device, boolean enabled) {
+        return false;
+    }
+
+    @Override
+    public boolean isProfileReady() {
+        return true;
+    }
+
+    @Override
+    public int getProfileId() {
+        return BluetoothProfile.VOLUME_CONTROL;
+    }
+
+    public String toString() {
+        return NAME;
+    }
+
+    @Override
+    public int getOrdinal() {
+        return ORDINAL;
+    }
+
+    @Override
+    public int getNameResource(BluetoothDevice device) {
+        return 0; // VCP profile not displayed in UI
+    }
+
+    @Override
+    public int getSummaryResourceForDevice(BluetoothDevice device) {
+        return 0;   // VCP profile not displayed in UI
+    }
+
+    @Override
+    public int getDrawableResource(BluetoothClass btClass) {
+        // no icon for VCP
+        return 0;
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java
index b7549ec..1d433e7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java
@@ -90,6 +90,10 @@
             macAddress = macAddresses[0];
         }
 
+        if (mWifiMacAddress == null) {
+            return;
+        }
+
         if (TextUtils.isEmpty(macAddress) || macAddress.equals(WifiInfo.DEFAULT_MAC_ADDRESS)) {
             mWifiMacAddress.setSummary(R.string.status_unavailable);
         } else {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/PrimarySwitchPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/PrimarySwitchPreferenceTest.java
new file mode 100644
index 0000000..4e2b63b
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/PrimarySwitchPreferenceTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.widget.LinearLayout;
+import android.widget.Switch;
+
+import androidx.preference.Preference.OnPreferenceChangeListener;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class PrimarySwitchPreferenceTest {
+
+    private Context mContext;
+    private PrimarySwitchPreference mPreference;
+    private PreferenceViewHolder mHolder;
+    private LinearLayout mWidgetView;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mPreference = new PrimarySwitchPreference(mContext);
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        mHolder = PreferenceViewHolder.createInstanceForTests(inflater.inflate(
+                com.android.settingslib.R.layout.preference_two_target, null));
+        mWidgetView = mHolder.itemView.findViewById(android.R.id.widget_frame);
+        inflater.inflate(R.layout.restricted_preference_widget_primary_switch, mWidgetView, true);
+    }
+
+    @Test
+    public void createNewPreference_shouldSetLayout() {
+        assertThat(mPreference.getWidgetLayoutResource())
+                .isEqualTo(R.layout.restricted_preference_widget_primary_switch);
+    }
+
+    @Test
+    public void setChecked_shouldUpdateButtonCheckedState() {
+        final Switch toggle = (Switch) mHolder.findViewById(R.id.switchWidget);
+        mPreference.onBindViewHolder(mHolder);
+
+        mPreference.setChecked(true);
+        assertThat(toggle.isChecked()).isTrue();
+
+        mPreference.setChecked(false);
+        assertThat(toggle.isChecked()).isFalse();
+    }
+
+    @Test
+    public void setSwitchEnabled_shouldUpdateButtonEnabledState() {
+        final Switch toggle = (Switch) mHolder.findViewById(R.id.switchWidget);
+        mPreference.onBindViewHolder(mHolder);
+
+        mPreference.setSwitchEnabled(true);
+        assertThat(toggle.isEnabled()).isTrue();
+
+        mPreference.setSwitchEnabled(false);
+        assertThat(toggle.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void setSwitchEnabled_shouldUpdateButtonEnabledState_beforeViewBound() {
+        final Switch toggle = (Switch) mHolder.findViewById(R.id.switchWidget);
+
+        mPreference.setSwitchEnabled(false);
+        mPreference.onBindViewHolder(mHolder);
+        assertThat(toggle.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void clickWidgetView_shouldToggleButton() {
+        assertThat(mWidgetView).isNotNull();
+
+        final Switch toggle = (Switch) mHolder.findViewById(R.id.switchWidget);
+        mPreference.onBindViewHolder(mHolder);
+
+        toggle.performClick();
+        assertThat(toggle.isChecked()).isTrue();
+
+        toggle.performClick();
+        assertThat(toggle.isChecked()).isFalse();
+    }
+
+    @Test
+    public void clickWidgetView_shouldNotToggleButtonIfDisabled() {
+        assertThat(mWidgetView).isNotNull();
+
+        final Switch toggle = (Switch) mHolder.findViewById(R.id.switchWidget);
+        mPreference.onBindViewHolder(mHolder);
+        toggle.setEnabled(false);
+
+        mWidgetView.performClick();
+        assertThat(toggle.isChecked()).isFalse();
+    }
+
+    @Test
+    public void clickWidgetView_shouldNotifyPreferenceChanged() {
+
+        final Switch toggle = (Switch) mHolder.findViewById(R.id.switchWidget);
+
+        final OnPreferenceChangeListener listener = mock(OnPreferenceChangeListener.class);
+        mPreference.setOnPreferenceChangeListener(listener);
+        mPreference.onBindViewHolder(mHolder);
+
+        mPreference.setChecked(false);
+        toggle.performClick();
+        verify(listener).onPreferenceChange(mPreference, true);
+
+        mPreference.setChecked(true);
+        toggle.performClick();
+        verify(listener).onPreferenceChange(mPreference, false);
+    }
+
+    @Test
+    public void setDisabledByAdmin_hasEnforcedAdmin_shouldDisableButton() {
+        final Switch toggle = (Switch) mHolder.findViewById(R.id.switchWidget);
+        toggle.setEnabled(true);
+        mPreference.onBindViewHolder(mHolder);
+
+        mPreference.setDisabledByAdmin(mock(EnforcedAdmin.class));
+        assertThat(toggle.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void setDisabledByAdmin_noEnforcedAdmin_shouldEnableButton() {
+        final Switch toggle = (Switch) mHolder.findViewById(R.id.switchWidget);
+        toggle.setEnabled(false);
+        mPreference.onBindViewHolder(mHolder);
+
+        mPreference.setDisabledByAdmin(null);
+        assertThat(toggle.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void onBindViewHolder_toggleButtonShouldHaveContentDescription() {
+        final Switch toggle = (Switch) mHolder.findViewById(R.id.switchWidget);
+        final String label = "TestButton";
+        mPreference.setTitle(label);
+
+        mPreference.onBindViewHolder(mHolder);
+
+        assertThat(toggle.getContentDescription()).isEqualTo(label);
+    }
+}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
index 80b7e10..6f42d59 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
@@ -81,6 +81,9 @@
         Settings.Global.POWER_BUTTON_LONG_PRESS,
         Settings.Global.AUTOMATIC_POWER_SAVE_MODE,
         Settings.Global.ADVANCED_BATTERY_USAGE_AMOUNT,
-        Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS
+        Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS,
+        Settings.Global.USER_PREFERRED_REFRESH_RATE,
+        Settings.Global.USER_PREFERRED_RESOLUTION_HEIGHT,
+        Settings.Global.USER_PREFERRED_RESOLUTION_WIDTH,
     };
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index 0a75eb8..93f900d 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -21,6 +21,7 @@
 import static android.provider.settings.validators.SettingsValidators.ANY_STRING_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.BOOLEAN_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.NONE_NEGATIVE_LONG_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.NON_NEGATIVE_FLOAT_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.PERCENTAGE_INTEGER_VALIDATOR;
@@ -321,6 +322,9 @@
         VALIDATORS.put(Global.Wearable.COMBINED_LOCATION_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Global.Wearable.WRIST_ORIENTATION_MODE,
                        new DiscreteValueValidator(new String[] {"0", "1", "2", "3"}));
+        VALIDATORS.put(Global.USER_PREFERRED_REFRESH_RATE, NON_NEGATIVE_FLOAT_VALIDATOR);
+        VALIDATORS.put(Global.USER_PREFERRED_RESOLUTION_HEIGHT, ANY_INTEGER_VALIDATOR);
+        VALIDATORS.put(Global.USER_PREFERRED_RESOLUTION_WIDTH, ANY_INTEGER_VALIDATOR);
     }
 }
 
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java
index 223cc51..49012b0 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java
@@ -74,6 +74,20 @@
         }
     };
 
+    public static final Validator NON_NEGATIVE_FLOAT_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(@Nullable String value) {
+            if (value == null) {
+                return true;
+            }
+            try {
+                return Float.parseFloat(value) >= 0.0f;
+            } catch (NumberFormatException e) {
+                return false;
+            }
+        }
+    };
+
     public static final Validator URI_VALIDATOR = new Validator() {
         @Override
         public boolean validate(@Nullable String value) {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index a4b4680..eb0bb77 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -657,10 +657,6 @@
         </service>
 
         <service
-            android:name=".communal.service.CommunalService"
-            android:exported="@bool/config_communalServiceEnabled"/>
-
-        <service
             android:name=".keyguard.KeyguardService"
             android:exported="true" />
 
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
index 3cbe435..9c1e129 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -482,7 +482,7 @@
             val endRadius = if (isExpandingFullyAbove) {
                 // Most of the time, expanding fully above the root view means expanding in full
                 // screen.
-                ScreenDecorationsUtils.getWindowCornerRadius(context.resources)
+                ScreenDecorationsUtils.getWindowCornerRadius(context)
             } else {
                 // This usually means we are in split screen mode, so 2 out of 4 corners will have
                 // a radius of 0.
diff --git a/packages/SystemUI/docs/broadcasts.md b/packages/SystemUI/docs/broadcasts.md
index e709278..e75ae29 100644
--- a/packages/SystemUI/docs/broadcasts.md
+++ b/packages/SystemUI/docs/broadcasts.md
@@ -27,6 +27,7 @@
 * Subscriptions can be done in any thread.
 * Broadcasts will be dispatched on the main thread (same as `system_server`) by default but a `Handler` can be specified for dispatching
 * A `UserHandle` can be provided to filter the broadcasts by user.
+* Flags (see [`Context#RegisterReceiverFlags`](/core/java/android/content/Context.java)) can be passed for the registration. By default, this will be `Context#RECEIVER_EXPORTED`.
 
 If introducing a new `BroadcastReceiver` (not declared in `AndroidManifest`) that satisfies the constraints above, use the dispatcher to reduce the load on `system_server`.
 
@@ -63,6 +64,8 @@
  *                 executor in the main thread (default).
  * @param user A user handle to determine which broadcast should be dispatched to this receiver.
  *             Pass `null` to use the user of the context (system user in SystemUI).
+ * @param flags Flags to use when registering the receiver. [Context.RECEIVER_EXPORTED] by
+ *              default.             
  * @throws IllegalArgumentException if the filter has other constraints that are not actions or
  *                                  categories or the filter has no actions.
  */
@@ -71,7 +74,8 @@
     receiver: BroadcastReceiver,
     filter: IntentFilter,
     executor: Executor? = null,
-    user: UserHandle? = null
+    user: UserHandle? = null,
+    @Context.RegisterReceiverFlags flags: Int = Context.RECEIVER_EXPORTED
 )
 ```
 
diff --git a/packages/SystemUI/res/color/prv_color_surface.xml b/packages/SystemUI/res/color/prv_color_surface.xml
new file mode 100644
index 0000000..b9d016c
--- /dev/null
+++ b/packages/SystemUI/res/color/prv_color_surface.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<selector xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+          xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?androidprv:attr/colorSurface" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/prv_text_color_on_accent.xml b/packages/SystemUI/res/color/prv_text_color_on_accent.xml
new file mode 100644
index 0000000..9f44aca
--- /dev/null
+++ b/packages/SystemUI/res/color/prv_text_color_on_accent.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<selector xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+          xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?androidprv:attr/textColorOnAccent" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_media_home_devices.xml b/packages/SystemUI/res/drawable/ic_media_home_devices.xml
new file mode 100644
index 0000000..886c64d9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_media_home_devices.xml
@@ -0,0 +1,16 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24"
+    android:tint="?attr/colorControlNormal">
+  <path
+      android:fillColor="@android:color/white"
+      android:pathData="M20,4H4c-1.1,0 -2,0.9 -2,2v11c0,1.1 0.9,2 2,2h4v2h3v-4H4V6h16v1h2V6c0,-1.1 -0.9,-2 -2,-2z"/>
+  <path
+      android:fillColor="@android:color/white"
+      android:pathData="M17.5,16.5m-2.33,0a2.33,2.33 0,1 1,4.66 0a2.33,2.33 0,1 1,-4.66 0"/>
+  <path
+      android:fillColor="@android:color/white"
+      android:pathData="M21,8h-7c-0.55,0 -1,0.45 -1,1v11c0,0.55 0.45,1 1,1h7c0.55,0 1,-0.45 1,-1L22,9c0,-0.55 -0.45,-1 -1,-1zM17.5,9c0.83,0 1.5,0.67 1.5,1.5s-0.67,1.5 -1.5,1.5 -1.5,-0.67 -1.5,-1.5 0.67,-1.5 1.5,-1.5zM17.5,20c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/qs_dialog_btn_filled.xml b/packages/SystemUI/res/drawable/qs_dialog_btn_filled.xml
new file mode 100644
index 0000000..1a128df
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_dialog_btn_filled.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+       xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+       android:insetTop="@dimen/qs_dialog_button_vertical_inset"
+       android:insetBottom="@dimen/qs_dialog_button_vertical_inset">
+    <ripple android:color="?android:attr/colorControlHighlight">
+        <item android:id="@android:id/mask">
+            <shape android:shape="rectangle">
+                <solid android:color="@android:color/white"/>
+                <corners android:radius="?android:attr/buttonCornerRadius"/>
+            </shape>
+        </item>
+        <item>
+            <shape android:shape="rectangle">
+                <corners android:radius="?android:attr/buttonCornerRadius"/>
+                <solid android:color="?androidprv:attr/colorAccentPrimary"/>
+                <padding android:left="@dimen/qs_dialog_button_horizontal_padding"
+                         android:top="@dimen/qs_dialog_button_vertical_padding"
+                         android:right="@dimen/qs_dialog_button_horizontal_padding"
+                         android:bottom="@dimen/qs_dialog_button_vertical_padding"/>
+            </shape>
+        </item>
+    </ripple>
+</inset>
diff --git a/packages/SystemUI/res/drawable/qs_dialog_btn_outline.xml b/packages/SystemUI/res/drawable/qs_dialog_btn_outline.xml
new file mode 100644
index 0000000..467c20f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_dialog_btn_outline.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+       xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+       android:insetTop="@dimen/qs_dialog_button_vertical_inset"
+       android:insetBottom="@dimen/qs_dialog_button_vertical_inset">
+    <ripple android:color="?android:attr/colorControlHighlight">
+        <item android:id="@android:id/mask">
+            <shape android:shape="rectangle">
+                <solid android:color="@android:color/white"/>
+                <corners android:radius="?android:attr/buttonCornerRadius"/>
+            </shape>
+        </item>
+        <item>
+            <shape android:shape="rectangle">
+                <corners android:radius="?android:attr/buttonCornerRadius"/>
+                <solid android:color="@android:color/transparent"/>
+                <stroke android:color="?androidprv:attr/colorAccentPrimary"
+                        android:width="1dp"
+                />
+                <padding android:left="@dimen/qs_dialog_button_horizontal_padding"
+                         android:top="@dimen/qs_dialog_button_vertical_padding"
+                         android:right="@dimen/qs_dialog_button_horizontal_padding"
+                         android:bottom="@dimen/qs_dialog_button_vertical_padding"/>
+            </shape>
+        </item>
+    </ripple>
+</inset>
diff --git a/packages/SystemUI/res/drawable/rounded_corner_bottom_secondary.xml b/packages/SystemUI/res/drawable/rounded_corner_bottom_secondary.xml
new file mode 100644
index 0000000..5cc8d6a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/rounded_corner_bottom_secondary.xml
@@ -0,0 +1,16 @@
+<!--
+    Copyright (C) 2021 The Android Open Source Project
+
+    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.
+-->
+<!-- Overlay this resource to change rounded_corners_bottom -->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/rounded_secondary"/>
diff --git a/packages/SystemUI/res/drawable/rounded_corner_top_secondary.xml b/packages/SystemUI/res/drawable/rounded_corner_top_secondary.xml
new file mode 100644
index 0000000..724e3ef
--- /dev/null
+++ b/packages/SystemUI/res/drawable/rounded_corner_top_secondary.xml
@@ -0,0 +1,16 @@
+<!--
+    Copyright (C) 2021 The Android Open Source Project
+
+    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.
+-->
+<!-- Overlay this resource to change rounded_corners_top -->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/rounded_secondary"/>
diff --git a/packages/SystemUI/res/drawable/rounded_secondary.xml b/packages/SystemUI/res/drawable/rounded_secondary.xml
new file mode 100644
index 0000000..eb72fa1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/rounded_secondary.xml
@@ -0,0 +1,24 @@
+<!--
+    Copyright (C) 2021 The Android Open Source Project
+
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="8dp"
+    android:height="8dp"
+    android:viewportWidth="8"
+    android:viewportHeight="8">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M8,0H0v8C0,3.6,3.6,0,8,0z" />
+
+</vector>
diff --git a/packages/SystemUI/res/layout/internet_list_item.xml b/packages/SystemUI/res/layout/internet_list_item.xml
index b52933d..05352c5 100644
--- a/packages/SystemUI/res/layout/internet_list_item.xml
+++ b/packages/SystemUI/res/layout/internet_list_item.xml
@@ -70,7 +70,7 @@
                 android:id="@+id/wifi_summary"
                 android:textDirection="locale"
                 android:layout_width="wrap_content"
-                android:layout_height="20dp"
+                android:layout_height="wrap_content"
                 android:gravity="start|center_vertical"
                 android:ellipsize="end"
                 android:textColor="?android:attr/textColorSecondary"
@@ -85,7 +85,7 @@
             android:clickable="false"
             android:layout_gravity="end|center_vertical">
             <ImageView
-                android:id="@+id/wifi_locked_icon"
+                android:id="@+id/wifi_end_icon"
                 android:layout_gravity="end|center_vertical"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"/>
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index eb76382..850b017 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -30,7 +30,6 @@
         android:id="@+id/status_icon_area"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
-        android:paddingEnd="@dimen/system_icons_keyguard_padding_end"
         android:paddingTop="@dimen/status_bar_padding_top"
         android:layout_alignParentEnd="true"
         android:gravity="center_vertical|end" >
@@ -39,6 +38,7 @@
             android:layout_height="match_parent"
             android:layout_weight="1"
             android:layout_marginStart="@dimen/system_icons_super_container_margin_start"
+            android:layout_marginEnd="@dimen/status_bar_padding_end"
             android:gravity="center_vertical|end">
             <include layout="@layout/system_icons" />
         </FrameLayout>
diff --git a/packages/SystemUI/res/layout/media_view.xml b/packages/SystemUI/res/layout/media_view.xml
index 075473a..566cd25 100644
--- a/packages/SystemUI/res/layout/media_view.xml
+++ b/packages/SystemUI/res/layout/media_view.xml
@@ -163,18 +163,6 @@
         </LinearLayout>
     </LinearLayout>
 
-    <ImageView
-        android:id="@+id/media_seamless_fallback"
-        android:layout_width="@dimen/qs_seamless_fallback_icon_size"
-        android:layout_height="@dimen/qs_seamless_fallback_icon_size"
-        android:layout_marginTop="@dimen/qs_media_padding"
-        android:layout_marginBottom="@dimen/qs_media_padding"
-        android:layout_marginStart="@dimen/qs_center_guideline_padding"
-        android:layout_marginEnd="@dimen/qs_seamless_fallback_margin"
-        android:tint="?android:attr/textColor"
-        android:src="@drawable/ic_cast_connected"
-        android:forceHasOverlappingRendering="false" />
-
     <!-- Seek Bar -->
     <!-- As per Material Design on Biderectionality, this is forced to LTR in code -->
     <SeekBar
diff --git a/packages/SystemUI/res/layout/qs_user_dialog_content.xml b/packages/SystemUI/res/layout/qs_user_dialog_content.xml
new file mode 100644
index 0000000..321fe68
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_user_dialog_content.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:sysui="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:padding="24dp"
+    android:layout_marginStart="16dp"
+    android:layout_marginEnd="16dp"
+    android:background="@drawable/qs_dialog_bg"
+>
+    <TextView
+        android:id="@+id/title"
+        android:layout_height="wrap_content"
+        android:layout_width="0dp"
+        android:textAlignment="center"
+        android:text="@string/qs_user_switch_dialog_title"
+        android:textAppearance="@style/TextAppearance.QSDialog.Title"
+        android:layout_marginBottom="32dp"
+        sysui:layout_constraintTop_toTopOf="parent"
+        sysui:layout_constraintStart_toStartOf="parent"
+        sysui:layout_constraintEnd_toEndOf="parent"
+        sysui:layout_constraintBottom_toTopOf="@id/grid"
+        />
+
+    <com.android.systemui.qs.PseudoGridView
+        android:id="@+id/grid"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="28dp"
+        sysui:verticalSpacing="4dp"
+        sysui:horizontalSpacing="4dp"
+        sysui:fixedChildWidth="80dp"
+        sysui:layout_constraintTop_toBottomOf="@id/title"
+        sysui:layout_constraintStart_toStartOf="parent"
+        sysui:layout_constraintEnd_toEndOf="parent"
+        sysui:layout_constraintBottom_toTopOf="@id/barrier"
+    />
+
+    <androidx.constraintlayout.widget.Barrier
+        android:id="@+id/barrier"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        sysui:barrierDirection="top"
+        sysui:constraint_referenced_ids="settings,done"
+        />
+
+    <Button
+        android:id="@+id/settings"
+        android:layout_width="wrap_content"
+        android:layout_height="48dp"
+        android:text="@string/quick_settings_more_user_settings"
+        sysui:layout_constraintTop_toBottomOf="@id/barrier"
+        sysui:layout_constraintBottom_toBottomOf="parent"
+        sysui:layout_constraintStart_toStartOf="parent"
+        sysui:layout_constraintEnd_toStartOf="@id/done"
+        sysui:layout_constraintHorizontal_chainStyle="spread_inside"
+        style="@style/Widget.QSDialog.Button.BorderButton"
+        />
+
+    <Button
+        android:id="@+id/done"
+        android:layout_width="wrap_content"
+        android:layout_height="48dp"
+        android:text="@string/quick_settings_done"
+        sysui:layout_constraintTop_toBottomOf="@id/barrier"
+        sysui:layout_constraintBottom_toBottomOf="parent"
+        sysui:layout_constraintStart_toEndOf="@id/settings"
+        sysui:layout_constraintEnd_toEndOf="parent"
+        style="@style/Widget.QSDialog.Button"
+        />
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/screen_record_dialog.xml b/packages/SystemUI/res/layout/screen_record_dialog.xml
index d1cc01f..c122829 100644
--- a/packages/SystemUI/res/layout/screen_record_dialog.xml
+++ b/packages/SystemUI/res/layout/screen_record_dialog.xml
@@ -113,6 +113,8 @@
                         android:layout_height="wrap_content"
                         android:minHeight="48dp"
                         android:layout_weight="1"
+                        android:layout_gravity="fill_vertical"
+                        android:gravity="center_vertical"
                         android:text="@string/screenrecord_taps_label"
                         android:textAppearance="?android:attr/textAppearanceMedium"
                         android:fontFamily="@*android:string/config_headlineFontFamily"
diff --git a/packages/SystemUI/res/layout/udfps_enroll_view.xml b/packages/SystemUI/res/layout/udfps_enroll_view.xml
index f1ff6d6..e41a632 100644
--- a/packages/SystemUI/res/layout/udfps_enroll_view.xml
+++ b/packages/SystemUI/res/layout/udfps_enroll_view.xml
@@ -20,10 +20,23 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
+    <!-- The layout height/width are placeholders, which will be overwritten by
+         FingerprintSensorPropertiesInternal. -->
+    <View
+        android:id="@+id/udfps_enroll_accessibility_view"
+        android:layout_gravity="center"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:contentDescription="@string/accessibility_fingerprint_label"/>
+
+    <ImageView
+        android:id="@+id/udfps_enroll_animation_fp_progress_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
     <!-- Fingerprint -->
     <ImageView
         android:id="@+id/udfps_enroll_animation_fp_view"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:contentDescription="@string/accessibility_fingerprint_label"/>
+        android:layout_height="match_parent"/>
 </com.android.systemui.biometrics.UdfpsEnrollView>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 6f2ee7c..028f14a 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gebruik vingerafdruk om oop te maak"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Stawing word vereis. Raak die vingerafdruksensor om te staaf."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Oproep aan die gang"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Vliegtuigmodus"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiele data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Gekoppel"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internet sal nie outomaties koppel nie"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobiele data sal nie outomaties koppel nie"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Geen verbinding nie"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Geen ander netwerke beskikbaar nie"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Geen netwerke beskikbaar nie"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 76eace5..798e0c3 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -1162,11 +1162,11 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ለመክፈት የጣት አሻራ ይጠቀሙ"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ማረጋገጥ ያስፈልጋል። ለማረጋገጥ የጣት አሻራ ዳሳሹን ይንኩ።"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"በመካሄድ ላይ የስልክ ጥሪ"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"የአውሮፕላን ሁነታ"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"የተንቀሳቃሽ ስልክ ውሂብ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"ተገናኝቷል"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"በይነመረብ በራስ-ሰር አይገናኝም"</string>
+    <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
+    <skip />
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"ግንኙነት የለም"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ሌላ አውታረ መረብ የሉም"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"ምንም አውታረ መረቦች የሉም"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 82e88b5..6f5d73c 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -1186,11 +1186,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"يمكنك استخدام بصمة الإصبع للفتح"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"المصادقة مطلوبة. المس مستشعر بصمات الإصبع للمصادقة."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"مكالمة هاتفية جارية"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"وضع الطيران"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"بيانات الجوّال"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"متصلة بالإنترنت"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"لن يتم الاتصال بالإنترنت تلقائيًا."</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"لن يتم تلقائيًا الاتصال ببيانات الجوّال."</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"لا يتوفّر اتصال بالإنترنت"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"لا تتوفّر شبكات أخرى."</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"لا تتوفّر أي شبكات."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 7d3ae96..614e4d8 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -1162,11 +1162,11 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"খুলিবলৈ ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণৰ আৱশ্যক। বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰিবলৈ ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো স্পৰ্শ কৰক।"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"চলি থকা ফ’ন কল"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"এয়াৰপ্লেন ম\'ড"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"ম’বাইল ডেটা"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"সংযোজিত হৈ আছে"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"ইণ্টাৰনেট স্বয়ংক্ৰিয়ভাৱে সংযুক্ত নহ’ব"</string>
+    <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
+    <skip />
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"সংযোগ নাই"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"অন্য কোনো নেটৱৰ্ক উপলব্ধ নহয়"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"কোনো নেটৱৰ্ক উপলব্ধ নহয়"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 9fdafb1..7cd3b32 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Açmaq üçün barmaq izindən istifadə edin"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Doğrulanma tələb olunur. Doğrulamaq üçün barmaq izi sensoruna toxunun."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Davam edən zəng"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Uçuş rejimi"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Qoşulub"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"İnternet avtomatik qoşulmayacaq"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobil data avtomatik qoşulmayacaq"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Bağlantı yoxdur"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Heç bir başqa şəbəkə əlçatan deyil"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Əlçatan şəbəkə yoxdur"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index bbd9d4f..f155b76 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -1014,7 +1014,7 @@
     <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacije koriste <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
     <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
     <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string>
-    <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Koristi <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Koristi: <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Nedavno koristio/la <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(posao)"</string>
     <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonski poziv"</string>
@@ -1168,11 +1168,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorite pomoću otiska prsta"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Potrebna je potvrda identiteta. Dodirnite senzor za otisak prsta da biste potvrdili identitet."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Aktuelni telefonski poziv"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Režim rada u avionu"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilni podaci"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Automatsko povezivanje na internet nije moguće"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Nije uspelo autom. povezivanje preko mob. podataka"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Veza nije uspostavljena"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nije dostupna nijedna druga mreža"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Nema dostupnih mreža"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index bb6c758..ab3940b 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -1174,11 +1174,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Каб адкрыць, скарыстайце адбітак пальца"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Патрабуецца аўтэнтыфікацыя. Дакраніцеся да сканера адбіткаў пальцаў."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Бягучы тэлефонны выклік"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Рэжым палёту"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мабільная перадача даных"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Падключана"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Аўтаматычнае падключэнне да інтэрнэту адсутнічае"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мабільная перадача даных не ўключаецца аўтаматычна"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Няма падключэння"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Больш няма даступных сетак"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Няма даступных сетак"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 2bca8e3..2d698ee 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Използвайте отпечатък за отваряне"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Изисква се удостоверяване на самоличността. За целта докоснете сензора за отпечатъци."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Текущо телефонно обаждане"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Самолетен режим"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилни данни"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Свързано"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Няма автоматично да се установи връзка с интернет"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Връзката за мобилни данни няма да е автоматична"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Няма връзка"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Няма други налични мрежи"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Няма налични мрежи"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index bd2d05a..46172bd 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -1162,11 +1162,11 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"খুলতে ফিঙ্গারপ্রিন্ট ব্যবহার করুন"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"যাচাইকরণ করতে হবে। যাচাইকরণ করতে আঙুলের ছাপের সেন্সরে টাচ করুন।"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ব্যবহারকারী এখন ফোনে কথা বলছেন"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"বিমান মোড"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"মোবাইল ডেটা"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"কানেক্ট করা আছে"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"ইন্টারনেট অটোমেটিক কানেক্ট হবে না"</string>
+    <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
+    <skip />
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"কানেকশন নেই"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"অন্য কোনও নেটওয়ার্ক উপলভ্য নেই"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"কোনও নেটওয়ার্ক উপলভ্য নেই"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index d66f1a8..d6a6602 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -1168,11 +1168,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorite pomoću otiska prsta"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Potrebna je autentifikacija. Dodirnite senzor za otisak prsta da autentificirate."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonski poziv u toku"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Način rada u avionu"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Prijenos podataka na mobilnoj mreži"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Nije se moguće automatski povezati s internetom"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Prijenos podataka se neće automatski povezati"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Niste povezani s mrežom"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Druge mreže nisu dostupne"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Nema dostupnih mreža"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index e4003d3..ea91dc1 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -1009,7 +1009,7 @@
     <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Algunes aplicacions estan fent servir el següent: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
     <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
     <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string>
-    <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"En ús per <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"<xliff:g id="APPLICATION_NAME">%1$s</xliff:g> ho està utilitzant"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Utilitzat recentment per <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(feina)"</string>
     <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Trucada"</string>
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Utilitza l\'empremta digital per obrir"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticació necessària. Toca el sensor d\'empremtes digitals per autenticar-te."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Trucada en curs"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Mode d\'avió"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dades mòbils"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connectat"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internet no es connectarà automàticament"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Les dades mòbils no es connectaran automàticament"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sense connexió"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No hi ha cap altra xarxa disponible"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"No hi ha cap xarxa disponible"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 6df9bdb..c9021f8 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -1174,11 +1174,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"K otevření použijte otisk prstu"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Je vyžadováno ověření. Dotkněte se snímače otisků prstů."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Probíhající hovor"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Režim Letadlo"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilní data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Připojeno"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internet se nebude automaticky připojovat"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilní data se nebudou připojovat automaticky"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Žádné připojení"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Žádné další sítě nejsou k dispozici"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Nejsou k dispozici žádné sítě"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index f7e18f1..c7214ff 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -384,7 +384,7 @@
     <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Manglende Wi-Fi-forbindelse"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Lysstyrke"</string>
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="2325362583903258677">"AUTO"</string>
-    <string name="quick_settings_inversion_label" msgid="5078769633069667698">"Byt om på farver"</string>
+    <string name="quick_settings_inversion_label" msgid="5078769633069667698">"Ombyt farver"</string>
     <string name="quick_settings_color_space_label" msgid="537528291083575559">"Farvekorrigeringstilstand"</string>
     <string name="quick_settings_more_settings" msgid="2878235926753776694">"Flere indstillinger"</string>
     <string name="quick_settings_more_user_settings" msgid="1064187451100861954">"Brugerindstillinger"</string>
@@ -678,8 +678,8 @@
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lås skærmindstillinger"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Arbejdsprofil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flytilstand"</string>
-    <string name="add_tile" msgid="6239678623873086686">"Tilføj et felt"</string>
-    <string name="broadcast_tile" msgid="5224010633596487481">"Broadcast-ikon"</string>
+    <string name="add_tile" msgid="6239678623873086686">"Tilføj felt"</string>
+    <string name="broadcast_tile" msgid="5224010633596487481">"Broadcast-felt"</string>
     <string name="zen_alarm_warning_indef" msgid="5252866591716504287">"Du vil ikke kunne høre din næste alarm <xliff:g id="WHEN">%1$s</xliff:g>, medmindre du slår funktionen fra inden da"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Du vil ikke kunne høre din næste alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="alarm_template" msgid="2234991538018805736">"kl. <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -911,15 +911,15 @@
   </string-array>
     <string name="tuner_low_priority" msgid="8412666814123009820">"Vis ikoner for notifikationer med lav prioritet"</string>
     <string name="other" msgid="429768510980739978">"Andet"</string>
-    <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"fjern kortet"</string>
-    <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"føj kortet til slutningen"</string>
-    <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Flyt kortet"</string>
-    <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Tilføj et kort"</string>
+    <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"fjern felt"</string>
+    <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"føj feltet til slutningen"</string>
+    <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Flyt felt"</string>
+    <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Tilføj felt"</string>
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Flyt til <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Føj til placering <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Placering <xliff:g id="POSITION">%1$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Kortet blev tilføjet"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Kortet blev fjernet"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Feltet blev tilføjet"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Feltet blev fjernet"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Redigeringsværktøj til Kvikmenu."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-notifikation: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Åbn Indstillinger."</string>
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Brug fingeraftryk for at åbne"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Godkendelse er påkrævet. Sæt fingeren på fingeraftrykslæseren for at godkende."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Igangværende telefonopkald"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Flytilstand"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Forbundet"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Der oprettes ikke automatisk internetforbindelse"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Der oprettes ikke automatisk mobildataforbindelse"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Der er ingen forbindelse"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Der er ingen andre tilgængelige netværk"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Der er ingen tilgængelige netværk"</string>
@@ -1177,7 +1176,7 @@
     <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Søger efter netværk…"</string>
     <string name="wifi_failed_connect_message" msgid="4161863112079000071">"Der kunne ikke oprettes forbindelse til netværket"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Se alle"</string>
-    <string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> vil føje følgende handlingsfelt til Kvikmenu"</string>
+    <string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> vil gerne føje dette handlingsfelt til Kvikmenu"</string>
     <string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Tilføj handlingsfelt"</string>
-    <string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Tilføj ikke et felt"</string>
+    <string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Tilføj ikke felt"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 56a127f..6b5281e 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -1162,11 +1162,11 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Mit Fingerabdruck öffnen"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentifizierung erforderlich. Tippe dazu einfach auf den Fingerabdrucksensor."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Aktiver Anruf"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Flugmodus"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile Daten"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Verbunden"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Keine automatische Verbindung mit dem Internet"</string>
+    <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
+    <skip />
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Keine Verbindung"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Keine anderen Netzwerke verfügbar"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Keine Netzwerke verfügbar"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 0ebcd70..b55256c 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Χρήση δακτυλικού αποτυπώματος για άνοιγμα"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Απαιτείται έλεγχος ταυτότητας. Αγγίξτε τον αισθητήρα δακτυλικών αποτυπωμάτων για έλεγχο ταυτότητας."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Τηλεφωνική κλήση σε εξέλιξη"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Λειτουργία πτήσης"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Δεδομένα κινητής τηλεφωνίας"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Συνδέθηκε"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Χωρίς αυτόματη σύνδεση στο διαδίκτυο"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Χωρίς αυτόματη σύνδεση δεδομένων κινητ. τηλεφωνίας"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Χωρίς σύνδεση"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Δεν υπάρχουν άλλα διαθέσιμα δίκτυα"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Δεν υπάρχουν διαθέσιμα δίκτυα"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 3424cf7..081bfcb 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Aeroplane mode"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internet won\'t auto‑connect"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobile data won\'t auto‑connect"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"No connection"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No other networks available"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"No networks available"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 7f0745a..4e32027 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Aeroplane mode"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internet won\'t auto‑connect"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobile data won\'t auto‑connect"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"No connection"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No other networks available"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"No networks available"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 3424cf7..081bfcb 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Aeroplane mode"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internet won\'t auto‑connect"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobile data won\'t auto‑connect"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"No connection"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No other networks available"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"No networks available"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 3424cf7..081bfcb 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Aeroplane mode"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internet won\'t auto‑connect"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobile data won\'t auto‑connect"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"No connection"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No other networks available"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"No networks available"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index dc239ee..6641705 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‎‎‏‏‏‎‎‎‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‎‏‎‎‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‏‏‎‏‎Use fingerprint to open‎‏‎‎‏‎"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‏‎‎‎‎‎‏‎‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‏‏‏‎Authentication required. Touch the fingerprint sensor to authenticate.‎‏‎‎‏‎"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎Ongoing phone call‎‏‎‎‏‎"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‏‏‎‎‏‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‎‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‎Airplane mode‎‏‎‎‏‎"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎Mobile data‎‏‎‎‏‎"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‏‎‏‎‎‎‏‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="STATE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ / ‎‏‎‎‏‏‎<xliff:g id="NETWORKMODE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‏‎‏‏‏‏‎‎‎‏‎‎‏‏‏‏‏‎‎‏‏‎Connected‎‏‎‎‏‎"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‏‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‎‎‏‎‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎Internet won\'t auto‑connect‎‏‎‎‏‎"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎‏‎‎‎‎‎‎‏‏‎‏‏‎‎‎‏‏‏‎‎‏‏‎‎‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‏‏‎Mobile data won\'t auto‑connect‎‏‎‎‏‎"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‎‏‏‎‎‎‎‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎‎‏‎No connection‎‏‎‎‏‎"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎No other networks available‎‏‎‎‏‎"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‎‎‏‏‏‎‎‎‎‎‏‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎No networks available‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 6d11fa0..154248c 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa la huella dactilar para abrir"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Se requiere de una autenticación. Toca el sensor de huellas dactilares para autenticarte."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Llamada en curso"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Modo de avión"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Conexión establecida"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"No se conectará automáticamente a Internet"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"No se conectarán automáticamente los datos móviles"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sin conexión"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No hay otras redes disponibles"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"No hay redes disponibles"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
index 5634f79..4f738c5 100644
--- a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
@@ -58,8 +58,8 @@
   </string-array>
   <string-array name="tile_states_flashlight">
     <item msgid="3465257127433353857">"No disponible"</item>
-    <item msgid="5044688398303285224">"Desactivado"</item>
-    <item msgid="8527389108867454098">"Activado"</item>
+    <item msgid="5044688398303285224">"Desactivada"</item>
+    <item msgid="8527389108867454098">"Activada"</item>
   </string-array>
   <string-array name="tile_states_rotation">
     <item msgid="4578491772376121579">"No disponible"</item>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 65b736c..8e19028 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa la huella digital para abrir"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticación obligatoria. Toca el sensor de huellas digitales para autenticarte."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Llamada en curso"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Modo avión"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internet no se conecta automáticamente"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Los datos móviles no se conectarán automáticamente"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sin conexión"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"No hay otras redes disponibles"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"No hay redes disponibles"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 63a6244..d603182 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Kasutage avamiseks sõrmejälge"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Vajalik on autentimine. Puudutage autentimiseks sõrmejäljeandurit."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Käimasolev telefonikõne"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Lennukirežiim"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiilne andmeside"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Ühendatud"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internetiühendust ei looda automaatselt"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobiilset andmesideühendust ei looda automaatselt"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Ühendus puudub"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Ühtegi muud võrku pole saadaval"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Ühtegi võrku pole saadaval"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 1f0afbf..d59dc7a 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Erabili hatz-marka irekitzeko"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentifikazioa behar da. Autentifikatzeko, ukitu hatz-marken sentsorea."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefono-dei bat abian da"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Hegaldi modua"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datu-konexioa"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> (<xliff:g id="NETWORKMODE">%2$s</xliff:g>)"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Konektatuta"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Ez da automatikoki konektatuko Internetera"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Ez da automatikoki aktibatuko datu-konexioa"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Konexiorik gabe"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Ez dago beste sare erabilgarririk"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Ez dago sare erabilgarririk"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index bb1be58..62281ef 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"از اثر انگشت برای باز کردن قفل استفاده کنید"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"اصالت‌سنجی لازم است. برای اصالت‌سنجی، حسگر اثر انگشت را لمس کنید."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"تماس تلفنی درحال انجام"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"حالت هواپیما"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"داده تلفن همراه"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"متصل است"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"اینترنت به‌طور خودکار متصل نخواهد شد"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"داده تلفن همراه به‌طور خودکار متصل نخواهد شد"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"اتصال برقرار نیست"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"شبکه دیگری وجود ندارد"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"شبکه‌ای در دسترس نیست"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 0bb2b91..629b1ff 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -861,7 +861,7 @@
     <string name="accessibility_status_bar_headset" msgid="2699275863720926104">"Kuulokemikrofoni liitetty"</string>
     <string name="data_saver" msgid="3484013368530820763">"Data Saver"</string>
     <string name="accessibility_data_saver_on" msgid="5394743820189757731">"Data Saver on käytössä."</string>
-    <string name="accessibility_data_saver_off" msgid="58339669022107171">"Data Saver on pois käytöstä."</string>
+    <string name="accessibility_data_saver_off" msgid="58339669022107171">"Data Saver on pois päältä."</string>
     <string name="switch_bar_on" msgid="1770868129120096114">"Päällä"</string>
     <string name="switch_bar_off" msgid="5669805115416379556">"Pois päältä"</string>
     <string name="tile_unavailable" msgid="3095879009136616920">"Ei käytettävissä"</string>
@@ -976,9 +976,9 @@
     <string name="mobile_data" msgid="4564407557775397216">"Mobiilitiedonsiirto"</string>
     <string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="mobile_carrier_text_format" msgid="8912204177152950766">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="MOBILE_DATA_TYPE">%2$s</xliff:g>"</string>
-    <string name="wifi_is_off" msgid="5389597396308001471">"Wi-Fi on pois käytöstä"</string>
+    <string name="wifi_is_off" msgid="5389597396308001471">"Wi-Fi on pois päältä"</string>
     <string name="bt_is_off" msgid="7436344904889461591">"Bluetooth ei ole käytössä"</string>
-    <string name="dnd_is_off" msgid="3185706903793094463">"Älä häiritse ‑tila on pois käytöstä"</string>
+    <string name="dnd_is_off" msgid="3185706903793094463">"Älä häiritse ‑tila on pois päältä"</string>
     <string name="qs_dnd_prompt_auto_rule" msgid="3535469468310002616">"Automaattinen sääntö otti käyttöön Älä häiritse ‑tilan (<xliff:g id="ID_1">%s</xliff:g>)."</string>
     <string name="qs_dnd_prompt_app" msgid="4027984447935396820">"Sovellus otti käyttöön Älä häiritse ‑tilan (<xliff:g id="ID_1">%s</xliff:g>)."</string>
     <string name="qs_dnd_prompt_auto_rule_app" msgid="1841469944118486580">"Automaattinen sääntö tai sovellus otti käyttöön Älä häiritse ‑tilan."</string>
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Avaa sormenjäljellä"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Todennus vaaditaan. Todenna koskettamalla sormenjälkitunnistinta."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Puhelu käynnissä"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Lentokonetila"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiilidata"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Yhdistetty"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internetyhteyttä ei muodosteta automaattisesti"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobiilidata ei yhdisty automaattisesti"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Ei yhteyttä"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Ei muita verkkoja käytettävissä"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Ei verkkoja käytettävissä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index f5539e3..a13f849 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -1009,7 +1009,7 @@
     <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Des applications utilisent votre <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
     <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
     <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" et "</string>
-    <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"En cours d\'utilisation par <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"En cours d\'utilisation par : <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Récemment utilisé par <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(travail)"</string>
     <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Appel téléphonique"</string>
@@ -1162,11 +1162,11 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Servez-vous de votre empreinte digitale pour ouvrir"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentification requise. Touchez le capteur d\'empreintes digitales pour vous authentifier."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Appel téléphonique en cours…"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Mode Avion"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Données cellulaires"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connexion active"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Connexion automatique à Internet impossible"</string>
+    <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
+    <skip />
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Aucune connexion"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Aucun autre réseau n\'est accessible"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Aucun réseau n\'est accessible"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index f7c1728..f0bc8be 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Utilisez votre empreinte pour ouvrir"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentification requise. Appuyez sur le lecteur d\'empreintes digitales pour vous authentifier."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Appel téléphonique en cours"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Mode Avion"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Données mobiles"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connecté"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Pas de connexion automatique à Internet"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Pas de connexion automatique des données mobiles"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Aucune connexion"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Aucun autre réseau disponible"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Aucun réseau disponible"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 9b6aa53..d6f8036 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -1009,7 +1009,7 @@
     <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Hai aplicacións que están utilizando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
     <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
     <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string>
-    <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Opción en uso por <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"En uso por: <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Opción usada recentemente por <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(traballo)"</string>
     <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Chamada de teléfono"</string>
@@ -1162,11 +1162,11 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa a impresión dixital para abrir"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Requírese autenticación. Para autenticarte, toca o sensor de impresión dixital."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada telefónica en curso"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Modo avión"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móbiles"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectada"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internet non se conectará automaticamente"</string>
+    <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
+    <skip />
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sen conexión"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Non hai outras redes dispoñibles"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Non hai redes dispoñibles"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index a2295ab..11fe9b9 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -1162,11 +1162,11 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ખોલવા માટે ફિંગરપ્રિન્ટનો ઉપયોગ કરો"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"પ્રમાણીકરણ આવશ્યક છે. પ્રમાણિત કરવા માટે ફિંગરપ્રિન્ટ સેન્સરને ટચ કરો."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ફોન કૉલ ચાલુ છે"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"એરપ્લેન મોડ"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"મોબાઇલ ડેટા"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"કનેક્ટ કરેલું"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"ઇન્ટરનેટ ઑટોમૅટિક રીતે કનેક્ટ થશે નહીં"</string>
+    <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
+    <skip />
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"કોઈ કનેક્શન નથી"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"બીજાં કોઈ નેટવર્ક ઉપલબ્ધ નથી"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"કોઈ નેટવર્ક ઉપલબ્ધ નથી"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index ce0f9b9..44100dc 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"खोलने के लिए, फ़िंगरप्रिंट का इस्तेमाल करें"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"पुष्टि करना ज़रूरी है. पुष्टि करने के लिए, फ़िंगरप्रिंट सेंसर को छुएं."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"फ़ोन कॉल चल रहा है"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"हवाई जहाज़ मोड"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"कनेक्ट हो गया"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"इंटरनेट अपने-आप कनेक्ट नहीं होगा"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"मोबाइल डेटा अपने-आप कनेक्ट नहीं होगा"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"इंटरनेट कनेक्शन नहीं है"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"कोई दूसरा नेटवर्क उपलब्ध नहीं है"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"कोई नेटवर्क उपलब्ध नहीं है"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index ff77b67..ed1f3cb 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -1168,11 +1168,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorite pomoću otiska prsta"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Potrebna je autentifikacija. Dodirnite senzor otiska prsta da biste se autentificirali."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonski poziv u tijeku"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Način rada u zrakoplovu"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilni podaci"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Neće biti automatskog povezivanja s internetom"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilni podaci neće se automatski povezati"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Niste povezani"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nije dostupna nijedna druga mreža"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Nema dostupnih mreža"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 172bec8..b47e75b 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -354,7 +354,7 @@
     <string name="quick_settings_ime_label" msgid="3351174938144332051">"Beviteli módszer"</string>
     <string name="quick_settings_location_label" msgid="2621868789013389163">"Tartózkodási hely"</string>
     <string name="quick_settings_location_off_label" msgid="7923929131443915919">"Hely kikapcsolva"</string>
-    <string name="quick_settings_camera_label" msgid="5612076679385269339">"Kameraelérés"</string>
+    <string name="quick_settings_camera_label" msgid="5612076679385269339">"Hozzáférés a kamerához"</string>
     <string name="quick_settings_mic_label" msgid="8392773746295266375">"Mikrofonelérés"</string>
     <string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Rendelkezésre áll"</string>
     <string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"Letiltva"</string>
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Ujjlenyomat használata a megnyitáshoz"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Hitelesítés szükséges. Érintse meg az ujjlenyomat-érzékelőt a hitelesítéshez."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Folyamatban lévő telefonhívás"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Repülős üzemmód"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiladat"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="NETWORKMODE">%2$s</xliff:g>/<xliff:g id="STATE">%1$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Csatlakozva"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Az internetre történő csatlakozás nem automatikus"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Nincs automatikus mobiladat-kapcsolat"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nincs kapcsolat"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nincs több rendelkezésre álló hálózat"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Nincs rendelkezésre álló hálózat"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index e875df8..0fcfd65 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Բացելու համար օգտագործեք մատնահետքը"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Պահանջվում է նույնականացում։ Դրա համար մատը հպեք մատնահետքի սկաներին։"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ընթացիկ հեռախոսազանգ"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Ավիառեժիմ"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Բջջային ինտերնետ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Միացած է"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Չհաջողվեց ավտոմատ միանալ համացանցին"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Բջջային ինտերնետն ավտոմատ չի միանա"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Կապ չկա"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Այլ հասանելի ցանցեր չկան"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Հասանելի ցանցեր չկան"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index aa07fed..6486b0b 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -191,7 +191,7 @@
     <string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ikon wajah"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Tombol perbesar/perkecil kompatibilitas."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="2617218726091234073">"Perbesar dari layar kecil ke besar."</string>
-    <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth tersambung."</string>
+    <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth terhubung."</string>
     <string name="accessibility_bluetooth_disconnected" msgid="7195823280221275929">"Bluetooth terputus."</string>
     <string name="accessibility_no_battery" msgid="3789287732041910804">"Tidak ada baterai."</string>
     <string name="accessibility_battery_one_bar" msgid="8868347318237585329">"Baterai satu batang."</string>
@@ -216,8 +216,8 @@
     <string name="accessibility_signal_full" msgid="5920148525598637311">"Sinyal penuh."</string>
     <string name="accessibility_desc_on" msgid="2899626845061427845">"Aktif."</string>
     <string name="accessibility_desc_off" msgid="8055389500285421408">"Nonaktif."</string>
-    <string name="accessibility_desc_connected" msgid="3082590384032624233">"Tersambung."</string>
-    <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Menyambung."</string>
+    <string name="accessibility_desc_connected" msgid="3082590384032624233">"Terhubung."</string>
+    <string name="accessibility_desc_connecting" msgid="8011433412112903614">"Menghubungkan."</string>
     <string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
     <string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
     <string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
@@ -272,7 +272,7 @@
     <string name="accessibility_quick_settings_bluetooth_off" msgid="3795983516942423240">"Bluetooth nonaktif."</string>
     <string name="accessibility_quick_settings_bluetooth_on" msgid="3819082137684078013">"Bluetooth aktif."</string>
     <string name="accessibility_quick_settings_bluetooth_connecting" msgid="7362294657419149294">"Bluetooth menyambung."</string>
-    <string name="accessibility_quick_settings_bluetooth_connected" msgid="5237625393869747261">"Bluetooth tersambung."</string>
+    <string name="accessibility_quick_settings_bluetooth_connected" msgid="5237625393869747261">"Bluetooth terhubung."</string>
     <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="3344226652293797283">"Bluetooth dinonaktifkan."</string>
     <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="1263282011749437549">"Bluetooth diaktifkan."</string>
     <string name="accessibility_quick_settings_location_off" msgid="6122523378294740598">"Pelaporan lokasi nonaktif."</string>
@@ -390,9 +390,9 @@
     <string name="quick_settings_more_user_settings" msgid="1064187451100861954">"Setelan pengguna"</string>
     <string name="quick_settings_done" msgid="2163641301648855793">"Selesai"</string>
     <string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Tutup"</string>
-    <string name="quick_settings_connected" msgid="3873605509184830379">"Tersambung"</string>
+    <string name="quick_settings_connected" msgid="3873605509184830379">"Terhubung"</string>
     <string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"Terhubung, baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="quick_settings_connecting" msgid="2381969772953268809">"Menyambung..."</string>
+    <string name="quick_settings_connecting" msgid="2381969772953268809">"Menghubungkan..."</string>
     <string name="quick_settings_tethering_label" msgid="5257299852322475780">"Menambatkan"</string>
     <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Hotspot"</string>
     <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Mengaktifkan…"</string>
@@ -563,30 +563,30 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Otoritas sertifikat diinstal di perangkat. Traffic jaringan aman Anda mungkin dipantau atau diubah."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"Admin telah mengaktifkan pencatatan log jaringan, yang memantau traffic di perangkat."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"Admin telah mengaktifkan pencatatan log jaringan, yang memantau traffic di profil kerja, tetapi tidak di profil pribadi."</string>
-    <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Anda tersambung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string>
-    <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Anda tersambung ke <xliff:g id="VPN_APP_0">%1$s</xliff:g> dan <xliff:g id="VPN_APP_1">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string>
-    <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Profil kerja Anda tersambung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs."</string>
-    <string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"Profil pribadi Anda tersambung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs."</string>
+    <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"Anda terhubung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string>
+    <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"Anda terhubung ke <xliff:g id="VPN_APP_0">%1$s</xliff:g> dan <xliff:g id="VPN_APP_1">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string>
+    <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"Profil kerja Anda terhubung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs."</string>
+    <string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"Profil pribadi Anda terhubung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs."</string>
     <string name="monitoring_description_do_header_generic" msgid="6130190408164834986">"Perangkat dikelola oleh <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>."</string>
     <string name="monitoring_description_do_header_with_name" msgid="2696255132542779511">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> menggunakan <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> untuk mengelola perangkat Anda."</string>
     <string name="monitoring_description_do_body" msgid="7700878065625769970">"Admin dapat memantau dan mengelola setelan, akses perusahaan, aplikasi, data terkait perangkat, dan informasi lokasi perangkat."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="1467280496376492558">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="645149183455573790">"Pelajari lebih lanjut"</string>
-    <string name="monitoring_description_do_body_vpn" msgid="7699280130070502303">"Anda tersambung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string>
+    <string name="monitoring_description_do_body_vpn" msgid="7699280130070502303">"Anda terhubung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Buka setelan VPN"</string>
     <string name="monitoring_description_ca_cert_settings_separator" msgid="7107390013344435439">" "</string>
     <string name="monitoring_description_ca_cert_settings" msgid="8329781950135541003">"Buka kredensial terpercaya"</string>
     <string name="monitoring_description_network_logging" msgid="577305979174002252">"Admin telah mengaktifkan pencatatan log jaringan, yang memantau traffic di perangkat.\n\nUntuk informasi selengkapnya, hubungi admin."</string>
     <string name="monitoring_description_vpn" msgid="1685428000684586870">"Anda memberikan izin kepada aplikasi untuk menyiapkan sambungan VPN.\n\nAplikasi ini ini dapat memantau aktivitas perangkat dan jaringan, termasuk email, aplikasi, dan situs web."</string>
-    <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Profil kerja dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdmin dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web.\n\nUntuk informasi selengkapnya, hubungi admin.\n\nAnda juga tersambung ke VPN, yang dapat memantau aktivitas jaringan."</string>
+    <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Profil kerja dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdmin dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web.\n\nUntuk informasi selengkapnya, hubungi admin.\n\nAnda juga terhubung ke VPN, yang dapat memantau aktivitas jaringan."</string>
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Perangkat ini dikelola oleh orang tuamu. Orang tuamu bisa melihat dan mengelola berbagai informasi, seperti aplikasi yang kamu gunakan, lokasimu, dan lama pemakaian perangkat."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
-    <string name="monitoring_description_app" msgid="376868879287922929">"Anda tersambung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs."</string>
-    <string name="monitoring_description_app_personal" msgid="1970094872688265987">"Anda tersambung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi, termasuk email, aplikasi, dan situs web."</string>
-    <string name="branded_monitoring_description_app_personal" msgid="1703511985892688885">"Anda tersambung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi, termasuk email, aplikasi, dan situs web.."</string>
-    <string name="monitoring_description_app_work" msgid="3713084153786663662">"Profil kerja Anda dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil tersambung ke <xliff:g id="APPLICATION">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan kerja, termasuk email, aplikasi, dan situs.\n\nHubungi admin untuk mendapatkan informasi lebih lanjut."</string>
-    <string name="monitoring_description_app_personal_work" msgid="6175816356939166101">"Profil kerja Anda dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil tersambung ke <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs.\n\nAnda juga tersambung ke <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi."</string>
+    <string name="monitoring_description_app" msgid="376868879287922929">"Anda terhubung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs."</string>
+    <string name="monitoring_description_app_personal" msgid="1970094872688265987">"Anda terhubung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi, termasuk email, aplikasi, dan situs web."</string>
+    <string name="branded_monitoring_description_app_personal" msgid="1703511985892688885">"Anda terhubung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi, termasuk email, aplikasi, dan situs web.."</string>
+    <string name="monitoring_description_app_work" msgid="3713084153786663662">"Profil kerja Anda dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil terhubung ke <xliff:g id="APPLICATION">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan kerja, termasuk email, aplikasi, dan situs.\n\nHubungi admin untuk mendapatkan informasi lebih lanjut."</string>
+    <string name="monitoring_description_app_personal_work" msgid="6175816356939166101">"Profil kerja Anda dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil terhubung ke <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs.\n\nAnda juga terhubung ke <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi."</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Tetap terbuka kuncinya oleh TrustAgent"</string>
     <string name="keyguard_indication_trust_disabled" msgid="6820793704816727918">"Perangkat akan tetap terkunci hingga Anda membukanya secara manual"</string>
     <string name="keyguard_indication_trust_unlocked_plugged_in" msgid="2323452175329362855">"<xliff:g id="KEYGUARD_INDICATION">%1$s</xliff:g>\n<xliff:g id="POWER_INDICATION">%2$s</xliff:g>"</string>
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gunakan sidik jari untuk membuka"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Perlu autentikasi. Sentuh sensor sidik jari untuk melakukan autentikasi."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Panggilan telepon sedang berlangsung"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Mode pesawat"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Data seluler"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Terhubung"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internet tidak akan terhubung otomatis"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Data seluler tidak akan terhubung otomatis"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Tidak ada koneksi"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Jaringan lain tidak tersedia"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Jaringan tidak tersedia"</string>
diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml
index d58cdc8..110eb09 100644
--- a/packages/SystemUI/res/values-in/strings_tv.xml
+++ b/packages/SystemUI/res/values-in/strings_tv.xml
@@ -21,7 +21,7 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mic_active" msgid="5766614241012047024">"Mikrofon Aktif"</string>
     <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s mengakses mikrofon"</string>
-    <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN tersambung"</string>
+    <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN terhubung"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN terputus"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Melalui <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
     <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifikasi"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 4ace524..0af672c 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Opna með fingrafari"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Auðkenningar krafist. Auðkenndu með því að snerta fingrafaralesarann."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Símtal í gangi"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Flugstilling"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Farsímagögn"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Tengt"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internetið tengist ekki sjálfkrafa"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Farsímagögn tengjast ekki sjálfkrafa"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Engin tenging"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Engin önnur net í boði"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Ekkert net í boði"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 29fd0cf..d2f6335 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa l\'impronta per aprire"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticazione obbligatoria. Eseguila toccando il sensore di impronte digitali."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonata in corso"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Modalità aereo"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dati mobili"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connessione attiva"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internet non si connetterà automaticamente"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Nessuna connessione dati mobili automatica"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nessuna connessione"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nessun\'altra rete disponibile"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Nessuna rete disponibile"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index cd2df4e..78370d6 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -1174,11 +1174,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"שימוש בטביעת אצבע כדי לפתוח"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"נדרש אימות. יש לגעת בחיישן טביעות האצבע כדי לבצע אימות."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"מתקיימת שיחה"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"מצב טיסה"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"חבילת גלישה"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"מחובר"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"לא ניתן להתחבר לאינטרנט באופן אוטומטי"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"החיבור לנתונים סלולריים לא מתבצע באופן אוטומטי"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"אין חיבור"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"אין רשתות זמינות אחרות"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"אין רשתות זמינות"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 77fa5aa..7e8c6a1 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"指紋を使って開いてください"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"認証が必要です。指紋認証センサーをタッチして認証してください。"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"通話中"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"機内モード"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"モバイルデータ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"接続済み"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"インターネットに自動的に接続されません"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"モバイルデータには自動接続しません"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"接続なし"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"利用できるネットワークはありません"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"ネットワークを利用できません"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index bad49d4..f7bcf7f 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"გასახსნელად გამოიყენეთ თითის ანაბეჭდი"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"საჭიროა ავტორიზაცია. ავტორიზაციისთვის შეეხეთ თითის ანაბეჭდის სენსორს."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"მიმდინარე სატელეფონო ზარი"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"თვითმფრინავის რეჟიმი"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"მობილური ინტერნეტი"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"დაკავშირებული"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"ინტერნეტს ავტომატურად არ დაუკავშირდება"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"მობილურ ინტერნეტს ავტომატურად არ დაუკავშირდება"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"კავშირი არ არის"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"სხვა ქსელები მიუწვდომელია"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"ქსელები მიუწვდომელია"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 41e93b1..92b93a0 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Ашу үшін саусақ ізін пайдаланыңыз."</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Аутентификациядан өту қажет. Ол үшін саусақ ізін оқу сканерін түртіңіз."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Телефон қоңырауы бар"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Ұшақ режимі"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобильдік интернет"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Жалғанды"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Интернет автоматты түрде қосылмайды."</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мобильдік интернет автоматты түрде қосылмайды."</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Байланыс жоқ"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Басқа қолжетімді желі жоқ"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Қолжетімді желілер жоқ"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index c9ab49b..2b25be6 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ប្រើស្នាមម្រាមដៃ ដើម្បីបើក"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"តម្រូវឱ្យ​មាន​ការផ្ទៀងផ្ទាត់។ សូមចុច​ឧបករណ៍​ចាប់ស្នាមម្រាមដៃ ដើម្បី​ផ្ទៀងផ្ទាត់​។"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ការហៅទូរសព្ទ​ដែលកំពុង​ដំណើរការ"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"ពេលជិះ​យន្តហោះ"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"ទិន្នន័យ​ទូរសព្ទចល័ត"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"បានភ្ជាប់"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"អ៊ីនធឺណិតនឹងមិនភ្ជាប់ដោយស្វ័យប្រវត្តិទេ"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"ទិន្នន័យទូរសព្ទចល័ត​នឹងមិនភ្ជាប់ដោយស្វ័យប្រវត្តិទេ"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"មិនមាន​ការតភ្ជាប់ទេ"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"មិន​មាន​បណ្ដាញផ្សេងទៀតដែល​អាច​ប្រើ​បានទេ"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"មិន​មាន​បណ្ដាញដែល​អាច​ប្រើ​បានទេ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 06db06d..13b4bd7 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -1162,11 +1162,11 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ತೆರೆಯುವುದಕ್ಕಾಗಿ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ಬಳಸಿ"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ದೃಢೀಕರಣದ ಅವಶ್ಯಕತೆಯಿದೆ. ದೃಢೀಕರಿಸಲು ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಫೋನ್ ಕರೆ"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"ಮೊಬೈಲ್ ಡೇಟಾ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"ಇಂಟರ್ನೆಟ್ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕನೆಕ್ಟ್ ಆಗುವುದಿಲ್ಲ"</string>
+    <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
+    <skip />
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"ಯಾವುದೇ ಕನೆಕ್ಷನ್ ಇಲ್ಲ"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ಇತರ ಯಾವುದೇ ನೆಟ್‌ವರ್ಕ್‌ಗಳು ಲಭ್ಯವಿಲ್ಲ"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"ಯಾವುದೇ ನೆಟ್‌ವರ್ಕ್‌ಗಳು ಲಭ್ಯವಿಲ್ಲ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index ad5c7e7..81b0ec0 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"지문으로 열기"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"인증이 필요합니다. 지문 센서를 터치하여 인증하세요."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"진행 중인 전화 통화"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"비행기 모드"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"모바일 데이터"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"연결됨"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"인터넷에 자동으로 연결되지 않음"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"모바일 데이터가 자동으로 연결되지 않음"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"연결되지 않음"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"사용 가능한 다른 네트워크가 없음"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"사용 가능한 네트워크가 없음"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 39a6f59..3161270 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Манжаңыздын изи менен ачыңыз"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Аныктыкты текшерүү талап кылынат. Аныктыгын текшерүү үчүн манжа изинин сенсоруна тийип коюңуз."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Учурдагы телефон чалуу"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Учак режими"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилдик трафик"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Туташты"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Интернет автоматтык түрдө туташпайт"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мобилдик трафик автоматтык түрдө туташтырылбайт"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Байланыш жок"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Башка тармактар жеткиликсиз"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Тармактар жеткиликтүү эмес"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 2e728b2..509a6f8 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ໃຊ້ລາຍນິ້ວມືເພື່ອເປີດ"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ຕ້ອງພິສູດຢືນຢັນ. ແຕະໃສ່ເຊັນເຊີລາຍນິ້ວມືເພື່ອພິສູດຢືນຢັນ."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ສາຍໂທອອກ"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"ໂໝດຢູ່ໃນຍົນ"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"ອິນເຕີເນັດມືຖື"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"ເຊື່ອມຕໍ່ແລ້ວ"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"ຈະບໍ່ເຊື່ອມຕໍ່ອິນເຕີເນັດອັດຕະໂນມັດ"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"ຈະບໍ່ເຊື່ອມຕໍ່ອິນເຕີເນັດມືຖືອັດຕະໂນມັດ"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"ບໍ່ມີການເຊື່ອມຕໍ່"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ບໍ່ມີເຄືອຂ່າຍອື່ນທີ່ສາມາດໃຊ້ໄດ້"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"ບໍ່​ມ​ີ​ເຄືອ​ຂ່າຍ​ທີ່​ສາ​ມາດ​ໃຊ້​ໄດ້"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 52aa239..87d67b7 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -1174,11 +1174,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Naudokite kontrolinį kodą, kad atidarytumėte"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Reikia nustatyti tapatybę. Nustatykite tapatybę palietę kontrolinio kodo jutiklį."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Vykstantis telefono skambutis"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Lėktuvo režimas"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiliojo ryšio duomenys"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Prisijungta"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Prie interneto nebus jungiamasi automatiškai"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Naud. mob. r. duomenis nebus autom. prisijungiama"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nėra ryšio"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nėra kitų pasiekiamų tinklų"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Nėra pasiekiamų tinklų"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index ac75d9e..242d6ba 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -1168,11 +1168,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Atvēršanai izmantojiet pirksta nospiedumu"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Nepieciešama autentifikācija. Pieskarieties pirksta nospieduma sensoram, lai veiktu autentificēšanu."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Notiekošs tālruņa zvans"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Lidojuma režīms"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilie dati"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Ir izveidots savienojums"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Interneta savienojums netiks izveidots automātiski"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilo datu savienojums netiks veidots automātiski"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nav savienojuma"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nav pieejams neviens cits tīkls"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Nav pieejams neviens tīkls"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 166e861..fe4040e 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Користете отпечаток за да се отвори"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Потребна е проверка. Допрете го сензорот за отпечаток за да автентицирате."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Тековен телефонски повик"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Авионски режим"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилен интернет"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Поврзано"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Не може автоматски да се поврзе на интернет"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мобилниот интернет не може автоматски да се поврзе"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Нема интернет-врска"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Нема други достапни мрежи"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Нема достапни мрежи"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 986141b..db170de 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"തുറക്കുന്നതിന് നിങ്ങളുടെ ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കുക"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"പരിശോധിച്ചുറപ്പിക്കേണ്ടതുണ്ട്. പരിശോധിച്ചുറപ്പിക്കാൻ, വിരലടയാള സെൻസറിൽ സ്‌പർശിക്കുക."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"സജീവമായ ഫോൺ കോൾ"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"ഫ്ലൈറ്റ് മോഡ്"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"മൊബൈൽ ഡാറ്റ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"കണക്റ്റ് ചെയ്തു"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"ഇന്റർനെറ്റ് സ്വയമേവ കണക്‌റ്റ് ചെയ്യില്ല"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"മൊബൈൽ ഡാറ്റ സ്വയമേവ കണക്റ്റ് ചെയ്യില്ല"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"കണക്ഷനില്ല"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"മറ്റ് നെറ്റ്‌വർക്കുകളൊന്നും ലഭ്യമല്ല"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"നെറ്റ്‌വർക്കുകളൊന്നും ലഭ്യമല്ല"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index ae48d21..aed89bb 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -659,7 +659,7 @@
     <string name="system_ui_tuner" msgid="1471348823289954729">"Системийн UI Тохируулагч"</string>
     <string name="show_battery_percentage" msgid="6235377891802910455">"Залгаатай тэжээлийн хувийг харуулах"</string>
     <string name="show_battery_percentage_summary" msgid="9053024758304102915">"Тэжээлийн хувийг цэнэглээгүй байх үед статусын хэсэгт харуулна уу"</string>
-    <string name="quick_settings" msgid="6211774484997470203">"Түргэвчилсэн Tохиргоо"</string>
+    <string name="quick_settings" msgid="6211774484997470203">"Шуурхай тохиргоо"</string>
     <string name="status_bar" msgid="4357390266055077437">"Статус самбар"</string>
     <string name="overview" msgid="3522318590458536816">"Тойм"</string>
     <string name="demo_mode" msgid="263484519766901593">"Системийн UI демо горим"</string>
@@ -684,7 +684,7 @@
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>-т та дараагийн сэрүүлгээ сонсохгүй"</string>
     <string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> цагт"</string>
     <string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g>-т"</string>
-    <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"Түргэн Тохиргоо, <xliff:g id="TITLE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"Шуурхай тохиргоо, <xliff:g id="TITLE">%s</xliff:g>."</string>
     <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"Сүлжээний цэг"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Ажлын профайл"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Зарим хүнд хөгжилтэй байж болох ч бүх хүнд тийм биш"</string>
@@ -697,8 +697,8 @@
     <string name="activity_not_found" msgid="8711661533828200293">"Аппыг таны төхөөрөмжид суулгаагүй байна"</string>
     <string name="clock_seconds" msgid="8709189470828542071">"Цагийн секундыг харуулах"</string>
     <string name="clock_seconds_desc" msgid="2415312788902144817">"Статус талбарт цагийн секундыг харуулах. Энэ нь тэжээлийн цэнэгт нөлөөлж болно."</string>
-    <string name="qs_rearrange" msgid="484816665478662911">"Түргэн тохиргоог дахин засварлах"</string>
-    <string name="show_brightness" msgid="6700267491672470007">"Түргэн тохиргоонд гэрэлтүүлэг харах"</string>
+    <string name="qs_rearrange" msgid="484816665478662911">"Шуурхай тохиргоог дахин засварлах"</string>
+    <string name="show_brightness" msgid="6700267491672470007">"Шуурхай тохиргоонд гэрэлтүүлэг харах"</string>
     <string name="experimental" msgid="3549865454812314826">"Туршилтын"</string>
     <string name="enable_bluetooth_title" msgid="866883307336662596">"Bluetooth-г асаах уу?"</string>
     <string name="enable_bluetooth_message" msgid="6740938333772779717">"Компьютерийн гараа таблетад холбохын тулд эхлээд Bluetooth-г асаана уу."</string>
@@ -920,11 +920,11 @@
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"<xliff:g id="POSITION">%1$d</xliff:g> байрлал"</string>
     <string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Хавтан нэмсэн"</string>
     <string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Хавтанг хассан"</string>
-    <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Түргэн тохиргоо засварлагч."</string>
+    <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Шуурхай тохиргоо засварлагч."</string>
     <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> мэдэгдэл: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Тохиргоог нээнэ үү."</string>
     <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Шуурхай тохиргоог нээнэ үү."</string>
-    <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Хурдан тохиргоог хаана уу."</string>
+    <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Шуурхай тохиргоог хаана уу."</string>
     <string name="accessibility_quick_settings_alarm_set" msgid="7237918261045099853">"Сэрүүлэг тавьсан."</string>
     <string name="accessibility_quick_settings_user" msgid="505821942882668619">"<xliff:g id="ID_1">%s</xliff:g>-р нэвтэрсэн"</string>
     <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"хэрэглэгчийг сонгох"</string>
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Нээхийн тулд хурууны хээг ашиглана уу"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Баталгаажуулалт шаардлагатай. Баталгаажуулахын тулд хурууны хээ мэдрэгчид хүрнэ үү."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Үргэлжилж буй утасны дуудлага"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Нислэгийн горим"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобайл дата"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Холбогдсон"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Интернэт автоматаар холбогдохгүй"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мобайл дата автоматаар холбогдохгүй"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Холболт алга"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Өөр боломжтой сүлжээ байхгүй байна"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Боломжтой сүлжээ байхгүй байна"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index dd75e9a..633519a 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -1162,11 +1162,11 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"उघडण्यासाठी फिंगरप्रिंट वापरा"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ऑथेंटिकेशन आवश्यक आहे. ऑथेंटिकेट करण्यासाठी फिंगरप्रिंट सेन्सरला स्पर्श करा."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"फोन कॉल सुरू आहे"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"विमान मोड"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"कनेक्ट केले आहे"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"इंटरनेट ऑटो-कनेक्ट होणार नाही"</string>
+    <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
+    <skip />
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"कोणतेही कनेक्शन नाही"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"इतर कोणतेही नेटवर्क उपलब्ध नाहीत"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"कोणतेही नेटवर्क उपलब्‍ध नाही"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index eb16281..a689bb3 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gunakan cap jari untuk membuka"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Pengesahan diperlukan. Sentuh penderia cap jari untuk pengesahan."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Panggilan telefon yang sedang berjalan"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Mod pesawat"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Data mudah alih"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Disambungkan"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internet tidak akan bersambung secara automatik"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Data mudah alih tidak akan autosambung"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Tiada sambungan"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Tiada rangkaian lain yang tersedia"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Tiada rangkaian tersedia"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 5dcb09e..4975a0a 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ဖွင့်ရန် လက်ဗွေကို သုံးပါ"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"အထောက်အထားစိစစ်ခြင်း လိုအပ်သည်။ အထောက်အထားစိစစ်ရန် လက်ဗွေ အာရုံခံကိရိယာကို ထိပါ။"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"လက်ရှိ ဖုန်းခေါ်ဆိုမှု"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"လေယာဉ်ပျံမုဒ်"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"မိုဘိုင်းဒေတာ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"ချိတ်ဆက်ထားသည်"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"အင်တာနက်က အလိုအလျောက် ချိတ်ဆက်မည်မဟုတ်ပါ"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"မိုဘိုင်းဒေတာက အလိုအလျောက် ချိတ်ဆက်မည်မဟုတ်ပါ"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"ချိတ်ဆက်မှုမရှိပါ"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"အခြားကွန်ရက်များ မရှိပါ"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"ကွန်ရက်များ မရှိပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index e789d10..af8d47b 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Bruk fingeravtrykk for å åpne"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentisering kreves. Trykk på fingeravtrykkssensoren for å autentisere."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Pågående telefonsamtale"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Flymodus"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Tilkoblet"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internett kobles ikke til automatisk"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobildata kobler ikke til automatisk"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Ingen tilkobling"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Ingen andre nettverk er tilgjengelige"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Ingen nettverk er tilgjengelige"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 400b997..b6a186e 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"फिंगरप्रिन्ट प्रयोग गरी खोल्नुहोस्"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"पुष्टि गर्नु पर्ने हुन्छ। पुष्टि गर्न फिंगरप्रिन्ट सेन्सर छुनुहोस्।"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"जारी फोन कल"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"हवाइजहाज मोड"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"इन्टरनेटमा कनेक्ट गरिएको छ"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"इन्टरनेट स्वतः कनेक्ट हुँदैन"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"मोबाइल डेटा स्वतः कनेक्ट हुँदैन"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"इन्टरनेट छैन"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"अन्य नेटवर्क उपलब्ध छैनन्"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"कुनै पनि नेटवर्क उपलब्ध छैन"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 765d222..135ca57 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gebruik vingerafdruk om te openen"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Verificatie vereist. Raak de vingerafdruksensor aan om de verificatie uit te voeren."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Actief telefoongesprek"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Vliegtuigmodus"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiele data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Verbonden"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internet maakt niet automatisch verbinding"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobiele data maakt niet automatisch verbinding"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Geen verbinding"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Geen andere netwerken beschikbaar"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Geen netwerken beschikbaar"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 2aafac4..1d5ff4b 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -248,7 +248,7 @@
     <skip />
     <string name="accessibility_notification_dismissed" msgid="4411652015138892952">"ବିଜ୍ଞପ୍ତି ଖାରଜ କରାଗଲା।"</string>
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ବିଜ୍ଞପ୍ତି ଶେଡ୍‍।"</string>
-    <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ଦ୍ରୁତ ସେଟିଂସ୍।"</string>
+    <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"କ୍ୱିକ୍ ସେଟିଂସ୍।"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ଲକ୍‌ ସ୍କ୍ରୀନ୍‌।"</string>
     <string name="accessibility_desc_settings" msgid="6728577365389151969">"ସେଟିଂସ୍"</string>
     <string name="accessibility_desc_recent_apps" msgid="1748675199348914194">"ସଂକ୍ଷିପ୍ତ ବିବରଣୀ"</string>
@@ -659,7 +659,7 @@
     <string name="system_ui_tuner" msgid="1471348823289954729">"ସିଷ୍ଟମ୍ UI ଟ୍ୟୁନର୍‍"</string>
     <string name="show_battery_percentage" msgid="6235377891802910455">"ଏମ୍ବେଡ୍‍ ହୋଇଥିବା ବ୍ୟାଟେରୀ ଶତକଡ଼ା ଦେଖାନ୍ତୁ"</string>
     <string name="show_battery_percentage_summary" msgid="9053024758304102915">"ଚାର୍ଜ ହେଉନଥିବାବେଳେ ଷ୍ଟାଟସ୍‍ ବାର୍‍ ଆଇକନ୍‍ ଭିତରେ ବ୍ୟାଟେରୀ ସ୍ତର ଶତକଡ଼ା ଦେଖାନ୍ତୁ"</string>
-    <string name="quick_settings" msgid="6211774484997470203">"ଦ୍ରୁତ ସେଟିଂସ୍"</string>
+    <string name="quick_settings" msgid="6211774484997470203">"କ୍ୱିକ୍ ସେଟିଂସ୍"</string>
     <string name="status_bar" msgid="4357390266055077437">"ଷ୍ଟାଟସ୍‍ ବାର୍‍"</string>
     <string name="overview" msgid="3522318590458536816">"ଅବଲୋକନ"</string>
     <string name="demo_mode" msgid="263484519766901593">"ସିଷ୍ଟମ୍‌ UI ଡେମୋ ମୋଡ୍‌"</string>
@@ -684,7 +684,7 @@
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>ବେଳେ ଆପଣ ନିଜର ପରବର୍ତ୍ତୀ ଆଲାର୍ମ ଶୁଣିପାରିବେ ନାହିଁ"</string>
     <string name="alarm_template" msgid="2234991538018805736">"<xliff:g id="WHEN">%1$s</xliff:g> ହେଲେ"</string>
     <string name="alarm_template_far" msgid="3561752195856839456">"<xliff:g id="WHEN">%1$s</xliff:g> ବେଳେ"</string>
-    <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"ଦ୍ରୁତ ସେଟିଙ୍ଗ, <xliff:g id="TITLE">%s</xliff:g>।"</string>
+    <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"କ୍ୱିକ୍ ସେଟିଂସ୍, <xliff:g id="TITLE">%s</xliff:g>।"</string>
     <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"ହଟସ୍ପଟ୍‌"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ୱର୍କ ପ୍ରୋଫାଇଲ୍‌"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"କେତେକଙ୍କ ପାଇଁ ମଜାଦାର, କିନ୍ତୁ ସମସ୍ତଙ୍କ ପାଇଁ ନୁହେଁ"</string>
@@ -1162,11 +1162,11 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ଖୋଲିବାକୁ ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ପ୍ରମାଣୀକରଣ ଆବଶ୍ୟକ। ପ୍ରମାଣୀକରଣ କରିବାକୁ ଟିପଚିହ୍ନ ସେନ୍ସରକୁ ସ୍ପର୍ଶ କରନ୍ତୁ।"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ଚାଲୁଥିବା ଫୋନ୍ କଲ୍"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"ଏୟାରପ୍ଲେନ୍ ମୋଡ୍"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"ମୋବାଇଲ ଡାଟା"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"ସଂଯୋଗ କରାଯାଇଛି"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"ଇଣ୍ଟରନେଟ୍ ସ୍ଵତଃ-ସଂଯୋଗ ହେବ ନାହିଁ"</string>
+    <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
+    <skip />
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"ସଂଯୋଗ ନାହିଁ"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ଅନ୍ୟ କୌଣସି ନେଟୱାର୍କ ଉପଲବ୍ଧ ନାହିଁ"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"କୌଣସି ନେଟୱାର୍କ ଉପଲବ୍ଧ ନାହିଁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 4459ae1c..055d75b 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -1162,11 +1162,11 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ਖੋਲ੍ਹਣ ਲਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ਪ੍ਰਮਾਣੀਕਰਨ ਲੋੜੀਂਦਾ ਹੈ। ਪ੍ਰਮਾਣਿਤ ਕਰਨ ਲਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨੂੰ ਸਪਰਸ਼ ਕਰੋ।"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ਜਾਰੀ ਫ਼ੋਨ ਕਾਲ"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"ਮੋਬਾਈਲ ਡਾਟਾ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"ਕਨੈਕਟ ਹੈ"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"ਇੰਟਰਨੈੱਟ ਸਵੈ-ਕਨੈਕਟ ਨਹੀਂ ਹੋਵੇਗਾ"</string>
+    <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
+    <skip />
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"ਕੋਈ ਕਨੈਕਸ਼ਨ ਨਹੀਂ"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ਕੋਈ ਹੋਰ ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"ਕੋਈ ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 7b165b2..fc32959 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -1174,11 +1174,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"By otworzyć, użyj odcisku palca"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Wymagane uwierzytelnienie. Dotknij czytnika liniii papilarnych, by uwierzytelnić."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Aktywne połączenie"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Tryb samolotowy"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilna transmisja danych"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Połączono"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Nie połączy się automatycznie z internetem"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilna transmisja danych nie połączy się automatycznie"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Brak połączenia"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Brak innych dostępnych sieci"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Brak dostępnych sieci"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 8496c92..2488012 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use a impressão digital para abrir"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação obrigatória. Toque no sensor de impressão digital para autenticar."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada em andamento"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Modo avião"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"A Internet não será conectada automaticamente"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Sem conexão automática com dados móveis"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sem conexão"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nenhuma outra rede disponível"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Nenhuma rede disponível"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 6da3120..68d306d 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Utilize a impressão digital para abrir"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação necessária. Toque no sensor de impressões digitais para autenticar."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada telefónica em curso"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Modo de avião"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Ligado"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"A Internet não estabelece ligação automaticamente"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Não é efetuada ligação de dados móveis automática"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sem ligação"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nenhuma outra rede disponível"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Sem redes disponíveis"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 8496c92..2488012 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use a impressão digital para abrir"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação obrigatória. Toque no sensor de impressão digital para autenticar."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada em andamento"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Modo avião"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"A Internet não será conectada automaticamente"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Sem conexão automática com dados móveis"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sem conexão"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nenhuma outra rede disponível"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Nenhuma rede disponível"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 61a8577..169108a 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -1168,11 +1168,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Folosiți amprenta ca să deschideți"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentificare obligatorie. Atingeți senzorul de amprentă pentru a vă autentifica."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Apel telefonic în desfășurare"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Modul Avion"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Date mobile"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectat"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Nu se conectează automat la internet"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Nu se conectează automat la date mobile"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nicio conexiune"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nu sunt disponibile alte rețele"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Nicio rețea disponibilă"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index deb9a42..1859acd 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -1174,11 +1174,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Используйте отпечаток пальца для входа."</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Требуется аутентификация. Приложите палец к сканеру отпечатков."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Текущий вызов"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Режим полета"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобильный интернет"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Подключено"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Без автоподключения к интернету"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Без автоподключения к мобильному интернету"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Нет подключения к интернету"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Нет других доступных сетей"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Нет доступных сетей"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 5660534..2df39d7 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"විවෘත කිරීමට ඇඟිලි සලකුණ භාවිත කරන්න"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"සත්‍යාපනය අවශ්‍යයි. සත්‍යාපනය කිරීමට ඇඟිලි සලකුණු සංවේදකය ස්පර්ශ කරන්න."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ක්‍රියාත්මක වන දුරකථන ඇමතුම"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"ගුවන් යානා ප්‍රකාරය"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"ජංගම දත්ත"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"සම්බන්ධයි"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"අන්තර්ජාලය ස්වයංක්‍රියව සම්බන්ධ නොවනු ඇත"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"ජංගම දත්ත ස්වංක්‍රියව සම්බන්ධ නොවනු ඇත"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"සම්බන්ධතාවයක් නැත"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ලබා ගත හැකි වෙනත් ජාල නැත"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"ජාලය නොතිබේ"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 4f7e4b5..6ef5ad5 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -1174,11 +1174,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorte odtlačkom prsta"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Vyžaduje sa overenie. Dotknite sa senzora odtlačkov prstov."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Prebiehajúci telefonický hovor"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Režim v lietadle"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilné dáta"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Pripojené"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internet sa nepripojí automaticky"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Automatické pripojenie cez mobilné dáta nefunguje"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Bez pripojenia"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nie sú k dispozícii žiadne ďalšie siete"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Nie sú k dispozícii žiadne siete"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index bffccff..977104c 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -1174,11 +1174,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Odprite s prstnim odtisom"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Zahtevano je preverjanje pristnosti. Za preverjanje pristnosti se dotaknite tipala prstnih odtisov."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Poteka klic"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Način za letalo"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Prenos podatkov v mobilnem omrežju"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Samodejna povezava z internetom ni mogoča."</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilna podatkovna povezava ne bo samodejna."</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Ni povezave"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nobeno drugo omrežje ni na voljo"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Na voljo ni nobeno omrežje"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 52ee8c6..970b84c 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -1162,11 +1162,11 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Përdor gjurmën e gishtit për ta hapur"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kërkohet vërtetimi. Prek sensorin e gjurmës së gishtit për t\'u vërtetuar."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonatë në vazhdim"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Modaliteti i aeroplanit"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Të dhënat celulare"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Lidhur"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Interneti nuk do të lidhet automatikisht"</string>
+    <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
+    <skip />
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Nuk ka lidhje"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nuk ofrohet asnjë rrjet tjetër"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Nuk ofrohet asnjë rrjet"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index bc65fe7..e83b423 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -1014,7 +1014,7 @@
     <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Апликације користе <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
     <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
     <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string>
-    <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Користи <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_using_op" msgid="426635338010011796">"Користи: <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_recent_op" msgid="2736290123662790026">"Недавно користио/ла <xliff:g id="APPLICATION_NAME">%1$s</xliff:g>"</string>
     <string name="ongoing_privacy_dialog_enterprise" msgid="3003314125311966061">"(посао)"</string>
     <string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Телефонски позив"</string>
@@ -1168,11 +1168,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Отворите помоћу отиска прста"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Потребна је потврда идентитета. Додирните сензор за отисак прста да бисте потврдили идентитет."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Актуелни телефонски позив"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Режим рада у авиону"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилни подаци"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Повезано"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Аутоматско повезивање на интернет није могуће"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Није успело аутом. повезивање преко моб. података"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Веза није успостављена"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Није доступна ниједна друга мрежа"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Нема доступних мрежа"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 022d8f7..bd819e5 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Öppna med fingeravtryck"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentisering krävs. Identifiera dig genom att trycka på fingeravtryckssensorn."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Pågående samtal"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Flygplansläge"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Ansluten"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Du ansluts inte automatiskt till internet"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Du ansluts inte till mobildata automatiskt"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Ingen anslutning"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Inga andra nätverk är tillgängliga"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Det finns inga tillgängliga nätverk"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index aef8cba..121bcd2 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Tumia alama ya kidole kufungua"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Uthibitishaji unahitajika. Gusa kitambua alama ya kidole ili uthibitishe."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Simu inayoendelea"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Hali ya ndegeni"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Data ya mtandao wa simu"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Imeunganishwa"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Intaneti haitaunganishwa kiotomatiki"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Data ya mtandao wa simu haitaunganishwa kiotomatiki"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Hakuna muunganisho"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Hakuna mitandao mingine inayopatikana"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Hakuna mitandao inayopatikana"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 93ac01d..74bdd32 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -452,7 +452,7 @@
     <string name="zen_silence_introduction" msgid="6117517737057344014">"இது அலாரங்கள், இசை, வீடியோக்கள் மற்றும் கேம்ஸ் உட்பட எல்லா ஒலிகளையும் அதிர்வுகளையும் தடுக்கும்."</string>
     <string name="keyguard_more_overflow_text" msgid="5819512373606638727">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="7248696377626341060">"அவசர நிலைக் குறைவான அறிவிப்புகள் கீழே உள்ளன"</string>
-    <string name="notification_tap_again" msgid="4477318164947497249">"திறக்க, மீண்டும் தட்டவும்"</string>
+    <string name="notification_tap_again" msgid="4477318164947497249">"அன்லாக் செய்ய, மீண்டும் தட்டவும்"</string>
     <string name="tap_again" msgid="1315420114387908655">"மீண்டும் தட்டவும்"</string>
     <string name="keyguard_unlock" msgid="8031975796351361601">"திறப்பதற்கு மேல் நோக்கி ஸ்வைப் செய்யவும்"</string>
     <string name="keyguard_unlock_press" msgid="8488350566398524740">"திறப்பதற்கு அழுத்தவும்"</string>
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"கைரேகையைப் பயன்படுத்தி திறந்திடுங்கள்"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"அங்கீகாரம் தேவை. கைரேகை சென்சாரைத் தொட்டு அங்கீகரியுங்கள்."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"செயலில் உள்ள மொபைல் அழைப்பு"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"விமானப் பயன்முறை"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"மொபைல் டேட்டா"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"இணைக்கப்பட்டது"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"இணையத்துடன் தானாகவே இணைக்காது"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"மொபைல் டேட்டாவுடன் தானாக இணைக்காது"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"இணைப்பு இல்லை"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"வேறு நெட்வொர்க்குகள் எதுவும் கிடைக்கவில்லை"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"நெட்வொர்க்குகள் எதுவும் கிடைக்கவில்லை"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 8c1d5b9..b643685 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -277,8 +277,8 @@
     <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="1263282011749437549">"బ్లూటూత్ ఆన్ చేయబడింది."</string>
     <string name="accessibility_quick_settings_location_off" msgid="6122523378294740598">"లొకేషన్ రిపోర్టింగ్ ఆఫ్‌లో ఉంది."</string>
     <string name="accessibility_quick_settings_location_on" msgid="6869947200325467243">"లొకేషన్ రిపోర్టింగ్ ఆన్‌లో ఉంది."</string>
-    <string name="accessibility_quick_settings_location_changed_off" msgid="5132776369388699133">"స్థాన నివేదన ఆఫ్ చేయబడింది."</string>
-    <string name="accessibility_quick_settings_location_changed_on" msgid="7159115433070112154">"స్థాన నివేదన ఆన్ చేయబడింది."</string>
+    <string name="accessibility_quick_settings_location_changed_off" msgid="5132776369388699133">"లొకేషన్ రిపోర్టింగ్ ఆఫ్ చేయబడింది."</string>
+    <string name="accessibility_quick_settings_location_changed_on" msgid="7159115433070112154">"లొకేషన్ రిపోర్టింగ్ ఆన్ చేయబడింది."</string>
     <string name="accessibility_quick_settings_alarm" msgid="558094529584082090">"<xliff:g id="TIME">%s</xliff:g>కి అలారం సెట్ చేయబడింది."</string>
     <string name="accessibility_quick_settings_close" msgid="2974895537860082341">"ప్యానెల్‌ను మూసివేయి."</string>
     <string name="accessibility_quick_settings_more_time" msgid="7646479831704665284">"ఎక్కువ సమయం."</string>
@@ -308,7 +308,7 @@
     <string name="data_usage_disabled_dialog" msgid="7933201635215099780">"మీరు సెట్ చేసిన డేటా పరిమితిని చేరుకున్నారు. మీరు ఇప్పుడు మొబైల్ డేటాను ఉపయోగించడం లేదు.\n\nమీరు పునఃప్రారంభిస్తే, డేటా వినియోగానికి ఛార్జీలు చెల్లించాల్సి రావచ్చు."</string>
     <string name="data_usage_disabled_dialog_enable" msgid="2796648546086408937">"పునఃప్రారంభించు"</string>
     <string name="gps_notification_searching_text" msgid="231304732649348313">"GPS కోసం శోధిస్తోంది"</string>
-    <string name="gps_notification_found_text" msgid="3145873880174658526">"స్థానం GPS ద్వారా సెట్ చేయబడింది"</string>
+    <string name="gps_notification_found_text" msgid="3145873880174658526">"లొకేషన్ GPS ద్వారా సెట్ చేయబడింది"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"లొకేషన్ రిక్వెస్ట్‌లు యాక్టివ్‌గా ఉన్నాయి"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"సెన్సార్‌లు ఆఫ్ యాక్టివ్‌లో ఉంది"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"అన్ని నోటిఫికేషన్‌లను క్లియర్ చేయండి."</string>
@@ -659,7 +659,7 @@
     <string name="system_ui_tuner" msgid="1471348823289954729">"సిస్టమ్ UI ట్యూనర్"</string>
     <string name="show_battery_percentage" msgid="6235377891802910455">"పొందుపరిచిన బ్యాటరీ శాతం చూపు"</string>
     <string name="show_battery_percentage_summary" msgid="9053024758304102915">"ఛార్జింగ్‌లో లేనప్పుడు స్థితి పట్టీ చిహ్నం లోపల బ్యాటరీ స్థాయి శాతం చూపుతుంది"</string>
-    <string name="quick_settings" msgid="6211774484997470203">"శీఘ్ర సెట్టింగ్‌లు"</string>
+    <string name="quick_settings" msgid="6211774484997470203">"క్విక్ సెట్టింగ్‌లు"</string>
     <string name="status_bar" msgid="4357390266055077437">"స్థితి పట్టీ"</string>
     <string name="overview" msgid="3522318590458536816">"ఓవర్‌వ్యూ"</string>
     <string name="demo_mode" msgid="263484519766901593">"సిస్టమ్ UI డెమో మోడ్"</string>
@@ -1162,11 +1162,11 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"తెరవడానికి వేలిముద్రను ఉపయోగించండి"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ప్రామాణీకరణ అవసరం. ప్రామాణీకరించడానికి వేలిముద్ర సెన్సార్‌ను తాకండి."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ఫోన్ కాల్ జరుగుతోంది"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"విమానం మోడ్"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"మొబైల్ డేటా"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"కనెక్ట్ చేయబడింది"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"ఇంటర్నెట్ ఆటోమెటిక్‌గా కనెక్ట్ అవ్వదు"</string>
+    <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
+    <skip />
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"కనెక్షన్ లేదు"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ఇతర నెట్‌వర్క్‌లేవీ అందుబాటులో లేవు"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"నెట్‌వర్క్‌లు అందుబాటులో లేవు"</string>
diff --git a/packages/SystemUI/res/values-television/styles.xml b/packages/SystemUI/res/values-television/styles.xml
index 0fb7898..6fdf2c4 100644
--- a/packages/SystemUI/res/values-television/styles.xml
+++ b/packages/SystemUI/res/values-television/styles.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
     <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Dialog" />
     <style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Dialog.Alert" />
 
@@ -25,7 +26,7 @@
 
     <style name="volume_dialog_theme" parent="Theme.SystemUI">
         <item name="android:colorAccent">@color/tv_volume_dialog_accent</item>
-        <item name="android:textColorPrimaryInverse">@color/tv_volume_dialog_accent</item>
+        <item name="androidprv:textColorOnAccent">@color/tv_volume_dialog_accent</item>
         <item name="android:dialogCornerRadius">@dimen/volume_dialog_panel_width_half</item>
     </style>
 
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 0a76977..b27cd3e 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ใช้ลายนิ้วมือเพื่อเปิด"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ต้องมีการตรวจสอบสิทธิ์ แตะเซ็นเซอร์ลายนิ้วมือเพื่อตรวจสอบสิทธิ์"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"กำลังโทรอยู่"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"โหมดบนเครื่องบิน"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"อินเทอร์เน็ตมือถือ"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"เชื่อมต่อแล้ว"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"อินเทอร์เน็ตจะไม่เชื่อมต่ออัตโนมัติ"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"อินเทอร์เน็ตมือถือจะไม่เชื่อมต่ออัตโนมัติ"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"ไม่มีการเชื่อมต่อ"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"ไม่มีเครือข่ายอื่นๆ ที่พร้อมใช้งาน"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"ไม่มีเครือข่ายที่พร้อมใช้งาน"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index c5c4cf3..11a23f8 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gamitin ang fingerprint para buksan"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kailangan ng pag-authenticate. Pindutin ang sensor para sa fingerprint para mag-authenticate."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Kasalukuyang may tawag sa telepono"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Airplane mode"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Nakakonekta"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Hindi awtomatikong kokonekta ang Internet"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Hindi awtomatikong kokonekta ang mobile data"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Walang koneksyon"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Walang available na iba pang network"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Walang available na network"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index d22472e..a5c06f1 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Açmak için parmak izi kullanın"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kimlik doğrulaması gerekiyor. Kimlik doğrulaması için parmak izi sensörüne dokunun."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Devam eden telefon görüşmesi"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Uçak modu"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil veri"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Bağlı"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"İnternete otomatik olarak bağlanmaz"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobil veri otomatik olarak bağlanmıyor"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Bağlantı yok"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Kullanılabilir başka ağ yok"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Kullanılabilir ağ yok"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index c364429..616b0f2 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -1174,11 +1174,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Щоб відкрити, використайте відбиток пальця"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Пройдіть автентифікацію. Для цього торкніться сканера відбитків пальців."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Активний телефонний виклик"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Режим польоту"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобільний трафік"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Підключено"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Автоматичне інтернет-з’єднання вимкнено"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Мобільний Інтернет не підключатиметься автоматично"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Немає з\'єднання"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Інші мережі недоступні"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Немає доступних мереж"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 59d2acf..a42729e 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -1162,11 +1162,11 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"کھولنے کے لیے فنگر پرنٹ کا استعمال کریں"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"توثیق مطلوب ہے۔ توثیق کرنے کے لیے فنگر پرنٹ سینسر کو ٹچ کریں۔"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"جاری فون کال"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"ہوائی جہاز وضع"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"موبائل ڈیٹا"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="NETWORKMODE">%2$s</xliff:g> / <xliff:g id="STATE">%1$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"منسلک ہے"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"انٹرنیٹ خود کار طور پر منسلک نہیں ہوگا"</string>
+    <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
+    <skip />
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"کوئی کنکشن نہیں"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"کوئی دوسرا نیٹ ورک دستیاب نہیں ہے"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"کوئی نیٹ ورکس دستیاب نہیں ہیں"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index b7a6448..e91ec32 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -1162,11 +1162,11 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Ochish uchun barmoq izidan foydalaning"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Haqiqiylikni tekshirish talab etiladi. Autentifikatsiya uchun barmoq izi skaneriga tegining."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Joriy telefon chaqiruvi"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Parvoz rejimi"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil internet"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Ulandi"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Internet avtomatik ravishda ulanmaydi"</string>
+    <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
+    <skip />
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Internetga ulanmagansiz"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Boshqa tarmoqlar mavjud emas"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Hech qanday tarmoq mavjud emas"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 48b3e4c..a52c999 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Dùng vân tay để mở"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Bạn cần phải xác thực. Hãy chạm vào cảm biến vân tay để xác thực."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Đang gọi điện thoại"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Chế độ trên máy bay"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dữ liệu di động"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Đã kết nối"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"Sẽ không tự động kết nối Internet"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Dữ liệu di động sẽ không tự động kết nối"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Không có kết nối mạng"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Không có mạng nào khác"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Không có mạng"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index aa3895b..d9fadf6 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"使用指纹即可打开"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"需要进行身份验证。请轻触指纹传感器以验证身份。"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"正在进行通话"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"飞行模式"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"移动数据网络"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"已连接"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"不会自动连接到互联网"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"系统将不会自动连接到移动数据网络"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"无网络连接"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"没有其他可用网络"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"没有可用网络"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 3a46bd4..ee853ce 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"使用指紋即可開啟"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"需要驗證。掂一下指紋感應器就可以驗證。"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"通話中"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"飛行模式"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"流動數據"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"已連線"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"不會自動連線至互聯網"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"不會自動連線至流動數據"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"沒有連線"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"沒有可用的其他網絡"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"沒有可用的網絡"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 2a04ca2..dccbcc4 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"使用指紋即可開啟"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"需要驗證。輕觸指紋感應器即可進行驗證。"</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"通話中"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"飛航模式"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"行動數據"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"已連線"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"不會自動連上網際網路"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"系統將不會自動使用行動數據連線"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"沒有網路連線"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"沒有可用的其他網路"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"沒有可用的網路"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 649b3cd..683890f 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -1162,11 +1162,10 @@
     <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Sebenzisa izigxivizo zeminwe ukuvula"</string>
     <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Ukufakazela ubuqiniso budingekile. Thinta inzwa yezigxivizo zeminwe ukuze uqinisekise."</string>
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ikholi yefoni eqhubekayo"</string>
-    <string name="airplane_mode" msgid="2536350001462130668">"Imodi yendiza"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Idatha yeselula"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Ixhunyiwe"</string>
-    <string name="mobile_data_off_summary" msgid="5621158216585822679">"I-inthanethi ngeke ixhumeke ngokuzenzakalelayo"</string>
+    <string name="mobile_data_off_summary" msgid="3663995422004150567">"Idatha yeselula ngeke ikwazi ukuxhuma ngokuzenzekelayo"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Alukho uxhumano"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"Awekho amanye amanethiwekhi atholakalayo"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"Awekho amanethiwekhi atholakalayo"</string>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 3121ce3..db69924 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -77,6 +77,7 @@
         <attr name="numColumns" format="integer" />
         <attr name="verticalSpacing" format="dimension" />
         <attr name="horizontalSpacing" format="dimension" />
+        <attr name="fixedChildWidth" format="dimension" />
     </declare-styleable>
 
     <!-- Theme for icons in the status/nav bar (light/dark). background/fillColor is used for dual
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index e309994..fb90d63 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -703,4 +703,36 @@
 
     <!-- Flag to activate notification to contents feature -->
     <bool name="config_notificationToContents">false</bool>
+
+    <!-- Respect drawable/rounded_secondary.xml intrinsic size for multiple radius corner path
+         customization for secondary display-->
+    <bool name="config_roundedCornerMultipleRadiusSecondary">false</bool>
+
+    <!-- Whether the rounded corners are multiple radius for each display in a multi-display device.
+         {@see com.android.internal.R.array#config_displayUniqueIdArray} -->
+    <array name="config_roundedCornerMultipleRadiusArray">
+        <item>@bool/config_roundedCornerMultipleRadius</item>
+        <item>@bool/config_roundedCornerMultipleRadiusSecondary</item>
+    </array>
+
+    <!-- The rounded corner drawable for each display in a multi-display device.
+         {@see com.android.internal.R.array#config_displayUniqueIdArray} -->
+    <array name="config_roundedCornerDrawableArray">
+        <item>@drawable/rounded</item>
+        <item>@drawable/rounded_secondary</item>
+    </array>
+
+    <!-- The top rounded corner drawable for each display in a multi-display device.
+         {@see com.android.internal.R.array#config_displayUniqueIdArray} -->
+    <array name="config_roundedCornerTopDrawableArray">
+        <item>@drawable/rounded_corner_top</item>
+        <item>@drawable/rounded_corner_top_secondary</item>
+    </array>
+
+    <!-- The bottom rounded corner drawable for each display in a multi-display device.
+         {@see com.android.internal.R.array#config_displayUniqueIdArray} -->
+    <array name="config_roundedCornerBottomDrawableArray">
+        <item>@drawable/rounded_corner_bottom</item>
+        <item>@drawable/rounded_corner_bottom_secondary</item>
+    </array>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 4d19c07..6d792be 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1306,8 +1306,6 @@
     <dimen name="qs_media_action_margin">12dp</dimen>
     <dimen name="qs_seamless_height">24dp</dimen>
     <dimen name="qs_seamless_icon_size">12dp</dimen>
-    <dimen name="qs_seamless_fallback_icon_size">@dimen/qs_seamless_icon_size</dimen>
-    <dimen name="qs_seamless_fallback_margin">20dp</dimen>
     <dimen name="qs_footer_horizontal_margin">22dp</dimen>
     <dimen name="qs_media_disabled_seekbar_height">1dp</dimen>
     <dimen name="qs_media_enabled_seekbar_height">2dp</dimen>
@@ -1640,4 +1638,9 @@
     <dimen name="qs_tile_service_request_dialog_width">304dp</dimen>
     <dimen name="qs_tile_service_request_tile_width">192dp</dimen>
     <dimen name="qs_tile_service_request_content_space">24dp</dimen>
+
+    <dimen name="qs_dialog_button_horizontal_padding">16dp</dimen>
+    <dimen name="qs_dialog_button_vertical_padding">8dp</dimen>
+    <!-- The button will be 48dp tall, but the background needs to be 36dp tall -->
+    <dimen name="qs_dialog_button_vertical_inset">6dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index a9cc6ac..5ef9163 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -56,4 +56,6 @@
     <bool name="flag_smartspace_deduping">true</bool>
 
     <bool name="flag_combined_status_bar_signal_icons">false</bool>
+
+    <bool name="flag_new_user_switcher">false</bool>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index fd31f3f..8f80421 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1008,7 +1008,7 @@
     <string name="sensor_privacy_start_use_mic_camera_dialog_content">This unblocks access for all apps and services allowed to use your camera or microphone.</string>
 
     <!-- Default name for the media device shown in the output switcher when the name is not available [CHAR LIMIT=30] -->
-    <string name="media_seamless_remote_device">Device</string>
+    <string name="media_seamless_other_device">Other device</string>
 
     <!-- QuickStep: Accessibility to toggle overview [CHAR LIMIT=40] -->
     <string name="quick_step_accessibility_toggle_overview">Toggle Overview</string>
@@ -3030,4 +3030,7 @@
     <string name="qs_tile_request_dialog_add">Add tile</string>
     <!-- Text for TileService request dialog. Text for button for user to reject adding the tile [CHAR LIMIT=20] -->
     <string name="qs_tile_request_dialog_not_add">Do not add tile</string>
+
+    <!-- Title for User Switch dialog. [CHAR LIMIT=20] -->
+    <string name="qs_user_switch_dialog_title">Select user</string>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 7f4866f..dc17afb 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -944,6 +944,39 @@
         <item name="actionDividerHeight">32dp</item>
     </style>
 
+    <style name="Theme.SystemUI.Dialog.QSDialog">
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:windowIsFloating">true</item>
+        <item name="android:backgroundDimEnabled">true</item>
+        <item name="android:windowCloseOnTouchOutside">true</item>
+        <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
+        <item name="android:dialogCornerRadius">28dp</item>
+        <item name="android:buttonCornerRadius">28dp</item>
+        <item name="android:colorBackground">@color/prv_color_surface</item>
+    </style>
+
+    <style name="TextAppearance.QSDialog.Title" parent="Theme.SystemUI.Dialog.QSDialog">
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:textSize">24sp</item>
+        <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+        <item name="android:lineHeight">32sp</item>
+    </style>
+
+    <style name="Widget.QSDialog.Button" parent = "Theme.SystemUI.Dialog.QSDialog">
+        <item name="android:background">@drawable/qs_dialog_btn_filled</item>
+        <item name="android:textColor">@color/prv_text_color_on_accent</item>
+        <item name="android:textSize">14sp</item>
+        <item name="android:lineHeight">20sp</item>
+        <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+        <item name="android:stateListAnimator">@null</item>
+    </style>
+
+    <style name="Widget.QSDialog.Button.BorderButton">
+        <item name="android:background">@drawable/qs_dialog_btn_outline</item>
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
+    </style>
+
     <style name="Theme.SystemUI.Dialog.Internet">
         <item name="android:windowBackground">@drawable/internet_dialog_background</item>
     </style>
diff --git a/packages/SystemUI/res/xml/media_collapsed.xml b/packages/SystemUI/res/xml/media_collapsed.xml
index d6c6a60..c3510b6 100644
--- a/packages/SystemUI/res/xml/media_collapsed.xml
+++ b/packages/SystemUI/res/xml/media_collapsed.xml
@@ -44,23 +44,6 @@
         />
 
     <Constraint
-        android:id="@+id/media_seamless_fallback"
-        android:layout_width="@dimen/qs_seamless_fallback_icon_size"
-        android:layout_height="@dimen/qs_seamless_fallback_icon_size"
-        android:layout_marginTop="@dimen/qs_media_padding"
-        android:layout_marginBottom="@dimen/qs_media_padding"
-        android:layout_marginStart="@dimen/qs_center_guideline_padding"
-        android:layout_marginEnd="@dimen/qs_seamless_fallback_margin"
-        android:alpha="0.5"
-        android:visibility="gone"
-        app:layout_constraintHorizontal_bias="1"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintBottom_toTopOf="@id/center_horizontal_guideline"
-        app:layout_constraintStart_toEndOf="@id/center_vertical_guideline"
-        app:layout_constraintEnd_toEndOf="parent"
-        />
-
-    <Constraint
         android:id="@+id/album_art"
         android:layout_width="@dimen/qs_media_album_size_small"
         android:layout_height="@dimen/qs_media_album_size_small"
diff --git a/packages/SystemUI/res/xml/media_expanded.xml b/packages/SystemUI/res/xml/media_expanded.xml
index 0e284e6..6b83aae 100644
--- a/packages/SystemUI/res/xml/media_expanded.xml
+++ b/packages/SystemUI/res/xml/media_expanded.xml
@@ -45,22 +45,6 @@
         android:layout_marginBottom="4dp" />
 
     <Constraint
-        android:id="@+id/media_seamless_fallback"
-        android:layout_width="@dimen/qs_seamless_fallback_icon_size"
-        android:layout_height="@dimen/qs_seamless_fallback_icon_size"
-        android:layout_marginTop="@dimen/qs_media_padding"
-        android:layout_marginBottom="16dp"
-        android:layout_marginStart="@dimen/qs_center_guideline_padding"
-        android:layout_marginEnd="@dimen/qs_seamless_fallback_margin"
-        android:alpha="0.5"
-        android:visibility="gone"
-        app:layout_constraintHorizontal_bias="1"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintStart_toEndOf="@id/center_vertical_guideline"
-        app:layout_constraintEnd_toEndOf="parent"
-        />
-
-    <Constraint
         android:id="@+id/album_art"
         android:layout_width="@dimen/qs_media_album_size"
         android:layout_height="@dimen/qs_media_album_size"
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
index 915e7f6..e5933e6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
@@ -16,7 +16,6 @@
 package com.android.systemui.shared.animation
 
 import android.graphics.Point
-import android.util.MathUtils.lerp
 import android.view.Surface
 import android.view.View
 import android.view.WindowManager
@@ -27,7 +26,7 @@
  * Creates an animation where all registered views are moved into their final location
  * by moving from the center of the screen to the sides
  */
-class UnfoldMoveFromCenterAnimator(
+class UnfoldMoveFromCenterAnimator @JvmOverloads constructor(
     private val windowManager: WindowManager,
     /**
      * Allows to set custom translation applier
@@ -36,14 +35,13 @@
      * using custom methods instead of [View.setTranslationX] or
      * [View.setTranslationY]
      */
-    var translationApplier: TranslationApplier = object : TranslationApplier {}
+    private val translationApplier: TranslationApplier = object : TranslationApplier {},
 ) : UnfoldTransitionProgressProvider.TransitionProgressListener {
 
     private val screenSize = Point()
     private var isVerticalFold = false
 
     private val animatedViews: MutableList<AnimatedView> = arrayListOf()
-    private val tmpArray = IntArray(2)
 
     /**
      * Updates display properties in order to calculate the initial position for the views
@@ -82,45 +80,52 @@
             it.view.get()?.let { view ->
                 translationApplier.apply(
                     view = view,
-                    x = lerp(it.startTranslationX, it.finishTranslationX, progress),
-                    y = lerp(it.startTranslationY, it.finishTranslationY, progress)
+                    x = it.startTranslationX * (1 - progress),
+                    y = it.startTranslationY * (1 - progress)
                 )
             }
         }
     }
 
     private fun createAnimatedView(view: View): AnimatedView {
-        val viewLocation = tmpArray
-        view.getLocationOnScreen(viewLocation)
+        val viewCenter = getViewCenter(view)
+        val viewCenterX = viewCenter.x
+        val viewCenterY = viewCenter.y
 
-        val viewX = viewLocation[0].toFloat()
-        val viewY = viewLocation[1].toFloat()
-
-        val viewCenterX = viewX + view.width / 2
-        val viewCenterY = viewY + view.height / 2
-
-        val translationXDiff: Float
-        val translationYDiff: Float
+        val translationX: Float
+        val translationY: Float
 
         if (isVerticalFold) {
             val distanceFromScreenCenterToViewCenter = screenSize.x / 2 - viewCenterX
-            translationXDiff = distanceFromScreenCenterToViewCenter * TRANSLATION_PERCENTAGE
-            translationYDiff = 0f
+            translationX = distanceFromScreenCenterToViewCenter * TRANSLATION_PERCENTAGE
+            translationY = 0f
         } else {
             val distanceFromScreenCenterToViewCenter = screenSize.y / 2 - viewCenterY
-            translationXDiff = 0f
-            translationYDiff = distanceFromScreenCenterToViewCenter * TRANSLATION_PERCENTAGE
+            translationX = 0f
+            translationY = distanceFromScreenCenterToViewCenter * TRANSLATION_PERCENTAGE
         }
 
         return AnimatedView(
             view = WeakReference(view),
-            startTranslationX = view.translationX + translationXDiff,
-            startTranslationY = view.translationY + translationYDiff,
-            finishTranslationX = view.translationX,
-            finishTranslationY = view.translationY
+            startTranslationX = translationX,
+            startTranslationY = translationY
         )
     }
 
+    private fun getViewCenter(view: View): Point {
+        val viewLocation = IntArray(2)
+        view.getLocationOnScreen(viewLocation)
+
+        val viewX = viewLocation[0]
+        val viewY = viewLocation[1]
+
+        val outPoint = Point()
+        outPoint.x = viewX + view.width / 2
+        outPoint.y = viewY + view.height / 2
+
+        return outPoint
+    }
+
     /**
      * Interface that allows to use custom logic to apply translation to view
      */
@@ -137,9 +142,7 @@
     private class AnimatedView(
         val view: WeakReference<View>,
         val startTranslationX: Float,
-        val startTranslationY: Float,
-        val finishTranslationX: Float,
-        val finishTranslationY: Float
+        val startTranslationY: Float
     )
 }
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/navigationbar/RegionSamplingHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/navigationbar/RegionSamplingHelper.java
index bcfb774..9808374 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/navigationbar/RegionSamplingHelper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/navigationbar/RegionSamplingHelper.java
@@ -72,6 +72,8 @@
     private boolean mWindowVisible;
     private boolean mWindowHasBlurs;
     private SurfaceControl mRegisteredStopLayer = null;
+    // A copy of mRegisteredStopLayer where we own the life cycle and can access from a bg thread.
+    private SurfaceControl mWrappedStopLayer = null;
     private ViewTreeObserver.OnDrawListener mUpdateOnDraw = new ViewTreeObserver.OnDrawListener() {
         @Override
         public void onDraw() {
@@ -184,16 +186,21 @@
             }
             if (!mSamplingRequestBounds.equals(mRegisteredSamplingBounds)
                     || mRegisteredStopLayer != stopLayerControl) {
-                // We only want to reregister if something actually changed
+                // We only want to re-register if something actually changed
                 unregisterSamplingListener();
                 mSamplingListenerRegistered = true;
-                SurfaceControl registeredStopLayer = stopLayerControl;
+                SurfaceControl wrappedStopLayer = stopLayerControl == null
+                        ? null : new SurfaceControl(stopLayerControl, "regionSampling");
                 mBackgroundExecutor.execute(() -> {
+                    if (wrappedStopLayer != null && !wrappedStopLayer.isValid()) {
+                        return;
+                    }
                     CompositionSamplingListener.register(mSamplingListener, DEFAULT_DISPLAY,
-                            registeredStopLayer, mSamplingRequestBounds);
+                            wrappedStopLayer, mSamplingRequestBounds);
                 });
                 mRegisteredSamplingBounds.set(mSamplingRequestBounds);
-                mRegisteredStopLayer = registeredStopLayer;
+                mRegisteredStopLayer = stopLayerControl;
+                mWrappedStopLayer = wrappedStopLayer;
             }
             mFirstSamplingAfterStart = false;
         } else {
@@ -204,10 +211,14 @@
     private void unregisterSamplingListener() {
         if (mSamplingListenerRegistered) {
             mSamplingListenerRegistered = false;
+            SurfaceControl wrappedStopLayer = mWrappedStopLayer;
             mRegisteredStopLayer = null;
             mRegisteredSamplingBounds.setEmpty();
             mBackgroundExecutor.execute(() -> {
                 CompositionSamplingListener.unregister(mSamplingListener);
+                if (wrappedStopLayer != null && wrappedStopLayer.isValid()) {
+                    wrappedStopLayer.release();
+                }
             });
         }
     }
@@ -262,6 +273,7 @@
         pw.println("  mWindowHasBlurs: " + mWindowHasBlurs);
         pw.println("  mWaitingOnDraw: " + mWaitingOnDraw);
         pw.println("  mRegisteredStopLayer: " + mRegisteredStopLayer);
+        pw.println("  mWrappedStopLayer: " + mWrappedStopLayer);
         pw.println("  mIsDestroyed: " + mIsDestroyed);
     }
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java
new file mode 100644
index 0000000..9ea4b57
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2016 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.shared.plugins;
+
+import android.app.Notification;
+import android.app.Notification.Action;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.util.ArraySet;
+import android.util.Log;
+import android.view.LayoutInflater;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.shared.plugins.VersionInfo.InvalidVersionException;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Coordinates all the available plugins for a given action.
+ *
+ * The available plugins are queried from the {@link PackageManager} via an an {@link Intent}
+ * action.
+ *
+ * @param <T> The type of plugin that this contains.
+ */
+public class PluginActionManager<T extends Plugin> {
+
+    private static final boolean DEBUG = false;
+
+    private static final String TAG = "PluginInstanceManager";
+    public static final String PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN";
+
+    private final Context mContext;
+    private final PluginListener<T> mListener;
+    private final String mAction;
+    private final boolean mAllowMultiple;
+    private final NotificationManager mNotificationManager;
+    private final PluginEnabler mPluginEnabler;
+    private final PluginInstance.Factory mPluginInstanceFactory;
+    private final ArraySet<String> mPrivilegedPlugins = new ArraySet<>();
+
+    @VisibleForTesting
+    private final ArrayList<PluginInstance<T>> mPluginInstances = new ArrayList<>();
+    private final boolean mIsDebuggable;
+    private final PackageManager mPm;
+    private final Class<T> mPluginClass;
+    private final Executor mMainExecutor;
+    private final Executor mBgExecutor;
+
+    private PluginActionManager(
+            Context context,
+            PackageManager pm,
+            String action,
+            PluginListener<T> listener,
+            Class<T> pluginClass,
+            boolean allowMultiple,
+            Executor mainExecutor,
+            Executor bgExecutor,
+            boolean debuggable,
+            NotificationManager notificationManager,
+            PluginEnabler pluginEnabler,
+            List<String> privilegedPlugins,
+            PluginInstance.Factory pluginInstanceFactory) {
+        mPluginClass = pluginClass;
+        mMainExecutor = mainExecutor;
+        mBgExecutor = bgExecutor;
+        mContext = context;
+        mPm = pm;
+        mAction = action;
+        mListener = listener;
+        mAllowMultiple = allowMultiple;
+        mNotificationManager = notificationManager;
+        mPluginEnabler = pluginEnabler;
+        mPluginInstanceFactory = pluginInstanceFactory;
+        mPrivilegedPlugins.addAll(privilegedPlugins);
+        mIsDebuggable = debuggable;
+    }
+
+    /** Load all plugins matching this instance's action. */
+    public void loadAll() {
+        if (DEBUG) Log.d(TAG, "startListening");
+        mBgExecutor.execute(this::queryAll);
+    }
+
+    /** Unload all plugins managed by this instance. */
+    public void destroy() {
+        if (DEBUG) Log.d(TAG, "stopListening");
+        ArrayList<PluginInstance<T>> plugins = new ArrayList<>(mPluginInstances);
+        for (PluginInstance<T> plugInstance : plugins) {
+            mMainExecutor.execute(() -> onPluginDisconnected(plugInstance));
+        }
+    }
+
+    /** Unload all matching plugins managed by this instance. */
+    public void onPackageRemoved(String pkg) {
+        mBgExecutor.execute(() -> removePkg(pkg));
+    }
+
+    /** Unload and then reload all matching plugins managed by this instance. */
+    public void reloadPackage(String pkg) {
+        mBgExecutor.execute(() -> {
+            removePkg(pkg);
+            queryPkg(pkg);
+        });
+    }
+
+    /** Disable a specific plugin managed by this instance. */
+    public boolean checkAndDisable(String className) {
+        boolean disableAny = false;
+        ArrayList<PluginInstance<T>> plugins = new ArrayList<>(mPluginInstances);
+        for (PluginInstance<T> info : plugins) {
+            if (className.startsWith(info.getPackage())) {
+                disableAny |= disable(info, PluginEnabler.DISABLED_FROM_EXPLICIT_CRASH);
+            }
+        }
+        return disableAny;
+    }
+
+    /** Disable all plugins managed by this instance. */
+    public boolean disableAll() {
+        ArrayList<PluginInstance<T>> plugins = new ArrayList<>(mPluginInstances);
+        boolean disabledAny = false;
+        for (int i = 0; i < plugins.size(); i++) {
+            disabledAny |= disable(plugins.get(i), PluginEnabler.DISABLED_FROM_SYSTEM_CRASH);
+        }
+        return disabledAny;
+    }
+
+    boolean isPluginPrivileged(ComponentName pluginName) {
+        for (String componentNameOrPackage : mPrivilegedPlugins) {
+            ComponentName componentName = ComponentName.unflattenFromString(componentNameOrPackage);
+            if (componentName == null) {
+                if (componentNameOrPackage.equals(pluginName.getPackageName())) {
+                    return true;
+                }
+            } else {
+                if (componentName.equals(pluginName)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private boolean disable(
+            PluginInstance<T> pluginInstance, @PluginEnabler.DisableReason int reason) {
+        // Live by the sword, die by the sword.
+        // Misbehaving plugins get disabled and won't come back until uninstall/reinstall.
+
+        ComponentName pluginComponent = pluginInstance.getComponentName();
+        // If a plugin is detected in the stack of a crash then this will be called for that
+        // plugin, if the plugin causing a crash cannot be identified, they are all disabled
+        // assuming one of them must be bad.
+        if (isPluginPrivileged(pluginComponent)) {
+            // Don't disable privileged plugins as they are a part of the OS.
+            return false;
+        }
+        Log.w(TAG, "Disabling plugin " + pluginComponent.flattenToShortString());
+        mPluginEnabler.setDisabled(pluginComponent, reason);
+
+        return true;
+    }
+
+    <C> boolean dependsOn(Plugin p, Class<C> cls) {
+        ArrayList<PluginInstance<T>> instances = new ArrayList<>(mPluginInstances);
+        for (PluginInstance<T> instance : instances) {
+            if (instance.containsPluginClass(p.getClass())) {
+                return instance.getVersionInfo() != null && instance.getVersionInfo().hasClass(cls);
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s@%s (action=%s)",
+                getClass().getSimpleName(), hashCode(), mAction);
+    }
+
+    private void onPluginConnected(PluginInstance<T> pluginInstance) {
+        if (DEBUG) Log.d(TAG, "onPluginConnected");
+        PluginPrefs.setHasPlugins(mContext);
+        pluginInstance.onCreate(mContext, mListener);
+    }
+
+    private void onPluginDisconnected(PluginInstance<T> pluginInstance) {
+        if (DEBUG) Log.d(TAG, "onPluginDisconnected");
+        pluginInstance.onDestroy(mListener);
+    }
+
+    private void queryAll() {
+        if (DEBUG) Log.d(TAG, "queryAll " + mAction);
+        for (int i = mPluginInstances.size() - 1; i >= 0; i--) {
+            PluginInstance<T> pluginInstance = mPluginInstances.get(i);
+            mMainExecutor.execute(() -> onPluginDisconnected(pluginInstance));
+        }
+        mPluginInstances.clear();
+        handleQueryPlugins(null);
+    }
+
+    private void removePkg(String pkg) {
+        for (int i = mPluginInstances.size() - 1; i >= 0; i--) {
+            final PluginInstance<T> pluginInstance = mPluginInstances.get(i);
+            if (pluginInstance.getPackage().equals(pkg)) {
+                mMainExecutor.execute(() -> onPluginDisconnected(pluginInstance));
+                mPluginInstances.remove(i);
+            }
+        }
+    }
+
+    private void queryPkg(String pkg) {
+        if (DEBUG) Log.d(TAG, "queryPkg " + pkg + " " + mAction);
+        if (mAllowMultiple || (mPluginInstances.size() == 0)) {
+            handleQueryPlugins(pkg);
+        } else {
+            if (DEBUG) Log.d(TAG, "Too many of " + mAction);
+        }
+    }
+
+    private void handleQueryPlugins(String pkgName) {
+        // This isn't actually a service and shouldn't ever be started, but is
+        // a convenient PM based way to manage our plugins.
+        Intent intent = new Intent(mAction);
+        if (pkgName != null) {
+            intent.setPackage(pkgName);
+        }
+        List<ResolveInfo> result = mPm.queryIntentServices(intent, 0);
+        if (DEBUG) Log.d(TAG, "Found " + result.size() + " plugins");
+        if (result.size() > 1 && !mAllowMultiple) {
+            // TODO: Show warning.
+            Log.w(TAG, "Multiple plugins found for " + mAction);
+            if (DEBUG) {
+                for (ResolveInfo info : result) {
+                    ComponentName name = new ComponentName(info.serviceInfo.packageName,
+                            info.serviceInfo.name);
+                    Log.w(TAG, "  " + name);
+                }
+            }
+            return;
+        }
+        for (ResolveInfo info : result) {
+            ComponentName name = new ComponentName(info.serviceInfo.packageName,
+                    info.serviceInfo.name);
+            PluginInstance<T> pluginInstance = loadPluginComponent(name);
+            if (pluginInstance != null) {
+                // add plugin before sending PLUGIN_CONNECTED message
+                mPluginInstances.add(pluginInstance);
+                mMainExecutor.execute(() -> onPluginConnected(pluginInstance));
+            }
+        }
+    }
+
+    private PluginInstance<T> loadPluginComponent(ComponentName component) {
+        // This was already checked, but do it again here to make extra extra sure, we don't
+        // use these on production builds.
+        if (!mIsDebuggable && !isPluginPrivileged(component)) {
+            // Never ever ever allow these on production builds, they are only for prototyping.
+            Log.w(TAG, "Plugin cannot be loaded on production build: " + component);
+            return null;
+        }
+        if (!mPluginEnabler.isEnabled(component)) {
+            if (DEBUG) {
+                Log.d(TAG, "Plugin is not enabled, aborting load: " + component);
+            }
+            return null;
+        }
+        String packageName = component.getPackageName();
+        try {
+            // TODO: This probably isn't needed given that we don't have IGNORE_SECURITY on
+            if (mPm.checkPermission(PLUGIN_PERMISSION, packageName)
+                    != PackageManager.PERMISSION_GRANTED) {
+                Log.d(TAG, "Plugin doesn't have permission: " + packageName);
+                return null;
+            }
+
+            ApplicationInfo appInfo = mPm.getApplicationInfo(packageName, 0);
+            // TODO: Only create the plugin before version check if we need it for
+            // legacy version check.
+            if (DEBUG) {
+                Log.d(TAG, "createPlugin");
+            }
+            try {
+                return mPluginInstanceFactory.create(
+                        mContext, appInfo, component,
+                        mPluginClass);
+            } catch (InvalidVersionException e) {
+                reportInvalidVersion(component, component.getClassName(), e);
+            }
+        } catch (Throwable e) {
+            Log.w(TAG, "Couldn't load plugin: " + packageName, e);
+            return null;
+        }
+
+        return null;
+    }
+
+    private void reportInvalidVersion(
+            ComponentName component, String className, InvalidVersionException e) {
+        final int icon = Resources.getSystem().getIdentifier(
+                "stat_sys_warning", "drawable", "android");
+        final int color = Resources.getSystem().getIdentifier(
+                "system_notification_accent_color", "color", "android");
+        final Notification.Builder nb = new Notification.Builder(mContext,
+                PluginManager.NOTIFICATION_CHANNEL_ID)
+                .setStyle(new Notification.BigTextStyle())
+                .setSmallIcon(icon)
+                .setWhen(0)
+                .setShowWhen(false)
+                .setVisibility(Notification.VISIBILITY_PUBLIC)
+                .setColor(mContext.getColor(color));
+        String label = className;
+        try {
+            label = mPm.getServiceInfo(component, 0).loadLabel(mPm).toString();
+        } catch (NameNotFoundException e2) {
+            // no-op
+        }
+        if (!e.isTooNew()) {
+            // Localization not required as this will never ever appear in a user build.
+            nb.setContentTitle("Plugin \"" + label + "\" is too old")
+                    .setContentText("Contact plugin developer to get an updated"
+                            + " version.\n" + e.getMessage());
+        } else {
+            // Localization not required as this will never ever appear in a user build.
+            nb.setContentTitle("Plugin \"" + label + "\" is too new")
+                    .setContentText("Check to see if an OTA is available.\n"
+                            + e.getMessage());
+        }
+        Intent i = new Intent(PluginManagerImpl.DISABLE_PLUGIN).setData(
+                Uri.parse("package://" + component.flattenToString()));
+        PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i,
+                PendingIntent.FLAG_IMMUTABLE);
+        nb.addAction(new Action.Builder(null, "Disable plugin", pi).build());
+        mNotificationManager.notify(SystemMessage.NOTE_PLUGIN, nb.build());
+        // TODO: Warn user.
+        Log.w(TAG, "Plugin has invalid interface version " + e.getActualVersion()
+                + ", expected " + e.getExpectedVersion());
+    }
+
+    /**
+     * Construct a {@link PluginActionManager}
+     */
+    public static class Factory {
+        private final Context mContext;
+        private final PackageManager mPackageManager;
+        private final Executor mMainExecutor;
+        private final Executor mBgExecutor;
+        private final NotificationManager mNotificationManager;
+        private final PluginEnabler mPluginEnabler;
+        private final List<String> mPrivilegedPlugins;
+        private final PluginInstance.Factory mPluginInstanceFactory;
+
+        public Factory(Context context, PackageManager packageManager,
+                Executor mainExecutor, Executor bgExecutor,
+                NotificationManager notificationManager, PluginEnabler pluginEnabler,
+                List<String> privilegedPlugins, PluginInstance.Factory pluginInstanceFactory) {
+            mContext = context;
+            mPackageManager = packageManager;
+            mMainExecutor = mainExecutor;
+            mBgExecutor = bgExecutor;
+            mNotificationManager = notificationManager;
+            mPluginEnabler = pluginEnabler;
+            mPrivilegedPlugins = privilegedPlugins;
+            mPluginInstanceFactory = pluginInstanceFactory;
+        }
+
+        <T extends Plugin> PluginActionManager<T> create(
+                String action, PluginListener<T> listener, Class<T> pluginClass,
+                boolean allowMultiple, boolean debuggable) {
+            return new PluginActionManager<>(mContext, mPackageManager, action, listener,
+                    pluginClass, allowMultiple, mMainExecutor, mBgExecutor,
+                    debuggable, mNotificationManager, mPluginEnabler,
+                    mPrivilegedPlugins, mPluginInstanceFactory);
+        }
+    }
+
+    /** */
+    public static class PluginContextWrapper extends ContextWrapper {
+        private final ClassLoader mClassLoader;
+        private LayoutInflater mInflater;
+
+        public PluginContextWrapper(Context base, ClassLoader classLoader) {
+            super(base);
+            mClassLoader = classLoader;
+        }
+
+        @Override
+        public ClassLoader getClassLoader() {
+            return mClassLoader;
+        }
+
+        @Override
+        public Object getSystemService(String name) {
+            if (LAYOUT_INFLATER_SERVICE.equals(name)) {
+                if (mInflater == null) {
+                    mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
+                }
+                return mInflater;
+            }
+            return getBaseContext().getSystemService(name);
+        }
+    }
+
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInitializer.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInitializer.java
deleted file mode 100644
index 895b6cd..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInitializer.java
+++ /dev/null
@@ -1,34 +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.systemui.shared.plugins;
-
-import android.content.Context;
-
-/**
- * Provides necessary components for initializing {@link PluginManagerImpl}.
- */
-public interface PluginInitializer {
-
-    /**
-     * Return a list of plugins that don't get disabled when an exception occurs.
-     */
-    String[] getPrivilegedPlugins(Context context);
-
-
-    /**
-     * Called from {@link PluginInstanceManager}.
-     */
-    void handleWtfs();
-}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java
new file mode 100644
index 0000000..2f84602
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.plugins;
+
+import android.app.LoadedApk;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.PluginFragment;
+import com.android.systemui.plugins.PluginListener;
+
+import dalvik.system.PathClassLoader;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Contains a single instantiation of a Plugin.
+ *
+ * This class and its related Factory are in charge of actually instantiating a plugin and
+ * managing any state related to it.
+ *
+ * @param <T> The type of plugin that this contains.
+ */
+public class PluginInstance<T extends Plugin> {
+    private static final String TAG = "PluginInstance";
+    private static final Map<String, ClassLoader> sClassLoaders = new ArrayMap<>();
+
+    private final Context mPluginContext;
+    private final VersionInfo mVersionInfo;
+    private final ComponentName mComponentName;
+    private final T mPlugin;
+
+    /** */
+    public PluginInstance(ComponentName componentName, T plugin, Context pluginContext,
+            VersionInfo versionInfo) {
+        mComponentName = componentName;
+        mPlugin = plugin;
+        mPluginContext = pluginContext;
+        mVersionInfo = versionInfo;
+    }
+
+    /** Alerts listener and plugin that the plugin has been created. */
+    public void onCreate(Context appContext, PluginListener<T> listener) {
+        if (!(mPlugin instanceof PluginFragment)) {
+            // Only call onCreate for plugins that aren't fragments, as fragments
+            // will get the onCreate as part of the fragment lifecycle.
+            mPlugin.onCreate(appContext, mPluginContext);
+        }
+        listener.onPluginConnected(mPlugin, mPluginContext);
+    }
+
+    /** Alerts listener and plugin that the plugin is being shutdown. */
+    public void onDestroy(PluginListener<T> listener) {
+        listener.onPluginDisconnected(mPlugin);
+        if (!(mPlugin instanceof PluginFragment)) {
+            // Only call onDestroy for plugins that aren't fragments, as fragments
+            // will get the onDestroy as part of the fragment lifecycle.
+            mPlugin.onDestroy();
+        }
+    }
+
+    /**
+     * Returns if the contained plugin matches the passed in class name.
+     *
+     * It does this by string comparison of the class names.
+     **/
+    public boolean containsPluginClass(Class pluginClass) {
+        return mPlugin.getClass().getName().equals(pluginClass.getName());
+    }
+
+    public ComponentName getComponentName() {
+        return mComponentName;
+    }
+
+    public String getPackage() {
+        return mComponentName.getPackageName();
+    }
+
+    public VersionInfo getVersionInfo() {
+        return mVersionInfo;
+    }
+
+    @VisibleForTesting
+    Context getPluginContext() {
+        return mPluginContext;
+    }
+
+    /** Used to create new {@link PluginInstance}s. */
+    public static class Factory {
+        private final ClassLoader mBaseClassLoader;
+        private final InstanceFactory<?> mInstanceFactory;
+        private final VersionChecker mVersionChecker;
+        private final boolean mIsDebug;
+        private final List<String> mPrivilegedPlugins;
+
+        /** Factory used to construct {@link PluginInstance}s. */
+        public Factory(ClassLoader classLoader, InstanceFactory<?> instanceFactory,
+                VersionChecker versionChecker,
+                List<String> privilegedPlugins,
+                boolean isDebug) {
+            mPrivilegedPlugins = privilegedPlugins;
+            mBaseClassLoader = classLoader;
+            mInstanceFactory = instanceFactory;
+            mVersionChecker = versionChecker;
+            mIsDebug = isDebug;
+        }
+
+        /** Construct a new PluginInstance. */
+        public <T extends Plugin> PluginInstance<T> create(
+                Context context,
+                ApplicationInfo appInfo,
+                ComponentName componentName,
+                Class<T> pluginClass)
+                throws PackageManager.NameNotFoundException, ClassNotFoundException,
+                InstantiationException, IllegalAccessException {
+
+            ClassLoader classLoader = getClassLoader(appInfo, mBaseClassLoader);
+            Context pluginContext = new PluginActionManager.PluginContextWrapper(
+                    context.createApplicationContext(appInfo, 0), classLoader);
+            Class<T> instanceClass = (Class<T>) Class.forName(
+                    componentName.getClassName(), true, classLoader);
+            // TODO: Only create the plugin before version check if we need it for
+            // legacy version check.
+            T instance = (T) mInstanceFactory.create(instanceClass);
+            VersionInfo version = mVersionChecker.checkVersion(
+                    instanceClass, pluginClass, instance);
+            return new PluginInstance<T>(componentName, instance, pluginContext, version);
+        }
+
+        private boolean isPluginPackagePrivileged(String packageName) {
+            for (String componentNameOrPackage : mPrivilegedPlugins) {
+                ComponentName componentName = ComponentName.unflattenFromString(
+                        componentNameOrPackage);
+                if (componentName != null) {
+                    if (componentName.getPackageName().equals(packageName)) {
+                        return true;
+                    }
+                } else if (componentNameOrPackage.equals(packageName)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        private ClassLoader getParentClassLoader(ClassLoader baseClassLoader) {
+            return new PluginManagerImpl.ClassLoaderFilter(
+                    baseClassLoader, "com.android.systemui.plugin");
+        }
+
+        /** Returns class loader specific for the given plugin. */
+        private ClassLoader getClassLoader(ApplicationInfo appInfo,
+                ClassLoader baseClassLoader) {
+            if (!mIsDebug && !isPluginPackagePrivileged(appInfo.packageName)) {
+                Log.w(TAG, "Cannot get class loader for non-privileged plugin. Src:"
+                        + appInfo.sourceDir + ", pkg: " + appInfo.packageName);
+                return null;
+            }
+            if (sClassLoaders.containsKey(appInfo.packageName)) {
+                return sClassLoaders.get(appInfo.packageName);
+            }
+
+            List<String> zipPaths = new ArrayList<>();
+            List<String> libPaths = new ArrayList<>();
+            LoadedApk.makePaths(null, true, appInfo, zipPaths, libPaths);
+            ClassLoader classLoader = new PathClassLoader(
+                    TextUtils.join(File.pathSeparator, zipPaths),
+                    TextUtils.join(File.pathSeparator, libPaths),
+                    getParentClassLoader(baseClassLoader));
+            sClassLoaders.put(appInfo.packageName, classLoader);
+            return classLoader;
+        }
+    }
+
+    /** Class that compares a plugin class against an implementation for version matching. */
+    public static class VersionChecker {
+        /** Compares two plugin classes. */
+        public <T extends Plugin> VersionInfo checkVersion(
+                Class<T> instanceClass, Class<T> pluginClass, Plugin plugin) {
+            VersionInfo pluginVersion = new VersionInfo().addClass(pluginClass);
+            VersionInfo instanceVersion = new VersionInfo().addClass(instanceClass);
+            if (instanceVersion.hasVersionInfo()) {
+                pluginVersion.checkVersion(instanceVersion);
+            } else {
+                int fallbackVersion = plugin.getVersion();
+                if (fallbackVersion != pluginVersion.getDefaultVersion()) {
+                    throw new VersionInfo.InvalidVersionException("Invalid legacy version", false);
+                }
+                return null;
+            }
+            return instanceVersion;
+        }
+    }
+
+    /**
+     *  Simple class to create a new instance. Useful for testing.
+     *
+     * @param <T> The type of plugin this create.
+     **/
+    public static class InstanceFactory<T extends Plugin> {
+        T create(Class cls) throws IllegalAccessException, InstantiationException {
+            return (T) cls.newInstance();
+        }
+    }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
deleted file mode 100644
index dcd3b3e..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright (C) 2016 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.shared.plugins;
-
-import android.app.LoadedApk;
-import android.app.Notification;
-import android.app.Notification.Action;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.net.Uri;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
-import android.view.LayoutInflater;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.systemui.plugins.Plugin;
-import com.android.systemui.plugins.PluginFragment;
-import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.VersionInfo.InvalidVersionException;
-
-import dalvik.system.PathClassLoader;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
-public class PluginInstanceManager<T extends Plugin> {
-
-    private static final boolean DEBUG = false;
-
-    private static final String TAG = "PluginInstanceManager";
-    public static final String PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN";
-
-    private final Context mContext;
-    private final PluginListener<T> mListener;
-    private final String mAction;
-    private final boolean mAllowMultiple;
-    private final VersionInfo mVersion;
-    private final NotificationManager mNotificationManager;
-    private final PluginEnabler mPluginEnabler;
-    private final InstanceFactory<T> mInstanceFactory;
-    private final ArraySet<String> mPrivilegedPlugins = new ArraySet<>();
-    private final Map<String, ClassLoader> mClassLoaders = new ArrayMap<>();
-
-    @VisibleForTesting
-    private final ArrayList<PluginInfo<T>> mPlugins = new ArrayList<>();
-    private final boolean mIsDebuggable;
-    private final PackageManager mPm;
-    private final PluginInitializer mInitializer;
-    private final Executor mMainExecutor;
-    private final Executor mBgExecutor;
-
-    private PluginManagerImpl.ClassLoaderFilter mParentClassLoader;
-
-    private PluginInstanceManager(Context context, PackageManager pm, String action,
-            PluginListener<T> listener, boolean allowMultiple, Executor mainExecutor,
-            Executor bgExecutor, VersionInfo version, boolean debuggable,
-            PluginInitializer initializer, NotificationManager notificationManager,
-            PluginEnabler pluginEnabler, List<String> privilegedPlugins,
-            InstanceFactory<T> instanceFactory) {
-        mInitializer = initializer;
-        mMainExecutor = mainExecutor;
-        mBgExecutor = bgExecutor;
-        mContext = context;
-        mPm = pm;
-        mAction = action;
-        mListener = listener;
-        mAllowMultiple = allowMultiple;
-        mVersion = version;
-        mNotificationManager = notificationManager;
-        mPluginEnabler = pluginEnabler;
-        mInstanceFactory = instanceFactory;
-        mPrivilegedPlugins.addAll(privilegedPlugins);
-        mIsDebuggable = debuggable;
-    }
-
-    public void loadAll() {
-        if (DEBUG) Log.d(TAG, "startListening");
-        mBgExecutor.execute(this::queryAll);
-    }
-
-    public void destroy() {
-        if (DEBUG) Log.d(TAG, "stopListening");
-        ArrayList<PluginInfo<T>> plugins = new ArrayList<>(mPlugins);
-        for (PluginInfo<T> pluginInfo : plugins) {
-            mMainExecutor.execute(() -> onPluginDisconnected(pluginInfo.mPlugin));
-        }
-    }
-
-    public void onPackageRemoved(String pkg) {
-        mBgExecutor.execute(() -> removePkg(pkg));
-    }
-
-    public void onPackageChange(String pkg) {
-        mBgExecutor.execute(() -> removePkg(pkg));
-        mBgExecutor.execute(() -> queryPkg(pkg));
-    }
-
-    public boolean checkAndDisable(String className) {
-        boolean disableAny = false;
-        ArrayList<PluginInfo<T>> plugins = new ArrayList<>(mPlugins);
-        for (PluginInfo<T> info : plugins) {
-            if (className.startsWith(info.mPackage)) {
-                disableAny |= disable(info, PluginEnabler.DISABLED_FROM_EXPLICIT_CRASH);
-            }
-        }
-        return disableAny;
-    }
-
-    public boolean disableAll() {
-        ArrayList<PluginInfo<T>> plugins = new ArrayList<>(mPlugins);
-        boolean disabledAny = false;
-        for (int i = 0; i < plugins.size(); i++) {
-            disabledAny |= disable(plugins.get(i), PluginEnabler.DISABLED_FROM_SYSTEM_CRASH);
-        }
-        return disabledAny;
-    }
-
-    private boolean isPluginPackagePrivileged(String packageName) {
-        for (String componentNameOrPackage : mPrivilegedPlugins) {
-            ComponentName componentName = ComponentName.unflattenFromString(componentNameOrPackage);
-            if (componentName != null) {
-                if (componentName.getPackageName().equals(packageName)) {
-                    return true;
-                }
-            } else if (componentNameOrPackage.equals(packageName)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private boolean isPluginPrivileged(ComponentName pluginName) {
-        for (String componentNameOrPackage : mPrivilegedPlugins) {
-            ComponentName componentName = ComponentName.unflattenFromString(componentNameOrPackage);
-            if (componentName == null) {
-                if (componentNameOrPackage.equals(pluginName.getPackageName())) {
-                    return true;
-                }
-            } else {
-                if (componentName.equals(pluginName)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private boolean disable(PluginInfo<T> info, @PluginEnabler.DisableReason int reason) {
-        // Live by the sword, die by the sword.
-        // Misbehaving plugins get disabled and won't come back until uninstall/reinstall.
-
-        ComponentName pluginComponent = new ComponentName(info.mPackage, info.mClass);
-        // If a plugin is detected in the stack of a crash then this will be called for that
-        // plugin, if the plugin causing a crash cannot be identified, they are all disabled
-        // assuming one of them must be bad.
-        if (isPluginPrivileged(pluginComponent)) {
-            // Don't disable whitelisted plugins as they are a part of the OS.
-            return false;
-        }
-        Log.w(TAG, "Disabling plugin " + pluginComponent.flattenToShortString());
-        mPluginEnabler.setDisabled(pluginComponent, reason);
-
-        return true;
-    }
-
-    <C> boolean dependsOn(Plugin p, Class<C> cls) {
-        ArrayList<PluginInfo<T>> plugins = new ArrayList<>(mPlugins);
-        for (PluginInfo<T> info : plugins) {
-            if (info.mPlugin.getClass().getName().equals(p.getClass().getName())) {
-                return info.mVersion != null && info.mVersion.hasClass(cls);
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s@%s (action=%s)",
-                getClass().getSimpleName(), hashCode(), mAction);
-    }
-
-    private void onPluginConnected(PluginInfo<T> pluginInfo) {
-        if (DEBUG) Log.d(TAG, "onPluginConnected");
-        PluginPrefs.setHasPlugins(mContext);
-        mInitializer.handleWtfs();
-        if (!(pluginInfo.mPlugin instanceof PluginFragment)) {
-            // Only call onCreate for plugins that aren't fragments, as fragments
-            // will get the onCreate as part of the fragment lifecycle.
-            pluginInfo.mPlugin.onCreate(mContext, pluginInfo.mPluginContext);
-        }
-        mListener.onPluginConnected(pluginInfo.mPlugin, pluginInfo.mPluginContext);
-    }
-
-    private void onPluginDisconnected(T plugin) {
-        if (DEBUG) Log.d(TAG, "onPluginDisconnected");
-        mListener.onPluginDisconnected(plugin);
-        if (!(plugin instanceof PluginFragment)) {
-            // Only call onDestroy for plugins that aren't fragments, as fragments
-            // will get the onDestroy as part of the fragment lifecycle.
-            plugin.onDestroy();
-        }
-    }
-
-    private void queryAll() {
-        if (DEBUG) Log.d(TAG, "queryAll " + mAction);
-        for (int i = mPlugins.size() - 1; i >= 0; i--) {
-            PluginInfo<T> pluginInfo = mPlugins.get(i);
-            mMainExecutor.execute(() -> onPluginDisconnected(pluginInfo.mPlugin));
-        }
-        mPlugins.clear();
-        handleQueryPlugins(null);
-    }
-
-    private void removePkg(String pkg) {
-        for (int i = mPlugins.size() - 1; i >= 0; i--) {
-            final PluginInfo<T> pluginInfo = mPlugins.get(i);
-            if (pluginInfo.mPackage.equals(pkg)) {
-                mMainExecutor.execute(() -> onPluginDisconnected(pluginInfo.mPlugin));
-                mPlugins.remove(i);
-            }
-        }
-    }
-
-    private void queryPkg(String pkg) {
-        if (DEBUG) Log.d(TAG, "queryPkg " + pkg + " " + mAction);
-        if (mAllowMultiple || (mPlugins.size() == 0)) {
-            handleQueryPlugins(pkg);
-        } else {
-            if (DEBUG) Log.d(TAG, "Too many of " + mAction);
-        }
-    }
-
-    private void handleQueryPlugins(String pkgName) {
-        // This isn't actually a service and shouldn't ever be started, but is
-        // a convenient PM based way to manage our plugins.
-        Intent intent = new Intent(mAction);
-        if (pkgName != null) {
-            intent.setPackage(pkgName);
-        }
-        List<ResolveInfo> result = mPm.queryIntentServices(intent, 0);
-        if (DEBUG) Log.d(TAG, "Found " + result.size() + " plugins");
-        if (result.size() > 1 && !mAllowMultiple) {
-            // TODO: Show warning.
-            Log.w(TAG, "Multiple plugins found for " + mAction);
-            if (DEBUG) {
-                for (ResolveInfo info : result) {
-                    ComponentName name = new ComponentName(info.serviceInfo.packageName,
-                            info.serviceInfo.name);
-                    Log.w(TAG, "  " + name);
-                }
-            }
-            return;
-        }
-        for (ResolveInfo info : result) {
-            ComponentName name = new ComponentName(info.serviceInfo.packageName,
-                    info.serviceInfo.name);
-            PluginInfo<T> pluginInfo = handleLoadPlugin(name);
-            if (pluginInfo == null) continue;
-
-            // add plugin before sending PLUGIN_CONNECTED message
-            mPlugins.add(pluginInfo);
-            mMainExecutor.execute(() -> onPluginConnected(pluginInfo));
-        }
-    }
-
-    protected PluginInfo<T> handleLoadPlugin(ComponentName component) {
-        // This was already checked, but do it again here to make extra extra sure, we don't
-        // use these on production builds.
-        if (!mIsDebuggable && !isPluginPrivileged(component)) {
-            // Never ever ever allow these on production builds, they are only for prototyping.
-            Log.w(TAG, "Plugin cannot be loaded on production build: " + component);
-            return null;
-        }
-        if (!mPluginEnabler.isEnabled(component)) {
-            if (DEBUG) Log.d(TAG, "Plugin is not enabled, aborting load: " + component);
-            return null;
-        }
-        String pkg = component.getPackageName();
-        String cls = component.getClassName();
-        try {
-            ApplicationInfo info = mPm.getApplicationInfo(pkg, 0);
-            // TODO: This probably isn't needed given that we don't have IGNORE_SECURITY on
-            if (mPm.checkPermission(PLUGIN_PERMISSION, pkg)
-                    != PackageManager.PERMISSION_GRANTED) {
-                Log.d(TAG, "Plugin doesn't have permission: " + pkg);
-                return null;
-            }
-            // Create our own ClassLoader so we can use our own code as the parent.
-            ClassLoader classLoader = getClassLoader(info);
-            Context pluginContext = new PluginContextWrapper(
-                    mContext.createApplicationContext(info, 0), classLoader);
-            Class<?> pluginClass = Class.forName(cls, true, classLoader);
-            // TODO: Only create the plugin before version check if we need it for
-            // legacy version check.
-            T plugin = mInstanceFactory.create(pluginClass);
-            try {
-                VersionInfo version = checkVersion(pluginClass, plugin, mVersion);
-                if (DEBUG) Log.d(TAG, "createPlugin");
-                return new PluginInfo<>(pkg, cls, plugin, pluginContext, version);
-            } catch (InvalidVersionException e) {
-                final int icon = Resources.getSystem().getIdentifier(
-                        "stat_sys_warning", "drawable", "android");
-                final int color = Resources.getSystem().getIdentifier(
-                        "system_notification_accent_color", "color", "android");
-                final Notification.Builder nb = new Notification.Builder(mContext,
-                        PluginManager.NOTIFICATION_CHANNEL_ID)
-                                .setStyle(new Notification.BigTextStyle())
-                                .setSmallIcon(icon)
-                                .setWhen(0)
-                                .setShowWhen(false)
-                                .setVisibility(Notification.VISIBILITY_PUBLIC)
-                                .setColor(mContext.getColor(color));
-                String label = cls;
-                try {
-                    label = mPm.getServiceInfo(component, 0).loadLabel(mPm).toString();
-                } catch (NameNotFoundException e2) {
-                }
-                if (!e.isTooNew()) {
-                    // Localization not required as this will never ever appear in a user build.
-                    nb.setContentTitle("Plugin \"" + label + "\" is too old")
-                            .setContentText("Contact plugin developer to get an updated"
-                                    + " version.\n" + e.getMessage());
-                } else {
-                    // Localization not required as this will never ever appear in a user build.
-                    nb.setContentTitle("Plugin \"" + label + "\" is too new")
-                            .setContentText("Check to see if an OTA is available.\n"
-                                    + e.getMessage());
-                }
-                Intent i = new Intent(PluginManagerImpl.DISABLE_PLUGIN).setData(
-                        Uri.parse("package://" + component.flattenToString()));
-                PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i,
-                        PendingIntent.FLAG_IMMUTABLE);
-                nb.addAction(new Action.Builder(null, "Disable plugin", pi).build());
-                mNotificationManager.notify(SystemMessage.NOTE_PLUGIN, nb.build());
-                // TODO: Warn user.
-                Log.w(TAG, "Plugin has invalid interface version " + plugin.getVersion()
-                        + ", expected " + mVersion);
-                return null;
-            }
-        } catch (Throwable e) {
-            Log.w(TAG, "Couldn't load plugin: " + pkg, e);
-            return null;
-        }
-    }
-
-    private VersionInfo checkVersion(Class<?> pluginClass, T plugin, VersionInfo version)
-            throws InvalidVersionException {
-        VersionInfo pv = new VersionInfo().addClass(pluginClass);
-        if (pv.hasVersionInfo()) {
-            version.checkVersion(pv);
-        } else {
-            int fallbackVersion = plugin.getVersion();
-            if (fallbackVersion != version.getDefaultVersion()) {
-                throw new InvalidVersionException("Invalid legacy version", false);
-            }
-            return null;
-        }
-        return pv;
-    }
-
-    /** Returns class loader specific for the given plugin. */
-    public ClassLoader getClassLoader(ApplicationInfo appInfo) {
-        if (!mIsDebuggable && !isPluginPackagePrivileged(appInfo.packageName)) {
-            Log.w(TAG, "Cannot get class loader for non-privileged plugin. Src:"
-                    + appInfo.sourceDir + ", pkg: " + appInfo.packageName);
-            return null;
-        }
-        if (mClassLoaders.containsKey(appInfo.packageName)) {
-            return mClassLoaders.get(appInfo.packageName);
-        }
-
-        List<String> zipPaths = new ArrayList<>();
-        List<String> libPaths = new ArrayList<>();
-        LoadedApk.makePaths(null, true, appInfo, zipPaths, libPaths);
-        ClassLoader classLoader = new PathClassLoader(
-                TextUtils.join(File.pathSeparator, zipPaths),
-                TextUtils.join(File.pathSeparator, libPaths),
-                getParentClassLoader());
-        mClassLoaders.put(appInfo.packageName, classLoader);
-        return classLoader;
-    }
-
-    private ClassLoader getParentClassLoader() {
-        if (mParentClassLoader == null) {
-            // Lazily load this so it doesn't have any effect on devices without plugins.
-            mParentClassLoader = new PluginManagerImpl.ClassLoaderFilter(
-                    getClass().getClassLoader(), "com.android.systemui.plugin");
-        }
-        return mParentClassLoader;
-    }
-
-    /**
-     * Construct a {@link PluginInstanceManager}
-     */
-    public static class Factory {
-        private final Context mContext;
-        private final PackageManager mPackageManager;
-        private final Executor mMainExecutor;
-        private final Executor mBgExecutor;
-        private final PluginInitializer mInitializer;
-        private final NotificationManager mNotificationManager;
-        private final PluginEnabler mPluginEnabler;
-        private final List<String> mPrivilegedPlugins;
-        private InstanceFactory<?> mInstanceFactory;
-
-        public Factory(Context context, PackageManager packageManager,
-                Executor mainExecutor, Executor bgExecutor, PluginInitializer initializer,
-                NotificationManager notificationManager, PluginEnabler pluginEnabler,
-                List<String> privilegedPlugins) {
-            mContext = context;
-            mPackageManager = packageManager;
-            mMainExecutor = mainExecutor;
-            mBgExecutor = bgExecutor;
-            mInitializer = initializer;
-            mNotificationManager = notificationManager;
-            mPluginEnabler = pluginEnabler;
-            mPrivilegedPlugins = privilegedPlugins;
-
-            mInstanceFactory = new InstanceFactory<>();
-        }
-
-        @VisibleForTesting
-        <T extends Plugin> Factory setInstanceFactory(InstanceFactory<T> instanceFactory) {
-            mInstanceFactory = instanceFactory;
-            return this;
-        }
-
-        <T extends Plugin> PluginInstanceManager<T> create(
-                String action, PluginListener<T> listener, boolean allowMultiple,
-                VersionInfo version, boolean debuggable) {
-            return new PluginInstanceManager<T>(mContext, mPackageManager, action, listener,
-                    allowMultiple, mMainExecutor, mBgExecutor, version, debuggable,
-                    mInitializer, mNotificationManager, mPluginEnabler,
-                    mPrivilegedPlugins, (InstanceFactory<T>) mInstanceFactory);
-        }
-    }
-
-    public static class PluginContextWrapper extends ContextWrapper {
-        private final ClassLoader mClassLoader;
-        private LayoutInflater mInflater;
-
-        public PluginContextWrapper(Context base, ClassLoader classLoader) {
-            super(base);
-            mClassLoader = classLoader;
-        }
-
-        @Override
-        public ClassLoader getClassLoader() {
-            return mClassLoader;
-        }
-
-        @Override
-        public Object getSystemService(String name) {
-            if (LAYOUT_INFLATER_SERVICE.equals(name)) {
-                if (mInflater == null) {
-                    mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
-                }
-                return mInflater;
-            }
-            return getBaseContext().getSystemService(name);
-        }
-    }
-
-    static class PluginInfo<T extends Plugin> {
-        private final Context mPluginContext;
-        private final VersionInfo mVersion;
-        private final String mClass;
-        T mPlugin;
-        String mPackage;
-
-        public PluginInfo(String pkg, String cls, T plugin, Context pluginContext,
-                VersionInfo info) {
-            mPlugin = plugin;
-            mClass = cls;
-            mPackage = pkg;
-            mPluginContext = pluginContext;
-            mVersion = info;
-        }
-    }
-
-    static class InstanceFactory<T extends Plugin> {
-        T create(Class cls) throws IllegalAccessException, InstantiationException {
-            return (T) cls.newInstance();
-        }
-    }
-}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManager.java
index d264bf2..c89be86 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManager.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManager.java
@@ -30,13 +30,15 @@
     /** Returns plugins that don't get disabled when an exceptoin occurs. */
     String[] getPrivilegedPlugins();
 
-    <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls);
-    <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls,
+    /** */
+    <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<T> cls);
+    /** */
+    <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<T> cls,
             boolean allowMultiple);
     <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
-            Class<?> cls);
+            Class<T> cls);
     <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
-            Class<?> cls, boolean allowMultiple);
+            Class<T> cls, boolean allowMultiple);
 
     void removePluginListener(PluginListener<?> listener);
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
index ea7b0c3..7539f99 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
@@ -47,26 +47,26 @@
     private static final String TAG = PluginManagerImpl.class.getSimpleName();
     static final String DISABLE_PLUGIN = "com.android.systemui.action.DISABLE_PLUGIN";
 
-    private final ArrayMap<PluginListener<?>, PluginInstanceManager<?>> mPluginMap
+    private final ArrayMap<PluginListener<?>, PluginActionManager<?>> mPluginMap
             = new ArrayMap<>();
     private final Map<String, ClassLoader> mClassLoaders = new ArrayMap<>();
     private final ArraySet<String> mPrivilegedPlugins = new ArraySet<>();
     private final Context mContext;
-    private final PluginInstanceManager.Factory mInstanceManagerFactory;
+    private final PluginActionManager.Factory mActionManagerFactory;
     private final boolean mIsDebuggable;
     private final PluginPrefs mPluginPrefs;
     private final PluginEnabler mPluginEnabler;
     private boolean mListening;
 
     public PluginManagerImpl(Context context,
-            PluginInstanceManager.Factory instanceManagerFactory,
+            PluginActionManager.Factory actionManagerFactory,
             boolean debuggable,
             Optional<UncaughtExceptionHandler> defaultHandlerOptional,
             PluginEnabler pluginEnabler,
             PluginPrefs pluginPrefs,
             List<String> privilegedPlugins) {
         mContext = context;
-        mInstanceManagerFactory = instanceManagerFactory;
+        mActionManagerFactory = actionManagerFactory;
         mIsDebuggable = debuggable;
         mPrivilegedPlugins.addAll(privilegedPlugins);
         mPluginPrefs = pluginPrefs;
@@ -85,25 +85,27 @@
         return mPrivilegedPlugins.toArray(new String[0]);
     }
 
-    public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls) {
+    /** */
+    public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<T> cls) {
         addPluginListener(listener, cls, false);
     }
 
-    public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls,
+    /** */
+    public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<T> cls,
             boolean allowMultiple) {
         addPluginListener(PluginManager.Helper.getAction(cls), listener, cls, allowMultiple);
     }
 
     public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
-            Class<?> cls) {
+            Class<T> cls) {
         addPluginListener(action, listener, cls, false);
     }
 
     public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
-            Class<?> cls, boolean allowMultiple) {
+            Class<T> cls, boolean allowMultiple) {
         mPluginPrefs.addAction(action);
-        PluginInstanceManager<T> p = mInstanceManagerFactory.create(action, listener, allowMultiple,
-                new VersionInfo().addClass(cls), isDebuggable());
+        PluginActionManager<T> p = mActionManagerFactory.create(action, listener, cls,
+                allowMultiple, isDebuggable());
         p.loadAll();
         synchronized (this) {
             mPluginMap.put(listener, p);
@@ -135,7 +137,7 @@
         filter.addAction(PLUGIN_CHANGED);
         filter.addAction(DISABLE_PLUGIN);
         filter.addDataScheme("package");
-        mContext.registerReceiver(this, filter, PluginInstanceManager.PLUGIN_PERMISSION, null);
+        mContext.registerReceiver(this, filter, PluginActionManager.PLUGIN_PERMISSION, null);
         filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
         mContext.registerReceiver(this, filter);
     }
@@ -150,7 +152,7 @@
     public void onReceive(Context context, Intent intent) {
         if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
             synchronized (this) {
-                for (PluginInstanceManager<?> manager : mPluginMap.values()) {
+                for (PluginActionManager<?> manager : mPluginMap.values()) {
                     manager.loadAll();
                 }
             }
@@ -189,12 +191,14 @@
                 }
             }
             synchronized (this) {
-                if (!Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
-                    for (PluginInstanceManager<?> manager : mPluginMap.values()) {
-                        manager.onPackageChange(pkg);
+                if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
+                        || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
+                        || Intent.ACTION_PACKAGE_REPLACED.equals(intent.getAction())) {
+                    for (PluginActionManager<?> actionManager : mPluginMap.values()) {
+                        actionManager.reloadPackage(pkg);
                     }
                 } else {
-                    for (PluginInstanceManager<?> manager : mPluginMap.values()) {
+                    for (PluginActionManager<?> manager : mPluginMap.values()) {
                         manager.onPackageRemoved(pkg);
                     }
                 }
@@ -284,7 +288,7 @@
                 // disable all the plugins, so we can be sure that SysUI is running as
                 // best as possible.
                 synchronized (this) {
-                    for (PluginInstanceManager<?> manager : mPluginMap.values()) {
+                    for (PluginActionManager<?> manager : mPluginMap.values()) {
                         disabledAny |= manager.disableAll();
                     }
                 }
@@ -304,7 +308,7 @@
             boolean disabledAny = false;
             synchronized (this) {
                 for (StackTraceElement element : throwable.getStackTrace()) {
-                    for (PluginInstanceManager<?> manager : mPluginMap.values()) {
+                    for (PluginActionManager<?> manager : mPluginMap.values()) {
                         disabledAny |= manager.checkAndDisable(element.getClassName());
                     }
                 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/VersionInfo.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/VersionInfo.java
index bb845cd..6be3243 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/VersionInfo.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/VersionInfo.java
@@ -119,6 +119,8 @@
 
     public static class InvalidVersionException extends RuntimeException {
         private final boolean mTooNew;
+        private int mExpected;
+        private int mActual;
 
         public InvalidVersionException(String str, boolean tooNew) {
             super(str);
@@ -128,11 +130,21 @@
         public InvalidVersionException(Class<?> cls, boolean tooNew, int expected, int actual) {
             super(cls.getSimpleName() + " expected version " + expected + " but had " + actual);
             mTooNew = tooNew;
+            mExpected = expected;
+            mActual = actual;
         }
 
         public boolean isTooNew() {
             return mTooNew;
         }
+
+        public int getExpectedVersion() {
+            return mExpected;
+        }
+
+        public int getActualVersion() {
+            return mActual;
+        }
     }
 
     private static class Version {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index b827356..196e6f3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -285,8 +285,8 @@
      * These values are expressed in pixels because they should not respect display or font
      * scaling, this means that we don't have to reload them on config changes.
      */
-    public static float getWindowCornerRadius(Resources resources) {
-        return ScreenDecorationsUtils.getWindowCornerRadius(resources);
+    public static float getWindowCornerRadius(Context context) {
+        return ScreenDecorationsUtils.getWindowCornerRadius(context);
     }
 
     /**
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
index 025d7ef..7aee721 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
@@ -37,6 +37,7 @@
 import android.view.SurfaceControl;
 import android.window.IRemoteTransition;
 import android.window.IRemoteTransitionFinishedCallback;
+import android.window.RemoteTransition;
 import android.window.TransitionInfo;
 
 import java.util.ArrayList;
@@ -62,7 +63,8 @@
 
     /** Helper to just build a remote transition. Use this if the legacy adapter isn't needed. */
     public static RemoteTransitionCompat buildRemoteTransition(RemoteAnimationRunnerCompat runner) {
-        return new RemoteTransitionCompat(wrapRemoteTransition(runner));
+        return new RemoteTransitionCompat(
+                new RemoteTransition(wrapRemoteTransition(runner)));
     }
 
     public RemoteTransitionCompat getRemoteTransition() {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index 0a14657..30db136 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -71,11 +71,11 @@
     public final boolean allowEnterPip;
     public final int rotationChange;
     public final int windowType;
+    public final WindowConfiguration windowConfiguration;
 
     private final SurfaceControl mStartLeash;
 
     // Fields used only to unrap into RemoteAnimationTarget
-    private final WindowConfiguration windowConfiguration;
     private final Rect startBounds;
 
     public RemoteAnimationTargetCompat(RemoteAnimationTarget app) {
@@ -235,8 +235,9 @@
         rotationChange = change.getEndRotation() - change.getStartRotation();
         windowType = INVALID_WINDOW_TYPE;
 
-        // TODO this probably isn't right but it's unused for now /shrug
-        windowConfiguration = new WindowConfiguration();
+        windowConfiguration = change.getTaskInfo() != null
+            ? change.getTaskInfo().configuration.windowConfiguration
+            : new WindowConfiguration();
         startBounds = change.getStartAbsBounds();
     }
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
index aac5235..9ec95a3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
@@ -42,6 +42,7 @@
 import android.window.IRemoteTransition;
 import android.window.IRemoteTransitionFinishedCallback;
 import android.window.PictureInPictureSurfaceTransaction;
+import android.window.RemoteTransition;
 import android.window.TransitionFilter;
 import android.window.TransitionInfo;
 import android.window.WindowContainerToken;
@@ -63,16 +64,16 @@
 public class RemoteTransitionCompat implements Parcelable {
     private static final String TAG = "RemoteTransitionCompat";
 
-    @NonNull final IRemoteTransition mTransition;
+    @NonNull final RemoteTransition mTransition;
     @Nullable TransitionFilter mFilter = null;
 
-    RemoteTransitionCompat(IRemoteTransition transition) {
+    RemoteTransitionCompat(RemoteTransition transition) {
         mTransition = transition;
     }
 
     public RemoteTransitionCompat(@NonNull RemoteTransitionRunner runner,
             @NonNull Executor executor) {
-        mTransition = new IRemoteTransition.Stub() {
+        IRemoteTransition remote = new IRemoteTransition.Stub() {
             @Override
             public void startAnimation(IBinder transition, TransitionInfo info,
                     SurfaceControl.Transaction t,
@@ -102,12 +103,13 @@
                         finishAdapter));
             }
         };
+        mTransition = new RemoteTransition(remote);
     }
 
     /** Constructor specifically for recents animation */
     public RemoteTransitionCompat(RecentsAnimationListener recents,
             RecentsAnimationControllerCompat controller) {
-        mTransition = new IRemoteTransition.Stub() {
+        IRemoteTransition remote = new IRemoteTransition.Stub() {
             final RecentsControllerWrap mRecentsSession = new RecentsControllerWrap();
             IBinder mToken = null;
 
@@ -166,6 +168,7 @@
                 }
             }
         };
+        mTransition = new RemoteTransition(remote);
     }
 
     /** Adds a filter check that restricts this remote transition to home open transitions. */
@@ -381,7 +384,7 @@
 
 
 
-    // Code below generated by codegen v1.0.21.
+    // Code below generated by codegen v1.0.23.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -393,8 +396,21 @@
     //   Settings > Editor > Code Style > Formatter Control
     //@formatter:off
 
+
     @DataClass.Generated.Member
-    public @NonNull IRemoteTransition getTransition() {
+    /* package-private */ RemoteTransitionCompat(
+            @NonNull RemoteTransition transition,
+            @Nullable TransitionFilter filter) {
+        this.mTransition = transition;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mTransition);
+        this.mFilter = filter;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull RemoteTransition getTransition() {
         return mTransition;
     }
 
@@ -412,7 +428,7 @@
         byte flg = 0;
         if (mFilter != null) flg |= 0x2;
         dest.writeByte(flg);
-        dest.writeStrongInterface(mTransition);
+        dest.writeTypedObject(mTransition, flags);
         if (mFilter != null) dest.writeTypedObject(mFilter, flags);
     }
 
@@ -428,7 +444,7 @@
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
         byte flg = in.readByte();
-        IRemoteTransition transition = IRemoteTransition.Stub.asInterface(in.readStrongBinder());
+        RemoteTransition transition = (RemoteTransition) in.readTypedObject(RemoteTransition.CREATOR);
         TransitionFilter filter = (flg & 0x2) == 0 ? null : (TransitionFilter) in.readTypedObject(TransitionFilter.CREATOR);
 
         this.mTransition = transition;
@@ -460,20 +476,20 @@
     @DataClass.Generated.Member
     public static class Builder {
 
-        private @NonNull IRemoteTransition mTransition;
+        private @NonNull RemoteTransition mTransition;
         private @Nullable TransitionFilter mFilter;
 
         private long mBuilderFieldsSet = 0L;
 
         public Builder(
-                @NonNull IRemoteTransition transition) {
+                @NonNull RemoteTransition transition) {
             mTransition = transition;
             com.android.internal.util.AnnotationValidations.validate(
                     NonNull.class, null, mTransition);
         }
 
         @DataClass.Generated.Member
-        public @NonNull Builder setTransition(@NonNull IRemoteTransition value) {
+        public @NonNull Builder setTransition(@NonNull RemoteTransition value) {
             checkNotUsed();
             mBuilderFieldsSet |= 0x1;
             mTransition = value;
@@ -496,8 +512,9 @@
             if ((mBuilderFieldsSet & 0x2) == 0) {
                 mFilter = null;
             }
-            RemoteTransitionCompat o = new RemoteTransitionCompat(mTransition);
-            o.mFilter = this.mFilter;
+            RemoteTransitionCompat o = new RemoteTransitionCompat(
+                    mTransition,
+                    mFilter);
             return o;
         }
 
@@ -510,10 +527,10 @@
     }
 
     @DataClass.Generated(
-            time = 1606862689344L,
-            codegenVersion = "1.0.21",
+            time = 1629321609807L,
+            codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java",
-            inputSignatures = "final @android.annotation.NonNull com.android.systemui.shared.system.IRemoteTransition mTransition\n @android.annotation.Nullable android.window.TransitionFilter mFilter\npublic  void addHomeOpenCheck()\nclass RemoteTransitionCompat extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass")
+            inputSignatures = "private static final  java.lang.String TAG\nfinal @android.annotation.NonNull android.window.RemoteTransition mTransition\n @android.annotation.Nullable android.window.TransitionFilter mFilter\npublic  void addHomeOpenCheck(android.content.ComponentName)\nclass RemoteTransitionCompat extends java.lang.Object implements [android.os.Parcelable]\nprivate  com.android.systemui.shared.system.RecentsAnimationControllerCompat mWrapped\nprivate  android.window.IRemoteTransitionFinishedCallback mFinishCB\nprivate  android.window.WindowContainerToken mPausingTask\nprivate  android.window.WindowContainerToken mPipTask\nprivate  android.window.TransitionInfo mInfo\nprivate  android.view.SurfaceControl mOpeningLeash\nprivate  android.util.ArrayMap<android.view.SurfaceControl,android.view.SurfaceControl> mLeashMap\nprivate  android.window.PictureInPictureSurfaceTransaction mPipTransaction\nprivate  android.os.IBinder mTransition\n  void setup(com.android.systemui.shared.system.RecentsAnimationControllerCompat,android.window.TransitionInfo,android.window.IRemoteTransitionFinishedCallback,android.window.WindowContainerToken,android.window.WindowContainerToken,android.util.ArrayMap<android.view.SurfaceControl,android.view.SurfaceControl>,android.os.IBinder)\n @android.annotation.SuppressLint boolean merge(android.window.TransitionInfo,android.view.SurfaceControl.Transaction,com.android.systemui.shared.system.RecentsAnimationListener)\npublic @java.lang.Override com.android.systemui.shared.recents.model.ThumbnailData screenshotTask(int)\npublic @java.lang.Override void setInputConsumerEnabled(boolean)\npublic @java.lang.Override void setAnimationTargetsBehindSystemBars(boolean)\npublic @java.lang.Override void hideCurrentInputMethod()\npublic @java.lang.Override void setFinishTaskTransaction(int,android.window.PictureInPictureSurfaceTransaction,android.view.SurfaceControl)\npublic @java.lang.Override @android.annotation.SuppressLint void finish(boolean,boolean)\npublic @java.lang.Override void setDeferCancelUntilNextTransition(boolean,boolean)\npublic @java.lang.Override void cleanupScreenshot()\npublic @java.lang.Override void setWillFinishToHome(boolean)\npublic @java.lang.Override boolean removeTask(int)\npublic @java.lang.Override void detachNavigationBarFromApp(boolean)\npublic @java.lang.Override void animateNavigationBarToApp(long)\nclass RecentsControllerWrap extends com.android.systemui.shared.system.RecentsAnimationControllerCompat implements []\n@com.android.internal.util.DataClass")
     @Deprecated
     private void __metadata() {}
 
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 1214ecd..9023d3a 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -597,11 +597,6 @@
         if (obj == null) {
             obj = createDependency(key);
             mDependencies.put(key, obj);
-
-            // TODO: Get dependencies to register themselves instead
-            if (autoRegisterModulesForDump() && obj instanceof Dumpable) {
-                mDumpManager.registerDumpable(obj.getClass().getName(), (Dumpable) obj);
-            }
         }
         return obj;
     }
@@ -619,17 +614,6 @@
         return provider.createDependency();
     }
 
-    // Currently, there are situations in tests where we might create more than one instance of a
-    // thing that should be a singleton: the "real" one (created by Dagger, usually as a result of
-    // inflating a view), and a mocked one (injected into Dependency). If we register the mocked
-    // one, the DumpManager will throw an exception complaining (rightly) that we have too many
-    // things registered with that name. So in tests, we disable the auto-registration until the
-    // root cause is fixed, i.e. inflated views in tests with Dagger dependencies.
-    @VisibleForTesting
-    protected boolean autoRegisterModulesForDump() {
-        return true;
-    }
-
     private static Dependency sDependency;
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
index d859a63..15e8c4e 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
@@ -42,7 +42,8 @@
     private final Handler mMainHandler;
 
     @Inject
-    public ForegroundServiceController(AppOpsController appOpsController,
+    public ForegroundServiceController(
+            AppOpsController appOpsController,
             @Main Handler mainHandler) {
         mMainHandler = mainHandler;
         appOpsController.addCallback(APP_OPS, (code, uid, packageName, active) -> {
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index c8f8404..cffc048 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -120,6 +120,7 @@
 
         @Override
         public void onCreate(SurfaceHolder surfaceHolder) {
+            Trace.beginSection("ImageWallpaper.Engine#onCreate");
             mEglHelper = getEglHelperInstance();
             // Deferred init renderer because we need to get wallpaper by display context.
             mRenderer = getRendererInstance();
@@ -129,6 +130,7 @@
             mRenderer.setOnBitmapChanged(this::updateMiniBitmap);
             getDisplayContext().getSystemService(DisplayManager.class)
                     .registerDisplayListener(this, mWorker.getThreadHandler());
+            Trace.endSection();
         }
 
         @Override
@@ -185,11 +187,13 @@
         }
 
         private void updateSurfaceSize() {
+            Trace.beginSection("ImageWallpaper#updateSurfaceSize");
             SurfaceHolder holder = getSurfaceHolder();
             Size frameSize = mRenderer.reportSurfaceSize();
             int width = Math.max(MIN_SURFACE_WIDTH, frameSize.getWidth());
             int height = Math.max(MIN_SURFACE_HEIGHT, frameSize.getHeight());
             holder.setFixedSize(width, height);
+            Trace.endSection();
         }
 
         @Override
@@ -198,6 +202,11 @@
         }
 
         @Override
+        public boolean shouldWaitForEngineShown() {
+            return true;
+        }
+
+        @Override
         public void onDestroy() {
             getDisplayContext().getSystemService(DisplayManager.class)
                     .unregisterDisplayListener(this);
@@ -340,8 +349,10 @@
         public void onSurfaceCreated(SurfaceHolder holder) {
             if (mWorker == null) return;
             mWorker.getThreadHandler().post(() -> {
+                Trace.beginSection("ImageWallpaper#onSurfaceCreated");
                 mEglHelper.init(holder, needSupportWideColorGamut());
                 mRenderer.onSurfaceCreated();
+                Trace.endSection();
             });
         }
 
@@ -358,9 +369,11 @@
         }
 
         private void drawFrame() {
+            Trace.beginSection("ImageWallpaper#drawFrame");
             preRender();
             requestRender();
             postRender();
+            Trace.endSection();
         }
 
         public void preRender() {
@@ -425,9 +438,8 @@
 
         public void postRender() {
             // This method should only be invoked from worker thread.
-            Trace.beginSection("ImageWallpaper#postRender");
             scheduleFinishRendering();
-            Trace.endSection();
+            reportEngineShown(false /* waitForEngineShown */);
         }
 
         private void cancelFinishRenderingTask() {
diff --git a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
index f9617ca..c7f1006 100644
--- a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
@@ -53,7 +53,7 @@
 
     private static final String TAG = "PluginInflateContainer";
 
-    private Class<?> mClass;
+    private Class<ViewProvider> mClass;
     private View mPluginView;
 
     public PluginInflateContainer(Context context, @Nullable AttributeSet attrs) {
@@ -61,7 +61,7 @@
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PluginInflateContainer);
         String viewType = a.getString(R.styleable.PluginInflateContainer_viewType);
         try {
-            mClass = Class.forName(viewType);
+            mClass = (Class<ViewProvider>) Class.forName(viewType);
         } catch (Exception e) {
             Log.d(TAG, "Problem getting class info " + viewType, e);
             mClass = null;
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index f653088..0ba183b 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -42,6 +42,7 @@
 import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Matrix;
@@ -59,6 +60,7 @@
 import android.os.UserHandle;
 import android.provider.Settings.Secure;
 import android.util.DisplayMetrics;
+import android.util.DisplayUtils;
 import android.util.Log;
 import android.view.Display;
 import android.view.DisplayCutout;
@@ -66,6 +68,7 @@
 import android.view.DisplayInfo;
 import android.view.Gravity;
 import android.view.LayoutInflater;
+import android.view.RoundedCorners;
 import android.view.Surface;
 import android.view.View;
 import android.view.View.OnLayoutChangeListener;
@@ -159,6 +162,10 @@
     private boolean mIsRoundedCornerMultipleRadius;
     private int mStatusBarHeightPortrait;
     private int mStatusBarHeightLandscape;
+    private Drawable mRoundedCornerDrawable;
+    private Drawable mRoundedCornerDrawableTop;
+    private Drawable mRoundedCornerDrawableBottom;
+    private String mDisplayUniqueId;
 
     private CameraAvailabilityListener.CameraTransitionCallback mCameraTransitionCallback =
             new CameraAvailabilityListener.CameraTransitionCallback() {
@@ -244,10 +251,11 @@
 
     private void startOnScreenDecorationsThread() {
         mRotation = mContext.getDisplay().getRotation();
+        mDisplayUniqueId = mContext.getDisplay().getUniqueId();
+        mIsRoundedCornerMultipleRadius = isRoundedCornerMultipleRadius(mContext, mDisplayUniqueId);
         mWindowManager = mContext.getSystemService(WindowManager.class);
         mDisplayManager = mContext.getSystemService(DisplayManager.class);
-        mIsRoundedCornerMultipleRadius = mContext.getResources().getBoolean(
-                R.bool.config_roundedCornerMultipleRadius);
+        updateRoundedCornerDrawable();
         updateRoundedCornerRadii();
         setupDecorations();
         setupCameraListener();
@@ -287,6 +295,14 @@
                         }
                     }
                 }
+                final String newUniqueId = mContext.getDisplay().getUniqueId();
+                if ((newUniqueId != null && !newUniqueId.equals(mDisplayUniqueId))
+                        || (mDisplayUniqueId != null && !mDisplayUniqueId.equals(newUniqueId))) {
+                    mDisplayUniqueId = newUniqueId;
+                    mIsRoundedCornerMultipleRadius =
+                            isRoundedCornerMultipleRadius(mContext, mDisplayUniqueId);
+                    updateRoundedCornerDrawable();
+                }
                 updateOrientation();
             }
         };
@@ -474,6 +490,7 @@
         updateRoundedCornerView(pos, R.id.left);
         updateRoundedCornerView(pos, R.id.right);
         updateRoundedCornerSize(mRoundedDefault, mRoundedDefaultTop, mRoundedDefaultBottom);
+        updateRoundedCornerImageView();
 
         // update cutout view rotation
         if (mCutoutViews != null && mCutoutViews[pos] != null) {
@@ -551,7 +568,8 @@
         }
     }
 
-    private static int getBoundPositionFromRotation(@BoundsPosition int pos, int rotation) {
+    @VisibleForTesting
+    static int getBoundPositionFromRotation(@BoundsPosition int pos, int rotation) {
         return (pos - rotation) < 0
                 ? pos - rotation + DisplayCutout.BOUNDS_POSITION_LENGTH
                 : pos - rotation;
@@ -677,12 +695,12 @@
         // upgrading all of the configs to contain (width, height) pairs. Instead assume that a
         // device configured using the single integer config value is okay with drawing the corners
         // as a square
-        final int newRoundedDefault = mContext.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.rounded_corner_radius);
-        final int newRoundedDefaultTop = mContext.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.rounded_corner_radius_top);
-        final int newRoundedDefaultBottom = mContext.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.rounded_corner_radius_bottom);
+        final int newRoundedDefault = RoundedCorners.getRoundedCornerRadius(
+                mContext.getResources(), mDisplayUniqueId);
+        final int newRoundedDefaultTop = RoundedCorners.getRoundedCornerTopRadius(
+                mContext.getResources(), mDisplayUniqueId);
+        final int newRoundedDefaultBottom = RoundedCorners.getRoundedCornerBottomRadius(
+                mContext.getResources(), mDisplayUniqueId);
 
         final boolean changed = mRoundedDefault.x != newRoundedDefault
                         || mRoundedDefaultTop.x != newRoundedDefaultTop
@@ -692,12 +710,12 @@
             // If config_roundedCornerMultipleRadius set as true, ScreenDecorations respect the
             // (width, height) size of drawable/rounded.xml instead of rounded_corner_radius
             if (mIsRoundedCornerMultipleRadius) {
-                Drawable d =  mContext.getDrawable(R.drawable.rounded);
-                mRoundedDefault.set(d.getIntrinsicWidth(), d.getIntrinsicHeight());
-                d =  mContext.getDrawable(R.drawable.rounded_corner_top);
-                mRoundedDefaultTop.set(d.getIntrinsicWidth(), d.getIntrinsicHeight());
-                d =  mContext.getDrawable(R.drawable.rounded_corner_bottom);
-                mRoundedDefaultBottom.set(d.getIntrinsicWidth(), d.getIntrinsicHeight());
+                mRoundedDefault.set(mRoundedCornerDrawable.getIntrinsicWidth(),
+                        mRoundedCornerDrawable.getIntrinsicHeight());
+                mRoundedDefaultTop.set(mRoundedCornerDrawableTop.getIntrinsicWidth(),
+                        mRoundedCornerDrawableTop.getIntrinsicHeight());
+                mRoundedDefaultBottom.set(mRoundedCornerDrawableBottom.getIntrinsicWidth(),
+                        mRoundedCornerDrawableBottom.getIntrinsicHeight());
             } else {
                 mRoundedDefault.set(newRoundedDefault, newRoundedDefault);
                 mRoundedDefaultTop.set(newRoundedDefaultTop, newRoundedDefaultTop);
@@ -707,6 +725,89 @@
         }
     }
 
+    /**
+     * Gets whether the rounded corners are multiple radii for current display.
+     *
+     * Loads the default config {@link R.bool#config_roundedCornerMultipleRadius} if
+     * {@link com.android.internal.R.array#config_displayUniqueIdArray} is not set.
+     */
+    private static boolean isRoundedCornerMultipleRadius(Context context, String displayUniqueId) {
+        final Resources res = context.getResources();
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
+        final TypedArray array = res.obtainTypedArray(
+                R.array.config_roundedCornerMultipleRadiusArray);
+        boolean isMultipleRadius;
+        if (index >= 0 && index < array.length()) {
+            isMultipleRadius = array.getBoolean(index, false);
+        } else {
+            isMultipleRadius = res.getBoolean(R.bool.config_roundedCornerMultipleRadius);
+        }
+        array.recycle();
+        return isMultipleRadius;
+    }
+
+    /**
+     * Gets the rounded corner drawable for current display.
+     *
+     * Loads the default config {@link R.drawable#rounded} if
+     * {@link com.android.internal.R.array#config_displayUniqueIdArray} is not set.
+     */
+    private static Drawable getRoundedCornerDrawable(Context context, String displayUniqueId) {
+        final Resources res = context.getResources();
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
+        final TypedArray array = res.obtainTypedArray(R.array.config_roundedCornerDrawableArray);
+        Drawable drawable;
+        if (index >= 0 && index < array.length()) {
+            drawable = array.getDrawable(index);
+        } else {
+            drawable = context.getDrawable(R.drawable.rounded);
+        }
+        array.recycle();
+        return drawable;
+    }
+
+    /**
+     * Gets the rounded corner top drawable for current display.
+     *
+     * Loads the default config {@link R.drawable#rounded_corner_top} if
+     * {@link com.android.internal.R.array#config_displayUniqueIdArray} is not set.
+     */
+    private static Drawable getRoundedCornerTopDrawable(Context context, String displayUniqueId) {
+        final Resources res = context.getResources();
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
+        final TypedArray array = res.obtainTypedArray(R.array.config_roundedCornerTopDrawableArray);
+        Drawable drawable;
+        if (index >= 0 && index < array.length()) {
+            drawable = array.getDrawable(index);
+        } else {
+            drawable = context.getDrawable(R.drawable.rounded_corner_top);
+        }
+        array.recycle();
+        return drawable;
+    }
+
+    /**
+     * Gets the rounded corner bottom drawable for current display.
+     *
+     * Loads the default config {@link R.drawable#rounded_corner_bottom} if
+     * {@link com.android.internal.R.array#config_displayUniqueIdArray} is not set.
+     */
+    private static Drawable getRoundedCornerBottomDrawable(
+            Context context, String displayUniqueId) {
+        final Resources res = context.getResources();
+        final int index = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId);
+        final TypedArray array = res.obtainTypedArray(
+                R.array.config_roundedCornerBottomDrawableArray);
+        Drawable drawable;
+        if (index >= 0 && index < array.length()) {
+            drawable = array.getDrawable(index);
+        } else {
+            drawable = context.getDrawable(R.drawable.rounded_corner_bottom);
+        }
+        array.recycle();
+        return drawable;
+    }
+
     private void updateRoundedCornerView(@BoundsPosition int pos, int id) {
         final View rounded = mOverlays[pos].findViewById(id);
         if (rounded == null) {
@@ -837,6 +938,52 @@
         });
     }
 
+    private void updateRoundedCornerDrawable() {
+        mRoundedCornerDrawable = getRoundedCornerDrawable(mContext, mDisplayUniqueId);
+        mRoundedCornerDrawableTop = getRoundedCornerTopDrawable(mContext, mDisplayUniqueId);
+        mRoundedCornerDrawableBottom = getRoundedCornerBottomDrawable(mContext, mDisplayUniqueId);
+        updateRoundedCornerImageView();
+    }
+
+    private void updateRoundedCornerImageView() {
+        final Drawable top = mRoundedCornerDrawableTop != null
+                ? mRoundedCornerDrawableTop : mRoundedCornerDrawable;
+        final Drawable bottom = mRoundedCornerDrawableBottom != null
+                ? mRoundedCornerDrawableBottom : mRoundedCornerDrawable;
+
+        if (mOverlays == null) {
+            return;
+        }
+        for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
+            if (mOverlays[i] == null) {
+                continue;
+            }
+            ((ImageView) mOverlays[i].findViewById(R.id.left)).setImageDrawable(
+                    isTopRoundedCorner(i, R.id.left) ? top : bottom);
+            ((ImageView) mOverlays[i].findViewById(R.id.right)).setImageDrawable(
+                    isTopRoundedCorner(i, R.id.right) ? top : bottom);
+        }
+    }
+
+    @VisibleForTesting
+    boolean isTopRoundedCorner(@BoundsPosition int pos, int id) {
+        switch (pos) {
+            case BOUNDS_POSITION_LEFT:
+            case BOUNDS_POSITION_RIGHT:
+                if (mRotation == ROTATION_270) {
+                    return id == R.id.left ? false : true;
+                } else {
+                    return id == R.id.left ? true : false;
+                }
+            case BOUNDS_POSITION_TOP:
+                return true;
+            case BOUNDS_POSITION_BOTTOM:
+                return false;
+            default:
+                throw new IllegalArgumentException("Unknown bounds position");
+        }
+    }
+
     private void updateRoundedCornerSize(
             Point sizeDefault,
             Point sizeTop,
@@ -855,21 +1002,10 @@
             if (mOverlays[i] == null) {
                 continue;
             }
-            if (i == BOUNDS_POSITION_LEFT || i == BOUNDS_POSITION_RIGHT) {
-                if (mRotation == ROTATION_270) {
-                    setSize(mOverlays[i].findViewById(R.id.left), sizeBottom);
-                    setSize(mOverlays[i].findViewById(R.id.right), sizeTop);
-                } else {
-                    setSize(mOverlays[i].findViewById(R.id.left), sizeTop);
-                    setSize(mOverlays[i].findViewById(R.id.right), sizeBottom);
-                }
-            } else if (i == BOUNDS_POSITION_TOP) {
-                setSize(mOverlays[i].findViewById(R.id.left), sizeTop);
-                setSize(mOverlays[i].findViewById(R.id.right), sizeTop);
-            } else if (i == BOUNDS_POSITION_BOTTOM) {
-                setSize(mOverlays[i].findViewById(R.id.left), sizeBottom);
-                setSize(mOverlays[i].findViewById(R.id.right), sizeBottom);
-            }
+            setSize(mOverlays[i].findViewById(R.id.left),
+                    isTopRoundedCorner(i, R.id.left) ? sizeTop : sizeBottom);
+            setSize(mOverlays[i].findViewById(R.id.right),
+                    isTopRoundedCorner(i, R.id.right) ? sizeTop : sizeBottom);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index bcc0530..0790af9 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -42,6 +42,7 @@
 import android.hardware.face.FaceSensorPropertiesInternal;
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.hardware.fingerprint.FingerprintStateListener;
 import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
 import android.hardware.fingerprint.IUdfpsHbmListener;
 import android.os.Bundle;
@@ -49,6 +50,7 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.util.Log;
+import android.util.SparseBooleanArray;
 import android.view.MotionEvent;
 import android.view.WindowManager;
 
@@ -76,6 +78,9 @@
 /**
  * Receives messages sent from {@link com.android.server.biometrics.BiometricService} and shows the
  * appropriate biometric UI (e.g. BiometricDialogView).
+ *
+ * Also coordinates biometric-related things, such as UDFPS, with
+ * {@link com.android.keyguard.KeyguardUpdateMonitor}
  */
 @SysUISingleton
 public class AuthController extends SystemUI implements CommandQueue.Callbacks,
@@ -115,6 +120,8 @@
     @Nullable private List<FingerprintSensorPropertiesInternal> mUdfpsProps;
     @Nullable private List<FingerprintSensorPropertiesInternal> mSidefpsProps;
 
+    @NonNull private final SparseBooleanArray mUdfpsEnrolledForUser;
+
     private class BiometricTaskStackListener extends TaskStackListener {
         @Override
         public void onTaskStackChanged() {
@@ -122,6 +129,21 @@
         }
     }
 
+    private final FingerprintStateListener mFingerprintStateListener =
+            new FingerprintStateListener() {
+        @Override
+        public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
+            Log.d(TAG, "onEnrollmentsChanged, userId: " + userId
+                    + ", sensorId: " + sensorId
+                    + ", hasEnrollments: " + hasEnrollments);
+            for (FingerprintSensorPropertiesInternal prop : mUdfpsProps) {
+                if (prop.sensorId == sensorId) {
+                    mUdfpsEnrolledForUser.put(userId, hasEnrollments);
+                }
+            }
+        }
+    };
+
     @NonNull
     private final IFingerprintAuthenticatorsRegisteredCallback
             mFingerprintAuthenticatorsRegisteredCallback =
@@ -436,6 +458,7 @@
         mUdfpsControllerFactory = udfpsControllerFactory;
         mSidefpsControllerFactory = sidefpsControllerFactory;
         mWindowManager = windowManager;
+        mUdfpsEnrolledForUser = new SparseBooleanArray();
         mOrientationListener = new BiometricOrientationEventListener(context,
                 () -> {
                     onOrientationChanged();
@@ -474,6 +497,7 @@
         if (mFingerprintManager != null) {
             mFingerprintManager.addAuthenticatorsRegisteredCallback(
                     mFingerprintAuthenticatorsRegisteredCallback);
+            mFingerprintManager.registerFingerprintStateListener(mFingerprintStateListener);
         }
 
         mTaskStackListener = new BiometricTaskStackListener();
@@ -673,7 +697,7 @@
             return false;
         }
 
-        return mFingerprintManager.hasEnrolledTemplatesForAnySensor(userId, mUdfpsProps);
+        return mUdfpsEnrolledForUser.get(userId);
     }
 
     private void showDialog(SomeArgs args, boolean skipAnimation, Bundle savedState) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index e13ae4c..ae426b6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -769,6 +769,7 @@
                 UdfpsEnrollView enrollView = (UdfpsEnrollView) mInflater.inflate(
                         R.layout.udfps_enroll_view, null);
                 mView.addView(enrollView);
+                enrollView.updateSensorLocation(mSensorProps);
                 return new UdfpsEnrollViewController(
                         enrollView,
                         mServerRequest.mEnrollHelper,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java
index b5273ab..d407756 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java
@@ -43,7 +43,6 @@
     // 1 + SCALE_MAX is the maximum that the moving target will animate to
     private static final float SCALE_MAX = 0.25f;
 
-    @NonNull private final UdfpsEnrollProgressBarDrawable mProgressDrawable;
     @NonNull private final Drawable mMovingTargetFpIcon;
     @NonNull private final Paint mSensorOutlinePaint;
     @NonNull private final Paint mBlueFill;
@@ -62,7 +61,6 @@
     UdfpsEnrollDrawable(@NonNull Context context) {
         super(context);
 
-        mProgressDrawable = new UdfpsEnrollProgressBarDrawable(context, this);
 
         mSensorOutlinePaint = new Paint(0 /* flags */);
         mSensorOutlinePaint.setAntiAlias(true);
@@ -100,8 +98,6 @@
     }
 
     void onEnrollmentProgress(int remaining, int totalSteps) {
-        mProgressDrawable.setEnrollmentProgress(remaining, totalSteps);
-
         if (mEnrollHelper.isCenterEnrollmentComplete()) {
             if (mAnimatorSet != null && mAnimatorSet.isRunning()) {
                 mAnimatorSet.end();
@@ -139,18 +135,8 @@
         }
     }
 
-    void onLastStepAcquired() {
-        mProgressDrawable.onLastStepAcquired();
-    }
-
-    void onEnrollmentHelp() {
-        mProgressDrawable.onEnrollmentHelp();
-    }
-
     @Override
     public void draw(@NonNull Canvas canvas) {
-        mProgressDrawable.draw(canvas);
-
         if (isIlluminationShowing()) {
             return;
         }
@@ -179,11 +165,6 @@
     }
 
     @Override
-    public void onBoundsChange(@NonNull Rect rect) {
-        mProgressDrawable.setBounds(rect);
-    }
-
-    @Override
     public void setAlpha(int alpha) {
         super.setAlpha(alpha);
         mSensorOutlinePaint.setAlpha(alpha);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java
index 9c486b9..373d17c8 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java
@@ -43,7 +43,6 @@
     private static final float PROGRESS_BAR_THICKNESS_DP = 12;
 
     @NonNull private final Context mContext;
-    @NonNull private final UdfpsEnrollDrawable mParent;
     @NonNull private final Paint mBackgroundCirclePaint;
     @NonNull private final Paint mProgressPaint;
 
@@ -57,10 +56,8 @@
     private int mRotation; // After last step, rotate the progress bar once
     private boolean mLastStepAcquired;
 
-    public UdfpsEnrollProgressBarDrawable(@NonNull Context context,
-            @NonNull UdfpsEnrollDrawable parent) {
+    public UdfpsEnrollProgressBarDrawable(@NonNull Context context) {
         mContext = context;
-        mParent = parent;
 
         mShortAnimationDuration = context.getResources()
                 .getInteger(com.android.internal.R.integer.config_shortAnimTime);
@@ -115,7 +112,7 @@
             rotationAnimator.addUpdateListener(animation -> {
                 Log.d(TAG, "Rotation: " + mRotation);
                 mRotation = (int) animation.getAnimatedValue();
-                mParent.invalidateSelf();
+                invalidateSelf();
             });
             rotationAnimator.start();
         }
@@ -128,11 +125,7 @@
         mProgressAnimator.setDuration(animationDuration);
         mProgressAnimator.addUpdateListener(animation -> {
             mProgress = (float) animation.getAnimatedValue();
-            // Use the parent to invalidate, since it's the one that's attached as the view's
-            // drawable and has its callback set automatically. Invalidating via
-            // `this.invalidateSelf` actually does not invoke draw(), since this drawable's callback
-            // is not really set.
-            mParent.invalidateSelf();
+            invalidateSelf();
         });
         mProgressAnimator.start();
     }
@@ -178,7 +171,6 @@
         animator.setDuration(mShortAnimationDuration);
         animator.addUpdateListener(animation -> {
             mProgressPaint.setColor((int) animation.getAnimatedValue());
-            mParent.invalidateSelf();
         });
         return animator;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java
index 56d5b31..d9edef4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java
@@ -17,9 +17,12 @@
 package com.android.systemui.biometrics;
 
 import android.content.Context;
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.os.Handler;
 import android.os.Looper;
 import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
 import android.widget.ImageView;
 
 import androidx.annotation.NonNull;
@@ -32,20 +35,25 @@
  */
 public class UdfpsEnrollView extends UdfpsAnimationView {
     @NonNull private final UdfpsEnrollDrawable mFingerprintDrawable;
+    @NonNull private final UdfpsEnrollProgressBarDrawable mFingerprintProgressDrawable;
     @NonNull private final Handler mHandler;
 
     @NonNull private ImageView mFingerprintView;
+    @NonNull private ImageView mFingerprintProgressView;
 
     public UdfpsEnrollView(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
         mFingerprintDrawable = new UdfpsEnrollDrawable(mContext);
+        mFingerprintProgressDrawable = new UdfpsEnrollProgressBarDrawable(context);
         mHandler = new Handler(Looper.getMainLooper());
     }
 
     @Override
     protected void onFinishInflate() {
         mFingerprintView = findViewById(R.id.udfps_enroll_animation_fp_view);
+        mFingerprintProgressView = findViewById(R.id.udfps_enroll_animation_fp_progress_view);
         mFingerprintView.setImageDrawable(mFingerprintDrawable);
+        mFingerprintProgressView.setImageDrawable(mFingerprintProgressDrawable);
     }
 
     @Override
@@ -53,19 +61,35 @@
         return mFingerprintDrawable;
     }
 
+    void updateSensorLocation(@NonNull FingerprintSensorPropertiesInternal sensorProps) {
+        View fingerprintAccessibilityView = findViewById(R.id.udfps_enroll_accessibility_view);
+        final int sensorHeight = sensorProps.sensorRadius * 2;
+        final int sensorWidth = sensorHeight;
+        ViewGroup.LayoutParams params = fingerprintAccessibilityView.getLayoutParams();
+        params.width = sensorWidth;
+        params.height = sensorHeight;
+        fingerprintAccessibilityView.setLayoutParams(params);
+        fingerprintAccessibilityView.requestLayout();
+    }
+
     void setEnrollHelper(UdfpsEnrollHelper enrollHelper) {
         mFingerprintDrawable.setEnrollHelper(enrollHelper);
     }
 
     void onEnrollmentProgress(int remaining, int totalSteps) {
-        mHandler.post(() -> mFingerprintDrawable.onEnrollmentProgress(remaining, totalSteps));
+        mHandler.post(() -> {
+            mFingerprintProgressDrawable.setEnrollmentProgress(remaining, totalSteps);
+            mFingerprintDrawable.onEnrollmentProgress(remaining, totalSteps);
+        });
     }
 
     void onLastStepAcquired() {
-        mHandler.post(mFingerprintDrawable::onLastStepAcquired);
+        mHandler.post(() -> {
+            mFingerprintProgressDrawable.onLastStepAcquired();
+        });
     }
 
     void onEnrollmentHelp() {
-        mHandler.post(mFingerprintDrawable::onEnrollmentHelp);
+        mHandler.post(mFingerprintProgressDrawable::onEnrollmentHelp);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 44ab69f..8ce4c3b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -292,7 +292,9 @@
                 : (int) MathUtils.constrain(
                     MathUtils.map(.5f, .9f, 0f, 255f, expansion),
                     0f, 255f);
-        alpha *= (1.0f - mTransitionToFullShadeProgress);
+        if (!mShowingUdfpsBouncer) {
+            alpha *= (1.0f - mTransitionToFullShadeProgress);
+        }
         mView.setUnpausedAlpha(alpha);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
index 39cbc90..bbb75c3 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
@@ -87,8 +87,11 @@
      * @param handler A handler to dispatch [BroadcastReceiver.onReceive].
      * @param user A user handle to determine which broadcast should be dispatched to this receiver.
      *             By default, it is the user of the context (system user in SystemUI).
+     * @param flags Flags to use when registering the receiver. [Context.RECEIVER_EXPORTED] by
+     *              default.
      * @throws IllegalArgumentException if the filter has other constraints that are not actions or
      *                                  categories or the filter has no actions.
+     *
      */
     @Deprecated(message = "Replacing Handler for Executor in SystemUI",
             replaceWith = ReplaceWith("registerReceiver(receiver, filter, executor, user)"))
@@ -97,9 +100,10 @@
         receiver: BroadcastReceiver,
         filter: IntentFilter,
         handler: Handler,
-        user: UserHandle = context.user
+        user: UserHandle = context.user,
+        @Context.RegisterReceiverFlags flags: Int = Context.RECEIVER_EXPORTED
     ) {
-        registerReceiver(receiver, filter, HandlerExecutor(handler), user)
+        registerReceiver(receiver, filter, HandlerExecutor(handler), user, flags)
     }
 
     /**
@@ -113,6 +117,8 @@
      *                 executor in the main thread (default).
      * @param user A user handle to determine which broadcast should be dispatched to this receiver.
      *             Pass `null` to use the user of the context (system user in SystemUI).
+     * @param flags Flags to use when registering the receiver. [Context.RECEIVER_EXPORTED] by
+     *              default.
      * @throws IllegalArgumentException if the filter has other constraints that are not actions or
      *                                  categories or the filter has no actions.
      */
@@ -121,16 +127,18 @@
         receiver: BroadcastReceiver,
         filter: IntentFilter,
         executor: Executor? = null,
-        user: UserHandle? = null
+        user: UserHandle? = null,
+        @Context.RegisterReceiverFlags flags: Int = Context.RECEIVER_EXPORTED
     ) {
         checkFilter(filter)
+        val data = ReceiverData(
+                receiver,
+                filter,
+                executor ?: context.mainExecutor,
+                user ?: context.user
+        )
         this.handler
-                .obtainMessage(MSG_ADD_RECEIVER, ReceiverData(
-                        receiver,
-                        filter,
-                        executor ?: context.mainExecutor,
-                        user ?: context.user
-                ))
+                .obtainMessage(MSG_ADD_RECEIVER, flags, 0, data)
                 .sendToTarget()
     }
 
@@ -188,6 +196,7 @@
             when (msg.what) {
                 MSG_ADD_RECEIVER -> {
                     val data = msg.obj as ReceiverData
+                    val flags = msg.arg1
                     // If the receiver asked to be registered under the current user, we register
                     // under the actual current user.
                     val userId = if (data.user.identifier == UserHandle.USER_CURRENT) {
@@ -201,7 +210,7 @@
                     }
                     val uBR = receiversByUser.get(userId, createUBRForUser(userId))
                     receiversByUser.put(userId, uBR)
-                    uBR.registerReceiver(data)
+                    uBR.registerReceiver(data, flags)
                 }
 
                 MSG_REMOVE_RECEIVER -> {
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
index 11da920..d4e9416 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
@@ -64,7 +64,7 @@
     private val bgHandler = object : Handler(bgLooper) {
         override fun handleMessage(msg: Message) {
             when (msg.what) {
-                MSG_REGISTER_RECEIVER -> handleRegisterReceiver(msg.obj as ReceiverData)
+                MSG_REGISTER_RECEIVER -> handleRegisterReceiver(msg.obj as ReceiverData, msg.arg1)
                 MSG_UNREGISTER_RECEIVER -> handleUnregisterReceiver(msg.obj as BroadcastReceiver)
                 else -> Unit
             }
@@ -73,7 +73,7 @@
 
     // Only modify in BG thread
     @VisibleForTesting
-    internal val actionsToActionsReceivers = ArrayMap<String, ActionReceiver>()
+    internal val actionsToActionsReceivers = ArrayMap<Pair<String, Int>, ActionReceiver>()
     private val receiverToActions = ArrayMap<BroadcastReceiver, MutableSet<String>>()
 
     @VisibleForTesting
@@ -86,8 +86,8 @@
     /**
      * Register a [ReceiverData] for this user.
      */
-    fun registerReceiver(receiverData: ReceiverData) {
-        bgHandler.obtainMessage(MSG_REGISTER_RECEIVER, receiverData).sendToTarget()
+    fun registerReceiver(receiverData: ReceiverData, flags: Int) {
+        bgHandler.obtainMessage(MSG_REGISTER_RECEIVER, flags, 0, receiverData).sendToTarget()
     }
 
     /**
@@ -97,7 +97,7 @@
         bgHandler.obtainMessage(MSG_UNREGISTER_RECEIVER, receiver).sendToTarget()
     }
 
-    private fun handleRegisterReceiver(receiverData: ReceiverData) {
+    private fun handleRegisterReceiver(receiverData: ReceiverData, flags: Int) {
         Preconditions.checkState(bgHandler.looper.isCurrentThread,
                 "This method should only be called from BG thread")
         if (DEBUG) Log.w(TAG, "Register receiver: ${receiverData.receiver}")
@@ -106,20 +106,27 @@
                 .addAll(receiverData.filter.actionsIterator()?.asSequence() ?: emptySequence())
         receiverData.filter.actionsIterator().forEach {
             actionsToActionsReceivers
-                    .getOrPut(it, { createActionReceiver(it) })
+                    .getOrPut(it to flags, { createActionReceiver(it, flags) })
                     .addReceiverData(receiverData)
         }
-        logger.logReceiverRegistered(userId, receiverData.receiver)
+        logger.logReceiverRegistered(userId, receiverData.receiver, flags)
     }
 
     @VisibleForTesting
-    internal open fun createActionReceiver(action: String): ActionReceiver {
+    internal open fun createActionReceiver(action: String, flags: Int): ActionReceiver {
         return ActionReceiver(
                 action,
                 userId,
                 {
-                    context.registerReceiverAsUser(this, UserHandle.of(userId), it, null, bgHandler)
-                    logger.logContextReceiverRegistered(userId, it)
+                    context.registerReceiverAsUser(
+                            this,
+                            UserHandle.of(userId),
+                            it,
+                            null,
+                            bgHandler,
+                            flags
+                    )
+                    logger.logContextReceiverRegistered(userId, flags, it)
                 },
                 {
                     try {
@@ -141,7 +148,11 @@
                 "This method should only be called from BG thread")
         if (DEBUG) Log.w(TAG, "Unregister receiver: $receiver")
         receiverToActions.getOrDefault(receiver, mutableSetOf()).forEach {
-            actionsToActionsReceivers.get(it)?.removeReceiver(receiver)
+            actionsToActionsReceivers.forEach { (key, value) ->
+                if (key.first == it) {
+                    value.removeReceiver(receiver)
+                }
+            }
         }
         receiverToActions.remove(receiver)
         logger.logReceiverUnregistered(userId, receiver)
@@ -149,8 +160,9 @@
 
     override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
         pw.indentIfPossible {
-            actionsToActionsReceivers.forEach { (action, actionReceiver) ->
-                println("$action:")
+            actionsToActionsReceivers.forEach { (actionAndFlags, actionReceiver) ->
+                println("(${actionAndFlags.first}: " +
+                        "${BroadcastDispatcherLogger.flagToString(actionAndFlags.second)}):")
                 actionReceiver.dump(fd, pw, args)
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt b/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
index 6ba88f4..8da6519 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.broadcast.logging
 
 import android.content.BroadcastReceiver
+import android.content.Context
 import android.content.Intent
 import android.content.IntentFilter
 import com.android.systemui.log.LogBuffer
@@ -33,6 +34,25 @@
     @BroadcastDispatcherLog private val buffer: LogBuffer
 ) {
 
+    companion object {
+        fun flagToString(@Context.RegisterReceiverFlags flag: Int): String {
+            val b = StringBuilder("")
+            if (flag and Context.RECEIVER_VISIBLE_TO_INSTANT_APPS != 0) {
+                b.append("instant_apps,")
+            }
+            if (flag and Context.RECEIVER_NOT_EXPORTED != 0) {
+                b.append("not_exported,")
+            }
+            if (flag and Context.RECEIVER_EXPORTED != 0) {
+                b.append("exported")
+            }
+            if (b.isEmpty()) {
+                b.append(flag)
+            }
+            return b.toString()
+        }
+    }
+
     fun logBroadcastReceived(broadcastId: Int, user: Int, intent: Intent) {
         val intentString = intent.toString()
         log(INFO, {
@@ -55,13 +75,15 @@
         })
     }
 
-    fun logReceiverRegistered(user: Int, receiver: BroadcastReceiver) {
+    fun logReceiverRegistered(user: Int, receiver: BroadcastReceiver, flags: Int) {
         val receiverString = receiver.toString()
+        val flagsString = flagToString(flags)
         log(INFO, {
             int1 = user
             str1 = receiverString
+            str2 = flagsString
         }, {
-            "Receiver $str1 registered for user $int1"
+            "Receiver $str1 ($str2) registered for user $int1"
         })
     }
 
@@ -75,7 +97,7 @@
         })
     }
 
-    fun logContextReceiverRegistered(user: Int, filter: IntentFilter) {
+    fun logContextReceiverRegistered(user: Int, flags: Int, filter: IntentFilter) {
         val actions = filter.actionsIterator().asSequence()
                 .joinToString(separator = ",", prefix = "Actions(", postfix = ")")
         val categories = if (filter.countCategories() != 0) {
@@ -91,9 +113,10 @@
             } else {
                 actions
             }
+            str2 = flagToString(flags)
         }, {
             """
-                Receiver registered with Context for user $int1.
+                Receiver registered with Context for user $int1. Flags=$str2
                 $str1
             """.trimIndent()
         })
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index 5b33428..7c281f9 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -29,6 +29,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 
 import java.io.FileDescriptor;
@@ -50,19 +51,32 @@
     private final GradientColors mBackdropColors;
 
     @Inject
-    public SysuiColorExtractor(Context context, ConfigurationController configurationController) {
-        this(context, new Tonal(context), configurationController,
-                context.getSystemService(WallpaperManager.class), false /* immediately */);
+    public SysuiColorExtractor(
+            Context context,
+            ConfigurationController configurationController,
+            DumpManager dumpManager) {
+        this(
+                context,
+                new Tonal(context),
+                configurationController,
+                context.getSystemService(WallpaperManager.class),
+                dumpManager,
+                false /* immediately */);
     }
 
     @VisibleForTesting
-    public SysuiColorExtractor(Context context, ExtractionType type,
+    public SysuiColorExtractor(
+            Context context,
+            ExtractionType type,
             ConfigurationController configurationController,
-            WallpaperManager wallpaperManager, boolean immediately) {
+            WallpaperManager wallpaperManager,
+            DumpManager dumpManager,
+            boolean immediately) {
         super(context, type, immediately, wallpaperManager);
         mTonal = type instanceof Tonal ? (Tonal) type : new Tonal(context);
         mNeutralColorsLock = new GradientColors();
         configurationController.addCallback(this);
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
 
         mBackdropColors = new GradientColors();
         mBackdropColors.setMainColor(Color.BLACK);
diff --git a/packages/SystemUI/src/com/android/systemui/communal/service/CommunalService.java b/packages/SystemUI/src/com/android/systemui/communal/service/CommunalService.java
deleted file mode 100644
index 1612670..0000000
--- a/packages/SystemUI/src/com/android/systemui/communal/service/CommunalService.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.communal.service;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-
-import androidx.annotation.Nullable;
-
-import com.android.systemui.communal.CommunalSourceMonitor;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.shared.communal.ICommunalHost;
-import com.android.systemui.shared.communal.ICommunalSource;
-
-import java.util.concurrent.Executor;
-
-import javax.inject.Inject;
-
-/**
- * CommunalService services requests to {@link ICommunalHost}, allowing clients to declare
- * themselves as the source of communal surfaces.
- */
-public class CommunalService extends Service {
-    final Executor mMainExecutor;
-    final CommunalSourceMonitor mMonitor;
-    private final CommunalSourceImpl.Factory mSourceFactory;
-
-    private ICommunalHost.Stub mBinder = new ICommunalHost.Stub() {
-        @Override
-        public void setSource(ICommunalSource source) {
-            mMonitor.setSource(
-                    source != null ? mSourceFactory.create(source) : null);
-        }
-    };
-
-    @Inject
-    CommunalService(@Main Executor mainExecutor, CommunalSourceImpl.Factory sourceFactory,
-            CommunalSourceMonitor monitor) {
-        mMainExecutor = mainExecutor;
-        mSourceFactory = sourceFactory;
-        mMonitor = monitor;
-    }
-
-    @Nullable
-    @Override
-    public IBinder onBind(Intent intent) {
-        // The service does not expect requests outside ICommunalHost.
-        return mBinder;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/service/CommunalSourceImpl.java b/packages/SystemUI/src/com/android/systemui/communal/service/CommunalSourceImpl.java
deleted file mode 100644
index b8070ab..0000000
--- a/packages/SystemUI/src/com/android/systemui/communal/service/CommunalSourceImpl.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.communal.service;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.SurfaceControlViewHost;
-import android.view.SurfaceView;
-
-import androidx.concurrent.futures.CallbackToFutureAdapter;
-
-import com.android.systemui.communal.CommunalSource;
-import com.android.systemui.communal.CommunalStateController;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.shared.communal.ICommunalSource;
-import com.android.systemui.shared.communal.ICommunalSurfaceCallback;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-
-import com.google.android.collect.Lists;
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-
-import javax.inject.Inject;
-
-/**
- * {@link CommunalSourceImpl} provides a wrapper around {@link ICommunalSource} proxies as an
- * implementation of {@link CommunalSource}. Requests and responses for communal surfaces are
- * translated into the proper binder calls.
- */
-public class CommunalSourceImpl implements CommunalSource {
-    private static final String TAG = "CommunalSourceImpl";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private final ICommunalSource mSourceProxy;
-    private final Resources mResources;
-    private final Executor mMainExecutor;
-    private final NotificationShadeWindowController mNotificationShadeWindowController;
-    private final CommunalStateController mCommunalStateController;
-
-    static class Factory {
-        private final Executor mExecutor;
-        private final Resources mResources;
-        private final CommunalStateController mCommunalStateController;
-        private final NotificationShadeWindowController mNotificationShadeWindowController;
-
-        @Inject
-        Factory(@Main Executor executor, @Main Resources resources,
-                NotificationShadeWindowController notificationShadeWindowController,
-                CommunalStateController communalStateController) {
-            mExecutor = executor;
-            mResources = resources;
-            mNotificationShadeWindowController = notificationShadeWindowController;
-            mCommunalStateController = communalStateController;
-        }
-
-        public CommunalSource create(ICommunalSource source) {
-            return new CommunalSourceImpl(mExecutor, mResources, mCommunalStateController,
-                    mNotificationShadeWindowController, source);
-        }
-    }
-
-    static class Request {
-        private final int mWidth;
-        private final int mHeight;
-        private final int mDisplayId;
-        private final IBinder mHostToken;
-
-        Request(int width, int height, int displayId, IBinder hostToken) {
-            mWidth = width;
-            mHeight = height;
-            mDisplayId = displayId;
-            mHostToken = hostToken;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (!(o instanceof Request)) return false;
-            Request request = (Request) o;
-            return mWidth == request.mWidth && mHeight == request.mHeight
-                    && mDisplayId == request.mDisplayId && Objects.equals(mHostToken,
-                    request.mHostToken);
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(mWidth, mHeight, mDisplayId, mHostToken);
-        }
-
-        @Override
-        public String toString() {
-            return "Request{"
-                    + "mWidth=" + mWidth
-                    + ", mHeight=" + mHeight
-                    + ", mDisplayId=" + mDisplayId
-                    + ", mHostToken=" + mHostToken
-                    + '}';
-        }
-    }
-
-    // mConnected is initialized to true as it is presumed instances are constructed with valid
-    // proxies. The source can never be reconnected once the proxy has died. Once this value
-    // becomes false, the source will always report disconnected to registering callbacks.
-    private boolean mConnected = true;
-
-    // A list of {@link Callback} that have registered to receive updates.
-    private final ArrayList<WeakReference<Callback>> mCallbacks = Lists.newArrayList();
-
-    public CommunalSourceImpl(Executor mainExecutor, Resources resources,
-            CommunalStateController communalStateController,
-            NotificationShadeWindowController notificationShadeWindowController,
-            ICommunalSource sourceProxy) {
-        mMainExecutor = mainExecutor;
-        mCommunalStateController = communalStateController;
-        mNotificationShadeWindowController = notificationShadeWindowController;
-        mResources = resources;
-        mSourceProxy = sourceProxy;
-
-        try {
-            // Track connection status based on proxy lifetime.
-            mSourceProxy.asBinder().linkToDeath(new IBinder.DeathRecipient() {
-                @Override
-                public void binderDied() {
-                    if (DEBUG) {
-                        Log.d(TAG, "Source lost. Clearing reporting disconnect.");
-                    }
-
-                    // Set connection state and inform callbacks.
-                    onDisconnected();
-                }
-            }, 0);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Could not link to the source proxy death:" + e);
-        }
-    }
-
-    private void onDisconnected() {
-        mConnected = false;
-        for (WeakReference<Callback> cbRef : mCallbacks) {
-            final Callback cb = cbRef.get();
-            if (cb != null) {
-                cb.onDisconnected();
-            }
-        }
-
-        mCallbacks.clear();
-    }
-
-    @Override
-    public ListenableFuture<CommunalViewResult> requestCommunalView(Context context) {
-        if (DEBUG) {
-            Log.d(TAG, "Received request for communal view");
-        }
-        ListenableFuture<CommunalViewResult> packageFuture =
-                CallbackToFutureAdapter.getFuture(completer -> {
-                    final SurfaceView view = new SurfaceView(context);
-                    completer.set(new CommunalViewResult(view,
-                            new CommunalSurfaceViewController(view, mResources, mMainExecutor,
-                                    mCommunalStateController, mNotificationShadeWindowController,
-                                    this)));
-                    return "CommunalSourceImpl::requestCommunalSurface::getCommunalSurface";
-                });
-
-        return packageFuture;
-    }
-
-    /**
-     * Called internally to request a new {@link android.view.SurfaceControlViewHost.SurfacePackage}
-     * for showing communal content.
-     *
-     * @param request A request with the parameters for the new communal surface.
-     * @return A future that returns the resulting
-     * {@link android.view.SurfaceControlViewHost.SurfacePackage}.
-     */
-    protected ListenableFuture<SurfaceControlViewHost.SurfacePackage> requestCommunalSurface(
-            Request request) {
-        return CallbackToFutureAdapter.getFuture(completer -> {
-            mSourceProxy.getCommunalSurface(request.mHostToken, request.mWidth, request.mHeight,
-                    request.mDisplayId, new ICommunalSurfaceCallback.Stub() {
-                        @Override
-                        public void onSurface(
-                                SurfaceControlViewHost.SurfacePackage surfacePackage) {
-                            completer.set(surfacePackage);
-                        }
-                    });
-            return "CommunalSourceImpl::requestCommunalSurface::getCommunalSurface";
-        });
-
-    }
-
-    @Override
-    public void addCallback(Callback callback) {
-        mCallbacks.add(new WeakReference<>(callback));
-
-        // If not connected anymore, immediately inform new callback of disconnection and remove.
-        if (!mConnected) {
-            onDisconnected();
-        }
-    }
-
-    @Override
-    public void removeCallback(Callback callback) {
-        mCallbacks.removeIf(el -> el.get() == callback);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/service/CommunalSourcePrimer.java b/packages/SystemUI/src/com/android/systemui/communal/service/CommunalSourcePrimer.java
deleted file mode 100644
index 0f013ff..0000000
--- a/packages/SystemUI/src/com/android/systemui/communal/service/CommunalSourcePrimer.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.communal.service;
-
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.ServiceConnection;
-import android.content.res.Resources;
-import android.os.IBinder;
-import android.os.PatternMatcher;
-import android.util.Log;
-
-import com.android.systemui.R;
-import com.android.systemui.SystemUI;
-import com.android.systemui.communal.CommunalSourceMonitor;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.shared.communal.ICommunalSource;
-import com.android.systemui.util.concurrency.DelayableExecutor;
-
-import javax.inject.Inject;
-
-/**
- * The {@link CommunalSourcePrimer} is responsible for priming SystemUI with a pre-configured
- * Communal source. The SystemUI service binds to the component to retrieve the
- * {@link com.android.systemui.communal.CommunalSource}. {@link CommunalSourcePrimer} has no effect
- * if there is no pre-defined value.
- */
-@SysUISingleton
-public class CommunalSourcePrimer extends SystemUI {
-    private static final String TAG = "CommunalSourcePrimer";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private static final String ACTION_COMMUNAL_SOURCE = "android.intent.action.COMMUNAL_SOURCE";
-
-    private final Context mContext;
-    private final DelayableExecutor mMainExecutor;
-    private final CommunalSourceMonitor mMonitor;
-    private final CommunalSourceImpl.Factory mSourceFactory;
-    private final ComponentName mComponentName;
-    private final int mBaseReconnectDelayMs;
-    private final int mMaxReconnectAttempts;
-
-    private int mReconnectAttempts = 0;
-    private Runnable mCurrentReconnectCancelable;
-
-    private final Runnable mConnectRunnable = new Runnable() {
-        @Override
-        public void run() {
-            mCurrentReconnectCancelable = null;
-            bindToService();
-        }
-    };
-
-
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (DEBUG) {
-                Log.d(TAG, "package added receiver - onReceive");
-            }
-
-            initiateConnectionAttempt();
-        }
-    };
-
-    private final ServiceConnection mConnection = new ServiceConnection() {
-        @Override
-        public void onServiceConnected(ComponentName className, IBinder service) {
-            final ICommunalSource source = ICommunalSource.Stub.asInterface(service);
-            if (DEBUG) {
-                Log.d(TAG, "onServiceConnected. source:" + source);
-            }
-
-            if (source == null) {
-                if (DEBUG) {
-                    Log.d(TAG, "onServiceConnected. invalid source");
-                    // Since the service could just repeatedly return null, the primer chooses
-                    // to schedule rather than initiate a new connection attempt sequence.
-                    scheduleConnectionAttempt();
-                }
-                return;
-            }
-
-            mMonitor.setSource(mSourceFactory.create(source));
-        }
-
-        @Override
-        public void onBindingDied(ComponentName name) {
-            if (DEBUG) {
-                Log.d(TAG, "onBindingDied. lost communal source. initiating reconnect");
-            }
-
-            initiateConnectionAttempt();
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName className) {
-            if (DEBUG) {
-                Log.d(TAG,
-                        "onServiceDisconnected. lost communal source. initiating reconnect");
-            }
-
-            initiateConnectionAttempt();
-        }
-    };
-
-    @Inject
-    public CommunalSourcePrimer(Context context, @Main Resources resources,
-            DelayableExecutor mainExecutor,
-            CommunalSourceMonitor monitor,
-            CommunalSourceImpl.Factory sourceFactory) {
-        super(context);
-        mContext = context;
-        mMainExecutor = mainExecutor;
-        mMonitor = monitor;
-        mSourceFactory = sourceFactory;
-        mMaxReconnectAttempts = resources.getInteger(
-                R.integer.config_communalSourceMaxReconnectAttempts);
-        mBaseReconnectDelayMs = resources.getInteger(
-                R.integer.config_communalSourceReconnectBaseDelay);
-
-        final String component = resources.getString(R.string.config_communalSourceComponent);
-        mComponentName = component != null && !component.isEmpty()
-                ? ComponentName.unflattenFromString(component) : null;
-    }
-
-    @Override
-    public void start() {
-    }
-
-    private void initiateConnectionAttempt() {
-        // Reset attempts
-        mReconnectAttempts = 0;
-        mMonitor.setSource(null);
-
-        // The first attempt is always a direct invocation rather than delayed.
-        bindToService();
-    }
-
-    private void registerPackageListening() {
-        if (mComponentName == null) {
-            return;
-        }
-
-        final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
-        filter.addDataScheme("package");
-        filter.addDataSchemeSpecificPart(mComponentName.getPackageName(),
-                PatternMatcher.PATTERN_LITERAL);
-        // Note that we directly register the receiver here as data schemes are not supported by
-        // BroadcastDispatcher.
-        mContext.registerReceiver(mReceiver, filter);
-    }
-
-    private void scheduleConnectionAttempt() {
-        // always clear cancelable if present.
-        if (mCurrentReconnectCancelable != null) {
-            mCurrentReconnectCancelable.run();
-            mCurrentReconnectCancelable = null;
-        }
-
-        if (mReconnectAttempts >= mMaxReconnectAttempts) {
-            if (DEBUG) {
-                Log.d(TAG, "exceeded max connection attempts.");
-            }
-            return;
-        }
-
-        final long reconnectDelayMs =
-                (long) Math.scalb(mBaseReconnectDelayMs, mReconnectAttempts);
-
-        if (DEBUG) {
-            Log.d(TAG,
-                    "scheduling connection attempt in " + reconnectDelayMs + "milliseconds");
-        }
-
-        mCurrentReconnectCancelable = mMainExecutor.executeDelayed(mConnectRunnable,
-                reconnectDelayMs);
-
-        mReconnectAttempts++;
-    }
-
-    @Override
-    protected void onBootCompleted() {
-        super.onBootCompleted();
-
-        if (DEBUG) {
-            Log.d(TAG, "onBootCompleted. communal source component:" + mComponentName);
-        }
-
-        registerPackageListening();
-        initiateConnectionAttempt();
-    }
-
-    private void bindToService() {
-        if (mComponentName == null) {
-            return;
-        }
-
-        if (DEBUG) {
-            Log.d(TAG, "attempting to bind to communal source");
-        }
-
-        final Intent intent = new Intent();
-        intent.setAction(ACTION_COMMUNAL_SOURCE);
-        intent.setComponent(mComponentName);
-
-        final boolean binding = mContext.bindService(intent, Context.BIND_AUTO_CREATE,
-                mMainExecutor, mConnection);
-
-        if (!binding) {
-            if (DEBUG) {
-                Log.d(TAG, "bindService failed, rescheduling");
-            }
-
-            scheduleConnectionAttempt();
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/service/CommunalSurfaceViewController.java b/packages/SystemUI/src/com/android/systemui/communal/service/CommunalSurfaceViewController.java
deleted file mode 100644
index 0de5029..0000000
--- a/packages/SystemUI/src/com/android/systemui/communal/service/CommunalSurfaceViewController.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.communal.service;
-
-import android.annotation.IntDef;
-import android.content.res.Resources;
-import android.graphics.PixelFormat;
-import android.graphics.Region;
-import android.util.Log;
-import android.view.IWindow;
-import android.view.SurfaceControlViewHost;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-
-import com.android.systemui.R;
-import com.android.systemui.communal.CommunalStateController;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.util.Utils;
-import com.android.systemui.util.ViewController;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.util.Optional;
-import java.util.concurrent.Executor;
-
-/**
- * {@link CommunalSurfaceViewController} coordinates requesting communal surfaces to populate a
- * {@link SurfaceView} with.
- */
-public class CommunalSurfaceViewController extends ViewController<SurfaceView> {
-    private static final String TAG = "CommunalSurfaceViewCtlr";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private final Executor mMainExecutor;
-    private final CommunalStateController mCommunalStateController;
-    private final NotificationShadeWindowController mNotificationShadeWindowController;
-    private final CommunalSourceImpl mSource;
-    private final Resources mResources;
-    private final Region mSurfaceViewTouchableRegion;
-
-    @IntDef({STATE_SURFACE_CREATED, STATE_SURFACE_VIEW_ATTACHED})
-    private @interface State {}
-
-    private static final int STATE_SURFACE_CREATED = 1 << 0;
-    private static final int STATE_SURFACE_VIEW_ATTACHED = 1 << 1;
-
-    private static final int STATE_CAN_SHOW_SURFACE =
-            STATE_SURFACE_CREATED | STATE_SURFACE_VIEW_ATTACHED;
-
-    private int mCurrentState;
-
-    private Optional<CommunalSourceImpl.Request> mLastRequest = Optional.empty();
-
-    // The current in-flight request for a surface package.
-    private ListenableFuture<SurfaceControlViewHost.SurfacePackage> mCurrentSurfaceFuture;
-
-    private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {
-        @Override
-        public void surfaceCreated(@NonNull SurfaceHolder holder) {
-            setState(STATE_SURFACE_CREATED, true);
-        }
-
-        @Override
-        public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width,
-                int height) {
-        }
-
-        @Override
-        public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
-            setState(STATE_SURFACE_CREATED, false);
-        }
-    };
-
-    private final View.OnLayoutChangeListener mOnLayoutChangeListener =
-            new View.OnLayoutChangeListener() {
-        @Override
-        public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
-                int oldTop, int oldRight, int oldBottom) {
-            // The margin for the status bar and keyguard indication are excluded from the tap
-            // exclusion to preserve vertical swipes in this region.
-            final int topMargin = mResources.getDimensionPixelSize(
-                    Utils.shouldUseSplitNotificationShade(mResources)
-                            ? R.dimen.split_shade_header_height
-                            : R.dimen.notification_panel_margin_top);
-            final int bottomMargin = mResources.getDimensionPixelSize(
-                    R.dimen.keyguard_indication_bottom_padding);
-
-            mSurfaceViewTouchableRegion.set(left, top + topMargin, right, bottom - bottomMargin);
-            updateTouchExclusion();
-
-            // Trigger showing (or hiding) surface based on new dimensions.
-            showSurface();
-        }
-    };
-
-    private CommunalStateController.Callback mCommunalStateCallback =
-            new CommunalStateController.Callback() {
-        @Override
-        public void onCommunalViewOccludedChanged() {
-            updateTouchExclusion();
-        }
-    };
-
-    protected CommunalSurfaceViewController(SurfaceView view, Resources resources,
-            Executor executor, CommunalStateController communalStateController,
-            NotificationShadeWindowController notificationShadeWindowController,
-            CommunalSourceImpl source) {
-        super(view);
-        mCommunalStateController = communalStateController;
-        mSource = source;
-        mResources = resources;
-        mMainExecutor = executor;
-        mNotificationShadeWindowController = notificationShadeWindowController;
-        mSurfaceViewTouchableRegion = new Region();
-    }
-
-    @Override
-    protected void onInit() {
-        mView.getHolder().setFormat(PixelFormat.TRANSPARENT);
-        mView.getHolder().addCallback(mSurfaceHolderCallback);
-        mView.addOnLayoutChangeListener(mOnLayoutChangeListener);
-    }
-
-    private void setState(@State int state, boolean enabled) {
-        if (DEBUG) {
-            Log.d(TAG, "setState. state:" + state + " enable:" + enabled);
-        }
-
-        final int newState = enabled ? mCurrentState | state : mCurrentState & ~state;
-
-        // no new state is available
-        if (newState == mCurrentState) {
-            return;
-        }
-
-        if (DEBUG) {
-            Log.d(TAG, "setState. new state:" + mCurrentState);
-        }
-
-        mCurrentState = newState;
-
-        showSurface();
-
-        updateTouchExclusion();
-    }
-
-    private void updateTouchExclusion() {
-        final IWindow window = IWindow.Stub.asInterface(mView.getWindowToken());
-        final boolean excludeTouches = (mCurrentState & STATE_SURFACE_VIEW_ATTACHED) != 0
-                && !mCommunalStateController.getCommunalViewOccluded();
-        if (excludeTouches) {
-            mNotificationShadeWindowController.setTouchExclusionRegion(mSurfaceViewTouchableRegion);
-        } else {
-            final Region emptyRegion = Region.obtain();
-            mNotificationShadeWindowController.setTouchExclusionRegion(emptyRegion);
-            emptyRegion.recycle();
-        }
-    }
-
-    private void showSurface() {
-        mView.setWillNotDraw(false);
-
-        if (mCurrentState != STATE_CAN_SHOW_SURFACE) {
-            // If the surface is no longer showing, cancel any in-flight requests.
-            if (mCurrentSurfaceFuture != null) {
-                mCurrentSurfaceFuture.cancel(true);
-                mCurrentSurfaceFuture = null;
-            }
-
-            mLastRequest = Optional.empty();
-            mView.setWillNotDraw(true);
-            return;
-        }
-
-        final CommunalSourceImpl.Request request = new CommunalSourceImpl.Request(
-                mView.getMeasuredWidth(), mView.getMeasuredHeight(),
-                mView.getDisplay().getDisplayId(), mView.getHostToken());
-
-        if (mLastRequest.isPresent() && mLastRequest.get().equals(request)) {
-            return;
-        }
-
-        mLastRequest = Optional.of(request);
-
-        // Since this method is only called when the state has changed, mCurrentSurfaceFuture should
-        // be null here.
-        mCurrentSurfaceFuture = mSource.requestCommunalSurface(request);
-
-        mCurrentSurfaceFuture.addListener(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    // If the request is received after detached, ignore.
-                    if (!mView.isAttachedToWindow()) {
-                        return;
-                    }
-
-                    SurfaceControlViewHost.SurfacePackage surfacePackage =
-                            mCurrentSurfaceFuture.get();
-                    mCurrentSurfaceFuture = null;
-
-                    if (DEBUG) {
-                        Log.d(TAG, "Received surface package:" + surfacePackage);
-                    }
-
-                    if (surfacePackage != null) {
-                        mView.setChildSurfacePackage(surfacePackage);
-                        mView.postInvalidate();
-                        mCommunalStateController.setCommunalViewShowing(true);
-                    } else {
-                        Log.e(TAG, "couldn't get the surface package");
-                    }
-                } catch (Exception e) {
-                    Log.e(TAG, "An error occurred retrieving the future result:" + e);
-                }
-            }
-        }, mMainExecutor);
-    }
-
-    @Override
-    protected void onViewAttached() {
-        setState(STATE_SURFACE_VIEW_ATTACHED, true);
-        mCommunalStateController.addCallback(mCommunalStateCallback);
-    }
-
-    @Override
-    protected void onViewDetached() {
-        mCommunalStateController.removeCallback(mCommunalStateCallback);
-        setState(STATE_SURFACE_VIEW_ATTACHED, false);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java
index 17bd14c3..fe79110 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java
@@ -20,7 +20,6 @@
 
 import com.android.systemui.ImageWallpaper;
 import com.android.systemui.SystemUIService;
-import com.android.systemui.communal.service.CommunalService;
 import com.android.systemui.doze.DozeService;
 import com.android.systemui.dump.SystemUIAuxiliaryDumpService;
 import com.android.systemui.keyguard.KeyguardService;
@@ -39,12 +38,6 @@
     /** */
     @Binds
     @IntoMap
-    @ClassKey(CommunalService.class)
-    public abstract Service bindCommunalService(CommunalService service);
-
-    /** */
-    @Binds
-    @IntoMap
     @ClassKey(DozeService.class)
     public abstract Service bindDozeService(DozeService service);
 
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index e7974bc..2d873f2 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -36,11 +36,8 @@
 import android.view.Choreographer;
 import android.view.IWindowManager;
 import android.view.LayoutInflater;
-import android.view.WindowManager;
-import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
 import com.android.internal.util.NotificationMessagingUtil;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
@@ -51,9 +48,7 @@
 import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
 import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
 import com.android.systemui.accessibility.ModeSwitchesController;
-import com.android.systemui.accessibility.SystemActions;
 import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController;
-import com.android.systemui.assist.AssistManager;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger;
 import com.android.systemui.dagger.qualifiers.Background;
@@ -62,48 +57,28 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.LifecycleScreenStatusProvider;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationBarA11yHelper;
-import com.android.systemui.navigationbar.NavigationBarController;
-import com.android.systemui.navigationbar.NavigationBarOverlayController;
-import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.navigationbar.TaskbarDelegate;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.qs.ReduceBrightColorsController;
-import com.android.systemui.recents.OverviewProxyService;
-import com.android.systemui.recents.Recents;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListeners;
 import com.android.systemui.shared.system.WindowManagerWrapper;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.phone.AutoHideController;
 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
-import com.android.systemui.statusbar.phone.ShadeController;
-import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DataSaverController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.theme.ThemeOverlayApplier;
-import com.android.systemui.util.leak.LeakDetector;
-import com.android.systemui.util.settings.SecureSettings;
 import com.android.systemui.unfold.UnfoldTransitionFactory;
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
 import com.android.systemui.unfold.config.UnfoldTransitionConfig;
-import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
-import com.android.wm.shell.pip.Pip;
+import com.android.systemui.util.leak.LeakDetector;
+import com.android.systemui.util.settings.SecureSettings;
 
-import java.util.Optional;
 import java.util.concurrent.Executor;
 
 import javax.inject.Named;
 
-import dagger.Lazy;
 import dagger.Module;
 import dagger.Provides;
 
@@ -171,9 +146,8 @@
     /** */
     @Provides
     @SysUISingleton
-    public LeakDetector provideLeakDetector() {
-        return LeakDetector.create();
-
+    public LeakDetector provideLeakDetector(DumpManager dumpManager) {
+        return LeakDetector.create(dumpManager);
     }
 
     @SuppressLint("MissingPermission")
@@ -208,69 +182,6 @@
     /** */
     @Provides
     @SysUISingleton
-    public NavigationBarController provideNavigationBarController(Context context,
-            WindowManager windowManager,
-            Lazy<AssistManager> assistManagerLazy,
-            AccessibilityManager accessibilityManager,
-            AccessibilityManagerWrapper accessibilityManagerWrapper,
-            DeviceProvisionedController deviceProvisionedController,
-            MetricsLogger metricsLogger,
-            OverviewProxyService overviewProxyService,
-            NavigationModeController navigationModeController,
-            AccessibilityButtonModeObserver accessibilityButtonModeObserver,
-            StatusBarStateController statusBarStateController,
-            SysUiState sysUiFlagsContainer,
-            BroadcastDispatcher broadcastDispatcher,
-            CommandQueue commandQueue,
-            Optional<Pip> pipOptional,
-            Optional<LegacySplitScreen> splitScreenOptional,
-            Optional<Recents> recentsOptional,
-            Lazy<Optional<StatusBar>> statusBarOptionalLazy,
-            ShadeController shadeController,
-            NotificationRemoteInputManager notificationRemoteInputManager,
-            NotificationShadeDepthController notificationShadeDepthController,
-            SystemActions systemActions,
-            @Main Handler mainHandler,
-            UiEventLogger uiEventLogger,
-            NavigationBarOverlayController navBarOverlayController,
-            ConfigurationController configurationController,
-            NavigationBarA11yHelper navigationBarA11yHelper,
-            TaskbarDelegate taskbarDelegate,
-            UserTracker userTracker) {
-        return new NavigationBarController(context,
-                windowManager,
-                assistManagerLazy,
-                accessibilityManager,
-                accessibilityManagerWrapper,
-                deviceProvisionedController,
-                metricsLogger,
-                overviewProxyService,
-                navigationModeController,
-                accessibilityButtonModeObserver,
-                statusBarStateController,
-                sysUiFlagsContainer,
-                broadcastDispatcher,
-                commandQueue,
-                pipOptional,
-                splitScreenOptional,
-                recentsOptional,
-                statusBarOptionalLazy,
-                shadeController,
-                notificationRemoteInputManager,
-                notificationShadeDepthController,
-                systemActions,
-                mainHandler,
-                uiEventLogger,
-                navBarOverlayController,
-                configurationController,
-                navigationBarA11yHelper,
-                taskbarDelegate,
-                userTracker);
-    }
-
-    /** */
-    @Provides
-    @SysUISingleton
     public AccessibilityFloatingMenuController provideAccessibilityFloatingMenuController(
             Context context, AccessibilityButtonTargetsObserver accessibilityButtonTargetsObserver,
             AccessibilityButtonModeObserver accessibilityButtonModeObserver,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java b/packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java
index 406981d..67ad3db 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java
@@ -24,6 +24,7 @@
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.GlobalActions;
+import com.android.systemui.plugins.PluginDependencyProvider;
 import com.android.systemui.plugins.VolumeDialogController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.StatusBarStateControllerImpl;
@@ -32,6 +33,7 @@
 
 import dagger.Binds;
 import dagger.Module;
+import dagger.Provides;
 
 /**
  * Module for binding Plugin implementations.
@@ -39,36 +41,40 @@
  * TODO(b/166258224): Many of these should be moved closer to their implementations.
  */
 @Module
-public interface PluginModule {
+public abstract class PluginModule {
+
+    /** */
+    @Provides
+    static ActivityStarter provideActivityStarter(ActivityStarterDelegate delegate,
+            PluginDependencyProvider dependencyProvider) {
+        dependencyProvider.allowPluginDependency(ActivityStarter.class, delegate);
+        return delegate;
+    }
 
     /** */
     @Binds
-    ActivityStarter provideActivityStarter(ActivityStarterDelegate delegate);
+    abstract DarkIconDispatcher provideDarkIconDispatcher(DarkIconDispatcherImpl controllerImpl);
 
     /** */
     @Binds
-    DarkIconDispatcher provideDarkIconDispatcher(DarkIconDispatcherImpl controllerImpl);
+    abstract FalsingManager provideFalsingManager(FalsingManagerProxy falsingManagerImpl);
 
     /** */
     @Binds
-    FalsingManager provideFalsingManager(FalsingManagerProxy falsingManagerImpl);
+    abstract GlobalActions provideGlobalActions(GlobalActionsImpl controllerImpl);
 
     /** */
     @Binds
-    GlobalActions provideGlobalActions(GlobalActionsImpl controllerImpl);
-
-    /** */
-    @Binds
-    GlobalActions.GlobalActionsManager provideGlobalActionsManager(
+    abstract GlobalActions.GlobalActionsManager provideGlobalActionsManager(
             GlobalActionsComponent controllerImpl);
 
     /** */
     @Binds
-    StatusBarStateController provideStatusBarStateController(
+    abstract StatusBarStateController provideStatusBarStateController(
             StatusBarStateControllerImpl controllerImpl);
 
     /** */
     @Binds
-    VolumeDialogController provideVolumeDialogController(VolumeDialogControllerImpl controllerImpl);
-
+    abstract VolumeDialogController provideVolumeDialogController(
+            VolumeDialogControllerImpl controllerImpl);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index f593ed2..8defe3c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -145,8 +145,10 @@
 
     @SysUISingleton
     @Provides
-    static SysUiState provideSysUiState() {
-        return new SysUiState();
+    static SysUiState provideSysUiState(DumpManager dumpManager) {
+        final SysUiState state = new SysUiState();
+        dumpManager.registerDumpable(state);
+        return state;
     }
 
     @BindsOptionalOf
diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
index 5b327bd..b0f3959 100644
--- a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
@@ -56,6 +56,15 @@
     }
 
     /**
+     * Same as the above override, but automatically uses the simple class name as the dumpable
+     * name.
+     */
+    @Synchronized
+    fun registerDumpable(module: Dumpable) {
+        registerDumpable(module::class.java.simpleName, module)
+    }
+
+    /**
      * Unregisters a previously-registered dumpable.
      */
     @Synchronized
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
index 1a6d6ae..3ff0883 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
@@ -191,6 +191,13 @@
         return FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
     }
 
+    /**
+     * Use the new version of the user switcher
+     */
+    public boolean useNewUserSwitcher() {
+        return mFlagReader.isEnabled(R.bool.flag_new_user_switcher);
+    }
+
     /** static method for the system setting */
     public static boolean isProviderModelSettingEnabled(Context context) {
         return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index 37b8a2c..4f5a969 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -22,6 +22,7 @@
 
 import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.qs.QSFragment;
 import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -60,11 +61,15 @@
             };
 
     @Inject
-    public FragmentService(FragmentCreator.Factory fragmentCreatorFactory,
-            ConfigurationController configurationController) {
+    public FragmentService(
+            FragmentCreator.Factory fragmentCreatorFactory,
+            ConfigurationController configurationController,
+            DumpManager dumpManager) {
         mFragmentCreator = fragmentCreatorFactory.build();
         initInjectionMap();
         configurationController.addCallback(mConfigurationListener);
+
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
     }
 
     ArrayMap<String, Method> getInjectionMap() {
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
index d30783c..a51ec54 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -102,7 +102,6 @@
 
     @Override
     public Size reportSurfaceSize() {
-        mTexture.use(null /* consumer */);
         mSurfaceSize.set(mTexture.getTextureDimensions());
         return new Size(mSurfaceSize.width(), mSurfaceSize.height());
     }
@@ -124,6 +123,7 @@
         private final WallpaperManager mWallpaperManager;
         private Bitmap mBitmap;
         private boolean mWcgContent;
+        private boolean mTextureUsed;
 
         private WallpaperTexture(WallpaperManager wallpaperManager) {
             mWallpaperManager = wallpaperManager;
@@ -141,6 +141,7 @@
                     mWallpaperManager.forgetLoadedWallpaper();
                     if (mBitmap != null) {
                         mDimensions.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
+                        mTextureUsed = true;
                     } else {
                         Log.w(TAG, "Can't get bitmap");
                     }
@@ -171,6 +172,9 @@
         }
 
         private Rect getTextureDimensions() {
+            if (!mTextureUsed) {
+                mDimensions.set(mWallpaperManager.peekBitmapDimensions());
+            }
             return mDimensions;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 3577395..a5dd6a1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -67,6 +67,7 @@
 import android.view.WindowManagerPolicyConstants;
 import android.window.IRemoteTransition;
 import android.window.IRemoteTransitionFinishedCallback;
+import android.window.RemoteTransition;
 import android.window.TransitionFilter;
 import android.window.TransitionInfo;
 
@@ -236,7 +237,8 @@
                 Slog.d(TAG, "KeyguardService registerRemote: TRANSIT_KEYGUARD_GOING_AWAY");
                 TransitionFilter f = new TransitionFilter();
                 f.mFlags = TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
-                shellTransitions.registerRemote(f, wrap(mExitAnimationRunner));
+                shellTransitions.registerRemote(f,
+                        new RemoteTransition(wrap(mExitAnimationRunner)));
             }
             if (sEnableRemoteKeyguardOccludeAnimation) {
                 Slog.d(TAG, "KeyguardService registerRemote: TRANSIT_KEYGUARD_(UN)OCCLUDE");
@@ -255,7 +257,7 @@
                 f.mRequirements[1].mMustBeIndependent = false;
                 f.mRequirements[1].mFlags = FLAG_OCCLUDES_KEYGUARD;
                 f.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
-                shellTransitions.registerRemote(f, mOccludeAnimation);
+                shellTransitions.registerRemote(f, new RemoteTransition(mOccludeAnimation));
 
                 // Now register for un-occlude.
                 f = new TransitionFilter();
@@ -275,7 +277,7 @@
                 f.mRequirements[0].mMustBeIndependent = false;
                 f.mRequirements[0].mFlags = FLAG_OCCLUDES_KEYGUARD;
                 f.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
-                shellTransitions.registerRemote(f, mUnoccludeAnimation);
+                shellTransitions.registerRemote(f, new RemoteTransition(mUnoccludeAnimation));
             }
         } else {
             RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java
index 084e84a..30983aa 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java
@@ -20,6 +20,7 @@
 
 import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -40,7 +41,8 @@
     private int mScreenState = SCREEN_OFF;
 
     @Inject
-    public ScreenLifecycle() {
+    public ScreenLifecycle(DumpManager dumpManager) {
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
     }
 
     public int getScreenState() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
index 6f878d1..2e1c9fa 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
@@ -32,6 +32,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -83,10 +84,13 @@
     @Inject
     public WakefulnessLifecycle(
             Context context,
-            @Nullable IWallpaperManager wallpaperManagerService) {
+            @Nullable IWallpaperManager wallpaperManagerService,
+            DumpManager dumpManager) {
         mContext = context;
         mDisplayMetrics = context.getResources().getDisplayMetrics();
         mWallpaperManagerService = wallpaperManagerService;
+
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
     }
 
     public @Wakefulness int getWakefulness() {
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index 2facf3d..db5dbb0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -212,14 +212,32 @@
                 isSsReactivated: Boolean
             ) {
                 if (addOrUpdatePlayer(key, oldKey, data)) {
+                    // Log card received if a new resumable media card is added
                     MediaPlayerData.getMediaPlayer(key)?.let {
                         logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
                                 it.mInstanceId,
+                                it.mUid,
                                 /* isRecommendationCard */ false,
                                 it.surfaceForSmartspaceLogging,
                                 rank = MediaPlayerData.getMediaPlayerIndex(key))
                     }
                 }
+                if (isSsReactivated) {
+                    // If resumable media is reactivated by headphone connection, update instance
+                    // id for each card and log a receive event.
+                    MediaPlayerData.players().forEachIndexed { index, it ->
+                        if (it.recommendationViewHolder == null) {
+                            it.mInstanceId = SmallHash.hash(it.mUid +
+                                    systemClock.currentTimeMillis().toInt())
+                            logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
+                                    it.mInstanceId,
+                                    it.mUid,
+                                    /* isRecommendationCard */ false,
+                                    it.surfaceForSmartspaceLogging,
+                                    rank = index)
+                        }
+                    }
+                }
                 if (mediaCarouselScrollHandler.visibleToUser &&
                         isSsReactivated && !mediaCarouselScrollHandler.qsExpanded) {
                     // It could happen that reactived media player isn't visible to user because
@@ -252,6 +270,7 @@
                     MediaPlayerData.getMediaPlayer(key)?.let {
                         logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
                                 it.mInstanceId,
+                                it.mUid,
                                 /* isRecommendationCard */ true,
                                 it.surfaceForSmartspaceLogging,
                                 rank = MediaPlayerData.getMediaPlayerIndex(key))
@@ -261,6 +280,7 @@
                                 MediaPlayerData.getMediaPlayerIndex(key)) {
                             logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN
                                     it.mInstanceId,
+                                    it.mUid,
                                     /* isRecommendationCard */ true,
                                     it.surfaceForSmartspaceLogging)
                         }
@@ -339,9 +359,9 @@
             if (activeMediaIndex != -1) {
                 previousVisiblePlayerKey?.let {
                     val previousVisibleIndex = MediaPlayerData.playerKeys()
-                        .indexOfFirst { key -> it == key }
+                            .indexOfFirst { key -> it == key }
                     mediaCarouselScrollHandler
-                        .scrollToPlayer(previousVisibleIndex, activeMediaIndex)
+                            .scrollToPlayer(previousVisibleIndex, activeMediaIndex)
                 } ?: {
                     mediaCarouselScrollHandler.scrollToPlayer(destIndex = activeMediaIndex)
                 }
@@ -355,11 +375,11 @@
         MediaPlayerData.moveIfExists(oldKey, key)
         val existingPlayer = MediaPlayerData.getMediaPlayer(key)
         val curVisibleMediaKey = MediaPlayerData.playerKeys()
-            .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
+                .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
         if (existingPlayer == null) {
             var newPlayer = mediaControlPanelFactory.get()
             newPlayer.attachPlayer(
-                PlayerViewHolder.create(LayoutInflater.from(context), mediaContent))
+                    PlayerViewHolder.create(LayoutInflater.from(context), mediaContent))
             newPlayer.mediaViewController.sizeChangedListener = this::updateCarouselDimensions
             val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                     ViewGroup.LayoutParams.WRAP_CONTENT)
@@ -407,14 +427,14 @@
 
         var newRecs = mediaControlPanelFactory.get()
         newRecs.attachRecommendation(
-            RecommendationViewHolder.create(LayoutInflater.from(context), mediaContent))
+                RecommendationViewHolder.create(LayoutInflater.from(context), mediaContent))
         newRecs.mediaViewController.sizeChangedListener = this::updateCarouselDimensions
         val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
-            ViewGroup.LayoutParams.WRAP_CONTENT)
+                ViewGroup.LayoutParams.WRAP_CONTENT)
         newRecs.recommendationViewHolder?.recommendations?.setLayoutParams(lp)
         newRecs.bindRecommendation(data.copy(backgroundColor = bgColor))
         val curVisibleMediaKey = MediaPlayerData.playerKeys()
-            .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
+                .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
         MediaPlayerData.addMediaRecommendation(key, data, newRecs, shouldPrioritize, systemClock)
         updatePlayerToState(newRecs, noAnimation = true)
         reorderAllPlayers(curVisibleMediaKey)
@@ -462,7 +482,7 @@
                 removePlayer(key, dismissMediaData = false, dismissRecommendation = false)
                 smartspaceMediaData?.let {
                     addSmartspaceMediaRecommendations(
-                        it.targetId, it, MediaPlayerData.shouldPrioritizeSs)
+                            it.targetId, it, MediaPlayerData.shouldPrioritizeSs)
                 }
             } else {
                 removePlayer(key, dismissMediaData = false, dismissRecommendation = false)
@@ -585,7 +605,7 @@
                 ?: endShowsActive
         if (currentlyShowingOnlyActive != endShowsActive ||
                 ((currentTransitionProgress != 1.0f && currentTransitionProgress != 0.0f) &&
-                            startShowsActive != endShowsActive)) {
+                        startShowsActive != endShowsActive)) {
             // Whenever we're transitioning from between differing states or the endstate differs
             // we reset the translation
             currentlyShowingOnlyActive = endShowsActive
@@ -696,23 +716,43 @@
             }
             logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN
                     mediaControlPanel.mInstanceId,
+                    mediaControlPanel.mUid,
                     isRecommendationCard,
                     mediaControlPanel.surfaceForSmartspaceLogging)
         }
     }
 
     @JvmOverloads
+    /**
+     * Log Smartspace events
+     *
+     * @param eventId UI event id (e.g. 800 for SMARTSPACE_CARD_SEEN)
+     * @param instanceId id to uniquely identify a card, e.g. each headphone generates a new
+     * instanceId
+     * @param uid uid for the application that media comes from
+     * @param isRecommendationCard whether the card is media recommendation
+     * @param surface which display surface the media card is on (e.g. lockscreen, shade)
+     * @param interactedSubcardRank the rank for interacted media item for recommendation card, -1
+     * for tapping on card but not on any media item, 0 for first media item, 1 for second, etc.
+     * @param interactedSubcardCardinality how many media items were shown to the user when there
+     * is user interaction
+     * @param rank the rank for media card in the media carousel, starting from 0
+     *
+     */
     fun logSmartspaceCardReported(
         eventId: Int,
         instanceId: Int,
+        uid: Int,
         isRecommendationCard: Boolean,
         surface: Int,
+        interactedSubcardRank: Int = 0,
+        interactedSubcardCardinality: Int = 0,
         rank: Int = mediaCarouselScrollHandler.visibleMediaIndex
     ) {
         // Only log media resume card when Smartspace data is available
         if (!isRecommendationCard &&
-                        !mediaManager.smartspaceMediaData.isActive &&
-                                MediaPlayerData.smartspaceMediaData == null) {
+                !mediaManager.smartspaceMediaData.isActive &&
+                MediaPlayerData.smartspaceMediaData == null) {
             return
         }
 
@@ -720,13 +760,20 @@
         SysUiStatsLog.write(SysUiStatsLog.SMARTSPACE_CARD_REPORTED,
                 eventId,
                 instanceId,
-                if (isRecommendationCard)
-                    SysUiStatsLog.SMART_SPACE_CARD_REPORTED__CARD_TYPE__HEADPHONE_MEDIA_RECOMMENDATIONS
-                else
-                    SysUiStatsLog.SMART_SPACE_CARD_REPORTED__CARD_TYPE__HEADPHONE_RESUME_MEDIA,
+                // Deprecated, replaced with AiAi feature type so we don't need to create logging
+                // card type for each new feature.
+                SysUiStatsLog.SMART_SPACE_CARD_REPORTED__CARD_TYPE__UNKNOWN_CARD,
                 surface,
                 rank,
-                mediaContent.getChildCount())
+                mediaContent.getChildCount(),
+                if (isRecommendationCard)
+                    15 // MEDIA_RECOMMENDATION
+                else
+                    31, // MEDIA_RESUME
+                uid,
+                interactedSubcardRank,
+                interactedSubcardCardinality
+        )
         /* ktlint-disable max-line-length */
     }
 
@@ -738,18 +785,20 @@
         if (!recommendation.isEmpty()) {
             logSmartspaceCardReported(761, // SMARTSPACE_CARD_DISMISS
                     recommendation.get(0).mInstanceId,
+                    recommendation.get(0).mUid,
                     true,
                     recommendation.get(0).surfaceForSmartspaceLogging,
-            /* rank */-1)
+                    rank = -1)
         } else {
             val visibleMediaIndex = mediaCarouselScrollHandler.visibleMediaIndex
             if (MediaPlayerData.players().size > visibleMediaIndex) {
                 val player = MediaPlayerData.players().elementAt(visibleMediaIndex)
                 logSmartspaceCardReported(761, // SMARTSPACE_CARD_DISMISS
                         player.mInstanceId,
-                false,
+                        player.mUid,
+                        false,
                         player.surfaceForSmartspaceLogging,
-                /* rank */-1)
+                        rank = -1)
             }
         }
         mediaManager.onSwipeToDismiss()
@@ -768,7 +817,7 @@
 @VisibleForTesting
 internal object MediaPlayerData {
     private val EMPTY = MediaData(-1, false, 0, null, null, null, null, null,
-        emptyList(), emptyList(), "INVALID", null, null, null, true, null)
+            emptyList(), emptyList(), "INVALID", null, null, null, true, null)
     // Whether should prioritize Smartspace card.
     internal var shouldPrioritizeSs: Boolean = false
         private set
@@ -776,18 +825,18 @@
         private set
 
     data class MediaSortKey(
-        // Whether the item represents a Smartspace media recommendation.
+            // Whether the item represents a Smartspace media recommendation.
         val isSsMediaRec: Boolean,
         val data: MediaData,
         val updateTime: Long = 0
     )
 
     private val comparator =
-        compareByDescending<MediaSortKey> { it.data.isPlaying }
-            .thenByDescending { if (shouldPrioritizeSs) it.isSsMediaRec else !it.isSsMediaRec }
-            .thenByDescending { it.data.isLocalSession }
-            .thenByDescending { !it.data.resumption }
-            .thenByDescending { it.updateTime }
+            compareByDescending<MediaSortKey> { it.data.isPlaying }
+                    .thenByDescending { if (shouldPrioritizeSs) it.isSsMediaRec else !it.isSsMediaRec }
+                    .thenByDescending { it.data.isLocalSession }
+                    .thenByDescending { !it.data.resumption }
+                    .thenByDescending { it.updateTime }
 
     private val mediaPlayers = TreeMap<MediaSortKey, MediaControlPanel>(comparator)
     private val mediaData: MutableMap<String, MediaSortKey> = mutableMapOf()
@@ -888,4 +937,4 @@
         }
         return false
     }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 15a7083..c125612 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -33,6 +33,7 @@
 import android.media.session.MediaController;
 import android.media.session.MediaSession;
 import android.media.session.PlaybackState;
+import android.os.Process;
 import android.text.Layout;
 import android.util.Log;
 import android.view.View;
@@ -111,6 +112,9 @@
     private int mAlbumArtSize;
     // Instance id for logging purpose.
     protected int mInstanceId = -1;
+    // Uid for the media app.
+    protected int mUid = Process.INVALID_UID;
+    private int mSmartspaceMediaItemsCount;
     private MediaCarouselController mMediaCarouselController;
     private final MediaOutputDialogFactory mMediaOutputDialogFactory;
 
@@ -266,7 +270,13 @@
         }
         mKey = key;
         MediaSession.Token token = data.getToken();
-        mInstanceId = SmallHash.hash(data.getPackageName());
+        PackageManager packageManager = mContext.getPackageManager();
+        try {
+            mUid = packageManager.getApplicationInfo(data.getPackageName(), 0 /* flags */).uid;
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(TAG, "Unable to look up package name", e);
+        }
+        mInstanceId = SmallHash.hash(mUid);
 
         mBackgroundColor = data.getBackgroundColor();
         if (mToken == null || !mToken.equals(token)) {
@@ -360,27 +370,16 @@
 
         final MediaDeviceData device = data.getDevice();
         final int seamlessId = mPlayerViewHolder.getSeamless().getId();
-        final int seamlessFallbackId = mPlayerViewHolder.getSeamlessFallback().getId();
-        final boolean showFallback = device != null && !device.getEnabled();
-        final int seamlessFallbackVisibility = showFallback ? View.VISIBLE : View.GONE;
-        mPlayerViewHolder.getSeamlessFallback().setVisibility(seamlessFallbackVisibility);
-        expandedSet.setVisibility(seamlessFallbackId, seamlessFallbackVisibility);
-        collapsedSet.setVisibility(seamlessFallbackId, seamlessFallbackVisibility);
-        final int seamlessVisibility = showFallback ? View.GONE : View.VISIBLE;
-        mPlayerViewHolder.getSeamless().setVisibility(seamlessVisibility);
-        expandedSet.setVisibility(seamlessId, seamlessVisibility);
-        collapsedSet.setVisibility(seamlessId, seamlessVisibility);
-        final float seamlessAlpha = data.getResumption() ? DISABLED_ALPHA : 1.0f;
+        // Disable clicking on output switcher for invalid devices and resumption controls
+        final boolean seamlessDisabled = (device != null && !device.getEnabled())
+                || data.getResumption();
+        final float seamlessAlpha = seamlessDisabled ? DISABLED_ALPHA : 1.0f;
         expandedSet.setAlpha(seamlessId, seamlessAlpha);
         collapsedSet.setAlpha(seamlessId, seamlessAlpha);
-        // Disable clicking on output switcher for resumption controls.
-        mPlayerViewHolder.getSeamless().setEnabled(!data.getResumption());
+        mPlayerViewHolder.getSeamless().setEnabled(!seamlessDisabled);
         String deviceString = null;
-        if (showFallback) {
-            iconView.setImageDrawable(null);
-        } else if (device != null) {
+        if (device != null && device.getEnabled()) {
             Drawable icon = device.getIcon();
-            iconView.setVisibility(View.VISIBLE);
             if (icon instanceof AdaptiveIcon) {
                 AdaptiveIcon aIcon = (AdaptiveIcon) icon;
                 aIcon.setBackgroundColor(mBackgroundColor);
@@ -391,10 +390,9 @@
             deviceString = device.getName();
         } else {
             // Reset to default
-            Log.w(TAG, "device is null. Not binding output chip.");
-            iconView.setVisibility(View.GONE);
-            deviceString = mContext.getString(
-                    com.android.internal.R.string.ext_media_seamless_action);
+            Log.w(TAG, "Device is null or not enabled: " + device + ", not binding output chip.");
+            iconView.setImageResource(R.drawable.ic_media_home_devices);
+            deviceString =  mContext.getString(R.string.media_seamless_other_device);
         }
         deviceName.setText(deviceString);
         seamlessView.setContentDescription(deviceString);
@@ -531,10 +529,11 @@
         }
 
         // Set up recommendation card's header.
-        ApplicationInfo applicationInfo = null;
+        ApplicationInfo applicationInfo;
         try {
             applicationInfo = mContext.getPackageManager()
                     .getApplicationInfo(data.getPackageName(), 0 /* flags */);
+            mUid = applicationInfo.uid;
         } catch (PackageManager.NameNotFoundException e) {
             Log.w(TAG, "Fail to get media recommendation's app info", e);
             return;
@@ -553,7 +552,8 @@
             headerTitleText.setText(appLabel);
         }
         // Set up media rec card's tap action if applicable.
-        setSmartspaceRecItemOnClickListener(recommendationCard, data.getCardAction());
+        setSmartspaceRecItemOnClickListener(recommendationCard, data.getCardAction(),
+                /* interactedSubcardRank */ -1);
         // Set up media rec card's accessibility label.
         recommendationCard.setContentDescription(
                 mContext.getString(R.string.controls_media_smartspace_rec_description, appLabel));
@@ -567,7 +567,8 @@
         ConstraintSet collapsedSet = mMediaViewController.getCollapsedLayout();
         int mediaRecommendationNum = Math.min(mediaRecommendationList.size(),
                 MEDIA_RECOMMENDATION_MAX_NUM);
-        for (int itemIndex = 0, uiComponentIndex = 0;
+        int uiComponentIndex = 0;
+        for (int itemIndex = 0;
                 itemIndex < mediaRecommendationNum && uiComponentIndex < mediaRecommendationNum;
                 itemIndex++) {
             SmartspaceAction recommendation = mediaRecommendationList.get(itemIndex);
@@ -582,7 +583,8 @@
 
             // Set up the media item's click listener if applicable.
             ViewGroup mediaCoverContainer = mediaCoverContainers.get(uiComponentIndex);
-            setSmartspaceRecItemOnClickListener(mediaCoverContainer, recommendation);
+            setSmartspaceRecItemOnClickListener(mediaCoverContainer, recommendation,
+                    uiComponentIndex);
 
             // Set up the accessibility label for the media item.
             String artistName = recommendation.getExtras()
@@ -614,10 +616,10 @@
                     mediaCoverItemsResIds.get(uiComponentIndex), true);
             setVisibleAndAlpha(expandedSet,
                     mediaCoverContainersResIds.get(uiComponentIndex), true);
-
             uiComponentIndex++;
         }
 
+        mSmartspaceMediaItemsCount = uiComponentIndex;
         // Set up long press to show guts setting panel.
         mRecommendationViewHolder.getDismiss().setOnClickListener(v -> {
             logSmartspaceCardReported(761, // SMARTSPACE_CARD_DISMISS
@@ -750,7 +752,8 @@
 
     private void setSmartspaceRecItemOnClickListener(
             @NonNull View view,
-            @NonNull SmartspaceAction action) {
+            @NonNull SmartspaceAction action,
+            int interactedSubcardRank) {
         if (view == null || action == null || action.getIntent() == null
                 || action.getIntent().getExtras() == null) {
             Log.e(TAG, "No tap action can be set up");
@@ -758,9 +761,10 @@
         }
 
         view.setOnClickListener(v -> {
-            // When media recommendation card is shown, it will always be the top card.
             logSmartspaceCardReported(760, // SMARTSPACE_CARD_CLICK
-                    /* isRecommendationCard */ true);
+                    /* isRecommendationCard */ true,
+                    interactedSubcardRank,
+                    getSmartspaceSubCardCardinality());
 
             if (shouldSmartspaceRecItemOpenInForeground(action)) {
                 // Request to unlock the device if the activity needs to be opened in foreground.
@@ -818,9 +822,28 @@
     }
 
     private void logSmartspaceCardReported(int eventId, boolean isRecommendationCard) {
+        logSmartspaceCardReported(eventId, isRecommendationCard,
+                /* interactedSubcardRank */ 0,
+                /* interactedSubcardCardinality */ 0);
+    }
+
+    private void logSmartspaceCardReported(int eventId, boolean isRecommendationCard,
+            int interactedSubcardRank, int interactedSubcardCardinality) {
         mMediaCarouselController.logSmartspaceCardReported(eventId,
                 mInstanceId,
+                mUid,
                 isRecommendationCard,
-                getSurfaceForSmartspaceLogging());
+                getSurfaceForSmartspaceLogging(),
+                interactedSubcardRank,
+                interactedSubcardCardinality);
     }
-}
+
+    private int getSmartspaceSubCardCardinality() {
+        if (!mMediaCarouselController.getMediaCarouselScrollHandler().getQsExpanded()
+                && mSmartspaceMediaItemsCount > 3) {
+            return 3;
+        }
+
+        return mSmartspaceMediaItemsCount;
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 0a28b47..ba99f5d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -212,8 +212,8 @@
         mediaDataCombineLatest.addListener(mediaDataFilter)
 
         // Set up links back into the pipeline for listeners that need to send events upstream.
-        mediaTimeoutListener.timeoutCallback = { token: String, timedOut: Boolean ->
-            setTimedOut(token, timedOut) }
+        mediaTimeoutListener.timeoutCallback = { key: String, timedOut: Boolean ->
+            setTimedOut(key, timedOut) }
         mediaResumeListener.setManager(this)
         mediaDataFilter.mediaDataManager = this
 
@@ -414,14 +414,18 @@
      * This will make the player not active anymore, hiding it from QQS and Keyguard.
      * @see MediaData.active
      */
-    internal fun setTimedOut(token: String, timedOut: Boolean, forceUpdate: Boolean = false) {
-        mediaEntries[token]?.let {
+    internal fun setTimedOut(key: String, timedOut: Boolean, forceUpdate: Boolean = false) {
+        mediaEntries[key]?.let {
             if (it.active == !timedOut && !forceUpdate) {
+                if (it.resumption) {
+                    if (DEBUG) Log.d(TAG, "timing out resume player $key")
+                    dismissMediaData(key, 0L /* delay */)
+                }
                 return
             }
             it.active = !timedOut
-            if (DEBUG) Log.d(TAG, "Updating $token timedOut: $timedOut")
-            onMediaDataLoaded(token, token, it)
+            if (DEBUG) Log.d(TAG, "Updating $key timedOut: $timedOut")
+            onMediaDataLoaded(key, key, it)
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
index ab568c8..608c784 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
@@ -35,6 +35,7 @@
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.tuner.TunerService
 import com.android.systemui.util.Utils
+import com.android.systemui.util.time.SystemClock
 import java.io.FileDescriptor
 import java.io.PrintWriter
 import java.util.concurrent.ConcurrentLinkedQueue
@@ -53,11 +54,13 @@
     @Background private val backgroundExecutor: Executor,
     private val tunerService: TunerService,
     private val mediaBrowserFactory: ResumeMediaBrowserFactory,
-    dumpManager: DumpManager
+    dumpManager: DumpManager,
+    private val systemClock: SystemClock
 ) : MediaDataManager.Listener, Dumpable {
 
     private var useMediaResumption: Boolean = Utils.useMediaResumption(context)
-    private val resumeComponents: ConcurrentLinkedQueue<ComponentName> = ConcurrentLinkedQueue()
+    private val resumeComponents: ConcurrentLinkedQueue<Pair<ComponentName, Long>> =
+            ConcurrentLinkedQueue()
 
     private lateinit var mediaDataManager: MediaDataManager
 
@@ -131,14 +134,32 @@
         val listString = prefs.getString(MEDIA_PREFERENCE_KEY + currentUserId, null)
         val components = listString?.split(ResumeMediaBrowser.DELIMITER.toRegex())
             ?.dropLastWhile { it.isEmpty() }
+        var needsUpdate = false
         components?.forEach {
             val info = it.split("/")
             val packageName = info[0]
             val className = info[1]
             val component = ComponentName(packageName, className)
-            resumeComponents.add(component)
+
+            val lastPlayed = if (info.size == 3) {
+                try {
+                    info[2].toLong()
+                } catch (e: NumberFormatException) {
+                    needsUpdate = true
+                    systemClock.currentTimeMillis()
+                }
+            } else {
+                needsUpdate = true
+                systemClock.currentTimeMillis()
+            }
+            resumeComponents.add(component to lastPlayed)
         }
         Log.d(TAG, "loaded resume components ${resumeComponents.toArray().contentToString()}")
+
+        if (needsUpdate) {
+            // Save any missing times that we had to fill in
+            writeSharedPrefs()
+        }
     }
 
     /**
@@ -149,9 +170,12 @@
             return
         }
 
+        val now = systemClock.currentTimeMillis()
         resumeComponents.forEach {
-            val browser = mediaBrowserFactory.create(mediaBrowserCallback, it)
-            browser.findRecentMedia()
+            if (now.minus(it.second) <= RESUME_MEDIA_TIMEOUT) {
+                val browser = mediaBrowserFactory.create(mediaBrowserCallback, it.first)
+                browser.findRecentMedia()
+            }
         }
     }
 
@@ -234,18 +258,24 @@
      */
     private fun updateResumptionList(componentName: ComponentName) {
         // Remove if exists
-        resumeComponents.remove(componentName)
+        resumeComponents.remove(resumeComponents.find { it.first.equals(componentName) })
         // Insert at front of queue
-        resumeComponents.add(componentName)
+        val currentTime = systemClock.currentTimeMillis()
+        resumeComponents.add(componentName to currentTime)
         // Remove old components if over the limit
         if (resumeComponents.size > ResumeMediaBrowser.MAX_RESUMPTION_CONTROLS) {
             resumeComponents.remove()
         }
 
-        // Save changes
+        writeSharedPrefs()
+    }
+
+    private fun writeSharedPrefs() {
         val sb = StringBuilder()
         resumeComponents.forEach {
-            sb.append(it.flattenToString())
+            sb.append(it.first.flattenToString())
+            sb.append("/")
+            sb.append(it.second)
             sb.append(ResumeMediaBrowser.DELIMITER)
         }
         val prefs = context.getSharedPreferences(MEDIA_PREFERENCES, Context.MODE_PRIVATE)
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt
index 9a39193..6f04771 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt
@@ -20,6 +20,7 @@
 import android.media.session.PlaybackState
 import android.os.SystemProperties
 import android.util.Log
+import com.android.internal.annotations.VisibleForTesting
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState
@@ -29,9 +30,15 @@
 
 private const val DEBUG = true
 private const val TAG = "MediaTimeout"
-private val PAUSED_MEDIA_TIMEOUT = SystemProperties
+
+@VisibleForTesting
+val PAUSED_MEDIA_TIMEOUT = SystemProperties
         .getLong("debug.sysui.media_timeout", TimeUnit.MINUTES.toMillis(10))
 
+@VisibleForTesting
+val RESUME_MEDIA_TIMEOUT = SystemProperties
+        .getLong("debug.sysui.media_timeout_resume", TimeUnit.DAYS.toMillis(3))
+
 /**
  * Controller responsible for keeping track of playback states and expiring inactive streams.
  */
@@ -45,8 +52,9 @@
 
     /**
      * Callback representing that a media object is now expired:
-     * @param token Media session unique identifier
-     * @param pauseTimeout True when expired for {@code PAUSED_MEDIA_TIMEOUT}
+     * @param key Media control unique identifier
+     * @param timedOut True when expired for {@code PAUSED_MEDIA_TIMEOUT} for active media,
+     *                 or {@code RESUME_MEDIA_TIMEOUT} for resume media
      */
     lateinit var timeoutCallback: (String, Boolean) -> Unit
 
@@ -122,6 +130,7 @@
 
         var timedOut = false
         var playing: Boolean? = null
+        var resumption: Boolean? = null
         var destroyed = false
 
         var mediaData: MediaData = data
@@ -159,12 +168,19 @@
         }
 
         override fun onSessionDestroyed() {
-            // If the session is destroyed, the controller is no longer valid, and we will need to
-            // recreate it if this key is updated later
             if (DEBUG) {
                 Log.d(TAG, "Session destroyed for $key")
             }
-            destroy()
+
+            if (resumption == true) {
+                // Some apps create a session when MBS is queried. We should unregister the
+                // controller since it will no longer be valid, but don't cancel the timeout
+                mediaController?.unregisterCallback(this)
+            } else {
+                // For active controls, if the session is destroyed, clean up everything since we
+                // will need to recreate it if this key is updated later
+                destroy()
+            }
         }
 
         private fun processState(state: PlaybackState?, dispatchEvents: Boolean) {
@@ -173,20 +189,28 @@
             }
 
             val isPlaying = state != null && isPlayingState(state.state)
-            if (playing == isPlaying && playing != null) {
+            val resumptionChanged = resumption != mediaData.resumption
+            if (playing == isPlaying && playing != null && !resumptionChanged) {
                 return
             }
             playing = isPlaying
+            resumption = mediaData.resumption
 
             if (!isPlaying) {
                 if (DEBUG) {
-                    Log.v(TAG, "schedule timeout for $key")
+                    Log.v(TAG, "schedule timeout for $key playing $isPlaying, $resumption")
                 }
-                if (cancellation != null) {
+                if (cancellation != null && !resumptionChanged) {
+                    // if the media changed resume state, we'll need to adjust the timeout length
                     if (DEBUG) Log.d(TAG, "cancellation already exists, continuing.")
                     return
                 }
-                expireMediaTimeout(key, "PLAYBACK STATE CHANGED - $state")
+                expireMediaTimeout(key, "PLAYBACK STATE CHANGED - $state, $resumption")
+                val timeout = if (mediaData.resumption) {
+                    RESUME_MEDIA_TIMEOUT
+                } else {
+                    PAUSED_MEDIA_TIMEOUT
+                }
                 cancellation = mainExecutor.executeDelayed({
                     cancellation = null
                     if (DEBUG) {
@@ -195,7 +219,7 @@
                     timedOut = true
                     // this event is async, so it's safe even when `dispatchEvents` is false
                     timeoutCallback(key, timedOut)
-                }, PAUSED_MEDIA_TIMEOUT)
+                }, timeout)
             } else {
                 expireMediaTimeout(key, "playback started - $state, $key")
                 timedOut = false
diff --git a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
index 791f59d..35603b6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
@@ -43,7 +43,6 @@
     val seamless = itemView.requireViewById<ViewGroup>(R.id.media_seamless)
     val seamlessIcon = itemView.requireViewById<ImageView>(R.id.media_seamless_image)
     val seamlessText = itemView.requireViewById<TextView>(R.id.media_seamless_text)
-    val seamlessFallback = itemView.requireViewById<ImageView>(R.id.media_seamless_fallback)
 
     // Seek bar
     val seekBar = itemView.requireViewById<SeekBar>(R.id.media_progress_bar)
@@ -124,7 +123,6 @@
                 R.id.header_title,
                 R.id.header_artist,
                 R.id.media_seamless,
-                R.id.media_seamless_fallback,
                 R.id.notification_media_progress_time,
                 R.id.media_progress_bar,
                 R.id.action0,
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 4a67e94..43315f6 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -125,6 +125,7 @@
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
 import com.android.systemui.navigationbar.buttons.KeyButtonView;
@@ -422,6 +423,12 @@
             new Handler(Looper.getMainLooper())) {
         @Override
         public void onChange(boolean selfChange, Uri uri) {
+            // TODO(b/198002034): Content observers currently can still be called back after being
+            // unregistered, and in this case we can ignore the change if the nav bar has been
+            // destroyed already
+            if (mNavigationBarView == null) {
+                return;
+            }
             updateAssistantEntrypoints();
         }
     };
@@ -648,7 +655,7 @@
         if (mIsOnDefaultDisplay) {
             final RotationButtonController rotationButtonController =
                     mNavigationBarView.getRotationButtonController();
-            rotationButtonController.addRotationCallback(mRotationWatcher);
+            rotationButtonController.setRotationCallback(mRotationWatcher);
 
             // Reset user rotation pref to match that of the WindowManager if starting in locked
             // mode. This will automatically happen when switching from auto-rotate to locked mode.
@@ -670,7 +677,8 @@
                 : new LightBarController(mContext,
                         Dependency.get(DarkIconDispatcher.class),
                         Dependency.get(BatteryController.class),
-                        Dependency.get(NavigationModeController.class));
+                        Dependency.get(NavigationModeController.class),
+                        Dependency.get(DumpManager.class));
         setLightBarController(lightBarController);
 
         // TODO(b/118592525): to support multi-display, we start to add something which is
@@ -687,6 +695,9 @@
 
     @Override
     public void onViewDetachedFromWindow(View v) {
+        final RotationButtonController rotationButtonController =
+                mNavigationBarView.getRotationButtonController();
+        rotationButtonController.setRotationCallback(null);
         mNavigationBarView.getBarTransitions().destroy();
         mNavigationBarView.getLightTransitionsController().destroy(mContext);
         mOverviewProxyService.removeCallback(mOverviewProxyListener);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 2e7ab6e..b8df49e 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -17,7 +17,6 @@
 package com.android.systemui.navigationbar;
 
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
 
 import static com.android.systemui.shared.recents.utilities.Utilities.isTablet;
 
@@ -52,6 +51,7 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.OverviewProxyService;
@@ -81,9 +81,11 @@
 
 /** A controller to handle navigation bars. */
 @SysUISingleton
-public class NavigationBarController implements Callbacks,
+public class NavigationBarController implements
+        Callbacks,
         ConfigurationController.ConfigurationListener,
-        NavigationModeController.ModeChangedListener, Dumpable {
+        NavigationModeController.ModeChangedListener,
+        Dumpable {
 
     private static final String TAG = NavigationBarController.class.getSimpleName();
 
@@ -157,7 +159,8 @@
             ConfigurationController configurationController,
             NavigationBarA11yHelper navigationBarA11yHelper,
             TaskbarDelegate taskbarDelegate,
-            UserTracker userTracker) {
+            UserTracker userTracker,
+            DumpManager dumpManager) {
         mContext = context;
         mWindowManager = windowManager;
         mAssistManagerLazy = assistManagerLazy;
@@ -195,6 +198,8 @@
                 navigationBarA11yHelper, navigationModeController, sysUiFlagsContainer);
         mIsTablet = isTablet(mContext);
         mUserTracker = userTracker;
+
+        dumpManager.registerDumpable(this);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 0f888cb..2de4026 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -279,7 +279,7 @@
             new RotationButtonUpdatesCallback() {
                 @Override
                 public void onVisibilityChanged(boolean visible) {
-                    if (visible) {
+                    if (visible && mAutoHideController != null) {
                         // If the button will actually become visible and the navbar is about
                         // to hide, tell the statusbar to keep it around for longer
                         mAutoHideController.touchAutoHide();
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java
index 422ffd5..0603bb7 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java
@@ -36,6 +36,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.UiBackground;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -99,12 +100,15 @@
     public NavigationModeController(Context context,
             DeviceProvisionedController deviceProvisionedController,
             ConfigurationController configurationController,
-            @UiBackground Executor uiBgExecutor) {
+            @UiBackground Executor uiBgExecutor,
+            DumpManager dumpManager) {
         mContext = context;
         mCurrentUserContext = context;
         mOverlayManager = IOverlayManager.Stub.asInterface(
                 ServiceManager.getService(Context.OVERLAY_SERVICE));
         mUiBgExecutor = uiBgExecutor;
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
+
         deviceProvisionedController.addCallback(mDeviceProvisionedCallback);
 
         IntentFilter overlayFilter = new IntentFilter(ACTION_OVERLAY_CHANGED);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java
index 196625b..0f5c03a 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/RotationButtonController.java
@@ -183,7 +183,7 @@
         TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
     }
 
-    void addRotationCallback(Consumer<Integer> watcher) {
+    void setRotationCallback(Consumer<Integer> watcher) {
         mRotWatcherListener = watcher;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index e0caf12..3167070 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -18,20 +18,27 @@
 
 import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
 import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
+import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
+import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
 
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISABLED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
 
+import android.app.StatusBarManager;
+import android.app.StatusBarManager.WindowVisibleState;
 import android.content.Context;
 import android.inputmethodservice.InputMethodService;
 import android.os.IBinder;
 import android.view.InsetsVisibilities;
 import android.view.View;
+import android.view.WindowInsetsController.Behavior;
 
 import com.android.internal.view.AppearanceRegion;
 import com.android.systemui.Dependency;
@@ -60,6 +67,8 @@
     private final NavigationBarA11yHelper.NavA11yEventListener mNavA11yEventListener =
             this::updateSysuiFlags;
     private int mDisabledFlags;
+    private @WindowVisibleState int mTaskBarWindowState = WINDOW_STATE_SHOWING;
+    private @Behavior int mBehavior;
 
     @Inject
     public TaskbarDelegate(Context context) {
@@ -114,6 +123,9 @@
                         (mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0)
                 .setFlag(SYSUI_STATE_BACK_DISABLED,
                         (mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0)
+                .setFlag(SYSUI_STATE_NAV_BAR_HIDDEN, !isWindowVisible())
+                .setFlag(SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY,
+                        allowSystemGestureIgnoringBarVisibility())
                 .commitUpdate(mDisplayId);
     }
 
@@ -130,6 +142,16 @@
     }
 
     @Override
+    public void setWindowState(int displayId, int window, int state) {
+        if (displayId == mDisplayId
+                && window == StatusBarManager.WINDOW_NAVIGATION_BAR
+                && mTaskBarWindowState != state) {
+            mTaskBarWindowState = state;
+            updateSysuiFlags();
+        }
+    }
+
+    @Override
     public void onRotationProposal(int rotation, boolean isValid) {
         mOverviewProxyService.onRotationProposal(rotation, isValid);
     }
@@ -146,6 +168,10 @@
             AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, int behavior,
             InsetsVisibilities requestedVisibilities, String packageName) {
         mOverviewProxyService.onSystemBarAttributesChanged(displayId, behavior);
+        if (mBehavior != behavior) {
+            mBehavior = behavior;
+            updateSysuiFlags();
+        }
     }
 
     @Override
@@ -161,4 +187,12 @@
     public void onNavigationModeChanged(int mode) {
         mEdgeBackGestureHandler.onNavigationModeChanged(mode);
     }
+
+    private boolean isWindowVisible() {
+        return mTaskBarWindowState == WINDOW_STATE_SHOWING;
+    }
+
+    private boolean allowSystemGestureIgnoringBarVisibility() {
+        return mBehavior != BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index aaa3bf0..bf1a98f 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -384,7 +384,7 @@
     private void onNavigationSettingsChanged() {
         boolean wasBackAllowed = isHandlingGestures();
         updateCurrentUserResources();
-        if (wasBackAllowed != isHandlingGestures()) {
+        if (mStateChangeCallback != null && wasBackAllowed != isHandlingGestures()) {
             mStateChangeCallback.run();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginInitializerImpl.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginInitializerImpl.java
deleted file mode 100644
index 654d000..0000000
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginInitializerImpl.java
+++ /dev/null
@@ -1,57 +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.systemui.plugins;
-
-import android.content.Context;
-import android.util.Log;
-
-import com.android.systemui.R;
-import com.android.systemui.shared.plugins.PluginInitializer;
-import com.android.systemui.shared.plugins.PluginManagerImpl;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/** */
-@Singleton
-public class PluginInitializerImpl implements PluginInitializer {
-
-    /**
-     * True if WTFs should lead to crashes
-     */
-    private static final boolean WTFS_SHOULD_CRASH = false;
-    private boolean mWtfsSet;
-
-    @Inject
-    public PluginInitializerImpl(PluginDependencyProvider  dependencyProvider) {
-        dependencyProvider.allowPluginDependency(ActivityStarter.class);
-    }
-
-    @Override
-    public String[] getPrivilegedPlugins(Context context) {
-        return context.getResources().getStringArray(R.array.config_pluginWhitelist);
-    }
-
-
-    @Override
-    public void handleWtfs() {
-        if (WTFS_SHOULD_CRASH && !mWtfsSet) {
-            mWtfsSet = true;
-            Log.setWtfHandler((tag, what, system) -> {
-                throw new PluginManagerImpl.CrashWhilePluginActiveException(what);
-            });
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java
index 1ea9b3c..a0cf44c 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java
@@ -23,10 +23,12 @@
 import android.content.pm.PackageManager;
 import android.os.Build;
 
+import com.android.systemui.R;
+import com.android.systemui.dagger.PluginModule;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.shared.plugins.PluginActionManager;
 import com.android.systemui.shared.plugins.PluginEnabler;
-import com.android.systemui.shared.plugins.PluginInitializer;
-import com.android.systemui.shared.plugins.PluginInstanceManager;
+import com.android.systemui.shared.plugins.PluginInstance;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.plugins.PluginManagerImpl;
 import com.android.systemui.shared.plugins.PluginPrefs;
@@ -66,19 +68,30 @@
     @Binds
     abstract PluginEnabler bindsPluginEnablerImpl(PluginEnablerImpl impl);
 
-    @Binds
-    abstract PluginInitializer bindsPluginInitializerImpl(PluginInitializerImpl impl);
+    @Provides
+    @Singleton
+    static PluginInstance.Factory providesPluginInstanceFactory(
+            @Named(PLUGIN_PRIVILEGED) List<String> privilegedPlugins,
+            @Named(PLUGIN_DEBUG) boolean isDebug) {
+        return new PluginInstance.Factory(
+                PluginModule.class.getClassLoader(),
+                new PluginInstance.InstanceFactory<>(),
+                new PluginInstance.VersionChecker(),
+                privilegedPlugins,
+                isDebug);
+    }
 
     @Provides
     @Singleton
-    static PluginInstanceManager.Factory providePluginInstanceManagerFactory(Context context,
+    static PluginActionManager.Factory providePluginInstanceManagerFactory(Context context,
             PackageManager packageManager, @Main Executor mainExecutor,
-            @Named(PLUGIN_THREAD) Executor pluginExecutor, PluginInitializer initializer,
+            @Named(PLUGIN_THREAD) Executor pluginExecutor,
             NotificationManager notificationManager, PluginEnabler pluginEnabler,
-            @Named(PLUGIN_PRIVILEGED) List<String> privilegedPlugins) {
-        return new PluginInstanceManager.Factory(
-                context, packageManager, mainExecutor, pluginExecutor, initializer,
-                notificationManager, pluginEnabler, privilegedPlugins);
+            @Named(PLUGIN_PRIVILEGED) List<String> privilegedPlugins,
+            PluginInstance.Factory pluginInstanceFactory) {
+        return new PluginActionManager.Factory(
+                context, packageManager, mainExecutor, pluginExecutor,
+                notificationManager, pluginEnabler, privilegedPlugins, pluginInstanceFactory);
     }
 
     @Provides
@@ -91,7 +104,7 @@
     @Provides
     static PluginManager providesPluginManager(
             Context context,
-            PluginInstanceManager.Factory instanceManagerFactory,
+            PluginActionManager.Factory instanceManagerFactory,
             @Named(PLUGIN_DEBUG) boolean debug,
             @Named(PRE_HANDLER)
                     Optional<Thread.UncaughtExceptionHandler> uncaughtExceptionHandlerOptional,
@@ -110,7 +123,7 @@
 
     @Provides
     @Named(PLUGIN_PRIVILEGED)
-    static List<String> providesPrivilegedPlugins(PluginInitializer initializer, Context context) {
-        return Arrays.asList(initializer.getPrivilegedPlugins(context));
+    static List<String> providesPrivilegedPlugins(Context context) {
+        return Arrays.asList(context.getResources().getStringArray(R.array.config_pluginWhitelist));
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java b/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java
index 87c64c7..2f189be 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java
@@ -38,6 +38,7 @@
     private int mNumColumns = 3;
     private int mVerticalSpacing;
     private int mHorizontalSpacing;
+    private int mFixedChildWidth = -1;
 
     public PseudoGridView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -53,6 +54,8 @@
                 mVerticalSpacing = a.getDimensionPixelSize(attr, 0);
             } else if (attr == R.styleable.PseudoGridView_horizontalSpacing) {
                 mHorizontalSpacing = a.getDimensionPixelSize(attr, 0);
+            } else if (attr == R.styleable.PseudoGridView_fixedChildWidth) {
+                mFixedChildWidth = a.getDimensionPixelSize(attr, -1);
             }
         }
 
@@ -65,8 +68,15 @@
             throw new UnsupportedOperationException("Needs a maximum width");
         }
         int width = MeasureSpec.getSize(widthMeasureSpec);
-
-        int childWidth = (width - (mNumColumns - 1) * mHorizontalSpacing) / mNumColumns;
+        int childWidth;
+        int necessarySpaceForChildWidth =
+                mFixedChildWidth * mNumColumns + mHorizontalSpacing * (mNumColumns - 1);
+        if (mFixedChildWidth != -1 && necessarySpaceForChildWidth <= width) {
+            childWidth = mFixedChildWidth;
+            width = mFixedChildWidth * mNumColumns + mHorizontalSpacing * (mNumColumns - 1);
+        } else {
+            childWidth = (width - (mNumColumns - 1) * mHorizontalSpacing) / mNumColumns;
+        }
         int childWidthSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY);
         int childHeightSpec = MeasureSpec.UNSPECIFIED;
         int totalHeight = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 7eedb3a..359f3a4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -326,6 +326,7 @@
                     public void onAnimationAtStart() {
                         super.onAnimationAtStart();
                         mClockDateView.setFreezeSwitching(false);
+                        mClockDateView.setVisibility(View.VISIBLE);
                         setSeparatorVisibility(mShowClockIconsSeparator);
                         // In QQS we never ignore RSSI.
                         mIconContainer.removeIgnoredSlots(mRssiIgnoredSlots);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index d33982c..e6ab436 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -116,6 +116,7 @@
      */
     void show(int x, int y, TileAdapter tileAdapter) {
         if (!isShown) {
+            mRecyclerView.getLayoutManager().scrollToPosition(0);
             int[] containerLocation = findViewById(R.id.customize_container).getLocationOnScreen();
             mX = x - containerLocation[0];
             mY = y - containerLocation[1];
@@ -131,6 +132,7 @@
 
     void showImmediately() {
         if (!isShown) {
+            mRecyclerView.getLayoutManager().scrollToPosition(0);
             setVisibility(VISIBLE);
             mClipper.cancelAnimator();
             mClipper.showBackground();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index c5fa76e..5bd02cc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -133,8 +133,8 @@
         updateDefaultTileAndIcon();
         if (mInitialDefaultIconFetched.compareAndSet(false, true)) {
             if (mDefaultIcon == null) {
-                mQSLogger.logTileDestroyed(getTileSpec(),
-                        "Custom tile default icon not available");
+                Log.w(TAG, "No default icon for " + getTileSpec() + ", destroying tile");
+                mHost.removeTile(getTileSpec());
             }
         }
         if (mServiceManager.isToggleableTile()) {
@@ -412,7 +412,7 @@
             tileState = Tile.STATE_UNAVAILABLE;
         }
         state.state = tileState;
-        Drawable drawable;
+        Drawable drawable = null;
         try {
             drawable = mTile.getIcon().loadDrawable(mUserContext);
         } catch (Exception e) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index d262412..e6612fe 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -329,7 +329,8 @@
         filter.addDataScheme("package");
         try {
             mPackageReceiverRegistered.set(true);
-            mContext.registerReceiverAsUser(this, mUser, filter, null, mHandler);
+            mContext.registerReceiverAsUser(
+                    this, mUser, filter, null, mHandler, Context.RECEIVER_EXPORTED);
         } catch (Exception ex) {
             mPackageReceiverRegistered.set(false);
             Log.e(TAG, "Could not register package receiver", ex);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index 7e76e57..fda755b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -92,7 +92,7 @@
         filter.addDataScheme("package");
         Context context = mServices.getContext();
         context.registerReceiverAsUser(mUninstallReceiver, userTracker.getUserHandle(), filter,
-                null, mHandler);
+                null, mHandler, Context.RECEIVER_EXPORTED);
     }
 
     boolean isLifecycleStarted() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
index e6da234..fe1a619 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
@@ -17,17 +17,20 @@
 package com.android.systemui.qs.external
 
 import android.app.Dialog
+import android.app.StatusBarManager
 import android.content.ComponentName
 import android.content.DialogInterface
 import android.graphics.drawable.Icon
 import android.util.Log
 import androidx.annotation.VisibleForTesting
+import com.android.internal.statusbar.IAddTileResultCallback
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.qs.QSTileHost
 import com.android.systemui.statusbar.commandline.Command
 import com.android.systemui.statusbar.commandline.CommandRegistry
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.R
+import com.android.systemui.statusbar.CommandQueue
 import java.io.PrintWriter
 import java.util.function.Consumer
 import javax.inject.Inject
@@ -39,24 +42,41 @@
  */
 class TileServiceRequestController constructor(
     private val qsTileHost: QSTileHost,
+    private val commandQueue: CommandQueue,
     private val commandRegistry: CommandRegistry,
     private val dialogCreator: () -> TileRequestDialog = { TileRequestDialog(qsTileHost.context) }
 ) {
 
     companion object {
-        // Temporary return values while there's no API
-        internal const val ADD_TILE = 0
-        internal const val DONT_ADD_TILE = 1
-        internal const val TILE_ALREADY_ADDED = 2
+        internal const val ADD_TILE = StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_ADDED
+        internal const val DONT_ADD_TILE = StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED
+        internal const val TILE_ALREADY_ADDED =
+                StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_ALREADY_ADDED
         internal const val DISMISSED = 3
     }
 
+    private val commandQueueCallback = object : CommandQueue.Callbacks {
+        override fun requestAddTile(
+            componentName: ComponentName,
+            appName: CharSequence,
+            label: CharSequence,
+            icon: Icon,
+            callback: IAddTileResultCallback
+        ) {
+            requestTileAdd(componentName, appName, label, icon) {
+                callback.onTileRequest(it)
+            }
+        }
+    }
+
     fun init() {
         commandRegistry.registerCommand("tile-service-add") { TileServiceRequestCommand() }
+        commandQueue.addCallback(commandQueueCallback)
     }
 
     fun destroy() {
         commandRegistry.unregisterCommand("tile-service-add")
+        commandQueue.removeCallback(commandQueueCallback)
     }
 
     private fun addTile(componentName: ComponentName) {
@@ -133,10 +153,11 @@
 
     @SysUISingleton
     class Builder @Inject constructor(
+        private val commandQueue: CommandQueue,
         private val commandRegistry: CommandRegistry
     ) {
         fun create(qsTileHost: QSTileHost): TileServiceRequestController {
-            return TileServiceRequestController(qsTileHost, commandRegistry)
+            return TileServiceRequestController(qsTileHost, commandQueue, commandRegistry)
         }
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index ccc08e0..b718ebf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -40,6 +40,8 @@
 import com.android.systemui.qs.QSUserSwitcherEvent;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 
+import java.util.function.Consumer;
+
 import javax.inject.Inject;
 
 /**
@@ -76,6 +78,7 @@
         private View mCurrentUserView;
         private final UiEventLogger mUiEventLogger;
         private final FalsingManager mFalsingManager;
+        private Consumer<UserSwitcherController.UserRecord> mClickCallback;
 
         @Inject
         public Adapter(Context context, UserSwitcherController controller,
@@ -93,6 +96,10 @@
             return createUserDetailItemView(convertView, parent, item);
         }
 
+        public void injectCallback(Consumer<UserSwitcherController.UserRecord> clickCallback) {
+            mClickCallback = clickCallback;
+        }
+
         public UserDetailItemView createUserDetailItemView(View convertView, ViewGroup parent,
                 UserSwitcherController.UserRecord item) {
             UserDetailItemView v = UserDetailItemView.convertOrInflate(
@@ -170,6 +177,13 @@
                 onUserListItemClicked(tag);
             }
             Trace.endSection();
+            if (mClickCallback != null) {
+                mClickCallback.accept(tag);
+            }
+        }
+
+        public void linkToViewGroup(ViewGroup viewGroup) {
+            PseudoGridView.ViewGroupAdapterBridge.link(viewGroup, this);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
index 4e897d9..99eb5b6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
@@ -16,15 +16,11 @@
 
 package com.android.systemui.qs.tiles.dialog;
 
-import static com.android.wifitrackerlib.WifiEntry.SECURITY_NONE;
-import static com.android.wifitrackerlib.WifiEntry.SECURITY_OWE;
-
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
 import android.text.Html;
 import android.text.TextUtils;
-import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -36,6 +32,7 @@
 import androidx.annotation.Nullable;
 import androidx.recyclerview.widget.RecyclerView;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.Utils;
 import com.android.settingslib.wifi.WifiUtils;
 import com.android.systemui.R;
@@ -114,10 +111,11 @@
         final ImageView mWifiIcon;
         final TextView mWifiTitleText;
         final TextView mWifiSummaryText;
-        final ImageView mWifiLockedIcon;
+        final ImageView mWifiEndIcon;
         final Context mContext;
         final InternetDialogController mInternetDialogController;
 
+        @VisibleForTesting
         protected WifiUtils.InternetIconInjector mWifiIconInjector;
 
         InternetViewHolder(View view, InternetDialogController internetDialogController) {
@@ -130,28 +128,25 @@
             mWifiIcon = view.requireViewById(R.id.wifi_icon);
             mWifiTitleText = view.requireViewById(R.id.wifi_title);
             mWifiSummaryText = view.requireViewById(R.id.wifi_summary);
-            mWifiLockedIcon = view.requireViewById(R.id.wifi_locked_icon);
+            mWifiEndIcon = view.requireViewById(R.id.wifi_end_icon);
             mWifiIconInjector = mInternetDialogController.getWifiIconInjector();
         }
 
-        void onBind(WifiEntry wifiEntry) {
-            int security = wifiEntry.getSecurity();
-            try {
-                mWifiIcon.setImageDrawable(getWifiDrawable(wifiEntry));
-                if (isOpenNetwork(security)) {
-                    mWifiLockedIcon.setVisibility(View.GONE);
-                } else {
-                    mWifiLockedIcon.setVisibility(View.VISIBLE);
-                    mWifiLockedIcon.setImageDrawable(
-                            mContext.getDrawable(R.drawable.ic_friction_lock_closed));
-                }
-            } catch (Throwable throwable) {
-                throwable.printStackTrace();
-            }
-
+        void onBind(@NonNull WifiEntry wifiEntry) {
+            mWifiIcon.setImageDrawable(getWifiDrawable(wifiEntry));
             setWifiNetworkLayout(wifiEntry.getTitle(),
                     Html.fromHtml(wifiEntry.getSummary(false), Html.FROM_HTML_MODE_LEGACY));
 
+            final int connectedState = wifiEntry.getConnectedState();
+            final int security = wifiEntry.getSecurity();
+            updateEndIcon(connectedState, security);
+
+            if (connectedState != WifiEntry.CONNECTED_STATE_DISCONNECTED) {
+                mWifiListLayout.setOnClickListener(
+                        v -> mInternetDialogController.launchWifiNetworkDetailsSetting(
+                                wifiEntry.getKey()));
+                return;
+            }
             mWifiListLayout.setOnClickListener(v -> {
                 if (wifiEntry.shouldEditBeforeConnect()) {
                     final Intent intent = new Intent(ACTION_WIFI_DIALOG);
@@ -165,25 +160,17 @@
             });
         }
 
-        /** Return true if this is an open network AccessPoint. */
-        boolean isOpenNetwork(int security) {
-            return security == SECURITY_NONE
-                    || security == SECURITY_OWE;
-        }
-
         void setWifiNetworkLayout(CharSequence title, CharSequence summary) {
-            mWifiNetworkLayout.setVisibility(View.VISIBLE);
             mWifiTitleText.setText(title);
             if (TextUtils.isEmpty(summary)) {
                 mWifiSummaryText.setVisibility(View.GONE);
                 return;
-            } else {
-                mWifiSummaryText.setVisibility(View.VISIBLE);
             }
+            mWifiSummaryText.setVisibility(View.VISIBLE);
             mWifiSummaryText.setText(summary);
         }
 
-        Drawable getWifiDrawable(@NonNull WifiEntry wifiEntry) throws Throwable {
+        Drawable getWifiDrawable(@NonNull WifiEntry wifiEntry) {
             if (wifiEntry.getLevel() == WifiEntry.WIFI_LEVEL_UNREACHABLE) {
                 return null;
             }
@@ -198,5 +185,20 @@
             shared.set(drawable);
             return shared.get();
         }
+
+        void updateEndIcon(int connectedState, int security) {
+            Drawable drawable = null;
+            if (connectedState != WifiEntry.CONNECTED_STATE_DISCONNECTED) {
+                drawable = mContext.getDrawable(R.drawable.ic_settings_24dp);
+            } else if (security != WifiEntry.SECURITY_NONE && security != WifiEntry.SECURITY_OWE) {
+                drawable = mContext.getDrawable(R.drawable.ic_friction_lock_closed);
+            }
+            if (drawable == null) {
+                mWifiEndIcon.setVisibility(View.GONE);
+                return;
+            }
+            mWifiEndIcon.setVisibility(View.VISIBLE);
+            mWifiEndIcon.setImageDrawable(drawable);
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index 52bf2df..b1db8a9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -423,7 +423,10 @@
     }
 
     void onClickConnectedWifi() {
-        mInternetDialogController.launchWifiNetworkDetailsSetting();
+        if (mConnectedWifiEntry == null) {
+            return;
+        }
+        mInternetDialogController.launchWifiNetworkDetailsSetting(mConnectedWifiEntry.getKey());
     }
 
     void onClickSeeMoreButton() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index 62fa3d4..70f52ad 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -248,8 +248,7 @@
         return new Intent(ACTION_NETWORK_PROVIDER_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
     }
 
-    protected Intent getWifiDetailsSettingsIntent() {
-        String key = mConnectedEntry == null ? null : mConnectedEntry.getKey();
+    protected Intent getWifiDetailsSettingsIntent(String key) {
         if (TextUtils.isEmpty(key)) {
             if (DEBUG) {
                 Log.d(TAG, "connected entry's key is empty");
@@ -338,6 +337,9 @@
     }
 
     Drawable getInternetWifiDrawable(@NonNull WifiEntry wifiEntry) {
+        if (wifiEntry.getLevel() == WifiEntry.WIFI_LEVEL_UNREACHABLE) {
+            return null;
+        }
         final Drawable drawable =
                 mWifiIconInjector.getIcon(wifiEntry.shouldShowXLevelIcon(), wifiEntry.getLevel());
         if (drawable == null) {
@@ -558,8 +560,8 @@
         mActivityStarter.postStartActivityDismissingKeyguard(getSettingsIntent(), 0);
     }
 
-    void launchWifiNetworkDetailsSetting() {
-        Intent intent = getWifiDetailsSettingsIntent();
+    void launchWifiNetworkDetailsSetting(String key) {
+        Intent intent = getWifiDetailsSettingsIntent(key);
         if (intent != null) {
             mCallback.dismissDialog();
             mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
@@ -739,7 +741,7 @@
                 final Intent intent = new Intent("com.android.settings.WIFI_DIALOG")
                         .putExtra(EXTRA_CHOSEN_WIFI_ENTRY_KEY, mWifiEntry.getKey());
                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                mActivityStarter.startActivity(intent, true);
+                mActivityStarter.startActivity(intent, false /* dismissShade */);
             } else if (status == CONNECT_STATUS_FAILURE_UNKNOWN) {
                 Toast.makeText(mContext, R.string.wifi_failed_connect_message,
                         Toast.LENGTH_SHORT).show();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt b/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt
new file mode 100644
index 0000000..2ad06c1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.user
+
+import android.content.Context
+import android.os.Bundle
+import android.view.Gravity
+import android.view.View
+import android.view.ViewGroup
+import android.view.WindowInsets
+import android.view.WindowManager
+import com.android.systemui.qs.PseudoGridView
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.R
+
+/**
+ * Dialog for switching users or creating new ones.
+ */
+class UserDialog(
+    context: Context
+) : SystemUIDialog(context, R.style.Theme_SystemUI_Dialog_QSDialog) {
+
+    // create() is no-op after creation
+    private lateinit var _doneButton: View
+    /**
+     * Button with text "Done" in dialog.
+     */
+    val doneButton: View
+        get() {
+            create()
+            return _doneButton
+        }
+
+    private lateinit var _settingsButton: View
+    /**
+     * Button with text "User Settings" in dialog.
+     */
+    val settingsButton: View
+        get() {
+            create()
+            return _settingsButton
+        }
+
+    private lateinit var _grid: PseudoGridView
+    /**
+     * Grid to populate with user avatar from adapter
+     */
+    val grid: ViewGroup
+        get() {
+            create()
+            return _grid
+        }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        window?.apply {
+            setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL)
+            attributes.fitInsetsTypes = attributes.fitInsetsTypes or WindowInsets.Type.statusBars()
+            attributes.receiveInsetsIgnoringZOrder = true
+            setLayout(
+                    context.resources.getDimensionPixelSize(R.dimen.qs_panel_width),
+                    ViewGroup.LayoutParams.WRAP_CONTENT
+            )
+            setGravity(Gravity.CENTER)
+        }
+        setContentView(R.layout.qs_user_dialog_content)
+
+        _doneButton = requireViewById(R.id.done)
+        _settingsButton = requireViewById(R.id.settings)
+        _grid = requireViewById(R.id.grid)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt b/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
new file mode 100644
index 0000000..a5e4ba1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.user
+
+import android.content.Context
+import android.content.Intent
+import android.provider.Settings
+import android.view.View
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.qs.tiles.UserDetailView
+import javax.inject.Inject
+import javax.inject.Provider
+
+/**
+ * Controller for [UserDialog].
+ */
+@SysUISingleton
+class UserSwitchDialogController @VisibleForTesting constructor(
+    private val userDetailViewAdapterProvider: Provider<UserDetailView.Adapter>,
+    private val activityStarter: ActivityStarter,
+    private val falsingManager: FalsingManager,
+    private val dialogFactory: (Context) -> UserDialog
+) {
+
+    @Inject
+    constructor(
+        userDetailViewAdapterProvider: Provider<UserDetailView.Adapter>,
+        activityStarter: ActivityStarter,
+        falsingManager: FalsingManager
+    ) : this(
+        userDetailViewAdapterProvider,
+        activityStarter,
+        falsingManager,
+        { UserDialog(it) }
+    )
+
+    companion object {
+        private val USER_SETTINGS_INTENT = Intent(Settings.ACTION_USER_SETTINGS)
+    }
+
+    /**
+     * Show a [UserDialog].
+     *
+     * Populate the dialog with information from and adapter obtained from
+     * [userDetailViewAdapterProvider] and show it as launched from [view].
+     */
+    fun showDialog(view: View) {
+        with(dialogFactory(view.context)) {
+            setShowForAllUsers(true)
+            setCanceledOnTouchOutside(true)
+            create() // Needs to be called before we can retrieve views
+
+            settingsButton.setOnClickListener {
+                if (!falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+                    activityStarter.postStartActivityDismissingKeyguard(USER_SETTINGS_INTENT, 0)
+                }
+                dismiss()
+            }
+            doneButton.setOnClickListener { dismiss() }
+
+            val adapter = userDetailViewAdapterProvider.get()
+            adapter.injectCallback {
+                dismiss()
+            }
+            adapter.linkToViewGroup(grid)
+
+            show()
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 50b1186..c76f01b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -78,6 +78,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.navigationbar.NavigationBar;
@@ -534,7 +535,8 @@
             ShellTransitions shellTransitions,
             ScreenLifecycle screenLifecycle,
             Optional<StartingSurface> startingSurface,
-            SmartspaceTransitionController smartspaceTransitionController) {
+            SmartspaceTransitionController smartspaceTransitionController,
+            DumpManager dumpManager) {
         super(broadcastDispatcher);
         mContext = context;
         mPipOptional = pipOptional;
@@ -547,7 +549,7 @@
                 com.android.internal.R.string.config_recentsComponentName));
         mQuickStepIntent = new Intent(ACTION_QUICKSTEP)
                 .setPackage(mRecentsComponentName.getPackageName());
-        mWindowCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(mContext.getResources());
+        mWindowCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(mContext);
         mSupportsRoundedCornersOnWindows = ScreenDecorationsUtils
                 .supportsRoundedCornersOnWindows(mContext.getResources());
         mSysUiState = sysUiState;
@@ -558,6 +560,8 @@
         // Assumes device always starts with back button until launcher tells it that it does not
         mNavBarButtonAlpha = 1.0f;
 
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
+
         // Listen for nav bar mode changes
         mNavBarMode = navModeController.addListener(this);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index aba1a24..f95dd34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -34,6 +34,7 @@
 import android.app.StatusBarManager.WindowVisibleState;
 import android.content.ComponentName;
 import android.content.Context;
+import android.graphics.drawable.Icon;
 import android.hardware.biometrics.BiometricAuthenticator.Modality;
 import android.hardware.biometrics.BiometricManager.BiometricMultiSensorMode;
 import android.hardware.biometrics.IBiometricSysuiReceiver;
@@ -58,6 +59,7 @@
 import androidx.annotation.NonNull;
 
 import com.android.internal.os.SomeArgs;
+import com.android.internal.statusbar.IAddTileResultCallback;
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.GcUtils;
@@ -79,7 +81,8 @@
  * coalescing these calls so they don't stack up.  For the calls
  * are coalesced, note that they are all idempotent.
  */
-public class CommandQueue extends IStatusBar.Stub implements CallbackController<Callbacks>,
+public class CommandQueue extends IStatusBar.Stub implements
+        CallbackController<Callbacks>,
         DisplayManager.DisplayListener {
     private static final String TAG = CommandQueue.class.getSimpleName();
 
@@ -148,6 +151,7 @@
     private static final int MSG_EMERGENCY_ACTION_LAUNCH_GESTURE      = 58 << MSG_SHIFT;
     private static final int MSG_SET_NAVIGATION_BAR_LUMA_SAMPLING_ENABLED = 59 << MSG_SHIFT;
     private static final int MSG_SET_UDFPS_HBM_LISTENER = 60 << MSG_SHIFT;
+    private static final int MSG_TILE_SERVICE_REQUEST_ADD = 61 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
     public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -402,6 +406,16 @@
          * @see IStatusBar#setNavigationBarLumaSamplingEnabled(int, boolean)
          */
         default void setNavigationBarLumaSamplingEnabled(int displayId, boolean enable) {}
+
+        /**
+         * @see IStatusBar#requestAddTile
+         */
+        default void requestAddTile(
+                @NonNull ComponentName componentName,
+                @NonNull CharSequence appName,
+                @NonNull CharSequence label,
+                @NonNull Icon icon,
+                @NonNull IAddTileResultCallback callback) {}
     }
 
     public CommandQueue(Context context) {
@@ -1107,6 +1121,23 @@
         GcUtils.runGcAndFinalizersSync();
     }
 
+    @Override
+    public void requestAddTile(
+            @NonNull ComponentName componentName,
+            @NonNull CharSequence appName,
+            @NonNull CharSequence label,
+            @NonNull Icon icon,
+            @NonNull IAddTileResultCallback callback
+    ) {
+        SomeArgs args = SomeArgs.obtain();
+        args.arg1 = componentName;
+        args.arg2 = appName;
+        args.arg3 = label;
+        args.arg4 = icon;
+        args.arg5 = callback;
+        mHandler.obtainMessage(MSG_TILE_SERVICE_REQUEST_ADD, args).sendToTarget();
+    }
+
     private final class H extends Handler {
         private H(Looper l) {
             super(l);
@@ -1480,6 +1511,19 @@
                                 msg.arg2 != 0);
                     }
                     break;
+                case MSG_TILE_SERVICE_REQUEST_ADD:
+                    args = (SomeArgs) msg.obj;
+                    ComponentName componentName = (ComponentName) args.arg1;
+                    CharSequence appName = (CharSequence) args.arg2;
+                    CharSequence label = (CharSequence) args.arg3;
+                    Icon icon = (Icon) args.arg4;
+                    IAddTileResultCallback callback = (IAddTileResultCallback) args.arg5;
+                    for (int i = 0; i < mCallbacks.size(); i++) {
+                        mCallbacks.get(i).requestAddTile(
+                                componentName, appName, label, icon, callback);
+                    }
+                    args.recycle();
+                    break;
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index eb5f82c..445715e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -723,15 +723,13 @@
     }
 
     protected String computePowerIndication() {
-        if (mPowerCharged) {
-            return mContext.getResources().getString(R.string.keyguard_charged);
-        }
-
         int chargingId;
-        String percentage = NumberFormat.getPercentInstance().format(mBatteryLevel / 100f);
         if (mBatteryOverheated) {
             chargingId = R.string.keyguard_plugged_in_charging_limited;
+            String percentage = NumberFormat.getPercentInstance().format(mBatteryLevel / 100f);
             return mContext.getResources().getString(chargingId, percentage);
+        } else if (mPowerCharged) {
+            return mContext.getResources().getString(R.string.keyguard_charged);
         }
 
         final boolean hasChargingTime = mChargingTimeRemaining > 0;
@@ -759,6 +757,7 @@
                     : R.string.keyguard_plugged_in_wireless;
         }
 
+        String percentage = NumberFormat.getPercentInstance().format(mBatteryLevel / 100f);
         if (hasChargingTime) {
             String chargingTimeFormatted = Formatter.formatShortElapsedTimeRoundingUpToMinutes(
                     mContext, mChargingTimeRemaining);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index c681a44..0fe3adb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -50,6 +50,7 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.recents.OverviewProxyService;
@@ -72,7 +73,9 @@
  */
 @SysUISingleton
 public class NotificationLockscreenUserManagerImpl implements
-        Dumpable, NotificationLockscreenUserManager, StateListener {
+        Dumpable,
+        NotificationLockscreenUserManager,
+        StateListener {
     private static final String TAG = "LockscreenUserManager";
     private static final boolean ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT = false;
 
@@ -202,7 +205,8 @@
             StatusBarStateController statusBarStateController,
             @Main Handler mainHandler,
             DeviceProvisionedController deviceProvisionedController,
-            KeyguardStateController keyguardStateController) {
+            KeyguardStateController keyguardStateController,
+            DumpManager dumpManager) {
         mContext = context;
         mMainHandler = mainHandler;
         mDevicePolicyManager = devicePolicyManager;
@@ -215,6 +219,8 @@
         mBroadcastDispatcher = broadcastDispatcher;
         mDeviceProvisionedController = deviceProvisionedController;
         mKeyguardStateController = keyguardStateController;
+
+        dumpManager.registerDumpable(this);
     }
 
     public void setUpWithPresenter(NotificationPresenter presenter) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 36d2d86..dcb1e4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -52,6 +52,7 @@
 import com.android.systemui.animation.Interpolators;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.media.MediaData;
 import com.android.systemui.media.MediaDataManager;
@@ -73,7 +74,6 @@
 import com.android.systemui.statusbar.phone.ScrimState;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.util.DeviceConfigProxy;
 import com.android.systemui.util.Utils;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 
@@ -188,8 +188,8 @@
             NotifCollection notifCollection,
             FeatureFlags featureFlags,
             @Main DelayableExecutor mainExecutor,
-            DeviceConfigProxy deviceConfig,
-            MediaDataManager mediaDataManager) {
+            MediaDataManager mediaDataManager,
+            DumpManager dumpManager) {
         mContext = context;
         mMediaArtworkProcessor = mediaArtworkProcessor;
         mKeyguardBypassController = keyguardBypassController;
@@ -214,6 +214,8 @@
             setupNotifPipeline();
             mUsingNotifPipeline = true;
         }
+
+        dumpManager.registerDumpable(this);
     }
 
     private void setupNotifPipeline() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 625d9cd..18a3d86 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -54,6 +54,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.dagger.StatusBarDependenciesModule;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
@@ -290,7 +291,8 @@
             @Main Handler mainHandler,
             RemoteInputUriController remoteInputUriController,
             NotificationClickNotifier clickNotifier,
-            ActionClickLogger logger) {
+            ActionClickLogger logger,
+            DumpManager dumpManager) {
         mContext = context;
         mLockscreenUserManager = lockscreenUserManager;
         mSmartReplyController = smartReplyController;
@@ -307,6 +309,8 @@
         mRemoteInputUriController = remoteInputUriController;
         mClickNotifier = clickNotifier;
 
+        dumpManager.registerDumpable(this);
+
         notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
             @Override
             public void onPreEntryUpdated(NotificationEntry entry) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index e845804..2a8771e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -78,7 +78,8 @@
     private var keyguardAnimator: Animator? = null
     private var notificationAnimator: Animator? = null
     private var updateScheduled: Boolean = false
-    private var shadeExpansion = 0f
+    @VisibleForTesting
+    var shadeExpansion = 0f
     private var isClosed: Boolean = true
     private var isOpen: Boolean = false
     private var isBlurred: Boolean = false
@@ -92,6 +93,9 @@
     // Only for dumpsys
     private var lastAppliedBlur = 0
 
+    // Shade expansion offset that happens when pulling down on a HUN.
+    var panelPullDownMinFraction = 0f
+
     var shadeAnimation = DepthAnimation()
 
     @VisibleForTesting
@@ -312,8 +316,10 @@
     /**
      * Update blurs when pulling down the shade
      */
-    override fun onPanelExpansionChanged(expansion: Float, tracking: Boolean) {
+    override fun onPanelExpansionChanged(rawExpansion: Float, tracking: Boolean) {
         val timestamp = SystemClock.elapsedRealtimeNanos()
+        val expansion = MathUtils.saturate(
+                (rawExpansion - panelPullDownMinFraction) / (1f - panelPullDownMinFraction))
 
         if (shadeExpansion == expansion && prevTracking == tracking) {
             prevTimestamp = timestamp
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index 545dca8..19876ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -48,6 +48,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.animation.Interpolators;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.policy.CallbackController;
@@ -63,8 +64,10 @@
  * Tracks and reports on {@link StatusBarState}.
  */
 @SysUISingleton
-public class StatusBarStateControllerImpl implements SysuiStatusBarStateController,
-        CallbackController<StateListener>, Dumpable {
+public class StatusBarStateControllerImpl implements
+        SysuiStatusBarStateController,
+        CallbackController<StateListener>,
+        Dumpable {
     private static final String TAG = "SbStateController";
     private static final boolean DEBUG_IMMERSIVE_APPS =
             SystemProperties.getBoolean("persist.debug.immersive_apps", false);
@@ -146,11 +149,13 @@
     private Interpolator mDozeInterpolator = Interpolators.FAST_OUT_SLOW_IN;
 
     @Inject
-    public StatusBarStateControllerImpl(UiEventLogger uiEventLogger) {
+    public StatusBarStateControllerImpl(UiEventLogger uiEventLogger, DumpManager dumpManager) {
         mUiEventLogger = uiEventLogger;
         for (int i = 0; i < HISTORY_SIZE; i++) {
             mHistoricalRecords[i] = new HistoricalState();
         }
+
+        dumpManager.registerDumpable(this);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
index f2cf93e..94f186f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
@@ -24,6 +24,7 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.media.MediaDataManager;
 import com.android.systemui.plugins.ActivityStarter;
@@ -65,7 +66,6 @@
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLogger;
 import com.android.systemui.statusbar.policy.RemoteInputUriController;
 import com.android.systemui.tracing.ProtoTracer;
-import com.android.systemui.util.DeviceConfigProxy;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.time.SystemClock;
 import com.android.wm.shell.bubbles.Bubbles;
@@ -98,7 +98,8 @@
             Handler mainHandler,
             RemoteInputUriController remoteInputUriController,
             NotificationClickNotifier clickNotifier,
-            ActionClickLogger actionClickLogger) {
+            ActionClickLogger actionClickLogger,
+            DumpManager dumpManager) {
         return new NotificationRemoteInputManager(
                 context,
                 lockscreenUserManager,
@@ -109,7 +110,8 @@
                 mainHandler,
                 remoteInputUriController,
                 clickNotifier,
-                actionClickLogger);
+                actionClickLogger,
+                dumpManager);
     }
 
     /** */
@@ -126,8 +128,8 @@
             NotifCollection notifCollection,
             FeatureFlags featureFlags,
             @Main DelayableExecutor mainExecutor,
-            DeviceConfigProxy deviceConfigProxy,
-            MediaDataManager mediaDataManager) {
+            MediaDataManager mediaDataManager,
+            DumpManager dumpManager) {
         return new NotificationMediaManager(
                 context,
                 statusBarOptionalLazy,
@@ -139,8 +141,8 @@
                 notifCollection,
                 featureFlags,
                 mainExecutor,
-                deviceConfigProxy,
-                mediaDataManager);
+                mediaDataManager,
+                dumpManager);
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index a65f3d5..a9ad000 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -37,6 +37,7 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.Dumpable;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.statusbar.NotificationLifetimeExtender;
 import com.android.systemui.statusbar.NotificationListener;
@@ -98,15 +99,16 @@
         CommonNotifCollection,
         Dumpable,
         VisualStabilityManager.Callback {
-    private static final String TAG = "NotificationEntryMgr";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    /**
-     * Used when a notification is removed and it doesn't have a reason that maps to one of the
-     * reasons defined in NotificationListenerService
-     * (e.g. {@link NotificationListenerService#REASON_CANCEL})
-     */
-    public static final int UNDEFINED_DISMISS_REASON = 0;
+    private final NotificationEntryManagerLogger mLogger;
+    private final NotificationGroupManagerLegacy mGroupManager;
+    private final FeatureFlags mFeatureFlags;
+    private final Lazy<NotificationRowBinder> mNotificationRowBinderLazy;
+    private final Lazy<NotificationRemoteInputManager> mRemoteInputManagerLazy;
+    private final LeakDetector mLeakDetector;
+    private final ForegroundServiceDismissalFeatureController mFgsFeatureController;
+    private final IStatusBarService mStatusBarService;
+    private final DumpManager mDumpManager;
 
     private final Set<NotificationEntry> mAllNotifications = new ArraySet<>();
     private final Set<NotificationEntry> mReadOnlyAllNotifications =
@@ -129,20 +131,8 @@
     private final Map<NotificationEntry, NotificationLifetimeExtender> mRetainedNotifications =
             new ArrayMap<>();
 
-    private final NotificationEntryManagerLogger mLogger;
-
-    private final IStatusBarService mStatusBarService;
-
-    // Lazily retrieved dependencies
-    private final Lazy<NotificationRowBinder> mNotificationRowBinderLazy;
-    private final Lazy<NotificationRemoteInputManager> mRemoteInputManagerLazy;
-    private final LeakDetector mLeakDetector;
     private final List<NotifCollectionListener> mNotifCollectionListeners = new ArrayList<>();
 
-    private final NotificationGroupManagerLegacy mGroupManager;
-    private final FeatureFlags mFeatureFlags;
-    private final ForegroundServiceDismissalFeatureController mFgsFeatureController;
-
     private LegacyNotificationRanker mRanker = new LegacyNotificationRankerStub();
     private NotificationPresenter mPresenter;
     private RankingMap mLatestRankingMap;
@@ -153,6 +143,40 @@
     private final List<NotificationEntryListener> mNotificationEntryListeners = new ArrayList<>();
     private final List<NotificationRemoveInterceptor> mRemoveInterceptors = new ArrayList<>();
 
+    /**
+     * Injected constructor. See {@link NotificationsModule}.
+     */
+    public NotificationEntryManager(
+            NotificationEntryManagerLogger logger,
+            NotificationGroupManagerLegacy groupManager,
+            FeatureFlags featureFlags,
+            Lazy<NotificationRowBinder> notificationRowBinderLazy,
+            Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy,
+            LeakDetector leakDetector,
+            ForegroundServiceDismissalFeatureController fgsFeatureController,
+            IStatusBarService statusBarService,
+            DumpManager dumpManager
+    ) {
+        mLogger = logger;
+        mGroupManager = groupManager;
+        mFeatureFlags = featureFlags;
+        mNotificationRowBinderLazy = notificationRowBinderLazy;
+        mRemoteInputManagerLazy = notificationRemoteInputManagerLazy;
+        mLeakDetector = leakDetector;
+        mFgsFeatureController = fgsFeatureController;
+        mStatusBarService = statusBarService;
+        mDumpManager = dumpManager;
+    }
+
+    /** Once called, the NEM will start processing notification events from system server. */
+    public void initialize(
+            NotificationListener notificationListener,
+            LegacyNotificationRanker ranker) {
+        mRanker = ranker;
+        notificationListener.addNotificationHandler(mNotifListener);
+        mDumpManager.registerDumpable(this);
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("NotificationEntryManager state:");
@@ -194,38 +218,6 @@
         }
     }
 
-    /**
-     * Injected constructor. See {@link NotificationsModule}.
-     */
-    public NotificationEntryManager(
-            NotificationEntryManagerLogger logger,
-            NotificationGroupManagerLegacy groupManager,
-            FeatureFlags featureFlags,
-            Lazy<NotificationRowBinder> notificationRowBinderLazy,
-            Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy,
-            LeakDetector leakDetector,
-            ForegroundServiceDismissalFeatureController fgsFeatureController,
-            IStatusBarService statusBarService
-    ) {
-        mLogger = logger;
-        mGroupManager = groupManager;
-        mFeatureFlags = featureFlags;
-        mNotificationRowBinderLazy = notificationRowBinderLazy;
-        mRemoteInputManagerLazy = notificationRemoteInputManagerLazy;
-        mLeakDetector = leakDetector;
-        mFgsFeatureController = fgsFeatureController;
-        mStatusBarService = statusBarService;
-    }
-
-    /** Once called, the NEM will start processing notification events from system server. */
-    public void attach(NotificationListener notificationListener) {
-        notificationListener.addNotificationHandler(mNotifListener);
-    }
-
-    public void setRanker(LegacyNotificationRanker ranker) {
-        mRanker = ranker;
-    }
-
     /** Adds a {@link NotificationEntryListener}. */
     public void addNotificationEntryListener(NotificationEntryListener listener) {
         mNotificationEntryListeners.add(listener);
@@ -976,4 +968,14 @@
         /** true if the notification is for the current profiles */
         boolean isNotificationForCurrentProfiles(StatusBarNotification sbn);
     }
+
+    private static final String TAG = "NotificationEntryMgr";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    /**
+     * Used when a notification is removed and it doesn't have a reason that maps to one of the
+     * reasons defined in NotificationListenerService
+     * (e.g. {@link NotificationListenerService#REASON_CANCEL})
+     */
+    public static final int UNDEFINED_DISMISS_REASON = 0;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
index f40f24a..5993f1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
@@ -25,6 +25,7 @@
 
 import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.StatusBarState;
@@ -60,8 +61,12 @@
  * 2. Tracking group expansion states
  */
 @SysUISingleton
-public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, StateListener,
-        GroupMembershipManager, GroupExpansionManager, Dumpable {
+public class NotificationGroupManagerLegacy implements
+        OnHeadsUpChangedListener,
+        StateListener,
+        GroupMembershipManager,
+        GroupExpansionManager,
+        Dumpable {
 
     private static final String TAG = "NotifGroupManager";
     private static final boolean DEBUG = StatusBar.DEBUG;
@@ -87,10 +92,13 @@
     public NotificationGroupManagerLegacy(
             StatusBarStateController statusBarStateController,
             Lazy<PeopleNotificationIdentifier> peopleNotificationIdentifier,
-            Optional<Bubbles> bubblesOptional) {
+            Optional<Bubbles> bubblesOptional,
+            DumpManager dumpManager) {
         statusBarStateController.addCallback(this);
         mPeopleNotificationIdentifier = peopleNotificationIdentifier;
         mBubblesOptional = bubblesOptional;
+
+        dumpManager.registerDumpable(this);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/VisualStabilityManager.java
index 165df30..6e47c7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/VisualStabilityManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/VisualStabilityManager.java
@@ -24,6 +24,7 @@
 
 import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
@@ -71,9 +72,11 @@
             NotificationEntryManager notificationEntryManager,
             @Main Handler handler,
             StatusBarStateController statusBarStateController,
-            WakefulnessLifecycle wakefulnessLifecycle) {
+            WakefulnessLifecycle wakefulnessLifecycle,
+            DumpManager dumpManager) {
 
         mHandler = handler;
+        dumpManager.registerDumpable(this);
 
         if (notificationEntryManager != null) {
             notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index 55620b6..94f5c44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -30,6 +30,7 @@
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
@@ -109,7 +110,8 @@
             Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy,
             LeakDetector leakDetector,
             ForegroundServiceDismissalFeatureController fgsFeatureController,
-            IStatusBarService statusBarService) {
+            IStatusBarService statusBarService,
+            DumpManager dumpManager) {
         return new NotificationEntryManager(
                 logger,
                 groupManager,
@@ -118,7 +120,8 @@
                 notificationRemoteInputManagerLazy,
                 leakDetector,
                 fgsFeatureController,
-                statusBarService);
+                statusBarService,
+                dumpManager);
     }
 
     /** Provides an instance of {@link NotificationGutsManager} */
@@ -142,7 +145,8 @@
             Optional<BubblesManager> bubblesManagerOptional,
             UiEventLogger uiEventLogger,
             OnUserInteractionCallback onUserInteractionCallback,
-            ShadeController shadeController) {
+            ShadeController shadeController,
+            DumpManager dumpManager) {
         return new NotificationGutsManager(
                 context,
                 statusBarOptionalLazy,
@@ -161,23 +165,25 @@
                 bubblesManagerOptional,
                 uiEventLogger,
                 onUserInteractionCallback,
-                shadeController);
+                shadeController,
+                dumpManager);
     }
 
     /** Provides an instance of {@link VisualStabilityManager} */
     @SysUISingleton
     @Provides
     static VisualStabilityManager provideVisualStabilityManager(
-            FeatureFlags featureFlags,
             NotificationEntryManager notificationEntryManager,
             Handler handler,
             StatusBarStateController statusBarStateController,
-            WakefulnessLifecycle wakefulnessLifecycle) {
+            WakefulnessLifecycle wakefulnessLifecycle,
+            DumpManager dumpManager) {
         return new VisualStabilityManager(
                 notificationEntryManager,
                 handler,
                 statusBarStateController,
-                wakefulnessLifecycle);
+                wakefulnessLifecycle,
+                dumpManager);
     }
 
     /** Provides an instance of {@link NotificationLogger} */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index c5899ad..11b0429 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -128,8 +128,7 @@
             groupManagerLegacy.get().setHeadsUpManager(headsUpManager)
             groupAlertTransferHelper.setHeadsUpManager(headsUpManager)
 
-            entryManager.setRanker(legacyRanker)
-            entryManager.attach(notificationListener)
+            entryManager.initialize(notificationListener, legacyRanker)
         }
 
         peopleSpaceWidgetManager.attach(notificationListener)
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 8fe0894..7eec95a 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
@@ -50,6 +50,7 @@
 import com.android.systemui.R;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -151,7 +152,8 @@
             Optional<BubblesManager> bubblesManagerOptional,
             UiEventLogger uiEventLogger,
             OnUserInteractionCallback onUserInteractionCallback,
-            ShadeController shadeController) {
+            ShadeController shadeController,
+            DumpManager dumpManager) {
         mContext = context;
         mStatusBarOptionalLazy = statusBarOptionalLazy;
         mMainHandler = mainHandler;
@@ -171,6 +173,8 @@
         mOnUserInteractionCallback = onUserInteractionCallback;
         mShadeController = shadeController;
         mAppWidgetManager = AppWidgetManager.getInstance(context);
+
+        dumpManager.registerDumpable(this);
     }
 
     public void setUpWithPresenter(NotificationPresenter presenter,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index c2716b9..a472710 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -75,7 +75,7 @@
     private float mDividerAlpha;
     private int mNotificationHeaderMargin;
 
-    private int mNotificatonTopPadding;
+    private int mNotificationTopPadding;
     private float mCollapsedBottompadding;
     private boolean mChildrenExpanded;
     private ExpandableNotificationRow mContainingNotification;
@@ -140,9 +140,9 @@
         mDividerAlpha = res.getFloat(R.dimen.notification_divider_alpha);
         mNotificationHeaderMargin = res.getDimensionPixelSize(
                 R.dimen.notification_children_container_margin_top);
-        mNotificatonTopPadding = res.getDimensionPixelSize(
+        mNotificationTopPadding = res.getDimensionPixelSize(
                 R.dimen.notification_children_container_top_padding);
-        mHeaderHeight = mNotificationHeaderMargin + mNotificatonTopPadding;
+        mHeaderHeight = mNotificationHeaderMargin + mNotificationTopPadding;
         mCollapsedBottompadding = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.notification_content_margin);
         mEnableShadowOnChildNotifications =
@@ -203,7 +203,7 @@
                     newHeightSpec);
         }
         int dividerHeightSpec = MeasureSpec.makeMeasureSpec(mDividerHeight, MeasureSpec.EXACTLY);
-        int height = mNotificationHeaderMargin + mNotificatonTopPadding;
+        int height = mNotificationHeaderMargin + mNotificationTopPadding;
         int childCount =
                 Math.min(mAttachedChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
         int collapsedChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
@@ -526,11 +526,11 @@
                 if (mUserLocked) {
                     intrinsicHeight += NotificationUtils.interpolate(
                             0,
-                            mNotificatonTopPadding + mDividerHeight,
+                            mNotificationTopPadding + mDividerHeight,
                             expandFactor);
                 } else {
                     intrinsicHeight += childrenExpanded
-                            ? mNotificatonTopPadding + mDividerHeight
+                            ? mNotificationTopPadding + mDividerHeight
                             : 0;
                 }
                 firstChild = false;
@@ -583,10 +583,10 @@
                 if (expandingToExpandedGroup) {
                     yPosition += NotificationUtils.interpolate(
                             0,
-                            mNotificatonTopPadding + mDividerHeight,
+                            mNotificationTopPadding + mDividerHeight,
                             expandFactor);
                 } else {
-                    yPosition += mChildrenExpanded ? mNotificatonTopPadding + mDividerHeight : 0;
+                    yPosition += mChildrenExpanded ? mNotificationTopPadding + mDividerHeight : 0;
                 }
                 firstChild = false;
             }
@@ -1009,7 +1009,7 @@
                     /* likeHighPriority */);
         }
         int maxContentHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation
-                + mNotificatonTopPadding;
+                + mNotificationTopPadding;
         int visibleChildren = 0;
         int childCount = mAttachedChildren.size();
         for (int i = 0; i < childCount; i++) {
@@ -1072,7 +1072,7 @@
 
     private int getVisibleChildrenExpandHeight() {
         int intrinsicHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation
-                + mNotificatonTopPadding + mDividerHeight;
+                + mNotificationTopPadding + mDividerHeight;
         int visibleChildren = 0;
         int childCount = mAttachedChildren.size();
         int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
@@ -1212,7 +1212,7 @@
 
     public int getPositionInLinearLayout(View childInGroup) {
         int position = mNotificationHeaderMargin + mCurrentHeaderTranslation
-                + mNotificatonTopPadding;
+                + mNotificationTopPadding;
 
         for (int i = 0; i < mAttachedChildren.size(); i++) {
             ExpandableNotificationRow child = mAttachedChildren.get(i);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
index f25359e..d06de75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
@@ -25,6 +25,7 @@
 
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.statusbar.CommandQueue;
 
 import java.io.FileDescriptor;
@@ -50,11 +51,16 @@
     /**
      */
     @Inject
-    public DarkIconDispatcherImpl(Context context, CommandQueue commandQueue) {
+    public DarkIconDispatcherImpl(
+            Context context,
+            CommandQueue commandQueue,
+            DumpManager dumpManager) {
         mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
         mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
 
         mTransitionsController = new LightBarTransitionsController(context, this, commandQueue);
+
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
     }
 
     public LightBarTransitionsController getTransitionsController() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 84b8f52..ab7f9d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -48,8 +48,10 @@
  * Retrieve doze information
  */
 @SysUISingleton
-public class DozeParameters implements TunerService.Tunable,
-        com.android.systemui.plugins.statusbar.DozeParameters, Dumpable {
+public class DozeParameters implements
+        TunerService.Tunable,
+        com.android.systemui.plugins.statusbar.DozeParameters,
+        Dumpable {
     private static final int MAX_DURATION = 60 * 1000;
     public static final boolean FORCE_NO_BLANKING =
             SystemProperties.getBoolean("debug.force_no_blanking", false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index df4bbcf..f4cc146 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -73,7 +73,8 @@
     private final UserManager mUserManager;
 
     private int mSystemIconsSwitcherHiddenExpandedMargin;
-    private int mSystemIconsBaseMargin;
+    private int mStatusBarPaddingEnd;
+    private int mMinDotWidth;
     private View mSystemIconsContainer;
 
     private View mCutoutSpace;
@@ -125,14 +126,7 @@
         mMultiUserAvatar.setLayoutParams(lp);
 
         // System icons
-        lp = (MarginLayoutParams) mSystemIconsContainer.getLayoutParams();
-        lp.setMarginStart(getResources().getDimensionPixelSize(
-                R.dimen.system_icons_super_container_margin_start));
-        mSystemIconsContainer.setLayoutParams(lp);
-        mSystemIconsContainer.setPaddingRelative(mSystemIconsContainer.getPaddingStart(),
-                mSystemIconsContainer.getPaddingTop(),
-                getResources().getDimensionPixelSize(R.dimen.system_icons_keyguard_padding_end),
-                mSystemIconsContainer.getPaddingBottom());
+        updateSystemIconsLayoutParams();
 
         // Respect font size setting.
         mCarrierLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
@@ -162,8 +156,10 @@
         Resources res = getResources();
         mSystemIconsSwitcherHiddenExpandedMargin = res.getDimensionPixelSize(
                 R.dimen.system_icons_switcher_hidden_expanded_margin);
-        mSystemIconsBaseMargin = res.getDimensionPixelSize(
-                R.dimen.system_icons_super_container_avatarless_margin_end);
+        mStatusBarPaddingEnd = res.getDimensionPixelSize(
+                R.dimen.status_bar_padding_end);
+        mMinDotWidth = res.getDimensionPixelSize(
+                R.dimen.ongoing_appops_dot_min_padding);
         mCutoutSideNudge = getResources().getDimensionPixelSize(
                 R.dimen.display_cutout_margin_consumption);
         mShowPercentAvailable = getContext().getResources().getBoolean(
@@ -203,16 +199,24 @@
     private void updateSystemIconsLayoutParams() {
         LinearLayout.LayoutParams lp =
                 (LinearLayout.LayoutParams) mSystemIconsContainer.getLayoutParams();
-        // If the avatar icon is gone, we need to have some end margin to display the system icons
-        // correctly.
-        int baseMarginEnd = mMultiUserAvatar.getVisibility() == View.GONE
-                ? mSystemIconsBaseMargin
-                : 0;
+
+        int marginStart = getResources().getDimensionPixelSize(
+                R.dimen.system_icons_super_container_margin_start);
+
+        // Use status_bar_padding_end to replace original
+        // system_icons_super_container_avatarless_margin_end to prevent different end alignment
+        // between PhoneStatusBarView and KeyguardStatusBarView
+        int baseMarginEnd = mStatusBarPaddingEnd;
         int marginEnd =
                 mKeyguardUserSwitcherEnabled ? mSystemIconsSwitcherHiddenExpandedMargin
                         : baseMarginEnd;
-        marginEnd = calculateMargin(marginEnd, mPadding.second);
-        if (marginEnd != lp.getMarginEnd()) {
+
+        // Align PhoneStatusBar right margin/padding, only use
+        // 1. status bar layout: mPadding(consider round_corner + privacy dot)
+        // 2. icon container: R.dimen.status_bar_padding_end
+
+        if (marginEnd != lp.getMarginEnd() || marginStart != lp.getMarginStart()) {
+            lp.setMarginStart(marginStart);
             lp.setMarginEnd(marginEnd);
             mSystemIconsContainer.setLayoutParams(lp);
         }
@@ -247,7 +251,13 @@
         mPadding =
                 StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner(
                         mDisplayCutout, cornerCutoutMargins, mRoundedCornerPadding);
-        setPadding(mPadding.first, waterfallTop, mPadding.second, 0);
+
+        // consider privacy dot space
+        final int minLeft = isLayoutRtl() ? Math.max(mMinDotWidth, mPadding.first) : mPadding.first;
+        final int minRight = isLayoutRtl() ? mPadding.second :
+                Math.max(mMinDotWidth, mPadding.second);
+
+        setPadding(minLeft, waterfallTop, minRight, 0);
     }
 
     private boolean updateLayoutParamsNoCutout() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 24c9021..51eb496 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -33,6 +33,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.shared.system.QuickStepContract;
@@ -86,8 +87,12 @@
     private boolean mNavbarColorManagedByIme;
 
     @Inject
-    public LightBarController(Context ctx, DarkIconDispatcher darkIconDispatcher,
-            BatteryController batteryController, NavigationModeController navModeController) {
+    public LightBarController(
+            Context ctx,
+            DarkIconDispatcher darkIconDispatcher,
+            BatteryController batteryController,
+            NavigationModeController navModeController,
+            DumpManager dumpManager) {
         mDarkModeColor = Color.valueOf(ctx.getColor(R.color.dark_mode_icon_color_single_tone));
         mStatusBarIconController = (SysuiDarkIconDispatcher) darkIconDispatcher;
         mBatteryController = batteryController;
@@ -95,6 +100,8 @@
         mNavigationMode = navModeController.addListener((mode) -> {
             mNavigationMode = mode;
         });
+
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
     }
 
     public void setNavigationBar(LightBarTransitionsController navigationBar) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java
index f27c7d2..2cacf92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java
@@ -23,10 +23,12 @@
 import android.view.ViewGroup;
 
 import com.android.systemui.R;
+import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.qs.QSDetailDisplayer;
 import com.android.systemui.qs.dagger.QSScope;
+import com.android.systemui.qs.user.UserSwitchDialogController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.util.ViewController;
 
@@ -39,6 +41,8 @@
     private final UserSwitcherController mUserSwitcherController;
     private final QSDetailDisplayer mQsDetailDisplayer;
     private final FalsingManager mFalsingManager;
+    private final UserSwitchDialogController mUserSwitchDialogController;
+    private final FeatureFlags mFeatureFlags;
 
     private UserSwitcherController.BaseUserAdapter mUserListener;
 
@@ -49,26 +53,33 @@
                 return;
             }
 
-            View center = mView.getChildCount() > 0 ? mView.getChildAt(0) : mView;
+            if (mFeatureFlags.useNewUserSwitcher()) {
+                mUserSwitchDialogController.showDialog(v);
+            } else {
+                View center = mView.getChildCount() > 0 ? mView.getChildAt(0) : mView;
 
-            int[] tmpInt = new int[2];
-            center.getLocationInWindow(tmpInt);
-            tmpInt[0] += center.getWidth() / 2;
-            tmpInt[1] += center.getHeight() / 2;
+                int[] tmpInt = new int[2];
+                center.getLocationInWindow(tmpInt);
+                tmpInt[0] += center.getWidth() / 2;
+                tmpInt[1] += center.getHeight() / 2;
 
-            mQsDetailDisplayer.showDetailAdapter(getUserDetailAdapter(), tmpInt[0], tmpInt[1]);
+                mQsDetailDisplayer.showDetailAdapter(getUserDetailAdapter(), tmpInt[0], tmpInt[1]);
+            }
         }
     };
 
     @Inject
     public MultiUserSwitchController(MultiUserSwitch view, UserManager userManager,
             UserSwitcherController userSwitcherController, QSDetailDisplayer qsDetailDisplayer,
-            FalsingManager falsingManager) {
+            FalsingManager falsingManager, UserSwitchDialogController userSwitchDialogController,
+            FeatureFlags featureFlags) {
         super(view);
         mUserManager = userManager;
         mUserSwitcherController = userSwitcherController;
         mQsDetailDisplayer = qsDetailDisplayer;
         mFalsingManager = falsingManager;
+        mUserSwitchDialogController = userSwitchDialogController;
+        mFeatureFlags = featureFlags;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index d241d4b..3aca18e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -630,6 +630,7 @@
     private int mQsClipBottom;
     private boolean mQsVisible;
     private final ContentResolver mContentResolver;
+    private float mMinFraction;
 
     private final Executor mUiExecutor;
     private final SecureSettings mSecureSettings;
@@ -1003,7 +1004,8 @@
                 R.dimen.pulse_expansion_max_top_overshoot);
         mScrimCornerRadius = mResources.getDimensionPixelSize(
                 R.dimen.notification_scrim_corner_radius);
-        mScreenCornerRadius = (int) ScreenDecorationsUtils.getWindowCornerRadius(mResources);
+        mScreenCornerRadius = (int) ScreenDecorationsUtils.getWindowCornerRadius(
+                mView.getContext());
         mLockscreenNotificationQSPadding = mResources.getDimensionPixelSize(
                 R.dimen.notification_side_paddings);
     }
@@ -1919,6 +1921,15 @@
         return !mQsTouchAboveFalsingThreshold;
     }
 
+    /**
+     * Percentage of panel expansion offset, caused by pulling down on a heads-up.
+     */
+    @Override
+    public void setMinFraction(float minFraction) {
+        mMinFraction = minFraction;
+        mDepthController.setPanelPullDownMinFraction(mMinFraction);
+    }
+
     private float computeQsExpansionFraction() {
         if (mQSAnimatingHiddenFromCollapsed) {
             // When hiding QS from collapsed state, the expansion can sometimes temporarily
@@ -2392,6 +2403,12 @@
                 }
             }
             top += mOverStretchAmount;
+            // Correction for instant expansion caused by HUN pull down/
+            if (mMinFraction > 0f && mMinFraction < 1f) {
+                float realFraction =
+                        (getExpandedFraction() - mMinFraction) / (1f - mMinFraction);
+                top *= MathUtils.saturate(realFraction / mMinFraction);
+            }
             bottom = getView().getBottom();
             // notification bounds should take full screen width regardless of insets
             left = 0;
@@ -3464,7 +3481,7 @@
     }
 
     public void setPanelScrimMinFraction(float minFraction) {
-        mBar.panelScrimMinFractionChanged(minFraction);
+        mBar.onPanelMinFractionChanged(minFraction);
     }
 
     public void clearNotificationEffects() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index f1b6c7c..eca91a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -18,6 +18,7 @@
 
 import static java.lang.Float.isNaN;
 
+import android.annotation.CallSuper;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Parcelable;
@@ -162,7 +163,13 @@
         return mPanel == null || mPanel.getView().dispatchTouchEvent(event);
     }
 
-    public abstract void panelScrimMinFractionChanged(float minFraction);
+    /**
+     * Percentage of panel expansion offset, caused by pulling down on a heads-up.
+     */
+    @CallSuper
+    public void onPanelMinFractionChanged(float minFraction) {
+        mPanel.setMinFraction(minFraction);
+    }
 
     /**
      * @param frac the fraction from the expansion in [0, 1]
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index a3877b0..51cae8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -340,6 +340,13 @@
     protected abstract float getOpeningHeight();
 
     /**
+     * Minimum fraction from where expansion should start. This is set when pulling down on a
+     * heads-up notification.
+     * @param minFraction Fraction from 0 to 1.
+     */
+    public abstract void setMinFraction(float minFraction);
+
+    /**
      * @return whether the swiping direction is upwards and above a 45 degree angle compared to the
      * horizontal direction
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 88a823c..a09b30f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -273,10 +273,11 @@
     }
 
     @Override
-    public void panelScrimMinFractionChanged(float minFraction) {
+    public void onPanelMinFractionChanged(float minFraction) {
         if (isNaN(minFraction)) {
             throw new IllegalArgumentException("minFraction cannot be NaN");
         }
+        super.onPanelMinFractionChanged(minFraction);
         if (mMinFraction != minFraction) {
             mMinFraction = minFraction;
             updateScrimFraction();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 0b688d3..575a3c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -146,6 +146,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.emergency.EmergencyGesture;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.fragments.ExtensionFragmentListener;
@@ -780,7 +781,8 @@
             WallpaperManager wallpaperManager,
             UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
             Optional<StartingSurface> startingSurfaceOptional,
-            TunerService tunerService) {
+            TunerService tunerService,
+            DumpManager dumpManager) {
         super(context);
         mNotificationsController = notificationsController;
         mLightBarController = lightBarController;
@@ -896,6 +898,8 @@
                 data -> mCommandQueueCallbacks.animateExpandSettingsPanel(data.mSubpanel));
         mMessageRouter.subscribeTo(MSG_LAUNCH_TRANSITION_TIMEOUT,
                 id -> onLaunchTransitionTimeout());
+
+        dumpManager.registerDumpable(this);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 9d1c1e6..6a63156 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -33,6 +33,7 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.demomode.DemoMode;
 import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.StatusIconDisplayable;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
@@ -72,7 +73,8 @@
     public StatusBarIconControllerImpl(
             Context context,
             CommandQueue commandQueue,
-            DemoModeController demoModeController) {
+            DemoModeController demoModeController,
+            DumpManager dumpManager) {
         super(context.getResources().getStringArray(
                 com.android.internal.R.array.config_statusBarIcons));
         Dependency.get(ConfigurationController.class).addCallback(this);
@@ -84,6 +86,7 @@
         commandQueue.addCallback(this);
         Dependency.get(TunerService.class).addTunable(this, ICON_HIDE_LIST);
         demoModeController.addCallback(this);
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index a7b57b9..63ee701 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -36,6 +36,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -225,7 +226,8 @@
             WallpaperManager wallpaperManager,
             UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
             Optional<StartingSurface> startingSurfaceOptional,
-            TunerService tunerService) {
+            TunerService tunerService,
+            DumpManager dumpManager) {
         return new StatusBar(
                 context,
                 notificationsController,
@@ -318,6 +320,7 @@
                 wallpaperManager,
                 unlockedScreenOffAnimationController,
                 startingSurfaceOptional,
-                tunerService);
+                tunerService,
+                dumpManager);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
index 5011d96..4c6c7e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
@@ -56,7 +56,8 @@
     /**
      */
     @Inject
-    public ExtensionControllerImpl(Context context,
+    public ExtensionControllerImpl(
+            Context context,
             LeakDetector leakDetector,
             PluginManager pluginManager,
             TunerService tunerService,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
index d7c2b96..ad47e2b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
@@ -33,6 +33,7 @@
 import androidx.annotation.NonNull;
 
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -72,10 +73,11 @@
     private boolean mTorchAvailable;
 
     @Inject
-    public FlashlightControllerImpl(Context context) {
+    public FlashlightControllerImpl(Context context, DumpManager dumpManager) {
         mContext = context;
         mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
 
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
         tryInitCamera();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index 987812b..f364e49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -36,6 +36,7 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dump.DumpManager;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -91,14 +92,18 @@
      * Controller used to retrieve information related to a hotspot.
      */
     @Inject
-    public HotspotControllerImpl(Context context, @Main Handler mainHandler,
-            @Background Handler backgroundHandler) {
+    public HotspotControllerImpl(
+            Context context,
+            @Main Handler mainHandler,
+            @Background Handler backgroundHandler,
+            DumpManager dumpManager) {
         mContext = context;
         mTetheringManager = context.getSystemService(TetheringManager.class);
         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
         mMainHandler = mainHandler;
         mTetheringManager.registerTetheringEventCallback(
                 new HandlerExecutor(backgroundHandler), mTetheringCallback);
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
index a29b72c..b6c683f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
@@ -35,10 +35,12 @@
 import com.android.systemui.R;
 import com.android.systemui.communal.CommunalStateController;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.qs.tiles.UserDetailView;
+import com.android.systemui.qs.user.UserSwitchDialogController;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.AnimatableProperty;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
@@ -76,6 +78,8 @@
     private final ConfigurationController mConfigurationController;
     private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
     private final KeyguardUserDetailAdapter mUserDetailAdapter;
+    private final FeatureFlags mFeatureFlags;
+    private final UserSwitchDialogController mUserSwitchDialogController;
     private NotificationPanelViewController mNotificationPanelViewController;
     UserSwitcherController.UserRecord mCurrentUser;
 
@@ -124,7 +128,9 @@
             SysuiStatusBarStateController statusBarStateController,
             DozeParameters dozeParameters,
             Provider<UserDetailView.Adapter> userDetailViewAdapterProvider,
-            UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
+            UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
+            FeatureFlags featureFlags,
+            UserSwitchDialogController userSwitchDialogController) {
         super(view);
         if (DEBUG) Log.d(TAG, "New KeyguardQsUserSwitchController");
         mContext = context;
@@ -140,6 +146,8 @@
                 unlockedScreenOffAnimationController,  /* animateYPos= */ false,
                 /* visibleOnCommunal= */ false);
         mUserDetailAdapter = new KeyguardUserDetailAdapter(context, userDetailViewAdapterProvider);
+        mFeatureFlags = featureFlags;
+        mUserSwitchDialogController = userSwitchDialogController;
     }
 
     @Override
@@ -163,7 +171,11 @@
             }
 
             // Tapping anywhere in the view will open QS user panel
-            openQsUserPanel();
+            if (mFeatureFlags.useNewUserSwitcher()) {
+                mUserSwitchDialogController.showDialog(mView);
+            } else {
+                openQsUserPanel();
+            }
         });
 
         mView.setAccessibilityDelegate(new View.AccessibilityDelegate() {
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 f787ecf..2dfcc98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
@@ -34,6 +34,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController;
 
 import java.io.FileDescriptor;
@@ -100,15 +101,20 @@
     /**
      */
     @Inject
-    public KeyguardStateControllerImpl(Context context,
-            KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils,
-            SmartspaceTransitionController smartspaceTransitionController) {
+    public KeyguardStateControllerImpl(
+            Context context,
+            KeyguardUpdateMonitor keyguardUpdateMonitor,
+            LockPatternUtils lockPatternUtils,
+            SmartspaceTransitionController smartspaceTransitionController,
+            DumpManager dumpManager) {
         mContext = context;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mLockPatternUtils = lockPatternUtils;
         mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
         mSmartspaceTransitionController = smartspaceTransitionController;
 
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
+
         update(true /* updateAlways */);
         if (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB) {
             // Watch for interesting updates
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java
index 20b66f0..cd8894c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java
@@ -103,7 +103,7 @@
             }
         }
 
-        if (animate) {
+        if (animate && userItemViews.length > 1) {
             // AnimationUtils will immediately hide/show the first item in the array. Since the
             // first view is the current user, we want to manage its visibility separately.
             // Set first item to null so AnimationUtils ignores it.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 3e661df..7c13173 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -55,6 +55,7 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.settings.CurrentUserTracker;
 
 import org.xmlpull.v1.XmlPullParserException;
@@ -109,7 +110,8 @@
             Context context,
             @Background Handler bgHandler,
             BroadcastDispatcher broadcastDispatcher,
-            @Background Executor bgExecutor
+            @Background Executor bgExecutor,
+            DumpManager dumpManager
     ) {
         super(broadcastDispatcher);
         mContext = context;
@@ -122,6 +124,8 @@
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
         mBgExecutor = bgExecutor;
 
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
+
         IntentFilter filter = new IntentFilter();
         filter.addAction(KeyChain.ACTION_TRUST_STORE_CHANGED);
         filter.addAction(Intent.ACTION_USER_UNLOCKED);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java
index 6f659c1..2b8d3a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java
@@ -29,7 +29,8 @@
  * Controls sensor privacy state and notification.
  */
 @SysUISingleton
-public class SensorPrivacyControllerImpl implements SensorPrivacyController,
+public class SensorPrivacyControllerImpl implements
+        SensorPrivacyController,
         SensorPrivacyManager.OnAllSensorPrivacyChangedListener {
     private SensorPrivacyManager mSensorPrivacyManager;
     private final List<OnSensorPrivacyChangedListener> mListeners = new ArrayList<>(1);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 251ecc6..22f08ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -68,6 +68,7 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.qs.DetailAdapter;
@@ -163,7 +164,8 @@
             IActivityTaskManager activityTaskManager,
             UserDetailAdapter userDetailAdapter,
             SecureSettings secureSettings,
-            @Background Executor bgExecutor) {
+            @Background Executor bgExecutor,
+            DumpManager dumpManager) {
         mContext = context;
         mUserTracker = userTracker;
         mBroadcastDispatcher = broadcastDispatcher;
@@ -231,6 +233,8 @@
         keyguardStateController.addCallback(mCallback);
         listenForCallState();
 
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
+
         refreshUsers(UserHandle.USER_NULL);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index 897a3b8..5acce7f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -44,6 +44,7 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.qs.GlobalSetting;
 import com.android.systemui.settings.CurrentUserTracker;
 import com.android.systemui.util.Utils;
@@ -80,8 +81,11 @@
     private NotificationManager.Policy mConsolidatedNotificationPolicy;
 
     @Inject
-    public ZenModeControllerImpl(Context context, @Main Handler handler,
-            BroadcastDispatcher broadcastDispatcher) {
+    public ZenModeControllerImpl(
+            Context context,
+            @Main Handler handler,
+            BroadcastDispatcher broadcastDispatcher,
+            DumpManager dumpManager) {
         super(broadcastDispatcher);
         mContext = context;
         mModeSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE) {
@@ -108,6 +112,8 @@
         mSetupObserver.register();
         mUserManager = context.getSystemService(UserManager.class);
         startTracking();
+
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java b/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java
index 8a8f92b..98b2cca 100644
--- a/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java
+++ b/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java
@@ -48,8 +48,13 @@
  * Controller for coordinating winscope proto tracing.
  */
 @SysUISingleton
-public class ProtoTracer implements Dumpable, ProtoTraceParams<MessageNano, SystemUiTraceFileProto,
-        SystemUiTraceEntryProto, SystemUiTraceProto> {
+public class ProtoTracer implements
+        Dumpable,
+        ProtoTraceParams<
+                MessageNano,
+                SystemUiTraceFileProto,
+                SystemUiTraceEntryProto,
+                SystemUiTraceProto> {
 
     private static final String TAG = "ProtoTracer";
     private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
@@ -62,7 +67,7 @@
     public ProtoTracer(Context context, DumpManager dumpManager) {
         mContext = context;
         mProtoTracer = new FrameProtoTracer<>(this);
-        dumpManager.registerDumpable(getClass().getName(), this);
+        dumpManager.registerDumpable(this);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
index 20857ea..fe183fc 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
@@ -38,8 +38,8 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.plugins.PluginEnablerImpl;
+import com.android.systemui.shared.plugins.PluginActionManager;
 import com.android.systemui.shared.plugins.PluginEnabler;
-import com.android.systemui.shared.plugins.PluginInstanceManager;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.plugins.PluginPrefs;
 
@@ -102,7 +102,7 @@
         }
 
         List<PackageInfo> apps = pm.getPackagesHoldingPermissions(new String[]{
-                PluginInstanceManager.PLUGIN_PERMISSION},
+                PluginActionManager.PLUGIN_PERMISSION},
                 PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.GET_SERVICES);
         apps.forEach(app -> {
             if (!plugins.containsKey(app.packageName)) return;
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index c799888..4318994 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -51,6 +51,7 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.qs.QSTile;
@@ -137,7 +138,8 @@
             @Background DelayableExecutor delayableExecutor,
             @Background MessageRouter messageRouter,
             LeakDetector leakDetector,
-            LeakReporter leakReporter) {
+            LeakReporter leakReporter,
+            DumpManager dumpManager) {
         mContext = context.getApplicationContext();
 
         mDelayableExecutor = delayableExecutor;
@@ -150,6 +152,8 @@
 
         mDumpTruck = new DumpTruck(mContext);
 
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
+
         if (ENABLE_AM_HEAP_LIMIT) {
             mHeapLimit = Settings.Global.getInt(context.getContentResolver(),
                     SETTINGS_KEY_AM_HEAP_LIMIT,
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java b/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java
index c50e8f8..f215082 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java
@@ -21,6 +21,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.systemui.Dumpable;
+import com.android.systemui.dump.DumpManager;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -38,12 +39,16 @@
     private final TrackedObjects mTrackedObjects;
 
     @VisibleForTesting
-    public LeakDetector(TrackedCollections trackedCollections,
+    public LeakDetector(
+            TrackedCollections trackedCollections,
             TrackedGarbage trackedGarbage,
-            TrackedObjects trackedObjects) {
+            TrackedObjects trackedObjects,
+            DumpManager dumpManager) {
         mTrackedCollections = trackedCollections;
         mTrackedGarbage = trackedGarbage;
         mTrackedObjects = trackedObjects;
+
+        dumpManager.registerDumpable(getClass().getSimpleName(), this);
     }
 
     /**
@@ -130,13 +135,16 @@
         pw.println();
     }
 
-    public static LeakDetector create() {
+    public static LeakDetector create(DumpManager dumpManager) {
         if (ENABLED) {
             TrackedCollections collections = new TrackedCollections();
-            return new LeakDetector(collections, new TrackedGarbage(collections),
-                    new TrackedObjects(collections));
+            return new LeakDetector(
+                    collections,
+                    new TrackedGarbage(collections),
+                    new TrackedObjects(collections),
+                    dumpManager);
         } else {
-            return new LeakDetector(null, null, null);
+            return new LeakDetector(null, null, null, dumpManager);
         }
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index ed5cbe2..4c7f959 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -17,6 +17,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM;
 import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
+import static android.view.DisplayCutout.BOUNDS_POSITION_LENGTH;
 import static android.view.DisplayCutout.BOUNDS_POSITION_RIGHT;
 import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
@@ -43,6 +44,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.res.Configuration;
+import android.content.res.TypedArray;
 import android.graphics.Insets;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -52,6 +54,7 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
+import android.util.RotationUtils;
 import android.view.Display;
 import android.view.DisplayCutout;
 import android.view.View;
@@ -60,7 +63,6 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.R.dimen;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.events.PrivacyDotViewController;
@@ -100,6 +102,8 @@
     private UserTracker mUserTracker;
     @Mock
     private PrivacyDotViewController mDotViewController;
+    @Mock
+    private TypedArray mMockTypedArray;
 
     @Before
     public void setup() {
@@ -121,6 +125,7 @@
                 .getDisplay(DEFAULT_DISPLAY);
         when(mDisplayManager.getDisplay(anyInt())).thenReturn(display);
         mContext.addMockSystemService(DisplayManager.class, mDisplayManager);
+        when(mMockTypedArray.length()).thenReturn(0);
 
         mScreenDecorations = spy(new ScreenDecorations(mContext, mExecutor, mSecureSettings,
                 mBroadcastDispatcher, mTunerService, mUserTracker, mDotViewController,
@@ -148,18 +153,9 @@
 
     @Test
     public void testNoRounding_NoCutout() {
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, 0);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_top, 0);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_bottom, 0);
-        mContext.getOrCreateTestableResources()
-                .addOverride(dimen.rounded_corner_content_padding, 0);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, false);
+        setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
+                0 /* roundedPadding */, false /* multipleRadius */,
+                false /* fillCutout */);
 
         // no cutout
         doReturn(null).when(mScreenDecorations).getCutout();
@@ -173,14 +169,9 @@
 
     @Test
     public void testRounding_NoCutout() {
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, 20);
-        mContext.getOrCreateTestableResources()
-                .addOverride(dimen.rounded_corner_content_padding, 20);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, false);
+        setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
+                20 /* roundedPadding */, false /* multipleRadius */,
+                false /* fillCutout */);
 
         // no cutout
         doReturn(null).when(mScreenDecorations).getCutout();
@@ -203,19 +194,10 @@
 
     @Test
     public void testRoundingRadius_NoCutout() {
-        final int testRadius = 1;
         final Point testRadiusPoint = new Point(1, 1);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, testRadius);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_top, testRadius);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_bottom, testRadius);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, false);
-
+        setupResources(1 /* radius */, 1 /* radiusTop */, 1 /* radiusBottom */,
+                0 /* roundedPadding */, false /* multipleRadius */,
+                false /* fillCutout */);
         // no cutout
         doReturn(null).when(mScreenDecorations).getCutout();
 
@@ -230,16 +212,8 @@
     public void testRoundingTopBottomRadius_OnTopBottomOverlay() {
         final int testTopRadius = 1;
         final int testBottomRadius = 5;
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, testTopRadius);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_top, testTopRadius);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_bottom, testBottomRadius);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, false);
+        setupResources(testTopRadius, testTopRadius, testBottomRadius, 0 /* roundedPadding */,
+                false /* multipleRadius */, false /* fillCutout */);
 
         // no cutout
         doReturn(null).when(mScreenDecorations).getCutout();
@@ -267,58 +241,49 @@
     public void testRoundingTopBottomRadius_OnLeftRightOverlay() {
         final int testTopRadius = 1;
         final int testBottomRadius = 5;
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, testTopRadius);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_top, testTopRadius);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_bottom, testBottomRadius);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, false);
+        setupResources(testTopRadius, testTopRadius, testBottomRadius, 0 /* roundedPadding */,
+                false /* multipleRadius */, false /* fillCutout */);
 
         // left cutout
-        doReturn(new DisplayCutout(
-                Insets.of(0, 10, 0, 0),
-                new Rect(0, 200, 1, 210),
-                ZERO_RECT,
-                ZERO_RECT,
-                ZERO_RECT,
-                Insets.NONE)).when(mScreenDecorations).getCutout();
+        final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
+        doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
+                .when(mScreenDecorations).getCutout();
 
         mScreenDecorations.start();
+        final Point topRadius = new Point(testTopRadius, testTopRadius);
+        final Point bottomRadius = new Point(testBottomRadius, testBottomRadius);
         View leftRoundedCorner =
                 mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].findViewById(R.id.left);
+        boolean isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_LEFT, R.id.left);
+        verify(mScreenDecorations, atLeastOnce())
+                .setSize(leftRoundedCorner, isTop ? topRadius : bottomRadius);
+
         View rightRoundedCorner =
                 mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].findViewById(R.id.right);
+        isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_LEFT, R.id.right);
         verify(mScreenDecorations, atLeastOnce())
-                .setSize(leftRoundedCorner, new Point(testTopRadius, testTopRadius));
-        verify(mScreenDecorations, atLeastOnce())
-                .setSize(rightRoundedCorner, new Point(testBottomRadius, testBottomRadius));
+                .setSize(rightRoundedCorner, isTop ? topRadius : bottomRadius);
+
         leftRoundedCorner =
                 mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].findViewById(R.id.left);
+        isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_RIGHT, R.id.left);
+        verify(mScreenDecorations, atLeastOnce())
+                .setSize(leftRoundedCorner, isTop ? topRadius : bottomRadius);
+
         rightRoundedCorner =
                 mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].findViewById(R.id.right);
+        isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_RIGHT, R.id.right);
         verify(mScreenDecorations, atLeastOnce())
-                .setSize(leftRoundedCorner, new Point(testTopRadius, testTopRadius));
-        verify(mScreenDecorations, atLeastOnce())
-                .setSize(rightRoundedCorner, new Point(testBottomRadius, testBottomRadius));
+                .setSize(rightRoundedCorner, isTop ? topRadius : bottomRadius);
     }
 
     @Test
     public void testRoundingMultipleRadius_NoCutout() {
         final VectorDrawable d = (VectorDrawable) mContext.getDrawable(R.drawable.rounded);
         final Point multipleRadiusSize = new Point(d.getIntrinsicWidth(), d.getIntrinsicHeight());
-
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, 9999);
-        mContext.getOrCreateTestableResources()
-                .addOverride(dimen.rounded_corner_content_padding, 9999);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, true);
+        setupResources(9999 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
+                9999 /* roundedPadding */, true /* multipleRadius */,
+                false /* fillCutout */);
 
         // no cutout
         doReturn(null).when(mScreenDecorations).getCutout();
@@ -345,27 +310,14 @@
 
     @Test
     public void testNoRounding_CutoutShortEdge() {
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, true);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, 0);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_top, 0);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_bottom, 0);
-        mContext.getOrCreateTestableResources()
-                .addOverride(dimen.rounded_corner_content_padding, 0);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, false);
+        setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
+                0 /* roundedPadding */, false /* multipleRadius */,
+                true /* fillCutout */);
 
         // top cutout
-        doReturn(new DisplayCutout(
-                        Insets.of(0, 10, 0, 0),
-                        ZERO_RECT,
-                        new Rect(9, 0, 10, 1),
-                        ZERO_RECT,
-                        ZERO_RECT,
-                        Insets.NONE)).when(mScreenDecorations).getCutout();
+        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+                .when(mScreenDecorations).getCutout();
 
         mScreenDecorations.start();
         // Top window is created for top cutout.
@@ -381,27 +333,14 @@
 
     @Test
     public void testNoRounding_CutoutLongEdge() {
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, true);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, 0);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_top, 0);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_bottom, 0);
-        mContext.getOrCreateTestableResources()
-                .addOverride(dimen.rounded_corner_content_padding, 0);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, false);
+        setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
+                0 /* roundedPadding */, false /* multipleRadius */,
+                true /* fillCutout */);
 
         // left cutout
-        doReturn(new DisplayCutout(
-                Insets.of(0, 10, 0, 0),
-                new Rect(0, 200, 1, 210),
-                ZERO_RECT,
-                ZERO_RECT,
-                ZERO_RECT,
-                Insets.NONE)).when(mScreenDecorations).getCutout();
+        final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
+        doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
+                .when(mScreenDecorations).getCutout();
 
         mScreenDecorations.start();
         // Left window is created for left cutout.
@@ -417,29 +356,20 @@
 
     @Test
     public void testRounding_CutoutShortEdge() {
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, true);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, 20);
-        mContext.getOrCreateTestableResources()
-                .addOverride(dimen.rounded_corner_content_padding, 20);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, false);
+        setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
+                20 /* roundedPadding */, false /* multipleRadius */,
+                true /* fillCutout */);
 
         // top cutout
-        doReturn(new DisplayCutout(
-                Insets.of(0, 10, 0, 0),
-                ZERO_RECT,
-                new Rect(9, 0, 10, 1),
-                ZERO_RECT,
-                ZERO_RECT,
-                Insets.NONE)).when(mScreenDecorations).getCutout();
+        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+                .when(mScreenDecorations).getCutout();
 
         mScreenDecorations.start();
-        // Top window is created for rouned corner and top cutout.
+        // Top window is created for rounded corner and top cutout.
         verify(mWindowManager, times(1))
                 .addView(eq(mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP]), any());
-        // Bottom window is created for rouned corner.
+        // Bottom window is created for rounded corner.
         verify(mWindowManager, times(1))
                 .addView(eq(mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM]), any());
         // Left window should be null.
@@ -450,29 +380,20 @@
 
     @Test
     public void testRounding_CutoutLongEdge() {
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, true);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, 20);
-        mContext.getOrCreateTestableResources()
-                .addOverride(dimen.rounded_corner_content_padding, 20);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, false);
+        setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
+                20 /* roundedPadding */, false /* multipleRadius */,
+                true /* fillCutout */);
 
         // left cutout
-        doReturn(new DisplayCutout(
-                Insets.of(0, 10, 0, 0),
-                new Rect(0, 200, 1, 210),
-                ZERO_RECT,
-                ZERO_RECT,
-                ZERO_RECT,
-                Insets.NONE)).when(mScreenDecorations).getCutout();
+        final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
+        doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
+                .when(mScreenDecorations).getCutout();
 
         mScreenDecorations.start();
-        // Left window is created for rouned corner and left cutout.
+        // Left window is created for rounded corner and left cutout.
         verify(mWindowManager, times(1))
                 .addView(eq(mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT]), any());
-        // Right window is created for rouned corner.
+        // Right window is created for rounded corner.
         verify(mWindowManager, times(1))
                 .addView(eq(mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT]), any());
         // Top window should be null.
@@ -483,29 +404,20 @@
 
     @Test
     public void testRounding_CutoutShortAndLongEdge() {
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, true);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, 20);
-        mContext.getOrCreateTestableResources()
-                .addOverride(dimen.rounded_corner_content_padding, 20);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, false);
+        setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
+                20 /* roundedPadding */, false /* multipleRadius */,
+                true /* fillCutout */);
 
         // top and left cutout
-        doReturn(new DisplayCutout(
-                Insets.of(0, 10, 0, 0),
-                new Rect(0, 200, 1, 210),
-                new Rect(9, 0, 10, 1),
-                ZERO_RECT,
-                ZERO_RECT,
-                Insets.NONE)).when(mScreenDecorations).getCutout();
+        final Rect[] bounds = {new Rect(0, 50, 1, 60), new Rect(9, 0, 10, 1), null, null};
+        doReturn(getDisplayCutoutForRotation(Insets.of(1, 1, 0, 0), bounds))
+                .when(mScreenDecorations).getCutout();
 
         mScreenDecorations.start();
-        // Top window is created for rouned corner and top cutout.
+        // Top window is created for rounded corner and top cutout.
         verify(mWindowManager, times(1))
                 .addView(eq(mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP]), any());
-        // Bottom window is created for rouned corner.
+        // Bottom window is created for rounded corner.
         verify(mWindowManager, times(1))
                 .addView(eq(mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM]), any());
         // Left window is created for left cutout.
@@ -517,27 +429,14 @@
 
     @Test
     public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout() {
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, true);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, 0);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_top, 0);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_bottom, 0);
-        mContext.getOrCreateTestableResources()
-                .addOverride(dimen.rounded_corner_content_padding, 0);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, false);
+        setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
+                0 /* roundedPadding */, false /* multipleRadius */,
+                true /* fillCutout */);
 
         // Set to short edge cutout(top).
-        doReturn(new DisplayCutout(
-                Insets.of(0, 10, 0, 0),
-                ZERO_RECT,
-                new Rect(9, 0, 10, 1),
-                ZERO_RECT,
-                ZERO_RECT,
-                Insets.NONE)).when(mScreenDecorations).getCutout();
+        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+                .when(mScreenDecorations).getCutout();
 
         mScreenDecorations.start();
         verify(mWindowManager, times(1))
@@ -547,14 +446,9 @@
         assertNull(mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT]);
 
         // Switch to long edge cutout(left).
-        // left cutout
-        doReturn(new DisplayCutout(
-                Insets.of(0, 10, 0, 0),
-                new Rect(0, 200, 1, 210),
-                ZERO_RECT,
-                ZERO_RECT,
-                ZERO_RECT,
-                Insets.NONE)).when(mScreenDecorations).getCutout();
+        final Rect[] newBounds = {new Rect(0, 50, 1, 60), null, null, null};
+        doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), newBounds))
+                .when(mScreenDecorations).getCutout();
 
         mScreenDecorations.onConfigurationChanged(new Configuration());
         verify(mWindowManager, times(1))
@@ -566,33 +460,21 @@
 
     @Test
     public void testDelayedCutout() {
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, 0);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_top, 0);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_bottom, 0);
-        mContext.getOrCreateTestableResources()
-                .addOverride(dimen.rounded_corner_content_padding, 0);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, false);
+        setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
+                0 /* roundedPadding */, false /* multipleRadius */,
+                false /* fillCutout */);
 
         // top cutout
-        doReturn(new DisplayCutout(
-                Insets.of(0, 10, 0, 0),
-                ZERO_RECT,
-                new Rect(9, 0, 10, 1),
-                ZERO_RECT,
-                ZERO_RECT,
-                Insets.NONE)).when(mScreenDecorations).getCutout();
+        final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
+        doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
+                .when(mScreenDecorations).getCutout();
 
         mScreenDecorations.start();
         assertNull(mScreenDecorations.mOverlays);
 
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, true);
+        when(mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout))
+                .thenReturn(true);
         mScreenDecorations.onConfigurationChanged(new Configuration());
 
         // Only top windows should be added.
@@ -612,34 +494,24 @@
 
     @Test
     public void testUpdateRoundedCorners() {
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, 20);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, false);
+        setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
+                0 /* roundedPadding */, false /* multipleRadius */,
+                false /* fillCutout */);
 
         mScreenDecorations.start();
         assertEquals(mScreenDecorations.mRoundedDefault, new Point(20, 20));
 
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, 5);
+        when(mContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.rounded_corner_radius)).thenReturn(5);
         mScreenDecorations.onConfigurationChanged(null);
         assertEquals(mScreenDecorations.mRoundedDefault, new Point(5, 5));
     }
 
     @Test
     public void testOnlyRoundedCornerRadiusTop() {
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, 0);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_top, 10);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_bottom, 0);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, false);
+        setupResources(0 /* radius */, 10 /* radiusTop */, 0 /* radiusBottom */,
+                0 /* roundedPadding */, false /* multipleRadius */,
+                false /* fillCutout */);
 
         mScreenDecorations.start();
         assertEquals(new Point(0, 0), mScreenDecorations.mRoundedDefault);
@@ -649,16 +521,9 @@
 
     @Test
     public void testOnlyRoundedCornerRadiusBottom() {
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius, 0);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_top, 0);
-        mContext.getOrCreateTestableResources().addOverride(
-                com.android.internal.R.dimen.rounded_corner_radius_bottom, 20);
-        mContext.getOrCreateTestableResources()
-                .addOverride(R.bool.config_roundedCornerMultipleRadius, false);
+        setupResources(0 /* radius */, 0 /* radiusTop */, 20 /* radiusBottom */,
+                0 /* roundedPadding */, false /* multipleRadius */,
+                false /* fillCutout */);
 
         mScreenDecorations.start();
         assertEquals(new Point(0, 0), mScreenDecorations.mRoundedDefault);
@@ -721,4 +586,59 @@
         verify(mTunerService, times(1)).removeTunable(any());
         assertThat(mScreenDecorations.mIsRegistered, is(false));
     }
+
+    private void setupResources(int radius, int radiusTop, int radiusBottom, int roundedPadding,
+            boolean multipleRadius, boolean fillCutout) {
+        mContext.getOrCreateTestableResources().addOverride(
+                com.android.internal.R.array.config_displayUniqueIdArray,
+                new String[]{});
+        mContext.getOrCreateTestableResources().addOverride(
+                com.android.internal.R.array.config_roundedCornerRadiusArray,
+                mMockTypedArray);
+        mContext.getOrCreateTestableResources().addOverride(
+                com.android.internal.R.array.config_roundedCornerTopRadiusArray,
+                mMockTypedArray);
+        mContext.getOrCreateTestableResources().addOverride(
+                com.android.internal.R.array.config_roundedCornerBottomRadiusArray,
+                mMockTypedArray);
+        mContext.getOrCreateTestableResources().addOverride(
+                R.array.config_roundedCornerDrawableArray,
+                mMockTypedArray);
+        mContext.getOrCreateTestableResources().addOverride(
+                R.array.config_roundedCornerTopDrawableArray,
+                mMockTypedArray);
+        mContext.getOrCreateTestableResources().addOverride(
+                R.array.config_roundedCornerBottomDrawableArray,
+                mMockTypedArray);
+        mContext.getOrCreateTestableResources().addOverride(
+                R.array.config_roundedCornerMultipleRadiusArray,
+                mMockTypedArray);
+        mContext.getOrCreateTestableResources().addOverride(
+                com.android.internal.R.dimen.rounded_corner_radius, radius);
+        mContext.getOrCreateTestableResources().addOverride(
+                com.android.internal.R.dimen.rounded_corner_radius_top, radiusTop);
+        mContext.getOrCreateTestableResources().addOverride(
+                com.android.internal.R.dimen.rounded_corner_radius_bottom, radiusBottom);
+        mContext.getOrCreateTestableResources().addOverride(
+                R.dimen.rounded_corner_content_padding, roundedPadding);
+        mContext.getOrCreateTestableResources().addOverride(
+                R.bool.config_roundedCornerMultipleRadius, multipleRadius);
+        mContext.getOrCreateTestableResources().addOverride(
+                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout);
+    }
+
+    private DisplayCutout getDisplayCutoutForRotation(Insets safeInsets, Rect[] cutoutBounds) {
+        final int rotation = mContext.getDisplay().getRotation();
+        final Insets insets = RotationUtils.rotateInsets(safeInsets, rotation);
+        final Rect[] sorted = new Rect[BOUNDS_POSITION_LENGTH];
+        for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
+            final int rotatedPos = ScreenDecorations.getBoundPositionFromRotation(i, rotation);
+            if (cutoutBounds[i] != null) {
+                RotationUtils.rotateBounds(cutoutBounds[i], new Rect(0, 0, 100, 200), rotation);
+            }
+            sorted[rotatedPos] = cutoutBounds[i];
+        }
+        return new DisplayCutout(insets, sorted[BOUNDS_POSITION_LEFT], sorted[BOUNDS_POSITION_TOP],
+                sorted[BOUNDS_POSITION_RIGHT], sorted[BOUNDS_POSITION_BOTTOM]);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java b/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java
index ee52c78..0751475 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java
@@ -56,11 +56,6 @@
         return mParent.createDependency(key);
     }
 
-    @Override
-    protected boolean autoRegisterModulesForDump() {
-        return false;
-    }
-
     public <T> boolean hasInstantiatedDependency(Class<T> key) {
         return mObjs.containsKey(key) || mInstantiatedObjects.contains(key);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
index 2c08fe6..be3e535 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
@@ -384,7 +384,41 @@
         // WHEN status bar expansion is 0 but udfps bouncer is requested
         mAltAuthInterceptor.showAlternateAuthBouncer();
 
-        // THEN alpha is 0
+        // THEN alpha is 255
+        verify(mView).setUnpausedAlpha(255);
+    }
+
+    @Test
+    public void testTransitionToFullShadeProgress() {
+        // GIVEN view is attached and status bar expansion is 1f
+        mController.onViewAttached();
+        captureExpansionListeners();
+        updateStatusBarExpansion(1f, true);
+        reset(mView);
+
+        // WHEN we're transitioning to the full shade
+        float transitionProgress = .6f;
+        mController.setTransitionToFullShadeProgress(transitionProgress);
+
+        // THEN alpha is between 0 and 255
+        verify(mView).setUnpausedAlpha((int) ((1f - transitionProgress) * 255));
+    }
+
+    @Test
+    public void testShowUdfpsBouncer_transitionToFullShadeProgress() {
+        // GIVEN view is attached and status bar expansion is 1f
+        mController.onViewAttached();
+        captureExpansionListeners();
+        captureKeyguardStateControllerCallback();
+        captureAltAuthInterceptor();
+        updateStatusBarExpansion(1f, true);
+        mAltAuthInterceptor.showAlternateAuthBouncer();
+        reset(mView);
+
+        // WHEN we're transitioning to the full shade
+        mController.setTransitionToFullShadeProgress(1.0f);
+
+        // THEN alpha is 255 (b/c udfps bouncer is requested)
         verify(mView).setUnpausedAlpha(255);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
index 65301fe..f514b56 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
@@ -31,6 +31,7 @@
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.time.FakeSystemClock
 import junit.framework.Assert.assertSame
 import org.junit.Before
@@ -54,6 +55,7 @@
     companion object {
         val user0 = UserHandle.of(0)
         val user1 = UserHandle.of(1)
+        const val DEFAULT_FLAG = Context.RECEIVER_EXPORTED
 
         fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
         const val TEST_ACTION = "TEST_ACTION"
@@ -96,6 +98,7 @@
         MockitoAnnotations.initMocks(this)
         testableLooper = TestableLooper.get(this)
         executor = FakeExecutor(FakeSystemClock())
+        `when`(mockContext.mainExecutor).thenReturn(executor)
 
         broadcastDispatcher = TestBroadcastDispatcher(
                 mockContext,
@@ -121,12 +124,12 @@
 
         testableLooper.processAllMessages()
 
-        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor))
+        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG))
 
         assertSame(broadcastReceiver, argumentCaptor.value.receiver)
         assertSame(intentFilter, argumentCaptor.value.filter)
 
-        verify(mockUBRUser1).registerReceiver(capture(argumentCaptor))
+        verify(mockUBRUser1).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG))
         assertSame(broadcastReceiverOther, argumentCaptor.value.receiver)
         assertSame(intentFilterOther, argumentCaptor.value.filter)
     }
@@ -139,17 +142,67 @@
 
         testableLooper.processAllMessages()
 
-        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor))
+        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG))
 
         assertSame(broadcastReceiver, argumentCaptor.value.receiver)
         assertSame(intentFilter, argumentCaptor.value.filter)
 
-        verify(mockUBRUser1).registerReceiver(capture(argumentCaptor))
+        verify(mockUBRUser1).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG))
         assertSame(broadcastReceiverOther, argumentCaptor.value.receiver)
         assertSame(intentFilterOther, argumentCaptor.value.filter)
     }
 
     @Test
+    fun testAddReceiverDefaultFlag_handler() {
+        broadcastDispatcher.registerReceiverWithHandler(
+                broadcastReceiver, intentFilter, mockHandler)
+        testableLooper.processAllMessages()
+
+        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG))
+
+        assertSame(broadcastReceiver, argumentCaptor.value.receiver)
+        assertSame(intentFilter, argumentCaptor.value.filter)
+    }
+
+    @Test
+    fun testAddReceiverCorrectFlag_handler() {
+        val flag = 3
+
+        broadcastDispatcher.registerReceiverWithHandler(
+                broadcastReceiver, intentFilter, mockHandler, flags = flag)
+        testableLooper.processAllMessages()
+
+        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(flag))
+
+        assertSame(broadcastReceiver, argumentCaptor.value.receiver)
+        assertSame(intentFilter, argumentCaptor.value.filter)
+    }
+
+    @Test
+    fun testAddReceiverDefaultFlag_executor() {
+        broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter)
+        testableLooper.processAllMessages()
+
+        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG))
+
+        assertSame(broadcastReceiver, argumentCaptor.value.receiver)
+        assertSame(intentFilter, argumentCaptor.value.filter)
+    }
+
+    @Test
+    fun testAddReceiverCorrectFlag_executor() {
+        val flag = 3
+
+        broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, flags = flag)
+        testableLooper.processAllMessages()
+
+        verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(flag))
+
+        assertSame(broadcastReceiver, argumentCaptor.value.receiver)
+        assertSame(intentFilter, argumentCaptor.value.filter)
+    }
+
+    @Test
     fun testRemovingReceiversRemovesFromAllUBR() {
         broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter,
                 mockHandler, user0)
@@ -188,7 +241,8 @@
 
         testableLooper.processAllMessages()
 
-        verify(mockUBRUser1).registerReceiver(capture(argumentCaptor))
+        verify(mockUBRUser1).registerReceiver(
+                capture(argumentCaptor), eq(Context.RECEIVER_EXPORTED))
         assertSame(broadcastReceiver, argumentCaptor.value.receiver)
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
index 1a78ca4..fd1c41e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
@@ -44,7 +44,8 @@
         receiver: BroadcastReceiver,
         filter: IntentFilter,
         handler: Handler,
-        user: UserHandle
+        user: UserHandle,
+        flags: Int
     ) {
         registeredReceivers.add(receiver)
     }
@@ -53,7 +54,8 @@
         receiver: BroadcastReceiver,
         filter: IntentFilter,
         executor: Executor?,
-        user: UserHandle?
+        user: UserHandle?,
+        flags: Int
     ) {
         registeredReceivers.add(receiver)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
index dfe1432..4e3345c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
@@ -30,6 +30,7 @@
 import com.android.systemui.util.time.FakeSystemClock
 import junit.framework.Assert.assertFalse
 import junit.framework.Assert.assertNotNull
+import junit.framework.Assert.assertNotSame
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -37,6 +38,7 @@
 import org.mockito.Mock
 import org.mockito.Mockito
 import org.mockito.Mockito.mock
+import org.mockito.Mockito.nullable
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 import java.util.concurrent.Executor
@@ -50,6 +52,7 @@
         private const val ACTION_1 = "com.android.systemui.tests.ACTION_1"
         private const val ACTION_2 = "com.android.systemui.tests.ACTION_2"
         private const val USER_ID = 0
+        private const val FLAG = 3
         private val USER_HANDLE = UserHandle.of(USER_ID)
 
         fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
@@ -82,7 +85,7 @@
 
         userBroadcastDispatcher = object : UserBroadcastDispatcher(
                 mockContext, USER_ID, testableLooper.looper, mock(Executor::class.java), logger) {
-            override fun createActionReceiver(action: String): ActionReceiver {
+            override fun createActionReceiver(action: String, flags: Int): ActionReceiver {
                 return mock(ActionReceiver::class.java)
             }
         }
@@ -93,23 +96,41 @@
         intentFilter = IntentFilter(ACTION_1)
         val receiverData = ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE)
 
-        userBroadcastDispatcher.registerReceiver(receiverData)
+        userBroadcastDispatcher.registerReceiver(receiverData, FLAG)
         testableLooper.processAllMessages()
 
-        val actionReceiver = userBroadcastDispatcher.getActionReceiver(ACTION_1)
+        val actionReceiver = userBroadcastDispatcher.getActionReceiver(ACTION_1, FLAG)
         assertNotNull(actionReceiver)
         verify(actionReceiver)?.addReceiverData(receiverData)
     }
 
     @Test
+    fun testDifferentActionReceiversForDifferentFlags() {
+        intentFilter = IntentFilter(ACTION_1)
+        val receiverData = ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE)
+
+        val flag1 = 0
+        val flag2 = 1
+
+        userBroadcastDispatcher.registerReceiver(receiverData, flag1)
+        userBroadcastDispatcher.registerReceiver(receiverData, flag2)
+        testableLooper.processAllMessages()
+
+        assertNotSame(
+                userBroadcastDispatcher.getActionReceiver(ACTION_1, flag1),
+                userBroadcastDispatcher.getActionReceiver(ACTION_1, flag2)
+        )
+    }
+
+    @Test
     fun testSingleReceiverRegistered_logging() {
         intentFilter = IntentFilter(ACTION_1)
 
         userBroadcastDispatcher.registerReceiver(
-                ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE))
+                ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE), FLAG)
         testableLooper.processAllMessages()
 
-        verify(logger).logReceiverRegistered(USER_HANDLE.identifier, broadcastReceiver)
+        verify(logger).logReceiverRegistered(USER_HANDLE.identifier, broadcastReceiver, FLAG)
     }
 
     @Test
@@ -117,13 +138,13 @@
         intentFilter = IntentFilter(ACTION_1)
 
         userBroadcastDispatcher.registerReceiver(
-                ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE))
+                ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE), FLAG)
         testableLooper.processAllMessages()
 
         userBroadcastDispatcher.unregisterReceiver(broadcastReceiver)
         testableLooper.processAllMessages()
 
-        val actionReceiver = userBroadcastDispatcher.getActionReceiver(ACTION_1)
+        val actionReceiver = userBroadcastDispatcher.getActionReceiver(ACTION_1, FLAG)
         assertNotNull(actionReceiver)
         verify(actionReceiver)?.removeReceiver(broadcastReceiver)
     }
@@ -133,7 +154,7 @@
         intentFilter = IntentFilter(ACTION_1)
 
         userBroadcastDispatcher.registerReceiver(
-                ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE))
+                ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE), FLAG)
         testableLooper.processAllMessages()
 
         userBroadcastDispatcher.unregisterReceiver(broadcastReceiver)
@@ -146,12 +167,18 @@
     fun testRemoveReceiverReferences() {
         intentFilter = IntentFilter(ACTION_1)
         userBroadcastDispatcher.registerReceiver(
-                ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE))
+                ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE), FLAG)
 
         intentFilterOther = IntentFilter(ACTION_1)
         intentFilterOther.addAction(ACTION_2)
         userBroadcastDispatcher.registerReceiver(
-                ReceiverData(broadcastReceiverOther, intentFilterOther, fakeExecutor, USER_HANDLE))
+                ReceiverData(
+                        broadcastReceiverOther,
+                        intentFilterOther,
+                        fakeExecutor,
+                        USER_HANDLE
+                ), FLAG
+        )
 
         userBroadcastDispatcher.unregisterReceiver(broadcastReceiver)
         testableLooper.processAllMessages()
@@ -160,7 +187,34 @@
         assertFalse(userBroadcastDispatcher.isReceiverReferenceHeld(broadcastReceiver))
     }
 
-    private fun UserBroadcastDispatcher.getActionReceiver(action: String): ActionReceiver? {
-        return actionsToActionsReceivers.get(action)
+    @Test
+    fun testCreateActionReceiver_registerWithFlag() {
+        val uBR = UserBroadcastDispatcher(
+                mockContext,
+                USER_ID,
+                testableLooper.looper,
+                fakeExecutor,
+                logger
+        )
+        uBR.registerReceiver(
+                ReceiverData(
+                        broadcastReceiver,
+                        IntentFilter(ACTION_1),
+                        fakeExecutor,
+                        USER_HANDLE
+                ),
+                FLAG
+        )
+
+        testableLooper.processAllMessages()
+        fakeExecutor.runAllReady()
+
+        verify(mockContext).registerReceiverAsUser(
+                any(), any(), any(), nullable(String::class.java), any(), eq(FLAG))
+    }
+
+    private fun UserBroadcastDispatcher
+            .getActionReceiver(action: String, flags: Int): ActionReceiver? {
+        return actionsToActionsReceivers.get(action to flags)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
index 41747f4..15e5e1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
@@ -35,6 +35,7 @@
 import com.android.internal.colorextraction.ColorExtractor;
 import com.android.internal.colorextraction.types.Tonal;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 
 import org.junit.Before;
@@ -60,6 +61,8 @@
 
     @Mock
     private WallpaperManager mWallpaperManager;
+    @Mock
+    private DumpManager mDumpManager;
     private ColorExtractor.GradientColors mColors;
     private SysuiColorExtractor mColorExtractor;
 
@@ -69,13 +72,18 @@
         mColors = new ColorExtractor.GradientColors();
         mColors.setMainColor(Color.RED);
         mColors.setSecondaryColor(Color.RED);
-        mColorExtractor = new SysuiColorExtractor(getContext(),
+        mColorExtractor = new SysuiColorExtractor(
+                getContext(),
                 (inWallpaperColors, outGradientColorsNormal, outGradientColorsDark,
                         outGradientColorsExtraDark) -> {
                     outGradientColorsNormal.set(mColors);
                     outGradientColorsDark.set(mColors);
                     outGradientColorsExtraDark.set(mColors);
-                }, mock(ConfigurationController.class), mWallpaperManager, true /* immediately */);
+                },
+                mock(ConfigurationController.class),
+                mWallpaperManager,
+                mDumpManager,
+                true /* immediately */);
     }
 
     @Test
@@ -111,8 +119,13 @@
     public void onUiModeChanged_reloadsColors() {
         Tonal tonal = mock(Tonal.class);
         ConfigurationController configurationController = mock(ConfigurationController.class);
-        SysuiColorExtractor sysuiColorExtractor = new SysuiColorExtractor(getContext(),
-                tonal, configurationController, mWallpaperManager, true /* immediately */);
+        SysuiColorExtractor sysuiColorExtractor = new SysuiColorExtractor(
+                getContext(),
+                tonal,
+                configurationController,
+                mWallpaperManager,
+                mDumpManager,
+                true /* immediately */);
         verify(configurationController).addCallback(eq(sysuiColorExtractor));
 
         reset(tonal);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/service/CommunalSourcePrimerTest.java b/packages/SystemUI/tests/src/com/android/systemui/communal/service/CommunalSourcePrimerTest.java
deleted file mode 100644
index 95ab5cb..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/service/CommunalSourcePrimerTest.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.communal.service;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.ServiceConnection;
-import android.content.res.Resources;
-import android.os.IBinder;
-import android.testing.AndroidTestingRunner;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.communal.CommunalSourceMonitor;
-import com.android.systemui.shared.communal.ICommunalSource;
-import com.android.systemui.util.concurrency.FakeExecutor;
-import com.android.systemui.util.time.FakeSystemClock;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.concurrent.Executor;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-public class CommunalSourcePrimerTest extends SysuiTestCase {
-    private static final String TEST_COMPONENT_NAME = "com.google.tests/.CommualService";
-    private static final ComponentName TEST_COMPONENT =
-            ComponentName.unflattenFromString(TEST_COMPONENT_NAME);
-    private static final int MAX_RETRIES = 5;
-    private static final int RETRY_DELAY_MS = 1000;
-
-    @Mock
-    private Context mContext;
-
-    @Mock
-    private Resources mResources;
-
-    private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
-
-    @Mock
-    private CommunalSourceMonitor mCommunalSourceMonitor;
-
-    @Mock
-    private CommunalSourceImpl.Factory mCommunalSourceFactory;
-
-    @Mock
-    private CommunalSourceImpl mCommunalSourceImpl;
-
-    @Mock
-    private IBinder mServiceProxy;
-
-    private CommunalSourcePrimer mPrimer;
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        when(mResources.getInteger(R.integer.config_communalSourceMaxReconnectAttempts))
-                .thenReturn(MAX_RETRIES);
-        when(mResources.getInteger(R.integer.config_communalSourceReconnectBaseDelay))
-                .thenReturn(RETRY_DELAY_MS);
-        when(mResources.getString(R.string.config_communalSourceComponent))
-                .thenReturn(TEST_COMPONENT_NAME);
-        when(mCommunalSourceFactory.create(any(ICommunalSource.class)))
-                .thenReturn(mCommunalSourceImpl);
-
-        mPrimer = new CommunalSourcePrimer(mContext, mResources, mFakeExecutor,
-                mCommunalSourceMonitor, mCommunalSourceFactory);
-    }
-
-    @Test
-    public void testNoConnectWithEmptyComponent() {
-        when(mResources.getString(R.string.config_communalSourceComponent)).thenReturn(null);
-        final CommunalSourcePrimer emptyComponentPrimer = new CommunalSourcePrimer(mContext,
-                mResources, mFakeExecutor, mCommunalSourceMonitor, mCommunalSourceFactory);
-
-        emptyComponentPrimer.onBootCompleted();
-        mFakeExecutor.runAllReady();
-        // When there is no component, we should not register any broadcast receives or bind to
-        // any service
-        verify(mContext, times(0))
-                .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
-        verify(mContext, times(0)).bindService(any(Intent.class), anyInt(),
-                any(Executor.class), any(ServiceConnection.class));
-    }
-
-    private ServiceConnection givenOnBootCompleted(boolean bindSucceed) {
-        ArgumentCaptor<ServiceConnection> connectionCapture =
-                ArgumentCaptor.forClass(ServiceConnection.class);
-
-        when(mContext.bindService(any(Intent.class), anyInt(), any(Executor.class),
-                any(ServiceConnection.class))).thenReturn(bindSucceed);
-
-        mPrimer.onBootCompleted();
-        mFakeExecutor.runAllReady();
-
-        verify(mContext).bindService(any(Intent.class), anyInt(), any(Executor.class),
-                connectionCapture.capture());
-
-        // Simulate successful connection.
-        return connectionCapture.getValue();
-    }
-
-    @Test
-    public void testConnect() {
-        final ServiceConnection connection = givenOnBootCompleted(true);
-
-        // Simulate successful connection.
-        connection.onServiceConnected(TEST_COMPONENT, mServiceProxy);
-
-        // Verify source created and monitor informed.
-        verify(mCommunalSourceFactory).create(any(ICommunalSource.class));
-        verify(mCommunalSourceMonitor).setSource(mCommunalSourceImpl);
-    }
-
-    @Test
-    public void testRetryOnBindFailure() {
-        // Fail to bind on connection.
-        givenOnBootCompleted(false);
-
-        // Verify attempts happen. Note that we account for the retries plus initial attempt, which
-        // is not scheduled.
-        for (int attemptCount = 0; attemptCount < MAX_RETRIES + 1; attemptCount++) {
-            verify(mContext, times(1)).bindService(any(Intent.class),
-                    anyInt(), any(Executor.class), any(ServiceConnection.class));
-            clearInvocations(mContext);
-            mFakeExecutor.advanceClockToNext();
-            mFakeExecutor.runAllReady();
-        }
-
-        // Verify no more attempts occur.
-        verify(mContext, times(0)).bindService(any(Intent.class), anyInt(),
-                any(Executor.class), any(ServiceConnection.class));
-
-        // Verify source is not created and monitor is not informed.
-        verify(mCommunalSourceFactory, times(0))
-                .create(any(ICommunalSource.class));
-        verify(mCommunalSourceMonitor, times(0))
-                .setSource(any(CommunalSourceImpl.class));
-    }
-
-    @Test
-    public void testAttemptOnPackageChange() {
-        ArgumentCaptor<BroadcastReceiver> receiverCapture =
-                ArgumentCaptor.forClass(BroadcastReceiver.class);
-
-        // Fail to bind initially.
-        givenOnBootCompleted(false);
-
-        // Capture broadcast receiver.
-        verify(mContext).registerReceiver(receiverCapture.capture(), any(IntentFilter.class));
-
-        clearInvocations(mContext);
-
-        // Inform package has been added.
-        receiverCapture.getValue().onReceive(mContext, new Intent());
-
-        // Verify bind has been attempted.
-        verify(mContext, times(1)).bindService(any(Intent.class), anyInt(),
-                any(Executor.class), any(ServiceConnection.class));
-    }
-
-    @Test
-    public void testRetryOnServiceDisconnected() {
-        verifyConnectionFailureReconnect(v -> v.onServiceDisconnected(TEST_COMPONENT));
-    }
-
-    @Test
-    public void testRetryOnBindingDied() {
-        verifyConnectionFailureReconnect(v -> v.onBindingDied(TEST_COMPONENT));
-    }
-
-    private void verifyConnectionFailureReconnect(ConnectionHandler connectionHandler) {
-        // Fail to bind on connection.
-        final ServiceConnection connection = givenOnBootCompleted(false);
-
-        clearInvocations(mContext, mCommunalSourceMonitor);
-
-        connectionHandler.onConnectionMade(connection);
-
-        // Ensure source is cleared.
-        verify(mCommunalSourceMonitor).setSource(null);
-
-        // Ensure request made to bind. This is not a reattempt so it should happen in the same
-        // execution loop.
-        verify(mContext).bindService(any(Intent.class), anyInt(), any(Executor.class),
-                any(ServiceConnection.class));
-    }
-
-    interface ConnectionHandler {
-        void onConnectionMade(ServiceConnection connection);
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/service/CommunalSurfaceViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/communal/service/CommunalSurfaceViewControllerTest.java
deleted file mode 100644
index cf2e029..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/service/CommunalSurfaceViewControllerTest.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.communal.service;
-
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.res.Resources;
-import android.graphics.PixelFormat;
-import android.graphics.Region;
-import android.os.IBinder;
-import android.view.Display;
-import android.view.SurfaceControlViewHost;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.View;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.communal.CommunalStateController;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.util.concurrency.FakeExecutor;
-import com.android.systemui.util.time.FakeSystemClock;
-
-import com.google.common.util.concurrent.SettableFuture;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-public class CommunalSurfaceViewControllerTest extends SysuiTestCase {
-    private static final int MEASURED_HEIGHT = 200;
-    private static final int MEASURED_WIDTH = 500;
-    private static final int DISPLAY_ID = 3;
-    private static final int SPLIT_NOTIFICATION_STATUS_BAR_HEIGHT = 23;
-    private static final int NOTIFICATION_PANEL_MARGIN_TOP = 20;
-    private static final int KEYGUARD_INDICATION_BOTTOM_PADDING = 15;
-
-    @Mock
-    private Display mDisplay;
-
-    @Mock
-    private IBinder mHostToken;
-
-    @Mock
-    private SurfaceView mSurfaceView;
-
-    @Mock
-    private SurfaceHolder mSurfaceHolder;
-
-    @Mock
-    private CommunalSourceImpl mCommunalSource;
-
-    @Mock
-    private SurfaceControlViewHost.SurfacePackage mSurfacePackage;
-
-    @Mock
-    private CommunalStateController mCommunalStateController;
-
-    @Mock
-    private Resources mResources;
-
-    @Mock
-    private NotificationShadeWindowController mNotificationShadeWindowController;
-
-    @Mock
-    private IBinder mWindowToken;
-
-    private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
-
-    private SurfaceHolder.Callback mCallback;
-
-    private CommunalSurfaceViewController mController;
-
-    private SettableFuture<SurfaceControlViewHost.SurfacePackage> mPackageFuture;
-
-    private View.OnLayoutChangeListener mLayoutChangeListener;
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        when(mSurfaceView.getHolder()).thenReturn(mSurfaceHolder);
-        when(mSurfaceView.getDisplay()).thenReturn(mDisplay);
-        when(mDisplay.getDisplayId()).thenReturn(DISPLAY_ID);
-        when(mSurfaceView.getHostToken()).thenReturn(mHostToken);
-        when(mSurfaceView.getWindowToken()).thenReturn(mWindowToken);
-        when(mSurfaceView.getMeasuredWidth()).thenReturn(MEASURED_WIDTH);
-        when(mSurfaceView.getMeasuredHeight()).thenReturn(MEASURED_HEIGHT);
-        when(mSurfaceView.isAttachedToWindow()).thenReturn(false);
-        when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true);
-        when(mResources.getDimensionPixelSize(R.dimen.split_shade_header_height))
-                .thenReturn(SPLIT_NOTIFICATION_STATUS_BAR_HEIGHT);
-        when(mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_top))
-                .thenReturn(NOTIFICATION_PANEL_MARGIN_TOP);
-        when(mResources.getDimensionPixelSize(R.dimen.keyguard_indication_bottom_padding))
-                .thenReturn(KEYGUARD_INDICATION_BOTTOM_PADDING);
-        mController = new CommunalSurfaceViewController(mSurfaceView, mResources, mFakeExecutor,
-                mCommunalStateController, mNotificationShadeWindowController, mCommunalSource);
-        mController.init();
-
-        final ArgumentCaptor<SurfaceHolder.Callback> callbackCapture =
-                ArgumentCaptor.forClass(SurfaceHolder.Callback.class);
-        verify(mSurfaceHolder).addCallback(callbackCapture.capture());
-        verify(mSurfaceHolder).setFormat(PixelFormat.TRANSPARENT);
-        mCallback = callbackCapture.getValue();
-
-        final ArgumentCaptor<View.OnLayoutChangeListener> listenerCapture =
-                ArgumentCaptor.forClass(View.OnLayoutChangeListener.class);
-        verify(mSurfaceView).addOnLayoutChangeListener(listenerCapture.capture());
-        mLayoutChangeListener = listenerCapture.getValue();
-
-        mPackageFuture = SettableFuture.create();
-
-        when(mCommunalSource.requestCommunalSurface(any()))
-                .thenReturn(mPackageFuture);
-    }
-
-    @Test
-    public void testSetSurfacePackage() {
-        // There should be no requests without the proper state.
-        verify(mCommunalSource, times(0))
-                .requestCommunalSurface(any());
-
-        // The full state must be present to make a request.
-        mController.onViewAttached();
-        verify(mCommunalSource, times(0))
-                .requestCommunalSurface(any());
-
-        clearInvocations(mSurfaceView);
-
-        // Request surface view once all conditions are met.
-        mCallback.surfaceCreated(mSurfaceHolder);
-        final CommunalSourceImpl.Request expectedRequest = new CommunalSourceImpl.Request(
-                MEASURED_WIDTH, MEASURED_HEIGHT, DISPLAY_ID, mHostToken);
-        verify(mCommunalSource).requestCommunalSurface(eq(expectedRequest));
-
-        when(mSurfaceView.isAttachedToWindow()).thenReturn(true);
-
-        // Respond to request.
-        mPackageFuture.set(mSurfacePackage);
-        mFakeExecutor.runAllReady();
-
-
-        // Make sure SurfaceView is set.
-        verify(mSurfaceView).setChildSurfacePackage(mSurfacePackage);
-        verify(mSurfaceView).setWillNotDraw(false);
-    }
-
-    @Test
-    public void testCommunalStateControllerShowNotified() {
-        // Move CommunalSurfaceView to show
-        mController.onViewAttached();
-        mCallback.surfaceCreated(mSurfaceHolder);
-        when(mSurfaceView.isAttachedToWindow()).thenReturn(true);
-        mPackageFuture.set(mSurfacePackage);
-        mFakeExecutor.runAllReady();
-
-        // Ensure state controller is informed that the communal view is showing.
-        verify(mCommunalStateController).setCommunalViewShowing(true);
-    }
-
-    // Invoked to setup surface view package.
-    private void givenSurfacePresent() {
-        mController.onViewAttached();
-        mCallback.surfaceCreated(mSurfaceHolder);
-        when(mSurfaceView.isAttachedToWindow()).thenReturn(true);
-        mPackageFuture.set(mSurfacePackage);
-        mFakeExecutor.runAllReady();
-        clearInvocations(mSurfaceView);
-    }
-
-    @Test
-    public void testClearOnDetach() {
-        givenSurfacePresent();
-        when(mSurfaceView.isAttachedToWindow()).thenReturn(false);
-        mController.onViewDetached();
-        verify(mSurfaceView).setWillNotDraw(true);
-    }
-
-    @Test
-    public void testClearOnSurfaceDestroyed() {
-        givenSurfacePresent();
-        mCallback.surfaceDestroyed(mSurfaceHolder);
-        verify(mSurfaceView).setWillNotDraw(true);
-    }
-
-    @Test
-    public void testCancelRequest() {
-        mController.onViewAttached();
-        mCallback.surfaceCreated(mSurfaceHolder);
-        when(mSurfaceView.isAttachedToWindow()).thenReturn(true);
-        mFakeExecutor.runAllReady();
-        clearInvocations(mSurfaceView);
-
-        final CommunalSourceImpl.Request expectedRequest = new CommunalSourceImpl.Request(
-                MEASURED_WIDTH, MEASURED_HEIGHT, DISPLAY_ID, mHostToken);
-        verify(mCommunalSource, times(1)).requestCommunalSurface(eq(expectedRequest));
-
-        mController.onViewDetached();
-        assertTrue(mPackageFuture.isCancelled());
-        verify(mSurfaceView).setWillNotDraw(true);
-    }
-
-    @Test
-    public void testTapExclusion() {
-        final int left = 0;
-        final int top = 0;
-        final int right = 200;
-        final int bottom = 100;
-        final Region splitNotificationExclusionRegion = new Region(
-                left,
-                top + SPLIT_NOTIFICATION_STATUS_BAR_HEIGHT,
-                right,
-                bottom - KEYGUARD_INDICATION_BOTTOM_PADDING);
-
-        final Region notificationExclusionRegion = new Region(
-                left,
-                top + NOTIFICATION_PANEL_MARGIN_TOP,
-                right,
-                bottom - KEYGUARD_INDICATION_BOTTOM_PADDING);
-
-        // There should be no exclusion when communal isn't present.
-        mLayoutChangeListener.onLayoutChange(mSurfaceView, left, top, right, bottom, 0, 0, 0, 0);
-        verify(mNotificationShadeWindowController)
-                .setTouchExclusionRegion(eq(new Region()));
-
-
-        // Attach view
-        mController.onViewAttached();
-        clearInvocations(mNotificationShadeWindowController);
-        // Verify tap exclusion area matches proper dimensions.
-        mLayoutChangeListener.onLayoutChange(mSurfaceView, left, top, right, bottom, 0, 0, 0, 0);
-        verify(mNotificationShadeWindowController)
-                .setTouchExclusionRegion(eq(splitNotificationExclusionRegion));
-
-        // Switch to normal notification margin, verify padding changes.
-        clearInvocations(mNotificationShadeWindowController);
-        when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(false);
-        mLayoutChangeListener.onLayoutChange(mSurfaceView, left, top, right, bottom, 0, 0, 0, 0);
-        verify(mNotificationShadeWindowController)
-                .setTouchExclusionRegion(eq(notificationExclusionRegion));
-
-        // Occlude, verify no exclude region.
-        clearInvocations(mNotificationShadeWindowController);
-        when(mCommunalStateController.getCommunalViewOccluded()).thenReturn(true);
-        mLayoutChangeListener.onLayoutChange(mSurfaceView, left, top, right, bottom, 0, 0, 0, 0);
-        verify(mNotificationShadeWindowController)
-                .setTouchExclusionRegion(eq(new Region()));
-    }
-
-    @Test
-    public void testLayoutChange() {
-        final int left = 0;
-        final int top = 0;
-        final int right = 200;
-        final int bottom = 100;
-
-        givenSurfacePresent();
-
-        // Layout change should trigger a request to get new communal surface.
-        mLayoutChangeListener.onLayoutChange(mSurfaceView, left, top, right, bottom, 0, 0, 0,
-                0);
-        // Note that the measured are preset and different than the layout input.
-        final CommunalSourceImpl.Request expectedRequest =
-                new CommunalSourceImpl.Request(MEASURED_WIDTH, MEASURED_HEIGHT, DISPLAY_ID,
-                        mHostToken);
-        verify(mCommunalSource)
-                .requestCommunalSurface(eq(expectedRequest));
-
-        clearInvocations(mCommunalSource);
-
-        // Subsequent matching layout change should not trigger any request.
-        mLayoutChangeListener.onLayoutChange(mSurfaceView, left, top, right, bottom, 0, 0, 0,
-                0);
-        verify(mCommunalSource, never()).requestCommunalSurface(any());
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
index a80fbbe..cff6b9a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
@@ -53,6 +53,7 @@
 import org.mockito.Captor
 import org.mockito.Mock
 import org.mockito.Mockito
+import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.`when`
 import org.mockito.Mockito.inOrder
 import org.mockito.Mockito.mock
@@ -167,7 +168,7 @@
         controller.auxiliaryPersistenceWrapper = auxiliaryPersistenceWrapper
 
         verify(broadcastDispatcher).registerReceiver(
-                capture(broadcastReceiverCaptor), any(), any(), eq(UserHandle.ALL))
+                capture(broadcastReceiverCaptor), any(), any(), eq(UserHandle.ALL), anyInt())
 
         verify(listingController).addCallback(capture(listingCallbackCaptor))
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt
index eb38073..5dea5a1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt
@@ -32,6 +32,7 @@
 import org.mockito.ArgumentCaptor
 import org.mockito.Captor
 import org.mockito.Mock
+import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.never
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
@@ -66,7 +67,8 @@
                         capture(receiverCaptor),
                         any(IntentFilter::class.java),
                         eq(executor),
-                        any(UserHandle::class.java))
+                        any(UserHandle::class.java),
+                        anyInt())
         receiver = receiverCaptor.value
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ScreenLifecycleTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ScreenLifecycleTest.java
index 06e597e..2d1b258 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ScreenLifecycleTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ScreenLifecycleTest.java
@@ -26,6 +26,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -43,7 +44,7 @@
 
     @Before
     public void setUp() throws Exception {
-        mScreen = new ScreenLifecycle();
+        mScreen = new ScreenLifecycle(mock(DumpManager.class));
         mScreenObserverMock = mock(ScreenLifecycle.Observer.class);
         mScreen.addObserver(mScreenObserverMock);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
index 910b381..e453ff2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
@@ -29,6 +29,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -49,7 +50,8 @@
     @Before
     public void setUp() throws Exception {
         mWallpaperManager = mock(IWallpaperManager.class);
-        mWakefulness = new WakefulnessLifecycle(mContext, mWallpaperManager);
+        mWakefulness =
+                new WakefulnessLifecycle(mContext, mWallpaperManager, mock(DumpManager.class));
         mWakefulnessObserver = mock(WakefulnessLifecycle.Observer.class);
         mWakefulness.addObserver(mWakefulnessObserver);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
index b129fdd..42629f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
@@ -37,6 +37,7 @@
 import androidx.constraintlayout.widget.ConstraintSet
 import androidx.lifecycle.LiveData
 import androidx.test.filters.SmallTest
+import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.media.dialog.MediaOutputDialogFactory
 import com.android.systemui.plugins.ActivityStarter
@@ -101,7 +102,6 @@
     private lateinit var seamless: ViewGroup
     private lateinit var seamlessIcon: ImageView
     private lateinit var seamlessText: TextView
-    private lateinit var seamlessFallback: ImageView
     private lateinit var seekBar: SeekBar
     private lateinit var elapsedTimeView: TextView
     private lateinit var totalTimeView: TextView
@@ -154,8 +154,6 @@
         whenever(holder.seamlessIcon).thenReturn(seamlessIcon)
         seamlessText = TextView(context)
         whenever(holder.seamlessText).thenReturn(seamlessText)
-        seamlessFallback = ImageView(context)
-        whenever(holder.seamlessFallback).thenReturn(seamlessFallback)
         seekBar = SeekBar(context)
         whenever(holder.seekBar).thenReturn(seekBar)
         elapsedTimeView = TextView(context)
@@ -239,21 +237,19 @@
     @Test
     fun bindDisabledDevice() {
         seamless.id = 1
-        seamlessFallback.id = 2
+        val fallbackString = context.getString(R.string.media_seamless_other_device)
         player.attachPlayer(holder)
         val state = MediaData(USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
                 emptyList(), PACKAGE, session.getSessionToken(), null, disabledDevice, true, null)
         player.bindPlayer(state, PACKAGE)
-        verify(expandedSet).setVisibility(seamless.id, View.GONE)
-        verify(expandedSet).setVisibility(seamlessFallback.id, View.VISIBLE)
-        verify(collapsedSet).setVisibility(seamless.id, View.GONE)
-        verify(collapsedSet).setVisibility(seamlessFallback.id, View.VISIBLE)
+        assertThat(seamless.isEnabled()).isFalse()
+        assertThat(seamlessText.getText()).isEqualTo(fallbackString)
+        assertThat(seamless.contentDescription).isEqualTo(fallbackString)
     }
 
     @Test
     fun bindNullDevice() {
-        val fallbackString = context.getResources().getString(
-                com.android.internal.R.string.ext_media_seamless_action)
+        val fallbackString = context.getResources().getString(R.string.media_seamless_other_device)
         player.attachPlayer(holder)
         val state = MediaData(USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
                 emptyList(), PACKAGE, session.getSessionToken(), null, null, true, null)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
index ba6dfd3..5c3108c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
@@ -163,7 +163,7 @@
     }
 
     @Test
-    fun testSetTimedOut_deactivatesMedia() {
+    fun testSetTimedOut_active_deactivatesMedia() {
         val data = MediaData(userId = USER_ID, initialized = true, backgroundColor = 0, app = null,
                 appIcon = null, artist = null, song = null, artwork = null, actions = emptyList(),
                 actionsToShowInCompact = emptyList(), packageName = "INVALID", token = null,
@@ -176,6 +176,25 @@
     }
 
     @Test
+    fun testSetTimedOut_resume_dismissesMedia() {
+        // WHEN resume controls are present, and time out
+        val desc = MediaDescription.Builder().run {
+            setTitle(SESSION_TITLE)
+            build()
+        }
+        mediaDataManager.addResumptionControls(USER_ID, desc, Runnable {}, session.sessionToken,
+                APP_NAME, pendingIntent, PACKAGE_NAME)
+        backgroundExecutor.runAllReady()
+        foregroundExecutor.runAllReady()
+        mediaDataManager.setTimedOut(PACKAGE_NAME, timedOut = true)
+
+        // THEN it is removed and listeners are informed
+        foregroundExecutor.advanceClockToLast()
+        foregroundExecutor.runAllReady()
+        verify(listener).onMediaDataRemoved(PACKAGE_NAME)
+    }
+
+    @Test
     fun testLoadsMetadataOnBackground() {
         mediaDataManager.onNotificationAdded(KEY, mediaNotification)
         assertThat(backgroundExecutor.numPending()).isEqualTo(1)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
index 150f4545..a17a03d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
@@ -91,10 +91,12 @@
 
     @Captor lateinit var callbackCaptor: ArgumentCaptor<ResumeMediaBrowser.Callback>
     @Captor lateinit var actionCaptor: ArgumentCaptor<Runnable>
+    @Captor lateinit var componentCaptor: ArgumentCaptor<String>
 
     private lateinit var executor: FakeExecutor
     private lateinit var data: MediaData
     private lateinit var resumeListener: MediaResumeListener
+    private val clock = FakeSystemClock()
 
     private var originalQsSetting = Settings.Global.getInt(context.contentResolver,
         Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS, 1)
@@ -122,9 +124,9 @@
         whenever(mockContext.packageManager).thenReturn(context.packageManager)
         whenever(mockContext.contentResolver).thenReturn(context.contentResolver)
 
-        executor = FakeExecutor(FakeSystemClock())
+        executor = FakeExecutor(clock)
         resumeListener = MediaResumeListener(mockContext, broadcastDispatcher, executor,
-                tunerService, resumeBrowserFactory, dumpManager)
+                tunerService, resumeBrowserFactory, dumpManager, clock)
         resumeListener.setManager(mediaDataManager)
         mediaDataManager.addListener(resumeListener)
 
@@ -163,10 +165,10 @@
 
         // When listener is created, we do NOT register a user change listener
         val listener = MediaResumeListener(context, broadcastDispatcher, executor, tunerService,
-                resumeBrowserFactory, dumpManager)
+                resumeBrowserFactory, dumpManager, clock)
         listener.setManager(mediaDataManager)
         verify(broadcastDispatcher, never()).registerReceiver(eq(listener.userChangeReceiver),
-            any(), any(), any())
+            any(), any(), any(), anyInt())
 
         // When data is loaded, we do NOT execute or update anything
         listener.onMediaDataLoaded(KEY, OLD_KEY, data)
@@ -279,7 +281,7 @@
         // Make sure broadcast receiver is registered
         resumeListener.setManager(mediaDataManager)
         verify(broadcastDispatcher).registerReceiver(eq(resumeListener.userChangeReceiver),
-                any(), any(), any())
+                any(), any(), any(), anyInt())
 
         // When we get an unlock event
         val intent = Intent(Intent.ACTION_USER_UNLOCKED)
@@ -328,4 +330,109 @@
         // Then we call restart
         verify(resumeBrowser).restart()
     }
+
+    @Test
+    fun testOnUserUnlock_missingTime_saves() {
+        val currentTime = clock.currentTimeMillis()
+
+        // When resume components without a last played time are loaded
+        testOnUserUnlock_loadsTracks()
+
+        // Then we save an update with the current time
+        verify(sharedPrefsEditor).putString(any(), (capture(componentCaptor)))
+        componentCaptor.value.split(ResumeMediaBrowser.DELIMITER.toRegex())
+                ?.dropLastWhile { it.isEmpty() }.forEach {
+            val result = it.split("/")
+            assertThat(result.size).isEqualTo(3)
+            assertThat(result[2].toLong()).isEqualTo(currentTime)
+        }
+        verify(sharedPrefsEditor, times(1)).apply()
+    }
+
+    @Test
+    fun testLoadComponents_recentlyPlayed_adds() {
+        // Set up browser to return successfully
+        val description = MediaDescription.Builder().setTitle(TITLE).build()
+        val component = ComponentName(PACKAGE_NAME, CLASS_NAME)
+        whenever(resumeBrowser.token).thenReturn(token)
+        whenever(resumeBrowser.appIntent).thenReturn(pendingIntent)
+        whenever(resumeBrowser.findRecentMedia()).thenAnswer {
+            callbackCaptor.value.addTrack(description, component, resumeBrowser)
+        }
+
+        // Set up shared preferences to have a component with a recent lastplayed time
+        val lastPlayed = clock.currentTimeMillis()
+        val componentsString = "$PACKAGE_NAME/$CLASS_NAME/$lastPlayed:"
+        whenever(sharedPrefs.getString(any(), any())).thenReturn(componentsString)
+        val resumeListener = MediaResumeListener(mockContext, broadcastDispatcher, executor,
+                tunerService, resumeBrowserFactory, dumpManager, clock)
+        resumeListener.setManager(mediaDataManager)
+        mediaDataManager.addListener(resumeListener)
+
+        // When we load a component that was played recently
+        val intent = Intent(Intent.ACTION_USER_UNLOCKED)
+        resumeListener.userChangeReceiver.onReceive(mockContext, intent)
+
+        // We add its resume controls
+        verify(resumeBrowser, times(1)).findRecentMedia()
+        verify(mediaDataManager, times(1)).addResumptionControls(anyInt(),
+                any(), any(), any(), any(), any(), eq(PACKAGE_NAME))
+    }
+
+    @Test
+    fun testLoadComponents_old_ignores() {
+        // Set up shared preferences to have a component with an old lastplayed time
+        val lastPlayed = clock.currentTimeMillis() - RESUME_MEDIA_TIMEOUT - 100
+        val componentsString = "$PACKAGE_NAME/$CLASS_NAME/$lastPlayed:"
+        whenever(sharedPrefs.getString(any(), any())).thenReturn(componentsString)
+        val resumeListener = MediaResumeListener(mockContext, broadcastDispatcher, executor,
+                tunerService, resumeBrowserFactory, dumpManager, clock)
+        resumeListener.setManager(mediaDataManager)
+        mediaDataManager.addListener(resumeListener)
+
+        // When we load a component that is not recent
+        val intent = Intent(Intent.ACTION_USER_UNLOCKED)
+        resumeListener.userChangeReceiver.onReceive(mockContext, intent)
+
+        // We do not try to add resume controls
+        verify(resumeBrowser, times(0)).findRecentMedia()
+        verify(mediaDataManager, times(0)).addResumptionControls(anyInt(),
+                any(), any(), any(), any(), any(), any())
+    }
+
+    @Test
+    fun testOnLoad_hasService_updatesLastPlayed() {
+        // Set up browser to return successfully
+        val description = MediaDescription.Builder().setTitle(TITLE).build()
+        val component = ComponentName(PACKAGE_NAME, CLASS_NAME)
+        whenever(resumeBrowser.token).thenReturn(token)
+        whenever(resumeBrowser.appIntent).thenReturn(pendingIntent)
+        whenever(resumeBrowser.findRecentMedia()).thenAnswer {
+            callbackCaptor.value.addTrack(description, component, resumeBrowser)
+        }
+
+        // Set up shared preferences to have a component with a lastplayed time
+        val currentTime = clock.currentTimeMillis()
+        val lastPlayed = currentTime - 1000
+        val componentsString = "$PACKAGE_NAME/$CLASS_NAME/$lastPlayed:"
+        whenever(sharedPrefs.getString(any(), any())).thenReturn(componentsString)
+        val resumeListener = MediaResumeListener(mockContext, broadcastDispatcher, executor,
+                tunerService, resumeBrowserFactory, dumpManager, clock)
+        resumeListener.setManager(mediaDataManager)
+        mediaDataManager.addListener(resumeListener)
+
+        // When media data is loaded that has not been checked yet, and does have a MBS
+        val dataCopy = data.copy(resumeAction = null, hasCheckedForResume = false)
+        resumeListener.onMediaDataLoaded(KEY, null, dataCopy)
+
+        // Then we store the new lastPlayed time
+        verify(sharedPrefsEditor).putString(any(), (capture(componentCaptor)))
+        componentCaptor.value.split(ResumeMediaBrowser.DELIMITER.toRegex())
+                ?.dropLastWhile { it.isEmpty() }.forEach {
+                    val result = it.split("/")
+                    assertThat(result.size).isEqualTo(3)
+                    assertThat(result[2].toLong()).isEqualTo(currentTime)
+                }
+        verify(sharedPrefsEditor, times(1)).apply()
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt
index 0a573cd..de2235d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt
@@ -71,6 +71,7 @@
     private lateinit var playbackBuilder: PlaybackState.Builder
     private lateinit var session: MediaSession
     private lateinit var mediaData: MediaData
+    private lateinit var resumeData: MediaData
     private lateinit var mediaTimeoutListener: MediaTimeoutListener
 
     @Before
@@ -97,6 +98,10 @@
         mediaData = MediaData(USER_ID, true, 0, PACKAGE, null, null, SESSION_TITLE, null,
             emptyList(), emptyList(), PACKAGE, session.sessionToken, clickIntent = null,
             device = null, active = true, resumeAction = null)
+
+        resumeData = MediaData(USER_ID, true, 0, PACKAGE, null, null, SESSION_TITLE, null,
+                emptyList(), emptyList(), PACKAGE, null, clickIntent = null,
+                device = null, active = false, resumeAction = null, resumption = true)
     }
 
     @Test
@@ -120,6 +125,7 @@
         verify(mediaController).registerCallback(capture(mediaCallbackCaptor))
         assertThat(executor.numPending()).isEqualTo(1)
         verify(timeoutCallback, never()).invoke(anyString(), anyBoolean())
+        assertThat(executor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT)
     }
 
     @Test
@@ -188,6 +194,7 @@
         mediaCallbackCaptor.value.onPlaybackStateChanged(PlaybackState.Builder()
                 .setState(PlaybackState.STATE_PAUSED, 0L, 0f).build())
         assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(executor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT)
     }
 
     @Test
@@ -229,7 +236,7 @@
     }
 
     @Test
-    fun testOnSessionDestroyed_clearsTimeout() {
+    fun testOnSessionDestroyed_active_clearsTimeout() {
         // GIVEN media that is paused
         val mediaPaused = mediaData.copy(isPlaying = false)
         mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaPaused)
@@ -247,7 +254,7 @@
     @Test
     fun testSessionDestroyed_thenRestarts_resetsTimeout() {
         // Assuming we have previously destroyed the session
-        testOnSessionDestroyed_clearsTimeout()
+        testOnSessionDestroyed_active_clearsTimeout()
 
         // WHEN we get an update with media playing
         val playingState = mock(android.media.session.PlaybackState::class.java)
@@ -264,4 +271,91 @@
         }
         verify(timeoutCallback).invoke(eq(KEY), eq(false))
     }
+
+    @Test
+    fun testOnSessionDestroyed_resume_continuesTimeout() {
+        // GIVEN resume media with session info
+        val resumeWithSession = resumeData.copy(token = session.sessionToken)
+        mediaTimeoutListener.onMediaDataLoaded(PACKAGE, null, resumeWithSession)
+        verify(mediaController).registerCallback(capture(mediaCallbackCaptor))
+        assertThat(executor.numPending()).isEqualTo(1)
+
+        // WHEN the session is destroyed
+        mediaCallbackCaptor.value.onSessionDestroyed()
+
+        // THEN the controller is unregistered, but the timeout is still scheduled
+        verify(mediaController).unregisterCallback(anyObject())
+        assertThat(executor.numPending()).isEqualTo(1)
+    }
+
+    @Test
+    fun testOnMediaDataLoaded_activeToResume_registersTimeout() {
+        // WHEN a regular media is loaded
+        mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+
+        // AND it turns into a resume control
+        mediaTimeoutListener.onMediaDataLoaded(PACKAGE, KEY, resumeData)
+
+        // THEN we register a timeout
+        assertThat(executor.numPending()).isEqualTo(1)
+        verify(timeoutCallback, never()).invoke(anyString(), anyBoolean())
+        assertThat(executor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT)
+    }
+
+    @Test
+    fun testOnMediaDataLoaded_pausedToResume_updatesTimeout() {
+        // WHEN regular media is paused
+        val pausedState = PlaybackState.Builder()
+                .setState(PlaybackState.STATE_PAUSED, 0L, 0f)
+                .build()
+        `when`(mediaController.playbackState).thenReturn(pausedState)
+        mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+        assertThat(executor.numPending()).isEqualTo(1)
+
+        // AND it turns into a resume control
+        mediaTimeoutListener.onMediaDataLoaded(PACKAGE, KEY, resumeData)
+
+        // THEN we update the timeout length
+        assertThat(executor.numPending()).isEqualTo(1)
+        verify(timeoutCallback, never()).invoke(anyString(), anyBoolean())
+        assertThat(executor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT)
+    }
+
+    @Test
+    fun testOnMediaDataLoaded_resumption_registersTimeout() {
+        // WHEN a resume media is loaded
+        mediaTimeoutListener.onMediaDataLoaded(PACKAGE, null, resumeData)
+
+        // THEN we register a timeout
+        assertThat(executor.numPending()).isEqualTo(1)
+        verify(timeoutCallback, never()).invoke(anyString(), anyBoolean())
+        assertThat(executor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT)
+    }
+
+    @Test
+    fun testOnMediaDataLoaded_resumeToActive_updatesTimeout() {
+        // WHEN we have a resume control
+        mediaTimeoutListener.onMediaDataLoaded(PACKAGE, null, resumeData)
+
+        // AND that media is resumed
+        val playingState = PlaybackState.Builder()
+                .setState(PlaybackState.STATE_PAUSED, 0L, 0f)
+                .build()
+        `when`(mediaController.playbackState).thenReturn(playingState)
+        mediaTimeoutListener.onMediaDataLoaded(KEY, PACKAGE, mediaData)
+
+        // THEN the timeout length is changed to a regular media control
+        assertThat(executor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT)
+    }
+
+    @Test
+    fun testOnMediaDataRemoved_resume_timeoutCancelled() {
+        // WHEN we have a resume control
+        testOnMediaDataLoaded_resumption_registersTimeout()
+        // AND the media is removed
+        mediaTimeoutListener.onMediaDataRemoved(PACKAGE)
+
+        // THEN the timeout runnable is cancelled
+        assertThat(executor.numPending()).isEqualTo(0)
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 3ea57be..c1a9739 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -48,6 +48,7 @@
 import com.android.systemui.accessibility.SystemActions;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.OverviewProxyService;
@@ -116,7 +117,8 @@
                         mock(ConfigurationController.class),
                         mock(NavigationBarA11yHelper.class),
                         mock(TaskbarDelegate.class),
-                        mock(UserTracker.class)));
+                        mock(UserTracker.class),
+                        mock(DumpManager.class)));
         initializeNavigationBars();
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
index 922c6b6..3e92e90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
@@ -143,7 +144,8 @@
     @Test
     public void testBroadcastReceiverRegistered() {
         verify(mBroadcastDispatcher).registerReceiver(
-                any(), mIntentFilterArgumentCaptor.capture(), any(), eq(UserHandle.of(USER)));
+                any(), mIntentFilterArgumentCaptor.capture(), any(), eq(UserHandle.of(USER)),
+                anyInt());
 
         assertTrue(
                 mIntentFilterArgumentCaptor.getValue().hasAction(Intent.ACTION_SETTING_RESTORED));
@@ -156,13 +158,13 @@
         InOrder inOrder = Mockito.inOrder(mBroadcastDispatcher);
         inOrder.verify(mBroadcastDispatcher).unregisterReceiver(any());
         inOrder.verify(mBroadcastDispatcher)
-                .registerReceiver(any(), any(), any(), eq(UserHandle.of(USER + 1)));
+                .registerReceiver(any(), any(), any(), eq(UserHandle.of(USER + 1)), anyInt());
     }
 
     @Test
     public void testSettingRestoredWithTilesNotRemovedInSource_noAutoAddedInTarget() {
         verify(mBroadcastDispatcher).registerReceiver(
-                mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any());
+                mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any(), anyInt());
 
         // These tiles were present in the original device
         String restoredTiles = "saver,work,internet,cast";
@@ -185,7 +187,8 @@
     @Test
     public void testSettingRestoredWithTilesRemovedInSource_noAutoAddedInTarget() {
         verify(mBroadcastDispatcher)
-                .registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any());
+                .registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any(),
+                        anyInt());
 
         // These tiles were present in the original device
         String restoredTiles = "saver,internet,cast";
@@ -208,7 +211,8 @@
     @Test
     public void testSettingRestoredWithTilesRemovedInSource_sameAutoAddedinTarget() {
         verify(mBroadcastDispatcher)
-                .registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any());
+                .registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any(),
+                        anyInt());
 
         // These tiles were present in the original device
         String restoredTiles = "saver,internet,cast";
@@ -232,7 +236,8 @@
     @Test
     public void testSettingRestoredWithTilesRemovedInSource_othersAutoAddedinTarget() {
         verify(mBroadcastDispatcher)
-                .registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any());
+                .registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any(),
+                        anyInt());
 
         // These tiles were present in the original device
         String restoredTiles = "saver,internet,cast";
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
index 9755d91..97ad8bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
@@ -51,6 +51,7 @@
 import org.mockito.Mockito.`when`
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
@@ -282,8 +283,10 @@
     @Test
     fun testNotAvailableAfterInitializationWithoutIcon() {
         val tile = CustomTile.create(customTileBuilder, TILE_SPEC, mContext)
+        reset(tileHost)
         tile.initialize()
         testableLooper.processAllMessages()
         assertFalse(tile.isAvailable)
+        verify(tileHost).removeTile(tile.tileSpec)
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
index 0a42865..f2303c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
@@ -19,6 +19,7 @@
 import static junit.framework.Assert.assertTrue;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.anyString;
@@ -27,8 +28,12 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageInfo;
 import android.content.pm.ServiceInfo;
 import android.net.Uri;
@@ -42,6 +47,7 @@
 import android.service.quicksettings.TileService;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import androidx.annotation.Nullable;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
@@ -69,6 +75,7 @@
     private HandlerThread mThread;
     private Handler mHandler;
     private TileLifecycleManager mStateManager;
+    private TestContextWrapper mWrappedContext;
 
     @Before
     public void setUp() throws Exception {
@@ -81,12 +88,14 @@
 
         mContext.addMockService(mTileServiceComponentName, mMockTileService);
 
+        mWrappedContext = new TestContextWrapper(mContext);
+
         mTileServiceIntent = new Intent().setComponent(mTileServiceComponentName);
         mUser = new UserHandle(UserHandle.myUserId());
         mThread = new HandlerThread("TestThread");
         mThread.start();
         mHandler = Handler.createAsync(mThread.getLooper());
-        mStateManager = new TileLifecycleManager(mHandler, mContext,
+        mStateManager = new TileLifecycleManager(mHandler, mWrappedContext,
                 Mockito.mock(IQSService.class), new Tile(),
                 mTileServiceIntent,
                 mUser,
@@ -97,6 +106,7 @@
     @After
     public void tearDown() throws Exception {
         mThread.quit();
+        mStateManager.handleDestroy();
     }
 
     private void setPackageEnabled(boolean enabled) throws Exception {
@@ -127,6 +137,18 @@
     }
 
     @Test
+    public void testPackageReceiverExported() throws Exception {
+        // Make sure that we register a receiver
+        setPackageEnabled(false);
+        mStateManager.setBindService(true);
+        IntentFilter filter = mWrappedContext.mLastIntentFilter;
+        assertTrue(filter.hasAction(Intent.ACTION_PACKAGE_ADDED));
+        assertTrue(filter.hasAction(Intent.ACTION_PACKAGE_CHANGED));
+        assertTrue(filter.hasDataScheme("package"));
+        assertNotEquals(0, mWrappedContext.mLastFlag & Context.RECEIVER_EXPORTED);
+    }
+
+    @Test
     public void testUnbind() {
         mStateManager.setBindService(true);
         mStateManager.setBindService(false);
@@ -247,4 +269,23 @@
     public void testToggleableTile() throws Exception {
         assertTrue(mStateManager.isToggleableTile());
     }
+
+    private static class TestContextWrapper extends ContextWrapper {
+        private IntentFilter mLastIntentFilter;
+        private int mLastFlag;
+
+        TestContextWrapper(Context base) {
+            super(base);
+        }
+
+        @Override
+        public Intent registerReceiverAsUser(@Nullable BroadcastReceiver receiver, UserHandle user,
+                IntentFilter filter, @Nullable String broadcastPermission,
+                @Nullable Handler scheduler, int flags) {
+            mLastIntentFilter = filter;
+            mLastFlag = flags;
+            return super.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
+                    scheduler, flags);
+        }
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java
index 6a9d9fa..573980d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java
@@ -20,6 +20,9 @@
 import static junit.framework.Assert.assertTrue;
 
 import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.UserHandle;
@@ -47,6 +50,7 @@
     private Handler mHandler;
     private TileServiceManager mTileServiceManager;
     private UserTracker mUserTracker;
+    private Context mMockContext;
 
     @Before
     public void setUp() throws Exception {
@@ -58,7 +62,8 @@
         Mockito.when(mUserTracker.getUserId()).thenReturn(UserHandle.USER_SYSTEM);
         Mockito.when(mUserTracker.getUserHandle()).thenReturn(UserHandle.SYSTEM);
 
-        Mockito.when(mTileServices.getContext()).thenReturn(mContext);
+        mMockContext = Mockito.mock(Context.class);
+        Mockito.when(mTileServices.getContext()).thenReturn(mMockContext);
         mTileLifecycle = Mockito.mock(TileLifecycleManager.class);
         Mockito.when(mTileLifecycle.isActiveTile()).thenReturn(false);
         ComponentName componentName = new ComponentName(mContext,
@@ -71,6 +76,25 @@
     @After
     public void tearDown() throws Exception {
         mThread.quit();
+        mTileServiceManager.handleDestroy();
+    }
+
+    @Test
+    public void testUninstallReceiverExported() {
+        ArgumentCaptor<IntentFilter> intentFilterCaptor =
+                ArgumentCaptor.forClass(IntentFilter.class);
+
+        Mockito.verify(mMockContext).registerReceiverAsUser(
+                Mockito.any(),
+                Mockito.any(),
+                intentFilterCaptor.capture(),
+                Mockito.any(),
+                Mockito.any(),
+                Mockito.eq(Context.RECEIVER_EXPORTED)
+        );
+        IntentFilter filter = intentFilterCaptor.getValue();
+        assertTrue(filter.hasAction(Intent.ACTION_PACKAGE_REMOVED));
+        assertTrue(filter.hasDataScheme("package"));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt
index ce8e58c..70e971c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt
@@ -21,8 +21,10 @@
 import android.graphics.drawable.Icon
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
+import com.android.internal.statusbar.IAddTileResultCallback
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.qs.QSTileHost
+import com.android.systemui.statusbar.CommandQueue
 import com.android.systemui.statusbar.commandline.CommandRegistry
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.capture
@@ -36,6 +38,7 @@
 import org.mockito.Mockito.anyBoolean
 import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.anyString
+import org.mockito.Mockito.atLeastOnce
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
@@ -58,6 +61,8 @@
     @Mock
     private lateinit var commandRegistry: CommandRegistry
     @Mock
+    private lateinit var commandQueue: CommandQueue
+    @Mock
     private lateinit var icon: Icon
 
     private lateinit var controller: TileServiceRequestController
@@ -69,7 +74,7 @@
         // Tile not present by default
         `when`(qsTileHost.indexOf(anyString())).thenReturn(-1)
 
-        controller = TileServiceRequestController(qsTileHost, commandRegistry) {
+        controller = TileServiceRequestController(qsTileHost, commandQueue, commandRegistry) {
             tileRequestDialog
         }
 
@@ -152,11 +157,44 @@
         verify(qsTileHost, never()).addTile(any(ComponentName::class.java), anyBoolean())
     }
 
-    private class Callback : Consumer<Int> {
+    @Test
+    fun commandQueueCallback_registered() {
+        verify(commandQueue).addCallback(any())
+    }
+
+    @Test
+    fun commandQueueCallback_dataPassedToDialog() {
+        val captor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java)
+        verify(commandQueue, atLeastOnce()).addCallback(capture(captor))
+
+        captor.value.requestAddTile(TEST_COMPONENT, TEST_APP_NAME, TEST_LABEL, icon, Callback())
+
+        verify(tileRequestDialog).setTileData(
+                TileRequestDialog.TileData(TEST_APP_NAME, TEST_LABEL, icon)
+        )
+    }
+
+    @Test
+    fun commandQueueCallback_callbackCalled() {
+        `when`(qsTileHost.indexOf(CustomTile.toSpec(TEST_COMPONENT))).thenReturn(2)
+        val captor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java)
+        verify(commandQueue, atLeastOnce()).addCallback(capture(captor))
+        val c = Callback()
+
+        captor.value.requestAddTile(TEST_COMPONENT, TEST_APP_NAME, TEST_LABEL, icon, c)
+
+        assertThat(c.lastAccepted).isEqualTo(TileServiceRequestController.TILE_ALREADY_ADDED)
+    }
+
+    private class Callback : IAddTileResultCallback.Stub(), Consumer<Int> {
         var lastAccepted: Int? = null
             private set
         override fun accept(t: Int) {
             lastAccepted = t
         }
+
+        override fun onTileRequest(r: Int) {
+            accept(r)
+        }
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
index fa5f70c..77946cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
@@ -10,21 +10,26 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.graphics.drawable.Drawable;
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableResources;
 import android.view.View;
 import android.widget.LinearLayout;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.settingslib.wifi.WifiUtils;
+import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.wifitrackerlib.WifiEntry;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import java.util.Arrays;
 import java.util.List;
@@ -35,6 +40,11 @@
 
     private static final String WIFI_TITLE = "Wi-Fi Title";
     private static final String WIFI_SUMMARY = "Wi-Fi Summary";
+    private static final int GEAR_ICON_RES_ID = R.drawable.ic_settings_24dp;
+    private static final int LOCK_ICON_RES_ID = R.drawable.ic_friction_lock_closed;
+
+    @Rule
+    public MockitoRule mRule = MockitoJUnit.rule();
 
     @Mock
     private WifiEntry mInternetWifiEntry;
@@ -46,13 +56,18 @@
     private InternetDialogController mInternetDialogController;
     @Mock
     private WifiUtils.InternetIconInjector mWifiIconInjector;
+    @Mock
+    private Drawable mGearIcon;
+    @Mock
+    private Drawable mLockIcon;
 
+    private TestableResources mTestableResources;
     private InternetAdapter mInternetAdapter;
     private InternetAdapter.InternetViewHolder mViewHolder;
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
+        mTestableResources = mContext.getOrCreateTestableResources();
         when(mInternetWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
         when(mInternetWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
         when(mInternetWifiEntry.isDefaultNetwork()).thenReturn(true);
@@ -83,7 +98,7 @@
         assertThat(mViewHolder.mWifiTitleText.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mViewHolder.mWifiSummaryText.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mViewHolder.mWifiIcon.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(mViewHolder.mWifiLockedIcon.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mWifiEndIcon.getVisibility()).isEqualTo(View.GONE);
     }
 
     @Test
@@ -94,7 +109,7 @@
         assertThat(mViewHolder.mWifiTitleText.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mViewHolder.mWifiSummaryText.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mViewHolder.mWifiIcon.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(mViewHolder.mWifiLockedIcon.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mWifiEndIcon.getVisibility()).isEqualTo(View.VISIBLE);
     }
 
     @Test
@@ -124,4 +139,29 @@
 
         verify(mWifiIconInjector).getIcon(eq(true) /* noInternet */, anyInt());
     }
+
+    @Test
+    public void viewHolderUpdateEndIcon_wifiConnected_updateGearIcon() {
+        mTestableResources.addOverride(GEAR_ICON_RES_ID, mGearIcon);
+
+        mViewHolder.updateEndIcon(WifiEntry.CONNECTED_STATE_CONNECTED, WifiEntry.SECURITY_PSK);
+
+        assertThat(mViewHolder.mWifiEndIcon.getDrawable()).isEqualTo(mGearIcon);
+    }
+
+    @Test
+    public void viewHolderUpdateEndIcon_wifiDisconnectedAndSecurityPsk_updateLockIcon() {
+        mTestableResources.addOverride(LOCK_ICON_RES_ID, mLockIcon);
+
+        mViewHolder.updateEndIcon(WifiEntry.CONNECTED_STATE_DISCONNECTED, WifiEntry.SECURITY_PSK);
+
+        assertThat(mViewHolder.mWifiEndIcon.getDrawable()).isEqualTo(mLockIcon);
+    }
+
+    @Test
+    public void viewHolderUpdateEndIcon_wifiDisconnectedAndSecurityNone_hideIcon() {
+        mViewHolder.updateEndIcon(WifiEntry.CONNECTED_STATE_DISCONNECTED, WifiEntry.SECURITY_NONE);
+
+        assertThat(mViewHolder.mWifiEndIcon.getVisibility()).isEqualTo(View.GONE);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
index cacc409..baddacc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
@@ -249,28 +249,17 @@
     }
 
     @Test
-    public void getWifiDetailsSettingsIntent_withNoConnectedEntry_returnNull() {
-        mInternetDialogController.onAccessPointsChanged(null /* accessPoints */);
-
-        assertThat(mInternetDialogController.getWifiDetailsSettingsIntent()).isNull();
+    public void getWifiDetailsSettingsIntent_withNoKey_returnNull() {
+        assertThat(mInternetDialogController.getWifiDetailsSettingsIntent(null)).isNull();
     }
 
     @Test
-    public void getWifiDetailsSettingsIntent_withNoConnectedEntryKey_returnNull() {
-        when(mConnectedEntry.getKey()).thenReturn(null);
-
-        assertThat(mInternetDialogController.getWifiDetailsSettingsIntent()).isNull();
+    public void getWifiDetailsSettingsIntent_withKey_returnIntent() {
+        assertThat(mInternetDialogController.getWifiDetailsSettingsIntent("test_key")).isNotNull();
     }
 
     @Test
-    public void getWifiDetailsSettingsIntent_withConnectedEntryKey_returnIntent() {
-        when(mConnectedEntry.getKey()).thenReturn("test_key");
-
-        assertThat(mInternetDialogController.getWifiDetailsSettingsIntent()).isNotNull();
-    }
-
-    @Test
-    public void getWifiDrawable_withConnectedEntry_returnIntentIconWithCorrectColor() {
+    public void getInternetWifiDrawable_withConnectedEntry_returnIntentIconWithCorrectColor() {
         final Drawable drawable = mock(Drawable.class);
         when(mWifiIconInjector.getIcon(anyBoolean(), anyInt())).thenReturn(drawable);
 
@@ -281,20 +270,25 @@
     }
 
     @Test
-    public void launchWifiNetworkDetailsSetting_withNoConnectedEntry_doNothing() {
-        mInternetDialogController.onAccessPointsChanged(null /* accessPoints */);
+    public void getInternetWifiDrawable_withWifiLevelUnreachable_returnNull() {
+        when(mConnectedEntry.getLevel()).thenReturn(WifiEntry.WIFI_LEVEL_UNREACHABLE);
 
-        mInternetDialogController.launchWifiNetworkDetailsSetting();
+        Drawable drawable = mInternetDialogController.getInternetWifiDrawable(mConnectedEntry);
+
+        assertThat(drawable).isNull();
+    }
+
+    @Test
+    public void launchWifiNetworkDetailsSetting_withNoWifiEntryKey_doNothing() {
+        mInternetDialogController.launchWifiNetworkDetailsSetting(null /* key */);
 
         verify(mActivityStarter, never())
                 .postStartActivityDismissingKeyguard(any(Intent.class), anyInt());
     }
 
     @Test
-    public void launchWifiNetworkDetailsSetting_withConnectedEntryKey_startActivity() {
-        when(mConnectedEntry.getKey()).thenReturn("test_key");
-
-        mInternetDialogController.launchWifiNetworkDetailsSetting();
+    public void launchWifiNetworkDetailsSetting_withWifiEntryKey_startActivity() {
+        mInternetDialogController.launchWifiNetworkDetailsSetting("wifi_entry_key");
 
         verify(mActivityStarter).postStartActivityDismissingKeyguard(any(Intent.class), anyInt());
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserDialogTest.kt
new file mode 100644
index 0000000..d5fe588
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserDialogTest.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.user
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.View
+import android.view.ViewGroup
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class UserDialogTest : SysuiTestCase() {
+
+    private lateinit var dialog: UserDialog
+
+    @Before
+    fun setUp() {
+        dialog = UserDialog(mContext)
+    }
+
+    @After
+    fun tearDown() {
+        dialog.dismiss()
+    }
+
+    @Test
+    fun doneButtonExists() {
+        assertThat(dialog.doneButton).isInstanceOf(View::class.java)
+    }
+
+    @Test
+    fun settingsButtonExists() {
+        assertThat(dialog.settingsButton).isInstanceOf(View::class.java)
+    }
+
+    @Test
+    fun gridExistsAndIsViewGroup() {
+        assertThat(dialog.grid).isInstanceOf(ViewGroup::class.java)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
new file mode 100644
index 0000000..a1760a7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.user
+
+import android.content.Intent
+import android.provider.Settings
+import android.testing.AndroidTestingRunner
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.qs.PseudoGridView
+import com.android.systemui.qs.tiles.UserDetailView
+import com.android.systemui.statusbar.policy.UserSwitcherController
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.eq
+import org.junit.Before
+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.Mockito.`when`
+import org.mockito.Mockito.any
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.argThat
+import org.mockito.Mockito.inOrder
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import java.util.function.Consumer
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class UserSwitchDialogControllerTest : SysuiTestCase() {
+
+    @Mock
+    private lateinit var dialog: UserDialog
+    @Mock
+    private lateinit var falsingManager: FalsingManager
+    @Mock
+    private lateinit var settingsView: View
+    @Mock
+    private lateinit var doneView: View
+    @Mock
+    private lateinit var activityStarter: ActivityStarter
+    @Mock
+    private lateinit var userDetailViewAdapter: UserDetailView.Adapter
+    @Mock
+    private lateinit var launchView: View
+    @Mock
+    private lateinit var gridView: PseudoGridView
+    @Captor
+    private lateinit var clickCaptor: ArgumentCaptor<View.OnClickListener>
+
+    private lateinit var controller: UserSwitchDialogController
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        `when`(dialog.settingsButton).thenReturn(settingsView)
+        `when`(dialog.doneButton).thenReturn(doneView)
+        `when`(dialog.grid).thenReturn(gridView)
+
+        `when`(launchView.context).thenReturn(mContext)
+
+        controller = UserSwitchDialogController(
+                { userDetailViewAdapter },
+                activityStarter,
+                falsingManager,
+                { dialog }
+        )
+    }
+
+    @Test
+    fun showDialog_callsDialogShow() {
+        controller.showDialog(launchView)
+        verify(dialog).show()
+    }
+
+    @Test
+    fun createCalledBeforeDoneButton() {
+        controller.showDialog(launchView)
+        val inOrder = inOrder(dialog)
+        inOrder.verify(dialog).create()
+        inOrder.verify(dialog).doneButton
+    }
+
+    @Test
+    fun createCalledBeforeSettingsButton() {
+        controller.showDialog(launchView)
+        val inOrder = inOrder(dialog)
+        inOrder.verify(dialog).create()
+        inOrder.verify(dialog).settingsButton
+    }
+
+    @Test
+    fun createCalledBeforeGrid() {
+        controller.showDialog(launchView)
+        val inOrder = inOrder(dialog)
+        inOrder.verify(dialog).create()
+        inOrder.verify(dialog).grid
+    }
+
+    @Test
+    fun dialog_showForAllUsers() {
+        controller.showDialog(launchView)
+        verify(dialog).setShowForAllUsers(true)
+    }
+
+    @Test
+    fun dialog_cancelOnTouchOutside() {
+        controller.showDialog(launchView)
+        verify(dialog).setCanceledOnTouchOutside(true)
+    }
+
+    @Test
+    fun adapterAndGridLinked() {
+        controller.showDialog(launchView)
+        verify(userDetailViewAdapter).linkToViewGroup(gridView)
+    }
+
+    @Test
+    fun clickDoneButton_dismiss() {
+        controller.showDialog(launchView)
+
+        verify(doneView).setOnClickListener(capture(clickCaptor))
+
+        clickCaptor.value.onClick(doneView)
+
+        verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt())
+        verify(dialog).dismiss()
+    }
+
+    @Test
+    fun clickSettingsButton_noFalsing_opensSettingsAndDismisses() {
+        `when`(falsingManager.isFalseTap(anyInt())).thenReturn(false)
+
+        controller.showDialog(launchView)
+
+        verify(settingsView).setOnClickListener(capture(clickCaptor))
+
+        clickCaptor.value.onClick(settingsView)
+
+        verify(activityStarter)
+                .postStartActivityDismissingKeyguard(
+                        argThat(IntentMatcher(Settings.ACTION_USER_SETTINGS)),
+                        eq(0)
+                )
+        verify(dialog).dismiss()
+    }
+
+    @Test
+    fun clickSettingsButton_Falsing_notOpensSettingsAndDismisses() {
+        `when`(falsingManager.isFalseTap(anyInt())).thenReturn(true)
+
+        controller.showDialog(launchView)
+
+        verify(settingsView).setOnClickListener(capture(clickCaptor))
+
+        clickCaptor.value.onClick(settingsView)
+
+        verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt())
+        verify(dialog).dismiss()
+    }
+
+    @Test
+    fun callbackFromDetailView_dismissesDialog() {
+        val captor = argumentCaptor<Consumer<UserSwitcherController.UserRecord>>()
+
+        controller.showDialog(launchView)
+        verify(userDetailViewAdapter).injectCallback(capture(captor))
+
+        captor.value.accept(mock(UserSwitcherController.UserRecord::class.java))
+
+        verify(dialog).dismiss()
+    }
+
+    private class IntentMatcher(private val action: String) : ArgumentMatcher<Intent> {
+        override fun matches(argument: Intent?): Boolean {
+            return argument?.action == action
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
index a9c6a53..ebc6f2a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
@@ -56,45 +56,71 @@
     @Test
     fun testRegisterViewOnTheLeftOfVerticalFold_halfProgress_viewTranslatedToTheRight() {
         givenScreen(width = 100, height = 100, rotation = ROTATION_0)
-        val view = createView(x = 20)
+        val view = createView(x = 20, width = 10, height = 10)
         animator.registerViewForAnimation(view)
         animator.onTransitionStarted()
 
         animator.onTransitionProgress(0.5f)
 
         // Positive translationX -> translated to the right
-        assertThat(view.translationX).isWithin(0.1f).of(3.75f)
+        // 10x10 view center is 25px from the center,
+        // When progress is 0.5 it should be translated at:
+        // 25 * 0.3 * (1 - 0.5) = 3.75px
+        assertThat(view.translationX).isWithin(0.01f).of(3.75f)
     }
 
     @Test
     fun testRegisterViewOnTheLeftOfVerticalFold_zeroProgress_viewTranslatedToTheRight() {
         givenScreen(width = 100, height = 100, rotation = ROTATION_0)
-        val view = createView(x = 20)
+        val view = createView(x = 20, width = 10, height = 10)
         animator.registerViewForAnimation(view)
         animator.onTransitionStarted()
 
         animator.onTransitionProgress(0f)
 
         // Positive translationX -> translated to the right
-        assertThat(view.translationX).isWithin(0.1f).of(7.5f)
+        // 10x10 view center is 25px from the center,
+        // When progress is 0 it should be translated at:
+        // 25 * 0.3 * (1 - 0) = 7.5px
+        assertThat(view.translationX).isWithin(0.01f).of(7.5f)
     }
 
     @Test
     fun testRegisterViewOnTheLeftOfVerticalFold_fullProgress_viewTranslatedToTheOriginalPosition() {
         givenScreen(width = 100, height = 100, rotation = ROTATION_0)
-        val view = createView(x = 20)
+        val view = createView(x = 20, width = 10, height = 10)
         animator.registerViewForAnimation(view)
         animator.onTransitionStarted()
 
         animator.onTransitionProgress(1f)
 
+        // Positive translationX -> translated to the right
+        // 10x10 view center is 25px from the center,
+        // When progress is 1 it should be translated at:
+        // 25 * 0.3 * 0 = 0px
         assertThat(view.translationX).isEqualTo(0f)
     }
 
     @Test
+    fun testViewOnTheLeftOfVerticalFoldWithTranslation_halfProgress_viewTranslatedToTheRight() {
+        givenScreen(width = 100, height = 100, rotation = ROTATION_0)
+        val view = createView(x = 20, width = 10, height = 10, translationX = 100f)
+        animator.registerViewForAnimation(view)
+        animator.onTransitionStarted()
+
+        animator.onTransitionProgress(0.5f)
+
+        // Positive translationX -> translated to the right, original translation is ignored
+        // 10x10 view center is 25px from the center,
+        // When progress is 0.5 it should be translated at:
+        // 25 * 0.3 * (1 - 0.5) = 3.75px
+        assertThat(view.translationX).isWithin(0.01f).of(3.75f)
+    }
+
+    @Test
     fun testRegisterViewAndUnregister_halfProgress_viewIsNotUpdated() {
         givenScreen(width = 100, height = 100, rotation = ROTATION_0)
-        val view = createView(x = 20)
+        val view = createView(x = 20, width = 10, height = 10)
         animator.registerViewForAnimation(view)
         animator.onTransitionStarted()
         animator.clearRegisteredViews()
@@ -107,7 +133,7 @@
     @Test
     fun testRegisterViewUpdateProgressAndUnregister_halfProgress_viewIsNotUpdated() {
         givenScreen(width = 100, height = 100, rotation = ROTATION_0)
-        val view = createView(x = 20)
+        val view = createView(x = 20, width = 10, height = 10)
         animator.registerViewForAnimation(view)
         animator.onTransitionStarted()
         animator.onTransitionProgress(0.2f)
@@ -121,14 +147,14 @@
     @Test
     fun testRegisterViewOnTheTopOfHorizontalFold_halfProgress_viewTranslatedToTheBottom() {
         givenScreen(width = 100, height = 100, rotation = ROTATION_90)
-        val view = createView(y = 20)
+        val view = createView(y = 20, width = 10, height = 10)
         animator.registerViewForAnimation(view)
         animator.onTransitionStarted()
 
         animator.onTransitionProgress(0.5f)
 
         // Positive translationY -> translated to the bottom
-        assertThat(view.translationY).isWithin(0.1f).of(3.75f)
+        assertThat(view.translationY).isWithin(0.01f).of(3.75f)
     }
 
     private fun createView(
@@ -156,9 +182,11 @@
         }
     }
 
-    private fun givenScreen(width: Int = 100,
-                            height: Int = 100,
-                            rotation: Int = ROTATION_0) {
+    private fun givenScreen(
+        width: Int = 100,
+        height: Int = 100,
+        rotation: Int = ROTATION_0
+    ) {
         val display = mock(Display::class.java)
         whenever(display.getSize(any())).thenAnswer {
             val size = (it.arguments[0] as Point)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java
similarity index 62%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceManagerTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java
index 790b4dd..05280fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java
@@ -1,15 +1,17 @@
 /*
  * Copyright (C) 2016 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
+ * 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.
+ * 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.shared.plugins;
@@ -19,8 +21,6 @@
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -41,13 +41,11 @@
 
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.SysuiTestableContext;
 import com.android.systemui.plugins.Plugin;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.annotations.Requires;
-import com.android.systemui.shared.plugins.VersionInfo.InvalidVersionException;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
@@ -64,30 +62,34 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class PluginInstanceManagerTest extends SysuiTestCase {
+public class PluginActionManagerTest extends SysuiTestCase {
 
     private static final String PRIVILEGED_PACKAGE = "com.android.systemui.shared.plugins";
     private TestPlugin mMockPlugin;
 
     private PackageManager mMockPm;
-    private PluginListener<Plugin> mMockListener;
-    private PluginInstanceManager<Plugin> mPluginInstanceManager;
+    private PluginListener<TestPlugin> mMockListener;
+    private PluginActionManager<TestPlugin> mPluginActionManager;
     private VersionInfo mMockVersionInfo;
     private PluginEnabler mMockEnabler;
     ComponentName mTestPluginComponentName =
             new ComponentName(PRIVILEGED_PACKAGE, TestPlugin.class.getName());
-    private PluginInitializer mInitializer;
     private final FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
     NotificationManager mNotificationManager;
-    private PluginInstanceManager.Factory mInstanceManagerFactory;
-    private final PluginInstanceManager.InstanceFactory<Plugin> mPluginInstanceFactory =
-            new PluginInstanceManager.InstanceFactory<Plugin>() {
+    private PluginInstance<TestPlugin> mPluginInstance;
+    private PluginInstance.Factory mPluginInstanceFactory = new PluginInstance.Factory(
+            this.getClass().getClassLoader(),
+            new PluginInstance.InstanceFactory<>(), new PluginInstance.VersionChecker(),
+            Collections.emptyList(), false) {
         @Override
-        Plugin create(Class cls) {
-            return mMockPlugin;
+        public <T extends Plugin> PluginInstance<T> create(Context context, ApplicationInfo appInfo,
+                ComponentName componentName, Class<T> pluginClass) {
+            return (PluginInstance<T>) mPluginInstance;
         }
     };
 
+    private PluginActionManager.Factory mActionManagerFactory;
+
     @Before
     public void setup() throws Exception {
         mContext = new MyContextWrapper(mContext);
@@ -95,16 +97,17 @@
         mMockListener = mock(PluginListener.class);
         mMockEnabler = mock(PluginEnabler.class);
         mMockVersionInfo = mock(VersionInfo.class);
-        mInitializer = mock(PluginInitializer.class);
         mNotificationManager = mock(NotificationManager.class);
         mMockPlugin = mock(TestPlugin.class);
-        mInstanceManagerFactory = new PluginInstanceManager.Factory(getContext(), mMockPm,
-                mFakeExecutor, mFakeExecutor, mInitializer, mNotificationManager, mMockEnabler,
-                new ArrayList<>())
-                .setInstanceFactory(mPluginInstanceFactory);
+        mPluginInstance = mock(PluginInstance.class);
+        when(mPluginInstance.getComponentName()).thenReturn(mTestPluginComponentName);
+        when(mPluginInstance.getPackage()).thenReturn(mTestPluginComponentName.getPackageName());
+        mActionManagerFactory = new PluginActionManager.Factory(getContext(), mMockPm,
+                mFakeExecutor, mFakeExecutor, mNotificationManager, mMockEnabler,
+                new ArrayList<>(), mPluginInstanceFactory);
 
-        mPluginInstanceManager = mInstanceManagerFactory.create("myAction", mMockListener,
-                true, mMockVersionInfo, true);
+        mPluginActionManager = mActionManagerFactory.create("myAction", mMockListener,
+                TestPlugin.class, true, true);
         when(mMockPlugin.getVersion()).thenReturn(1);
     }
 
@@ -112,7 +115,7 @@
     public void testNoPlugins() {
         when(mMockPm.queryIntentServices(any(), anyInt())).thenReturn(
                 Collections.emptyList());
-        mPluginInstanceManager.loadAll();
+        mPluginActionManager.loadAll();
 
         mFakeExecutor.runAllReady();
 
@@ -121,68 +124,47 @@
 
     @Test
     public void testPluginCreate() throws Exception {
+        //Debug.waitForDebugger();
         createPlugin();
 
         // Verify startup lifecycle
-        verify(mMockPlugin).onCreate(ArgumentCaptor.forClass(Context.class).capture(),
-                ArgumentCaptor.forClass(Context.class).capture());
-        verify(mMockListener).onPluginConnected(any(), any());
+        verify(mPluginInstance).onCreate(mContext, mMockListener);
     }
 
     @Test
     public void testPluginDestroy() throws Exception {
         createPlugin(); // Get into valid created state.
 
-        mPluginInstanceManager.destroy();
+        mPluginActionManager.destroy();
 
         mFakeExecutor.runAllReady();
 
-
         // Verify shutdown lifecycle
-        verify(mMockListener).onPluginDisconnected(ArgumentCaptor.forClass(Plugin.class).capture());
-        verify(mMockPlugin).onDestroy();
-    }
-
-    @Test
-    public void testIncorrectVersion() throws Exception {
-        setupFakePmQuery();
-        doThrow(new InvalidVersionException("", false)).when(mMockVersionInfo).checkVersion(any());
-
-        mPluginInstanceManager.loadAll();
-
-        mFakeExecutor.runAllReady();
-
-        // Plugin shouldn't be connected because it is the wrong version.
-        verify(mMockListener, never()).onPluginConnected(any(), any());
-        verify(mNotificationManager).notify(eq(SystemMessage.NOTE_PLUGIN), any());
+        verify(mPluginInstance).onDestroy(mMockListener);
     }
 
     @Test
     public void testReloadOnChange() throws Exception {
         createPlugin(); // Get into valid created state.
 
-        mPluginInstanceManager.onPackageChange(PRIVILEGED_PACKAGE);
+        mPluginActionManager.reloadPackage(PRIVILEGED_PACKAGE);
 
         mFakeExecutor.runAllReady();
 
         // Verify the old one was destroyed.
-        verify(mMockListener).onPluginDisconnected(ArgumentCaptor.forClass(Plugin.class).capture());
-        verify(mMockPlugin).onDestroy();
-        // Also verify we got a second onCreate.
-        verify(mMockPlugin, Mockito.times(2)).onCreate(
-                ArgumentCaptor.forClass(Context.class).capture(),
-                ArgumentCaptor.forClass(Context.class).capture());
-        verify(mMockListener, Mockito.times(2)).onPluginConnected(any(), any());
+        verify(mPluginInstance).onDestroy(mMockListener);
+        verify(mPluginInstance, Mockito.times(2))
+                .onCreate(mContext, mMockListener);
     }
 
     @Test
     public void testNonDebuggable() throws Exception {
         // Create a version that thinks the build is not debuggable.
-        mPluginInstanceManager = mInstanceManagerFactory.create("myAction", mMockListener,
-                true, mMockVersionInfo, false);
+        mPluginActionManager = mActionManagerFactory.create("myAction", mMockListener,
+                TestPlugin.class, true, false);
         setupFakePmQuery();
 
-        mPluginInstanceManager.loadAll();
+        mPluginActionManager.loadAll();
 
         mFakeExecutor.runAllReady();
 
@@ -193,22 +175,20 @@
     @Test
     public void testNonDebuggable_privileged() throws Exception {
         // Create a version that thinks the build is not debuggable.
-        PluginInstanceManager.Factory factory = new PluginInstanceManager.Factory(getContext(),
-                mMockPm, mFakeExecutor, mFakeExecutor, mInitializer, mNotificationManager,
-                mMockEnabler, Collections.singletonList(PRIVILEGED_PACKAGE));
-        factory.setInstanceFactory(mPluginInstanceFactory);
-        mPluginInstanceManager = factory.create("myAction", mMockListener,
-                true, mMockVersionInfo, false);
+        PluginActionManager.Factory factory = new PluginActionManager.Factory(getContext(),
+                mMockPm, mFakeExecutor, mFakeExecutor, mNotificationManager,
+                mMockEnabler, Collections.singletonList(PRIVILEGED_PACKAGE),
+                mPluginInstanceFactory);
+        mPluginActionManager = factory.create("myAction", mMockListener,
+                TestPlugin.class, true, false);
         setupFakePmQuery();
 
-        mPluginInstanceManager.loadAll();
+        mPluginActionManager.loadAll();
 
         mFakeExecutor.runAllReady();
 
         // Verify startup lifecycle
-        verify(mMockPlugin).onCreate(ArgumentCaptor.forClass(Context.class).capture(),
-                ArgumentCaptor.forClass(Context.class).capture());
-        verify(mMockListener).onPluginConnected(any(), any());
+        verify(mPluginInstance).onCreate(mContext, mMockListener);
     }
 
     @Test
@@ -216,12 +196,12 @@
         createPlugin(); // Get into valid created state.
 
         // Start with an unrelated class.
-        boolean result = mPluginInstanceManager.checkAndDisable(Activity.class.getName());
+        boolean result = mPluginActionManager.checkAndDisable(Activity.class.getName());
         assertFalse(result);
         verify(mMockEnabler, never()).setDisabled(any(ComponentName.class), anyInt());
 
         // Now hand it a real class and make sure it disables the plugin.
-        result = mPluginInstanceManager.checkAndDisable(TestPlugin.class.getName());
+        result = mPluginActionManager.checkAndDisable(TestPlugin.class.getName());
         assertTrue(result);
         verify(mMockEnabler).setDisabled(
                 mTestPluginComponentName, PluginEnabler.DISABLED_FROM_EXPLICIT_CRASH);
@@ -231,24 +211,24 @@
     public void testDisableAll() throws Exception {
         createPlugin(); // Get into valid created state.
 
-        mPluginInstanceManager.disableAll();
+        mPluginActionManager.disableAll();
 
         verify(mMockEnabler).setDisabled(
                 mTestPluginComponentName, PluginEnabler.DISABLED_FROM_SYSTEM_CRASH);
     }
 
     @Test
-    public void testDisableWhitelisted() throws Exception {
-        PluginInstanceManager.Factory factory = new PluginInstanceManager.Factory(getContext(),
-                mMockPm, mFakeExecutor, mFakeExecutor, mInitializer, mNotificationManager,
-                mMockEnabler, Collections.singletonList(PRIVILEGED_PACKAGE));
-        factory.setInstanceFactory(mPluginInstanceFactory);
-        mPluginInstanceManager = factory.create("myAction", mMockListener,
-                true, mMockVersionInfo, false);
+    public void testDisablePrivileged() throws Exception {
+        PluginActionManager.Factory factory = new PluginActionManager.Factory(getContext(),
+                mMockPm, mFakeExecutor, mFakeExecutor, mNotificationManager,
+                mMockEnabler, Collections.singletonList(PRIVILEGED_PACKAGE),
+                mPluginInstanceFactory);
+        mPluginActionManager = factory.create("myAction", mMockListener,
+                TestPlugin.class, true, false);
 
         createPlugin(); // Get into valid created state.
 
-        mPluginInstanceManager.disableAll();
+        mPluginActionManager.disableAll();
 
         verify(mMockPm, never()).setComponentEnabledSetting(
                 ArgumentCaptor.forClass(ComponentName.class).capture(),
@@ -282,14 +262,14 @@
     private void createPlugin() throws Exception {
         setupFakePmQuery();
 
-        mPluginInstanceManager.loadAll();
+        mPluginActionManager.loadAll();
 
         mFakeExecutor.runAllReady();
     }
 
     // Real context with no registering/unregistering of receivers.
     private static class MyContextWrapper extends SysuiTestableContext {
-        public MyContextWrapper(Context base) {
+        MyContextWrapper(Context base) {
             super(base);
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
new file mode 100644
index 0000000..bb9a1e9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.plugins;
+
+import static junit.framework.Assert.assertNotNull;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+import com.android.systemui.plugins.annotations.Requires;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Collections;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PluginInstanceTest extends SysuiTestCase {
+
+    private static final String PRIVILEGED_PACKAGE = "com.android.systemui.plugins";
+
+    @Mock
+    private TestPluginImpl mMockPlugin;
+    @Mock
+    private PluginListener<TestPlugin> mMockListener;
+    @Mock
+    private VersionInfo mVersionInfo;
+    ComponentName mTestPluginComponentName =
+            new ComponentName(PRIVILEGED_PACKAGE, TestPluginImpl.class.getName());
+    private PluginInstance<TestPlugin> mPluginInstance;
+    private PluginInstance.Factory mPluginInstanceFactory;
+
+    private ApplicationInfo mAppInfo;
+    private Context mPluginContext;
+    @Mock
+    private PluginInstance.VersionChecker mVersionChecker;
+
+    @Before
+    public void setup() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mAppInfo = mContext.getApplicationInfo();
+        mAppInfo.packageName = mTestPluginComponentName.getPackageName();
+        when(mVersionChecker.checkVersion(any(), any(), any())).thenReturn(mVersionInfo);
+
+        mPluginInstanceFactory = new PluginInstance.Factory(
+                this.getClass().getClassLoader(),
+                new PluginInstance.InstanceFactory<TestPlugin>() {
+                    @Override
+                    TestPlugin create(Class cls) {
+                        return mMockPlugin;
+                    }
+                },
+                mVersionChecker,
+                Collections.singletonList(PRIVILEGED_PACKAGE),
+                false);
+
+        mPluginInstance = mPluginInstanceFactory.create(
+                mContext, mAppInfo, mTestPluginComponentName, TestPlugin.class);
+        mPluginContext = mPluginInstance.getPluginContext();
+    }
+
+    @Test
+    public void testCorrectVersion() {
+        assertNotNull(mPluginInstance);
+    }
+
+    @Test(expected = VersionInfo.InvalidVersionException.class)
+    public void testIncorrectVersion() throws Exception {
+
+        ComponentName wrongVersionTestPluginComponentName =
+                new ComponentName(PRIVILEGED_PACKAGE, TestPlugin.class.getName());
+
+        when(mVersionChecker.checkVersion(any(), any(), any())).thenThrow(
+                new VersionInfo.InvalidVersionException("test", true));
+
+        mPluginInstanceFactory.create(
+                mContext, mAppInfo, wrongVersionTestPluginComponentName, TestPlugin.class);
+    }
+
+    @Test
+    public void testOnCreate() {
+        mPluginInstance.onCreate(mContext, mMockListener);
+        verify(mMockPlugin).onCreate(mContext, mPluginContext);
+        verify(mMockListener).onPluginConnected(mMockPlugin, mPluginContext);
+    }
+
+    @Test
+    public void testOnDestroy() {
+        mPluginInstance.onDestroy(mMockListener);
+        verify(mMockListener).onPluginDisconnected(mMockPlugin);
+        verify(mMockPlugin).onDestroy();
+    }
+
+    // This target class doesn't matter, it just needs to have a Requires to hit the flow where
+    // the mock version info is called.
+    @ProvidesInterface(action = TestPlugin.ACTION, version = TestPlugin.VERSION)
+    public interface TestPlugin extends Plugin {
+        int VERSION = 1;
+        String ACTION = "testAction";
+    }
+
+    @Requires(target = TestPlugin.class, version = TestPlugin.VERSION)
+    public static class TestPluginImpl implements TestPlugin {
+        @Override
+        public void onCreate(Context sysuiContext, Context pluginContext) {
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java
index 4590dd8..1eadd52 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java
@@ -13,6 +13,7 @@
  */
 package com.android.systemui.shared.plugins;
 
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
@@ -54,10 +55,10 @@
 
     private static final String PRIVILEGED_PACKAGE = "com.android.systemui";
 
-    private PluginInstanceManager.Factory mMockFactory;
-    private PluginInstanceManager<Plugin> mMockPluginInstance;
+    private PluginActionManager.Factory mMockFactory;
+    private PluginActionManager<TestPlugin> mMockPluginInstance;
     private PluginManagerImpl mPluginManager;
-    private PluginListener<?> mMockListener;
+    private PluginListener<TestPlugin> mMockListener;
     private PackageManager mMockPackageManager;
     private PluginEnabler mPluginEnabler;
     private PluginPrefs mPluginPrefs;
@@ -70,11 +71,11 @@
     public void setup() throws Exception {
         mRealExceptionHandler = Thread.getUncaughtExceptionPreHandler();
         mMockExceptionHandler = mock(UncaughtExceptionHandler.class);
-        mMockFactory = mock(PluginInstanceManager.Factory.class);
-        mMockPluginInstance = mock(PluginInstanceManager.class);
+        mMockFactory = mock(PluginActionManager.Factory.class);
+        mMockPluginInstance = mock(PluginActionManager.class);
         mPluginEnabler = mock(PluginEnabler.class);
         mPluginPrefs = mock(PluginPrefs.class);
-        when(mMockFactory.create(any(), any(), Mockito.anyBoolean(), any(), Mockito.anyBoolean()))
+        when(mMockFactory.create(any(), any(), eq(TestPlugin.class), anyBoolean(), anyBoolean()))
                 .thenReturn(mMockPluginInstance);
 
         mMockPackageManager = mock(PackageManager.class);
@@ -116,8 +117,8 @@
         applicationInfo.sourceDir = sourceDir;
         applicationInfo.packageName = PRIVILEGED_PACKAGE;
         mPluginManager.addPluginListener("myAction", mMockListener, TestPlugin.class);
-        verify(mMockFactory).create(eq("myAction"), eq(mMockListener), eq(false),
-                any(VersionInfo.class), eq(false));
+        verify(mMockFactory).create(eq("myAction"), eq(mMockListener), eq(TestPlugin.class),
+                eq(false), eq(false));
         verify(mMockPluginInstance).loadAll();
     }
 
@@ -138,8 +139,8 @@
         invalidApplicationInfo.sourceDir = sourceDir;
         invalidApplicationInfo.packageName = "com.android.invalidpackage";
         mPluginManager.addPluginListener("myAction", mMockListener, TestPlugin.class);
-        verify(mMockFactory).create(eq("myAction"), eq(mMockListener), eq(false),
-                any(VersionInfo.class), eq(false));
+        verify(mMockFactory).create(eq("myAction"), eq(mMockListener), eq(TestPlugin.class),
+                eq(false), eq(false));
         verify(mMockPluginInstance).loadAll();
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 4c90063..09a3d35 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -639,7 +639,7 @@
     }
 
     @Test
-    public void onRefreshBatteryInfo_fullChargedWithOverheat_presentCharged() {
+    public void onRefreshBatteryInfo_fullChargedWithOverheat_presentChargingLimited() {
         createController();
         BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
                 100 /* level */, BatteryManager.BATTERY_PLUGGED_AC,
@@ -651,6 +651,24 @@
 
         verifyIndicationMessage(
                 INDICATION_TYPE_BATTERY,
+                mContext.getString(
+                        R.string.keyguard_plugged_in_charging_limited,
+                        NumberFormat.getPercentInstance().format(100 / 100f)));
+    }
+
+    @Test
+    public void onRefreshBatteryInfo_fullChargedWithoutOverheat_presentCharged() {
+        createController();
+        BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
+                100 /* level */, BatteryManager.BATTERY_PLUGGED_AC,
+                BatteryManager.BATTERY_HEALTH_GOOD, 0 /* maxChargingWattage */,
+                true /* present */);
+
+        mController.getKeyguardCallback().onRefreshBatteryInfo(status);
+        mController.setVisible(true);
+
+        verifyIndicationMessage(
+                INDICATION_TYPE_BATTERY,
                 mContext.getString(R.string.keyguard_charged));
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index 0c65830..ea21aa9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -56,6 +56,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager.KeyguardNotificationSuppressor;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -423,7 +424,8 @@
                     mStatusBarStateController,
                     Handler.createAsync(Looper.myLooper()),
                     mDeviceProvisionedController,
-                    mKeyguardStateController);
+                    mKeyguardStateController,
+                    mock(DumpManager.class));
         }
 
         public BroadcastReceiver getBaseBroadcastReceiverForTest() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
index 8b7c76a..5944e9c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
@@ -25,6 +25,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationRemoteInputManager.RemoteInputActiveExtender;
 import com.android.systemui.statusbar.NotificationRemoteInputManager.RemoteInputHistoryExtender;
@@ -87,7 +88,8 @@
                 Handler.createAsync(Looper.myLooper()),
                 mRemoteInputUriController,
                 mClickNotifier,
-                mock(ActionClickLogger.class));
+                mock(ActionClickLogger.class),
+                mock(DumpManager.class));
         mEntry = new NotificationEntryBuilder()
                 .setPkg(TEST_PACKAGE_NAME)
                 .setOpPkg(TEST_PACKAGE_NAME)
@@ -272,7 +274,8 @@
                 Handler mainHandler,
                 RemoteInputUriController remoteInputUriController,
                 NotificationClickNotifier clickNotifier,
-                ActionClickLogger actionClickLogger) {
+                ActionClickLogger actionClickLogger,
+                DumpManager dumpManager) {
             super(
                     context,
                     lockscreenUserManager,
@@ -283,7 +286,8 @@
                     mainHandler,
                     remoteInputUriController,
                     clickNotifier,
-                    actionClickLogger);
+                    actionClickLogger,
+                    dumpManager);
         }
 
         public void setUpWithPresenterForTest(Callback callback,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
index 7f72f19..465370b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
@@ -33,6 +33,7 @@
 import com.android.systemui.statusbar.phone.ScrimController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.mockito.eq
+import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -168,6 +169,22 @@
     }
 
     @Test
+    fun onPanelExpansionChanged_respectsMinPanelPullDownFraction() {
+        notificationShadeDepthController.panelPullDownMinFraction = 0.5f
+        notificationShadeDepthController.onPanelExpansionChanged(0.5f /* expansion */,
+                true /* tracking */)
+        assertThat(notificationShadeDepthController.shadeExpansion).isEqualTo(0f)
+
+        notificationShadeDepthController.onPanelExpansionChanged(0.75f /* expansion */,
+                true /* tracking */)
+        assertThat(notificationShadeDepthController.shadeExpansion).isEqualTo(0.5f)
+
+        notificationShadeDepthController.onPanelExpansionChanged(1f /* expansion */,
+                true /* tracking */)
+        assertThat(notificationShadeDepthController.shadeExpansion).isEqualTo(1f)
+    }
+
+    @Test
     fun onStateChanged_reevalutesBlurs_ifSameRadiusAndNewState() {
         onPanelExpansionChanged_apliesBlur_ifShade()
         clearInvocations(choreographer)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
index 659d96e..837d71f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
@@ -38,6 +38,7 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -97,7 +98,8 @@
                 Handler.createAsync(Looper.myLooper()),
                 mRemoteInputUriController,
                 mClickNotifier,
-                mock(ActionClickLogger.class));
+                mock(ActionClickLogger.class),
+                mock(DumpManager.class));
         mRemoteInputManager.setUpWithCallback(mCallback, mDelegate);
         mNotification = new Notification.Builder(mContext, "")
                 .setSmallIcon(R.drawable.ic_person)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
index fca6bc5..c974882 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
@@ -21,10 +21,12 @@
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.testing.UiEventLoggerFake
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
 import org.junit.Assert.assertEquals
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.Mockito.mock
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
@@ -37,7 +39,7 @@
     @Before
     fun setUp() {
         uiEventLogger = UiEventLoggerFake()
-        controller = StatusBarStateControllerImpl(uiEventLogger)
+        controller = StatusBarStateControllerImpl(uiEventLogger, mock(DumpManager::class.java))
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 8a32ce6..1f3e1c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -64,8 +64,10 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.statusbar.NotificationLifetimeExtender;
+import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -130,6 +132,7 @@
     @Mock private LeakDetector mLeakDetector;
     @Mock private NotificationMediaManager mNotificationMediaManager;
     @Mock private NotificationRowBinder mNotificationRowBinder;
+    @Mock private NotificationListener mNotificationListener;
 
     private int mId;
     private NotificationEntry mEntry;
@@ -195,9 +198,11 @@
                 () -> mRemoteInputManager,
                 mLeakDetector,
                 mock(ForegroundServiceDismissalFeatureController.class),
-                mock(IStatusBarService.class)
+                mock(IStatusBarService.class),
+                mock(DumpManager.class)
         );
-        mEntryManager.setRanker(
+        mEntryManager.initialize(
+                mNotificationListener,
                 new NotificationRankingManager(
                         () -> mNotificationMediaManager,
                         mGroupManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
index b1eef4b..b02a336 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
@@ -42,6 +42,7 @@
 
 import com.android.systemui.ForegroundServiceController;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.media.MediaFeatureFlag;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -119,7 +120,8 @@
                 new NotificationGroupManagerLegacy(
                         mock(StatusBarStateController.class),
                         () -> mock(PeopleNotificationIdentifier.class),
-                        Optional.of(mock(Bubbles.class))));
+                        Optional.of(mock(Bubbles.class)),
+                        mock(DumpManager.class)));
         mDependency.injectMockDependency(ShadeController.class);
         mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
         mDependency.injectTestDependency(KeyguardEnvironment.class, mEnvironment);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
index baeedcf..a737ce5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java
@@ -32,6 +32,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -70,7 +71,8 @@
                 mock(NotificationEntryManager.class),
                 new Handler(mTestableLooper.getLooper()),
                 statusBarStateController,
-                wakefulnessLifecycle);
+                wakefulnessLifecycle,
+                mock(DumpManager.class));
 
         mVisualStabilityManager.setVisibilityLocationProvider(mLocationProvider);
         mEntry = new NotificationEntryBuilder().build();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
index 4562e4f..d3738f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -47,11 +47,13 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.classifier.FalsingCollectorFake;
 import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.media.MediaFeatureFlag;
 import com.android.systemui.media.dialog.MediaOutputDialogFactory;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationPresenter;
@@ -119,6 +121,7 @@
         throw new RuntimeException("Timed out waiting to inflate");
     };
 
+    @Mock private NotificationListener mNotificationListener;
     @Mock private NotificationPresenter mPresenter;
     @Mock private NotificationEntryManager.KeyguardEnvironment mEnvironment;
     @Mock private NotificationListContainer mListContainer;
@@ -186,9 +189,11 @@
                 () -> mRemoteInputManager,
                 mLeakDetector,
                 mock(ForegroundServiceDismissalFeatureController.class),
-                mock(IStatusBarService.class)
+                mock(IStatusBarService.class),
+                mock(DumpManager.class)
         );
-        mEntryManager.setRanker(
+        mEntryManager.initialize(
+                mNotificationListener,
                 new NotificationRankingManager(
                         () -> mock(NotificationMediaManager.class),
                         mGroupMembershipManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index fc44669..7d8e0d2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -68,6 +68,7 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.logging.testing.UiEventLoggerFake;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.settings.UserContextProvider;
@@ -159,7 +160,7 @@
                 mPeopleSpaceWidgetManager, mLauncherApps, mShortcutManager,
                 mChannelEditorDialogController, mContextTracker, mAssistantFeedbackController,
                 Optional.of(mBubblesManager), new UiEventLoggerFake(), mOnUserInteractionCallback,
-                mShadeController);
+                mShadeController, mock(DumpManager.class));
         mGutsManager.setUpWithPresenter(mPresenter, mNotificationListContainer,
                 mCheckSaveListener, mOnSettingsClickListener);
         mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index 0bb66fc..42aecfd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -46,6 +46,7 @@
 import com.android.systemui.TestableDependency;
 import com.android.systemui.classifier.FalsingCollectorFake;
 import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.media.MediaFeatureFlag;
 import com.android.systemui.media.dialog.MediaOutputDialogFactory;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -125,7 +126,8 @@
         mGroupMembershipManager = new NotificationGroupManagerLegacy(
                 mStatusBarStateController,
                 () -> mock(PeopleNotificationIdentifier.class),
-                Optional.of((mock(Bubbles.class))));
+                Optional.of((mock(Bubbles.class))),
+                mock(DumpManager.class));
         mGroupExpansionManager = mGroupMembershipManager;
         mHeadsUpManager = new HeadsUpManagerPhone(mContext, mStatusBarStateController,
                 mock(KeyguardBypassController.class), mock(NotificationGroupManagerLegacy.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
index ccdc69a..7e33c01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
@@ -34,6 +34,7 @@
 
 import com.android.internal.view.AppearanceRegion;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.statusbar.policy.BatteryController;
 
@@ -56,8 +57,12 @@
         mLightBarTransitionsController = mock(LightBarTransitionsController.class);
         when(mStatusBarIconController.getTransitionsController()).thenReturn(
                 mLightBarTransitionsController);
-        mLightBarController = new LightBarController(mContext, mStatusBarIconController,
-                mock(BatteryController.class), mock(NavigationModeController.class));
+        mLightBarController = new LightBarController(
+                mContext,
+                mStatusBarIconController,
+                mock(BatteryController.class),
+                mock(NavigationModeController.class),
+                mock(DumpManager.class));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
index 88852f1..80d9c08 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
@@ -37,6 +37,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -93,7 +94,8 @@
         mGroupManager = new NotificationGroupManagerLegacy(
                 mock(StatusBarStateController.class),
                 () -> mPeopleNotificationIdentifier,
-                Optional.of(mock(Bubbles.class)));
+                Optional.of(mock(Bubbles.class)),
+                mock(DumpManager.class));
         mDependency.injectTestDependency(NotificationGroupManagerLegacy.class, mGroupManager);
         mGroupManager.setHeadsUpManager(mHeadsUpManager);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java
index 0110d7b..1be27da 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java
@@ -33,6 +33,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
@@ -76,7 +77,8 @@
         mGroupManager = new NotificationGroupManagerLegacy(
                 mock(StatusBarStateController.class),
                 () -> mPeopleNotificationIdentifier,
-                Optional.of(mock(Bubbles.class)));
+                Optional.of(mock(Bubbles.class)),
+                mock(DumpManager.class));
         mGroupManager.setHeadsUpManager(mHeadsUpManager);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
similarity index 98%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
index a8b2990..e05035d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
@@ -96,6 +96,7 @@
 import com.android.systemui.communal.dagger.CommunalViewComponent;
 import com.android.systemui.controls.dagger.ControlsComponent;
 import com.android.systemui.doze.DozeLog;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentService;
@@ -155,7 +156,7 @@
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
-public class NotificationPanelViewTest extends SysuiTestCase {
+public class NotificationPanelViewControllerTest extends SysuiTestCase {
 
     private static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50;
 
@@ -344,6 +345,8 @@
     private ControlsComponent mControlsComponent;
     @Mock
     private LockscreenGestureLogger mLockscreenGestureLogger;
+    @Mock
+    private DumpManager mDumpManager;
 
     private SysuiStatusBarStateController mStatusBarStateController;
     private NotificationPanelViewController mNotificationPanelViewController;
@@ -355,7 +358,7 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger);
+        mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager);
 
         mKeyguardStatusView = new KeyguardStatusView(mContext);
         mKeyguardStatusView.setId(R.id.keyguard_status_view);
@@ -421,7 +424,7 @@
         NotificationWakeUpCoordinator coordinator =
                 new NotificationWakeUpCoordinator(
                         mock(HeadsUpManagerPhone.class),
-                        new StatusBarStateControllerImpl(new UiEventLoggerFake()),
+                        new StatusBarStateControllerImpl(new UiEventLoggerFake(), mDumpManager),
                         mKeyguardBypassController,
                         mDozeParameters,
                         mUnlockedScreenOffAnimationController);
@@ -536,6 +539,12 @@
     }
 
     @Test
+    public void testSetMinFraction() {
+        mNotificationPanelViewController.setMinFraction(0.5f);
+        verify(mNotificationShadeDepthController).setPanelPullDownMinFraction(eq(0.5f));
+    }
+
+    @Test
     public void testSetDozing_notifiesNsslAndStateController() {
         mNotificationPanelViewController.setDozing(true /* dozing */, false /* animate */,
                 null /* touch */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 38f36bf..5115614 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -45,6 +45,7 @@
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dock.DockManager;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.keyguard.FaceAuthScreenBrightnessController;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
@@ -120,7 +121,10 @@
                 .thenReturn(mBouncer);
 
         when(mContainer.findViewById(anyInt())).thenReturn(mKeyguardMessageArea);
-        mWakefulnessLifecycle = new WakefulnessLifecycle(getContext(), null);
+        mWakefulnessLifecycle = new WakefulnessLifecycle(
+                getContext(),
+                null,
+                mock(DumpManager.class));
         mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(
                 getContext(),
                 mViewMediatorCallback,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 2f7e39b..b23414b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -83,6 +83,7 @@
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -326,7 +327,7 @@
         }).when(mStatusBarKeyguardViewManager).addAfterKeyguardGoneRunnable(any());
 
         WakefulnessLifecycle wakefulnessLifecycle =
-                new WakefulnessLifecycle(mContext, mIWallpaperManager);
+                new WakefulnessLifecycle(mContext, mIWallpaperManager, mock(DumpManager.class));
         wakefulnessLifecycle.dispatchStartedWakingUp(PowerManager.WAKE_REASON_UNKNOWN);
         wakefulnessLifecycle.dispatchFinishedWakingUp();
 
@@ -381,7 +382,7 @@
                 mNetworkController,
                 mBatteryController,
                 mColorExtractor,
-                new ScreenLifecycle(),
+                new ScreenLifecycle(mock(DumpManager.class)),
                 wakefulnessLifecycle,
                 mStatusBarStateController,
                 Optional.of(mBubblesManager),
@@ -440,7 +441,8 @@
                 mWallpaperManager,
                 mUnlockedScreenOffAnimationController,
                 Optional.of(mStartingSurface),
-                mTunerService);
+                mTunerService,
+                mock(DumpManager.class));
         when(mKeyguardViewMediator.registerStatusBar(any(StatusBar.class), any(ViewGroup.class),
                 any(NotificationPanelViewController.class), any(BiometricUnlockController.class),
                 any(ViewGroup.class), any(KeyguardBypassController.class)))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
index 1240a48..14cc032 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
@@ -63,8 +63,12 @@
         mPluginManager = mDependency.injectMockDependency(PluginManager.class);
         mTunerService = mDependency.injectMockDependency(TunerService.class);
         mConfigurationController = mDependency.injectMockDependency(ConfigurationController.class);
-        mExtensionController = new ExtensionControllerImpl(mContext,
-                mock(LeakDetector.class), mPluginManager, mTunerService, mConfigurationController);
+        mExtensionController = new ExtensionControllerImpl(
+                mContext,
+                mock(LeakDetector.class),
+                mPluginManager,
+                mTunerService,
+                mConfigurationController);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
index 5771472..4f1fb02 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
@@ -37,6 +37,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -57,6 +58,8 @@
 public class HotspotControllerImplTest extends SysuiTestCase {
 
     @Mock
+    private DumpManager mDumpManager;
+    @Mock
     private TetheringManager mTetheringManager;
     @Mock
     private WifiManager mWifiManager;
@@ -95,7 +98,7 @@
 
         Handler handler = new Handler(mLooper.getLooper());
 
-        mController = new HotspotControllerImpl(mContext, handler, handler);
+        mController = new HotspotControllerImpl(mContext, handler, handler, mDumpManager);
         verify(mTetheringManager)
                 .registerTetheringEventCallback(any(), mTetheringCallbackCaptor.capture());
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
index 4b87ec8..8ccaf93 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
@@ -32,6 +32,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController;
 
 import org.junit.Before;
@@ -52,12 +53,18 @@
     private KeyguardStateController mKeyguardStateController;
     @Mock
     private SmartspaceTransitionController mSmartSpaceTransitionController;
+    @Mock
+    private DumpManager mDumpManager;
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        mKeyguardStateController = new KeyguardStateControllerImpl(mContext,
-                mKeyguardUpdateMonitor, mLockPatternUtils, mSmartSpaceTransitionController);
+        mKeyguardStateController = new KeyguardStateControllerImpl(
+                mContext,
+                mKeyguardUpdateMonitor,
+                mLockPatternUtils,
+                mSmartSpaceTransitionController,
+                mDumpManager);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
index c38a547..d44cdb2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
@@ -49,6 +49,7 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
@@ -56,6 +57,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -105,7 +107,8 @@
                 mContext,
                 mHandler,
                 mBroadcastDispatcher,
-                mBgExecutor);
+                mBgExecutor,
+                Mockito.mock(DumpManager.class));
 
         verify(mBroadcastDispatcher).registerReceiverWithHandler(
                 brCaptor.capture(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
index b1b9ff4..a59ba8c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
@@ -37,6 +37,7 @@
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.dump.DumpManager
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.qs.QSUserSwitcherEvent
@@ -76,6 +77,7 @@
     @Mock private lateinit var telephonyListenerManager: TelephonyListenerManager
     @Mock private lateinit var secureSettings: SecureSettings
     @Mock private lateinit var falsingManager: FalsingManager
+    @Mock private lateinit var dumpManager: DumpManager
     private lateinit var testableLooper: TestableLooper
     private lateinit var uiBgExecutor: FakeExecutor
     private lateinit var uiEventLogger: UiEventLoggerFake
@@ -106,7 +108,8 @@
 
         `when`(userManager.canAddMoreUsers()).thenReturn(true)
 
-        userSwitcherController = UserSwitcherController(context,
+        userSwitcherController = UserSwitcherController(
+                context,
                 userManager,
                 userTracker,
                 keyguardStateController,
@@ -121,7 +124,8 @@
                 activityTaskManager,
                 userDetailAdapter,
                 secureSettings,
-                uiBgExecutor)
+                uiBgExecutor,
+                dumpManager)
         userSwitcherController.mPauseRefreshUsers = true
 
         picture = UserIcons.convertToBitmap(context.getDrawable(R.drawable.ic_avatar_user))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
index dcf0ef7..336f2b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
@@ -34,6 +34,7 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.statusbar.policy.ZenModeController.Callback;
 
 import org.junit.Before;
@@ -54,6 +55,8 @@
     ZenModeConfig mConfig;
     @Mock
     BroadcastDispatcher mBroadcastDispatcher;
+    @Mock
+    DumpManager mDumpManager;
 
     private ZenModeControllerImpl mController;
 
@@ -63,8 +66,11 @@
         mContext.addMockSystemService(NotificationManager.class, mNm);
         when(mNm.getZenModeConfig()).thenReturn(mConfig);
 
-        mController = new ZenModeControllerImpl(mContext, Handler.createAsync(Looper.myLooper()),
-                mBroadcastDispatcher);
+        mController = new ZenModeControllerImpl(
+                mContext,
+                Handler.createAsync(Looper.myLooper()),
+                mBroadcastDispatcher,
+                mDumpManager);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt
index 2489c30..1fb2aec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt
@@ -34,6 +34,7 @@
 import org.mockito.Captor
 import org.mockito.Mock
 import org.mockito.Mockito
+import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyNoMoreInteractions
 import org.mockito.MockitoAnnotations
@@ -86,14 +87,15 @@
     @Test
     fun testOnActive_broadcastRegistered() {
         liveData.observeForever(observer)
-        verify(broadcastDispatcher).registerReceiver(any(), any(), eq(executor), eq(UserHandle.ALL))
+        verify(broadcastDispatcher)
+                .registerReceiver(any(), any(), eq(executor), eq(UserHandle.ALL), anyInt())
     }
 
     @Test
     fun testOnActive_intentFilterHasIntent() {
         liveData.observeForever(observer)
         verify(broadcastDispatcher).registerReceiver(any(), capture(intentFilterCaptor), any(),
-                any())
+                any(), anyInt())
         assertTrue(intentFilterCaptor.value.hasAction(INTENT))
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/leak/GarbageMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/leak/GarbageMonitorTest.java
index 724d14e..a2b016f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/leak/GarbageMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/leak/GarbageMonitorTest.java
@@ -26,6 +26,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.concurrency.MessageRouterImpl;
 import com.android.systemui.util.time.FakeSystemClock;
@@ -42,6 +43,7 @@
 
     @Mock private LeakReporter mLeakReporter;
     @Mock private TrackedGarbage mTrackedGarbage;
+    @Mock private DumpManager mDumpManager;
     private GarbageMonitor mGarbageMonitor;
     private final FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
 
@@ -53,8 +55,9 @@
                         mContext,
                         mFakeExecutor,
                         new MessageRouterImpl(mFakeExecutor),
-                        new LeakDetector(null, mTrackedGarbage, null),
-                        mLeakReporter);
+                        new LeakDetector(null, mTrackedGarbage, null, mDumpManager),
+                        mLeakReporter,
+                        mDumpManager);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakDetectorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakDetectorTest.java
index c68c920..6e42f0c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakDetectorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakDetectorTest.java
@@ -21,12 +21,14 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.util.leak.ReferenceTestUtils.CollectionWaiter;
 
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mockito;
 
 import java.io.FileOutputStream;
 import java.io.PrintWriter;
@@ -67,7 +69,7 @@
 
     @Before
     public void setup() {
-        mLeakDetector = LeakDetector.create();
+        mLeakDetector = LeakDetector.create(Mockito.mock(DumpManager.class));
 
         // Note: Do not try to factor out object / collection waiter creation. The optimizer will
         // try and cache accesses to fields and thus create a GC root for the duration of the test
@@ -112,7 +114,7 @@
 
     @Test
     public void testDisabled() throws Exception {
-        mLeakDetector = new LeakDetector(null, null, null);
+        mLeakDetector = new LeakDetector(null, null, null, Mockito.mock(DumpManager.class));
 
         Object o1 = new Object();
         Object o2 = new Object();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java
index 8e1c0f7..d245c72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java
@@ -30,24 +30,24 @@
 
     @Override
     public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
-            Class<?> cls, boolean allowMultiple) {
+            Class<T> cls, boolean allowMultiple) {
         mLeakChecker.addCallback(listener);
     }
 
     @Override
-    public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls) {
+    public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<T> cls) {
         mLeakChecker.addCallback(listener);
     }
 
     @Override
-    public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls,
+    public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<T> cls,
             boolean allowMultiple) {
         mLeakChecker.addCallback(listener);
     }
 
     @Override
     public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
-            Class<?> cls) {
+            Class<T> cls) {
         mLeakChecker.addCallback(listener);
     }
 
diff --git a/packages/VpnDialogs/res/values-in/strings.xml b/packages/VpnDialogs/res/values-in/strings.xml
index 059008f..88a588c 100644
--- a/packages/VpnDialogs/res/values-in/strings.xml
+++ b/packages/VpnDialogs/res/values-in/strings.xml
@@ -19,19 +19,19 @@
     <string name="prompt" msgid="3183836924226407828">"Permintaan sambungan"</string>
     <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ingin menyiapkan sambungan VPN yang memungkinkannya memantau traffic jaringan. Terima hanya jika Anda memercayai sumber. &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; muncul di bagian atas layar Anda saat VPN aktif."</string>
     <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ingin menyiapkan koneksi VPN yang memungkinkannya memantau traffic jaringan. Hanya terima jika Anda memercayai sumbernya. &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; muncul di layar bila VPN aktif."</string>
-    <string name="legacy_title" msgid="192936250066580964">"VPN tersambung"</string>
+    <string name="legacy_title" msgid="192936250066580964">"VPN terhubung"</string>
     <string name="session" msgid="6470628549473641030">"Sesi:"</string>
     <string name="duration" msgid="3584782459928719435">"Durasi:"</string>
     <string name="data_transmitted" msgid="7988167672982199061">"Terkirim:"</string>
     <string name="data_received" msgid="4062776929376067820">"Diterima:"</string>
     <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bita / <xliff:g id="NUMBER_1">%2$s</xliff:g> paket"</string>
-    <string name="always_on_disconnected_title" msgid="1906740176262776166">"Tidak dapat tersambung ke VPN yang selalu aktif"</string>
-    <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> disiapkan untuk selalu tersambung, tetapi saat ini tidak dapat tersambung. Ponsel akan menggunakan jaringan publik sampai dapat tersambung ulang ke <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string>
-    <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> disiapkan untuk selalu tersambung, tetapi saat ini tidak dapat tersambung. Anda akan tersambung jika VPN dapat tersambung ulang."</string>
+    <string name="always_on_disconnected_title" msgid="1906740176262776166">"Tidak dapat terhubung ke VPN yang selalu aktif"</string>
+    <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> disiapkan untuk selalu terhubung, tetapi saat ini tidak dapat terhubung. Ponsel akan menggunakan jaringan publik sampai dapat terhubung ulang ke <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string>
+    <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> disiapkan untuk selalu terhubung, tetapi saat ini tidak dapat terhubung. Anda akan terhubung jika VPN dapat terhubung ulang."</string>
     <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
     <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Ubah setelan VPN"</string>
     <string name="configure" msgid="4905518375574791375">"Konfigurasikan"</string>
-    <string name="disconnect" msgid="971412338304200056">"Putuskan sambungan"</string>
+    <string name="disconnect" msgid="971412338304200056">"Putuskan koneksi"</string>
     <string name="open_app" msgid="3717639178595958667">"Buka aplikasi"</string>
     <string name="dismiss" msgid="6192859333764711227">"Tutup"</string>
 </resources>
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index b88366b..acdbcb58 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -86,7 +86,7 @@
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
 import com.android.server.accessibility.AccessibilityWindowManager.RemoteAccessibilityConnection;
-import com.android.server.accessibility.magnification.FullScreenMagnificationController;
+import com.android.server.accessibility.magnification.MagnificationProcessor;
 import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -223,10 +223,10 @@
         @Nullable FingerprintGestureDispatcher getFingerprintGestureDispatcher();
 
         /**
-         * @return The magnification controller
+         * @return The magnification processor
          */
         @NonNull
-        FullScreenMagnificationController getFullScreenMagnificationController();
+        MagnificationProcessor getMagnificationProcessor();
 
         /**
          * Called back to notify system that the client has changed
@@ -975,7 +975,7 @@
         }
         final long identity = Binder.clearCallingIdentity();
         try {
-            return mSystemSupport.getFullScreenMagnificationController().getScale(displayId);
+            return mSystemSupport.getMagnificationProcessor().getScale(displayId);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -991,19 +991,15 @@
             if (!hasRightsToCurrentUserLocked()) {
                 return region;
             }
-            FullScreenMagnificationController magnificationController =
-                    mSystemSupport.getFullScreenMagnificationController();
-            boolean registeredJustForThisCall =
-                    registerMagnificationIfNeeded(displayId, magnificationController);
+            MagnificationProcessor magnificationProcessor =
+                    mSystemSupport.getMagnificationProcessor();
             final long identity = Binder.clearCallingIdentity();
             try {
-                magnificationController.getMagnificationRegion(displayId, region);
+                magnificationProcessor.getMagnificationRegion(displayId, region,
+                        mSecurityPolicy.canControlMagnification(this));
                 return region;
             } finally {
                 Binder.restoreCallingIdentity(identity);
-                if (registeredJustForThisCall) {
-                    magnificationController.unregister(displayId);
-                }
             }
         }
     }
@@ -1017,18 +1013,14 @@
             if (!hasRightsToCurrentUserLocked()) {
                 return 0.0f;
             }
-            FullScreenMagnificationController magnificationController =
-                    mSystemSupport.getFullScreenMagnificationController();
-            boolean registeredJustForThisCall =
-                    registerMagnificationIfNeeded(displayId, magnificationController);
+            MagnificationProcessor magnificationProcessor =
+                    mSystemSupport.getMagnificationProcessor();
             final long identity = Binder.clearCallingIdentity();
             try {
-                return magnificationController.getCenterX(displayId);
+                return magnificationProcessor.getCenterX(displayId,
+                        mSecurityPolicy.canControlMagnification(this));
             } finally {
                 Binder.restoreCallingIdentity(identity);
-                if (registeredJustForThisCall) {
-                    magnificationController.unregister(displayId);
-                }
             }
         }
     }
@@ -1042,32 +1034,18 @@
             if (!hasRightsToCurrentUserLocked()) {
                 return 0.0f;
             }
-            FullScreenMagnificationController magnificationController =
-                    mSystemSupport.getFullScreenMagnificationController();
-            boolean registeredJustForThisCall =
-                    registerMagnificationIfNeeded(displayId, magnificationController);
+            MagnificationProcessor magnificationProcessor =
+                    mSystemSupport.getMagnificationProcessor();
             final long identity = Binder.clearCallingIdentity();
             try {
-                return magnificationController.getCenterY(displayId);
+                return magnificationProcessor.getCenterY(displayId,
+                        mSecurityPolicy.canControlMagnification(this));
             } finally {
                 Binder.restoreCallingIdentity(identity);
-                if (registeredJustForThisCall) {
-                    magnificationController.unregister(displayId);
-                }
             }
         }
     }
 
-    private boolean registerMagnificationIfNeeded(int displayId,
-            FullScreenMagnificationController magnificationController) {
-        if (!magnificationController.isRegistered(displayId)
-                && mSecurityPolicy.canControlMagnification(this)) {
-            magnificationController.register(displayId);
-            return true;
-        }
-        return false;
-    }
-
     @Override
     public boolean resetMagnification(int displayId, boolean animate) {
         if (svcConnTracingEnabled()) {
@@ -1083,10 +1061,10 @@
         }
         final long identity = Binder.clearCallingIdentity();
         try {
-            FullScreenMagnificationController magnificationController =
-                    mSystemSupport.getFullScreenMagnificationController();
-            return (magnificationController.reset(displayId, animate)
-                    || !magnificationController.isMagnifying(displayId));
+            MagnificationProcessor magnificationProcessor =
+                    mSystemSupport.getMagnificationProcessor();
+            return (magnificationProcessor.reset(displayId, animate)
+                    || !magnificationProcessor.isMagnifying(displayId));
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -1109,12 +1087,9 @@
             }
             final long identity = Binder.clearCallingIdentity();
             try {
-                FullScreenMagnificationController magnificationController =
-                        mSystemSupport.getFullScreenMagnificationController();
-                if (!magnificationController.isRegistered(displayId)) {
-                    magnificationController.register(displayId);
-                }
-                return magnificationController
+                MagnificationProcessor magnificationProcessor =
+                        mSystemSupport.getMagnificationProcessor();
+                return magnificationProcessor
                         .setScaleAndCenter(displayId, scale, centerX, centerY, animate, mId);
             } finally {
                 Binder.restoreCallingIdentity(identity);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 7d2b71f..10cfd04 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -608,7 +608,8 @@
             final Context uiContext = displayContext.createWindowContext(
                     TYPE_MAGNIFICATION_OVERLAY, null /* options */);
             magnificationGestureHandler = new FullScreenMagnificationGestureHandler(uiContext,
-                    mAms.getFullScreenMagnificationController(), mAms.getTraceManager(),
+                    mAms.getMagnificationController().getFullScreenMagnificationController(),
+                    mAms.getTraceManager(),
                     mAms.getMagnificationController(), detectControlGestures, triggerable,
                     new WindowMagnificationPromptController(displayContext, mUserId), displayId);
         }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index a9cd0ed..aff7eb2 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -126,8 +126,8 @@
 import com.android.internal.util.IntPair;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
-import com.android.server.accessibility.magnification.FullScreenMagnificationController;
 import com.android.server.accessibility.magnification.MagnificationController;
+import com.android.server.accessibility.magnification.MagnificationProcessor;
 import com.android.server.accessibility.magnification.WindowMagnificationManager;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.wm.ActivityTaskManagerInternal;
@@ -219,6 +219,9 @@
 
     private final ActivityTaskManagerInternal mActivityTaskManagerService;
 
+    private final MagnificationController mMagnificationController;
+    private final MagnificationProcessor mMagnificationProcessor;
+
     private final MainHandler mMainHandler;
 
     // Lazily initialized - access through getSystemActionPerfomer()
@@ -261,7 +264,6 @@
 
     private Point mTempPoint = new Point();
     private boolean mIsAccessibilityButtonShown;
-    private MagnificationController mMagnificationController;
 
     private AccessibilityUserState getCurrentUserStateLocked() {
         return getUserStateLocked(mCurrentUserId);
@@ -308,6 +310,7 @@
         mA11yWindowManager = a11yWindowManager;
         mA11yDisplayListener = a11yDisplayListener;
         mMagnificationController = magnificationController;
+        mMagnificationProcessor = new MagnificationProcessor(mMagnificationController);
         init();
     }
 
@@ -336,6 +339,7 @@
                 mWindowManagerService, this, mSecurityPolicy, this, mTraceManager);
         mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler);
         mMagnificationController = new MagnificationController(this, mLock, mContext);
+        mMagnificationProcessor = new MagnificationProcessor(mMagnificationController);
         init();
     }
 
@@ -2535,7 +2539,7 @@
 
         if (mUiAutomationManager.suppressingAccessibilityServicesLocked()
                 && mMagnificationController.isFullScreenMagnificationControllerInitialized()) {
-            getFullScreenMagnificationController().unregisterAll();
+            getMagnificationController().getFullScreenMagnificationController().unregisterAll();
             return;
         }
 
@@ -2547,7 +2551,8 @@
                 || userState.isShortcutMagnificationEnabledLocked()) {
             for (int i = 0; i < displays.size(); i++) {
                 final Display display = displays.get(i);
-                getFullScreenMagnificationController().register(display.getDisplayId());
+                getMagnificationController().getFullScreenMagnificationController().register(
+                        display.getDisplayId());
             }
             return;
         }
@@ -2557,9 +2562,11 @@
             final Display display = displays.get(i);
             final int displayId = display.getDisplayId();
             if (userHasListeningMagnificationServicesLocked(userState, displayId)) {
-                getFullScreenMagnificationController().register(displayId);
+                getMagnificationController().getFullScreenMagnificationController().register(
+                        displayId);
             } else if (mMagnificationController.isFullScreenMagnificationControllerInitialized()) {
-                getFullScreenMagnificationController().unregister(displayId);
+                getMagnificationController().getFullScreenMagnificationController().unregister(
+                        displayId);
             }
         }
     }
@@ -2922,7 +2929,9 @@
         }
         // In case user assigned magnification to the given shortcut.
         if (targetName.equals(MAGNIFICATION_CONTROLLER_NAME)) {
-            final boolean enabled = !getFullScreenMagnificationController().isMagnifying(displayId);
+            final boolean enabled =
+                    !getMagnificationController().getFullScreenMagnificationController()
+                            .isMagnifying(displayId);
             logAccessibilityShortcutActivated(mContext, MAGNIFICATION_COMPONENT_NAME, shortcutType,
                     enabled);
             sendAccessibilityButtonToInputFilter(displayId);
@@ -3259,9 +3268,7 @@
      * @return MagnificationController
      */
     MagnificationController getMagnificationController() {
-        synchronized (mLock) {
-            return mMagnificationController;
-        }
+        return mMagnificationController;
     }
 
     @Override
@@ -3378,10 +3385,8 @@
     }
 
     @Override
-    public FullScreenMagnificationController getFullScreenMagnificationController() {
-        synchronized (mLock) {
-            return mMagnificationController.getFullScreenMagnificationController();
-        }
+    public MagnificationProcessor getMagnificationProcessor() {
+        return mMagnificationProcessor;
     }
 
     @Override
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index 467cab5..4bf48a2 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -123,7 +123,7 @@
         AccessibilityUserState userState = mUserStateWeakReference.get();
         if (userState == null) return;
         userState.removeServiceLocked(this);
-        mSystemSupport.getFullScreenMagnificationController().resetAllIfNeeded(mId);
+        mSystemSupport.getMagnificationProcessor().resetAllIfNeeded(mId);
         mActivityTaskManagerService.setAllowAppSwitches(mComponentName.flattenToString(), -1,
                 userState.mUserId);
         resetLocked();
@@ -334,7 +334,7 @@
                 userState.serviceDisconnectedLocked(this);
             }
             resetLocked();
-            mSystemSupport.getFullScreenMagnificationController().resetAllIfNeeded(mId);
+            mSystemSupport.getMagnificationProcessor().resetAllIfNeeded(mId);
             mSystemSupport.onClientChangeLocked(false);
         }
     }
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java
new file mode 100644
index 0000000..efc6d51
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility.magnification;
+
+import android.annotation.NonNull;
+import android.graphics.Region;
+
+/**
+ * Processor class for AccessibilityService connection to control magnification on the specified
+ * display. This wraps the function of magnification controller.
+ *
+ * @see MagnificationController
+ * @see FullScreenMagnificationController
+ */
+public class MagnificationProcessor {
+
+    private final MagnificationController mController;
+
+    public MagnificationProcessor(MagnificationController controller) {
+        mController = controller;
+    }
+
+    /**
+     * {@link FullScreenMagnificationController#getScale(int)}
+     */
+    public float getScale(int displayId) {
+        return mController.getFullScreenMagnificationController().getScale(displayId);
+    }
+
+    /**
+     * {@link FullScreenMagnificationController#getCenterX(int)}
+     */
+    public float getCenterX(int displayId, boolean canControlMagnification) {
+        boolean registeredJustForThisCall = registerMagnificationIfNeeded(displayId,
+                canControlMagnification);
+        try {
+            return mController.getFullScreenMagnificationController().getCenterX(displayId);
+        } finally {
+            if (registeredJustForThisCall) {
+                unregister(displayId);
+            }
+        }
+    }
+
+    /**
+     * {@link FullScreenMagnificationController#getCenterY(int)}
+     */
+    public float getCenterY(int displayId, boolean canControlMagnification) {
+        boolean registeredJustForThisCall = registerMagnificationIfNeeded(displayId,
+                canControlMagnification);
+        try {
+            return mController.getFullScreenMagnificationController().getCenterY(displayId);
+        } finally {
+            if (registeredJustForThisCall) {
+                unregister(displayId);
+            }
+        }
+    }
+
+    /**
+     * {@link FullScreenMagnificationController#getMagnificationRegion(int, Region)}
+     */
+    public Region getMagnificationRegion(int displayId, @NonNull Region outRegion,
+            boolean canControlMagnification) {
+        boolean registeredJustForThisCall = registerMagnificationIfNeeded(displayId,
+                canControlMagnification);
+        try {
+            mController.getFullScreenMagnificationController().getMagnificationRegion(displayId,
+                    outRegion);
+            return outRegion;
+        } finally {
+            if (registeredJustForThisCall) {
+                unregister(displayId);
+            }
+        }
+    }
+
+    /**
+     * {@link FullScreenMagnificationController#setScaleAndCenter(int, float, float, float, boolean,
+     * int)}
+     */
+    public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY,
+            boolean animate, int id) {
+        if (!isRegistered(displayId)) {
+            register(displayId);
+        }
+        return mController.getFullScreenMagnificationController().setScaleAndCenter(displayId,
+                scale,
+                centerX, centerY, animate, id);
+    }
+
+    /**
+     * {@link FullScreenMagnificationController#reset(int, boolean)}
+     */
+    public boolean reset(int displayId, boolean animate) {
+        return mController.getFullScreenMagnificationController().reset(displayId, animate);
+    }
+
+    /**
+     * {@link FullScreenMagnificationController#resetIfNeeded(int, boolean)}
+     */
+    public void resetAllIfNeeded(int connectionId) {
+        mController.getFullScreenMagnificationController().resetAllIfNeeded(connectionId);
+    }
+
+    /**
+     * {@link FullScreenMagnificationController#register(int)}
+     */
+    public void register(int displayId) {
+        mController.getFullScreenMagnificationController().register(displayId);
+    }
+
+    /**
+     * {@link FullScreenMagnificationController#unregister(int)} (int)}
+     */
+    public void unregister(int displayId) {
+        mController.getFullScreenMagnificationController().unregister(displayId);
+    }
+
+    /**
+     * {@link FullScreenMagnificationController#isMagnifying(int)}
+     */
+    public boolean isMagnifying(int displayId) {
+        return mController.getFullScreenMagnificationController().isMagnifying(displayId);
+    }
+
+    /**
+     * {@link FullScreenMagnificationController#isRegistered(int)}
+     */
+    public boolean isRegistered(int displayId) {
+        return mController.getFullScreenMagnificationController().isRegistered(displayId);
+    }
+
+    private boolean registerMagnificationIfNeeded(int displayId, boolean canControlMagnification) {
+        if (!isRegistered(displayId) && canControlMagnification) {
+            register(displayId);
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/services/backup/lint-baseline.xml b/services/backup/lint-baseline.xml
new file mode 100644
index 0000000..28bb937
--- /dev/null
+++ b/services/backup/lint-baseline.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 7.1.0-dev" type="baseline" client="" dependencies="true" name="" variant="all" version="7.1.0-dev">
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        return Settings.Secure.getInt(mContext.getContentResolver(), SKIP_USER_FACING_PACKAGES,"
+        errorLine2="               ~~~~~~">
+        <location
+            file="frameworks/base/services/backup/java/com/android/server/backup/UserBackupManagerService.java"
+            line="3702"
+            column="16"/>
+    </issue>
+
+</issues>
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 28a40eb..44a4997 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -48,6 +48,7 @@
 import android.annotation.SuppressLint;
 import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
+import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.role.RoleManager;
 import android.bluetooth.BluetoothAdapter;
@@ -584,12 +585,16 @@
             }
         }
 
+        /**
+        * @deprecated Use
+        * {@link NotificationManager#isNotificationListenerAccessGranted(ComponentName)} instead.
+        */
+        @Deprecated
         @Override
         public boolean hasNotificationAccess(ComponentName component) throws RemoteException {
             checkCanCallNotificationApi(component.getPackageName());
-            String setting = Settings.Secure.getString(getContext().getContentResolver(),
-                    Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
-            return new ComponentNameSet(setting).contains(component);
+            NotificationManager nm = getContext().getSystemService(NotificationManager.class);
+            return nm.isNotificationListenerAccessGranted(component);
         }
 
         @Override
diff --git a/services/companion/lint-baseline.xml b/services/companion/lint-baseline.xml
new file mode 100644
index 0000000..03eae39
--- /dev/null
+++ b/services/companion/lint-baseline.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 7.1.0-dev" type="baseline" client="" dependencies="true" name="" variant="all" version="7.1.0-dev">
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="            String setting = Settings.Secure.getString(getContext().getContentResolver(),"
+        errorLine2="             ~~~~~~~~~">
+        <location
+            file="frameworks/base/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java"
+            line="590"
+            column="14"/>
+    </issue>
+
+</issues>
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 608cbf2..d911388 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -186,8 +186,6 @@
     private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock();
     private boolean mBinding;
     private boolean mUnbinding;
-    private int mWaitForEnableRetry;
-    private int mWaitForDisableRetry;
 
     private BluetoothModeChangeHelper mBluetoothModeChangeHelper;
 
@@ -956,14 +954,15 @@
         if (mState == BluetoothAdapter.STATE_ON
                 || mState == BluetoothAdapter.STATE_BLE_ON
                 || mState == BluetoothAdapter.STATE_TURNING_ON
-                || mState == BluetoothAdapter.STATE_TURNING_OFF) {
-            Log.d(TAG, "enableBLE(): Bluetooth already enabled");
+                || mState == BluetoothAdapter.STATE_TURNING_OFF
+                || mState == BluetoothAdapter.STATE_BLE_TURNING_ON) {
+            Log.d(TAG, "enableBLE(): Bluetooth is already enabled or is turning on");
             return true;
         }
         synchronized (mReceiver) {
             // waive WRITE_SECURE_SETTINGS permission check
-            sendEnableMsg(false,
-                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
+            sendEnableMsg(false, BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
+                    packageName, true);
         }
         return true;
     }
@@ -1776,6 +1775,8 @@
 
     private class BluetoothHandler extends Handler {
         boolean mGetNameAddressOnly = false;
+        private int mWaitForEnableRetry;
+        private int mWaitForDisableRetry;
 
         BluetoothHandler(Looper looper) {
             super(looper);
@@ -1826,11 +1827,12 @@
 
                 case MESSAGE_ENABLE:
                     int quietEnable = msg.arg1;
+                    int isBle  = msg.arg2;
                     if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED)
                             || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) {
                         // We are handling enable or disable right now, wait for it.
                         mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_ENABLE,
-                                quietEnable, 0), ENABLE_DISABLE_DELAY_MS);
+                                quietEnable, isBle), ENABLE_DISABLE_DELAY_MS);
                         break;
                     }
 
@@ -1845,13 +1847,28 @@
                     try {
                         mBluetoothLock.readLock().lock();
                         if (mBluetooth != null) {
+                            boolean isHandled = true;
                             int state = mBluetooth.getState();
-                            if (state == BluetoothAdapter.STATE_BLE_ON) {
-                                Slog.w(TAG, "BT Enable in BLE_ON State, going to ON");
-                                mBluetooth.onLeServiceUp(mContext.getAttributionSource());
-                                persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
-                                break;
+                            switch (state) {
+                                case BluetoothAdapter.STATE_BLE_ON:
+                                    if (isBle == 1) {
+                                        Slog.i(TAG, "Already at BLE_ON State");
+                                    } else {
+                                        Slog.w(TAG, "BT Enable in BLE_ON State, going to ON");
+                                        mBluetooth.onLeServiceUp(mContext.getAttributionSource());
+                                        persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
+                                    }
+                                    break;
+                                case BluetoothAdapter.STATE_BLE_TURNING_ON:
+                                case BluetoothAdapter.STATE_TURNING_ON:
+                                case BluetoothAdapter.STATE_ON:
+                                    Slog.i(TAG, "MESSAGE_ENABLE: already enabled");
+                                    break;
+                                default:
+                                    isHandled = false;
+                                    break;
                             }
+                            if (isHandled) break;
                         }
                     } catch (RemoteException e) {
                         Slog.e(TAG, "", e);
@@ -2617,7 +2634,12 @@
     }
 
     private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
-        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0));
+        sendEnableMsg(quietMode, reason, packageName, false);
+    }
+
+    private void sendEnableMsg(boolean quietMode, int reason, String packageName, boolean isBle) {
+        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0,
+                  isBle ? 1 : 0));
         addActiveLog(reason, packageName, true);
         mLastEnabledTime = SystemClock.elapsedRealtime();
     }
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index c3543e7..c1c9fbb 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -327,18 +327,23 @@
         }
     }
 
-    private static int getMaxRescueLevel() {
-        return SystemProperties.getBoolean(PROP_DISABLE_FACTORY_RESET_FLAG, false)
-                ? LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS : LEVEL_FACTORY_RESET;
+    private static int getMaxRescueLevel(boolean mayPerformFactoryReset) {
+        if (!mayPerformFactoryReset
+                || SystemProperties.getBoolean(PROP_DISABLE_FACTORY_RESET_FLAG, false)) {
+            return LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS;
+        }
+        return LEVEL_FACTORY_RESET;
     }
 
     /**
      * Get the rescue level to perform if this is the n-th attempt at mitigating failure.
      *
      * @param mitigationCount: the mitigation attempt number (1 = first attempt etc.)
+     * @param mayPerformFactoryReset: whether or not a factory reset may be performed for the given
+     *                              failure.
      * @return the rescue level for the n-th mitigation attempt.
      */
-    private static int getRescueLevel(int mitigationCount) {
+    private static int getRescueLevel(int mitigationCount, boolean mayPerformFactoryReset) {
         if (mitigationCount == 1) {
             return LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS;
         } else if (mitigationCount == 2) {
@@ -346,9 +351,9 @@
         } else if (mitigationCount == 3) {
             return LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS;
         } else if (mitigationCount == 4) {
-            return Math.min(getMaxRescueLevel(), LEVEL_WARM_REBOOT);
+            return Math.min(getMaxRescueLevel(mayPerformFactoryReset), LEVEL_WARM_REBOOT);
         } else if (mitigationCount >= 5) {
-            return Math.min(getMaxRescueLevel(), LEVEL_FACTORY_RESET);
+            return Math.min(getMaxRescueLevel(mayPerformFactoryReset), LEVEL_FACTORY_RESET);
         } else {
             Slog.w(TAG, "Expected positive mitigation count, was " + mitigationCount);
             return LEVEL_NONE;
@@ -614,7 +619,8 @@
                 @FailureReasons int failureReason, int mitigationCount) {
             if (!isDisabled() && (failureReason == PackageWatchdog.FAILURE_REASON_APP_CRASH
                     || failureReason == PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING)) {
-                return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount));
+                return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount,
+                        mayPerformFactoryReset(failedPackage)));
             } else {
                 return PackageHealthObserverImpact.USER_IMPACT_NONE;
             }
@@ -628,7 +634,8 @@
             }
             if (failureReason == PackageWatchdog.FAILURE_REASON_APP_CRASH
                     || failureReason == PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING) {
-                final int level = getRescueLevel(mitigationCount);
+                final int level = getRescueLevel(mitigationCount,
+                        mayPerformFactoryReset(failedPackage));
                 executeRescueLevel(mContext,
                         failedPackage == null ? null : failedPackage.getPackageName(), level);
                 return true;
@@ -653,12 +660,7 @@
             } catch (PackageManager.NameNotFoundException ignore) {
             }
 
-            try {
-                ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
-                return (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK;
-            } catch (PackageManager.NameNotFoundException e) {
-                return false;
-            }
+            return isPersistentSystemApp(packageName);
         }
 
         @Override
@@ -666,7 +668,7 @@
             if (isDisabled()) {
                 return PackageHealthObserverImpact.USER_IMPACT_NONE;
             }
-            return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount));
+            return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount, true));
         }
 
         @Override
@@ -674,7 +676,8 @@
             if (isDisabled()) {
                 return false;
             }
-            executeRescueLevel(mContext, /*failedPackage=*/ null, getRescueLevel(mitigationCount));
+            executeRescueLevel(mContext, /*failedPackage=*/ null,
+                    getRescueLevel(mitigationCount, true));
             return true;
         }
 
@@ -683,6 +686,29 @@
             return NAME;
         }
 
+        /**
+         * Returns {@code true} if the failing package is non-null and performing a reboot or
+         * prompting a factory reset is an acceptable mitigation strategy for the package's
+         * failure, {@code false} otherwise.
+         */
+        private boolean mayPerformFactoryReset(@Nullable VersionedPackage failingPackage) {
+            if (failingPackage == null) {
+                return false;
+            }
+
+            return isPersistentSystemApp(failingPackage.getPackageName());
+        }
+
+        private boolean isPersistentSystemApp(@NonNull String packageName) {
+            PackageManager pm = mContext.getPackageManager();
+            try {
+                ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
+                return (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK;
+            } catch (PackageManager.NameNotFoundException e) {
+                return false;
+            }
+        }
+
         private synchronized void recordDeviceConfigAccess(@NonNull String callingPackage,
                 @NonNull String namespace) {
             // Record it in calling packages to namespace map
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index edf832f..b4413a4 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1889,11 +1889,12 @@
                         try {
                             if (!mConfigurationProvider.isDisplayInfoNrAdvancedSupported(
                                     r.callingPackage, Binder.getCallingUserHandle())) {
-                                telephonyDisplayInfo =
+                                r.callback.onDisplayInfoChanged(
                                         getBackwardCompatibleTelephonyDisplayInfo(
-                                                telephonyDisplayInfo);
+                                                telephonyDisplayInfo));
+                            } else {
+                                r.callback.onDisplayInfoChanged(telephonyDisplayInfo);
                             }
-                            r.callback.onDisplayInfoChanged(telephonyDisplayInfo);
                         } catch (RemoteException ex) {
                             mRemoveList.add(r.binder);
                         }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 3ba1cb2..baf5af5 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -5286,7 +5286,7 @@
                 psr.updateBoundClientUids();
             }
 
-            // Sanity check: if the service listed for the app is not one
+            // Check: if the service listed for the app is not one
             // we actually are maintaining, just let it drop.
             final ServiceRecord curRec = smap.mServicesByInstanceName.get(sr.instanceName);
             if (curRec != sr) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index ac537fa..db49b56 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -169,6 +169,7 @@
     private static final float DEFAULT_FGS_ATOM_SAMPLE_RATE = 1; // 100 %
     private static final float DEFAULT_FGS_START_ALLOWED_LOG_SAMPLE_RATE = 0.25f; // 25%
     private static final float DEFAULT_FGS_START_DENIED_LOG_SAMPLE_RATE = 1; // 100%
+    private static final long DEFAULT_PROCESS_KILL_TIMEOUT_MS = 10 * 1000;
 
     static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60 * 1000;
     static final long DEFAULT_KILL_BG_RESTRICTED_CACHED_IDLE_SETTLE_TIME_MS = 60 * 1000;
@@ -286,6 +287,11 @@
     private static final String KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR =
             "push_messaging_over_quota_behavior";
 
+    /**
+     * Time in milliseconds; the allowed duration from a process is killed until it's really gone.
+     */
+    private static final String KEY_PROCESS_KILL_TIMEOUT = "process_kill_timeout";
+
     // Maximum number of cached processes we will allow.
     public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
 
@@ -566,6 +572,11 @@
             DEFAULT_KILL_BG_RESTRICTED_CACHED_IDLE_SETTLE_TIME_MS;
 
     /**
+     * The allowed duration from a process is killed until it's really gone.
+     */
+    volatile long mProcessKillTimeoutMs = DEFAULT_PROCESS_KILL_TIMEOUT_MS;
+
+    /**
      * Whether to allow "opt-out" from the foreground service restrictions.
      * (https://developer.android.com/about/versions/12/foreground-services)
      */
@@ -828,6 +839,9 @@
                             case KEY_COMPONENT_ALIAS_OVERRIDES:
                                 updateComponentAliases();
                                 break;
+                            case KEY_PROCESS_KILL_TIMEOUT:
+                                updateProcessKillTimeout();
+                                break;
                             default:
                                 break;
                         }
@@ -1271,6 +1285,13 @@
         mService.mComponentAliasResolver.update(mEnableComponentAlias, mComponentAliasOverrides);
     }
 
+    private void updateProcessKillTimeout() {
+        mProcessKillTimeoutMs = DeviceConfig.getLong(
+                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_PROCESS_KILL_TIMEOUT,
+                DEFAULT_PROCESS_KILL_TIMEOUT_MS);
+    }
+
     private void updateImperceptibleKillExemptions() {
         IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.clear();
         IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.addAll(mDefaultImperceptibleKillExemptPackages);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 18cc154..0e57236 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -121,6 +121,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.MemoryStatUtil.hasMemcg;
+import static com.android.server.am.ProcessList.ProcStartHandler;
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
@@ -376,6 +377,7 @@
 import com.android.server.ThreadPriorityBooster;
 import com.android.server.UserspaceRebootLogger;
 import com.android.server.Watchdog;
+import com.android.server.am.ComponentAliasResolver.Resolution;
 import com.android.server.am.LowMemDetector.MemFactor;
 import com.android.server.appop.AppOpsService;
 import com.android.server.compat.PlatformCompat;
@@ -1502,7 +1504,7 @@
     final MainHandler mHandler;
     final Handler mUiHandler;
     final ServiceThread mProcStartHandlerThread;
-    final Handler mProcStartHandler;
+    final ProcStartHandler mProcStartHandler;
 
     ActivityManagerConstants mConstants;
 
@@ -1691,7 +1693,7 @@
             case PROC_START_TIMEOUT_MSG: {
                 ProcessRecord app = (ProcessRecord) msg.obj;
                 synchronized (ActivityManagerService.this) {
-                    processStartTimedOutLocked(app);
+                    handleProcessStartOrKillTimeoutLocked(app, /* isKillTimeout */ false);
                 }
             } break;
             case CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG: {
@@ -2261,7 +2263,7 @@
         mProcStartHandlerThread = new ServiceThread(TAG + ":procStart",
                 THREAD_PRIORITY_FOREGROUND, false /* allowIo */);
         mProcStartHandlerThread.start();
-        mProcStartHandler = new Handler(mProcStartHandlerThread.getLooper());
+        mProcStartHandler = new ProcStartHandler(this, mProcStartHandlerThread.getLooper());
 
         mConstants = new ActivityManagerConstants(mContext, this, mHandler);
         final ActiveUids activeUids = new ActiveUids(this, true /* postChangesToAtm */);
@@ -4254,47 +4256,81 @@
     }
 
     @GuardedBy("this")
-    private final void processStartTimedOutLocked(ProcessRecord app) {
+    void handleProcessStartOrKillTimeoutLocked(ProcessRecord app, boolean isKillTimeout) {
         final int pid = app.getPid();
-        boolean gone = removePidIfNoThreadLocked(app);
+        boolean gone = isKillTimeout || removePidIfNoThreadLocked(app);
 
         if (gone) {
-            Slog.w(TAG, "Process " + app + " failed to attach");
-            EventLogTags.writeAmProcessStartTimeout(app.userId, pid, app.uid, app.processName);
+            if (isKillTimeout) {
+                // It's still alive... maybe blocked at uninterruptible sleep ?
+                final ProcessRecord successor = app.mSuccessor;
+                if (successor == null) {
+                    // There might be a race, nothing to do here.
+                    return;
+                }
+                Slog.wtf(TAG, app.toString() + " " + app.getDyingPid()
+                        + " refused to die while trying to launch " + successor
+                        + ", cancelling the process start");
+
+                // It doesn't make sense to proceed with launching the new instance while the old
+                // instance is still alive, abort the launch.
+                app.mSuccessorStartRunnable = null;
+                app.mSuccessor = null;
+                successor.mPredecessor = null;
+
+                // We're going to cleanup the successor process record, which wasn't started at all.
+                app = successor;
+            } else {
+                Slog.w(TAG, "Process " + app + " failed to attach");
+                EventLogTags.writeAmProcessStartTimeout(app.userId, pid, app.uid, app.processName);
+            }
             synchronized (mProcLock) {
                 mProcessList.removeProcessNameLocked(app.processName, app.uid);
                 mAtmInternal.clearHeavyWeightProcessIfEquals(app.getWindowProcessController());
-                mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
                 // Take care of any launching providers waiting for this process.
                 mCpHelper.cleanupAppInLaunchingProvidersLocked(app, true);
                 // Take care of any services that are waiting for the process.
                 mServices.processStartTimedOutLocked(app);
-                app.killLocked("start timeout", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
-                        true);
+                if (!isKillTimeout) {
+                    mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
+                    app.killLocked("start timeout",
+                            ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true);
+                    removeLruProcessLocked(app);
+                }
                 if (app.isolated) {
                     mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
+                    mProcessList.mAppExitInfoTracker.mIsolatedUidRecords.removeIsolatedUid(
+                            app.uid, app.info.uid);
+                    getPackageManagerInternal().removeIsolatedUid(app.uid);
                 }
-                removeLruProcessLocked(app);
             }
             final BackupRecord backupTarget = mBackupTargets.get(app.userId);
-            if (backupTarget != null && backupTarget.app.getPid() == pid) {
+            if (!isKillTimeout && backupTarget != null && backupTarget.app.getPid() == pid) {
                 Slog.w(TAG, "Unattached app died before backup, skipping");
+                final int userId = app.userId;
+                final String packageName = app.info.packageName;
                 mHandler.post(new Runnable() {
                 @Override
                     public void run(){
                         try {
                             IBackupManager bm = IBackupManager.Stub.asInterface(
                                     ServiceManager.getService(Context.BACKUP_SERVICE));
-                            bm.agentDisconnectedForUser(app.userId, app.info.packageName);
+                            bm.agentDisconnectedForUser(userId, packageName);
                         } catch (RemoteException e) {
                             // Can't happen; the backup manager is local
                         }
                     }
                 });
             }
-            if (isPendingBroadcastProcessLocked(pid)) {
-                Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
-                skipPendingBroadcastLocked(pid);
+            if (!isKillTimeout) {
+                if (isPendingBroadcastProcessLocked(pid)) {
+                    Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
+                    skipPendingBroadcastLocked(pid);
+                }
+            } else {
+                if (isPendingBroadcastProcessLocked(app)) {
+                    skipCurrentReceiverLocked(app);
+                }
             }
         } else {
             Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
@@ -7775,6 +7811,17 @@
                         } else {
                             killUid(UserHandle.getAppId(uid), UserHandle.getUserId(uid),
                                     "Too many Binders sent to SYSTEM");
+                            // We need to run a GC here, because killing the processes involved
+                            // actually isn't guaranteed to free up the proxies; in fact, if the
+                            // GC doesn't run for a long time, we may even exceed the global
+                            // proxy limit for a process (20000), resulting in system_server itself
+                            // being killed.
+                            // Note that the GC here might not actually clean up all the proxies,
+                            // because the binder reference decrements will come in asynchronously;
+                            // but if new processes belonging to the UID keep adding proxies, we
+                            // will get another callback here, and run the GC again - this time
+                            // cleaning up the old proxies.
+                            VMRuntime.getRuntime().requestConcurrentGC();
                         }
                     }, mHandler);
             t.traceEnd(); // setBinderProxies
@@ -12394,6 +12441,12 @@
                 || mOffloadBroadcastQueue.isPendingBroadcastProcessLocked(pid);
     }
 
+    boolean isPendingBroadcastProcessLocked(ProcessRecord app) {
+        return mFgBroadcastQueue.isPendingBroadcastProcessLocked(app)
+                || mBgBroadcastQueue.isPendingBroadcastProcessLocked(app)
+                || mOffloadBroadcastQueue.isPendingBroadcastProcessLocked(app);
+    }
+
     void skipPendingBroadcastLocked(int pid) {
             Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
             for (BroadcastQueue queue : mBroadcastQueues) {
@@ -12432,7 +12485,8 @@
         // Dynamic receivers are exported by default for versions prior to T
         final boolean exported =
                 ((flags & Context.RECEIVER_EXPORTED) != 0
-                        || (!Compatibility.isChangeEnabled(161145287)));
+                        || (!Compatibility.isChangeEnabled(
+                                DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED)));
 
         int callingUid;
         int callingPid;
@@ -12502,7 +12556,8 @@
 
             // If the change is enabled, but neither exported or not exported is set, we need to log
             // an error so the consumer can know to explicitly set the value for their flag
-            if (!onlyProtectedBroadcasts && (Compatibility.isChangeEnabled(161145287)
+            if (!onlyProtectedBroadcasts && (Compatibility.isChangeEnabled(
+                    DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED)
                     && (flags & (Context.RECEIVER_EXPORTED | Context.RECEIVER_NOT_EXPORTED))
                     == 0)) {
                 Slog.e(TAG,
@@ -12723,9 +12778,26 @@
                     }
                 }
             }
+            // Replace the alias receivers with their targets.
+            if (newReceivers != null) {
+                for (int i = newReceivers.size() - 1; i >= 0; i--) {
+                    final ResolveInfo ri = newReceivers.get(i);
+                    final Resolution<ResolveInfo> resolution = mComponentAliasResolver
+                            .resolveReceiver(intent, ri, resolvedType, pmFlags, user, callingUid);
+                    if (resolution == null) {
+                        // It was an alias, but the target was not found.
+                        newReceivers.remove(i);
+                        continue;
+                    }
+                    if (resolution.isAlias()) {
+                        newReceivers.set(i, resolution.getTarget());
+                    }
+                }
+            }
             if (newReceivers != null && newReceivers.size() == 0) {
                 newReceivers = null;
             }
+
             if (receivers == null) {
                 receivers = newReceivers;
             } else if (newReceivers != null) {
diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java
index 979a9ee..fc29982 100644
--- a/services/core/java/com/android/server/am/AppExitInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java
@@ -1507,6 +1507,20 @@
             }
         }
 
+        void removeIsolatedUid(int isolatedUid, int uid) {
+            synchronized (mLock) {
+                final int index = mUidToIsolatedUidMap.indexOfKey(uid);
+                if (index >= 0) {
+                    final ArraySet<Integer> set = mUidToIsolatedUidMap.valueAt(index);
+                    set.remove(isolatedUid);
+                    if (set.isEmpty()) {
+                        mUidToIsolatedUidMap.removeAt(index);
+                    }
+                }
+                mIsolatedUidToUidMap.remove(isolatedUid);
+            }
+        }
+
         @GuardedBy("mLock")
         Integer getUidByIsolatedUid(int isolatedUid) {
             if (UserHandle.isIsolated(isolatedUid)) {
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index f2fb371..d44d729 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -1047,6 +1047,7 @@
                     mService.setProcessTrackerStateLOSP(app, trackerMemFactor, now);
                     state.setProcStateChanged(false);
                 }
+                trimMemoryUiHiddenIfNecessaryLSP(app);
                 if (curProcState >= ActivityManager.PROCESS_STATE_HOME && !app.isKilledByAm()) {
                     if (trimMemoryLevel < curLevel[0] && (thread = app.getThread()) != null) {
                         try {
@@ -1089,24 +1090,6 @@
                     }
                     profile.setTrimMemoryLevel(ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
                 } else {
-                    if ((curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
-                                || state.isSystemNoUi()) && profile.hasPendingUiClean()) {
-                        // If this application is now in the background and it
-                        // had done UI, then give it the special trim level to
-                        // have it free UI resources.
-                        final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
-                        if (trimMemoryLevel < level && (thread = app.getThread()) != null) {
-                            try {
-                                if (DEBUG_SWITCH || DEBUG_OOM_ADJ) {
-                                    Slog.v(TAG_OOM_ADJ, "Trimming memory of bg-ui "
-                                            + app.processName + " to " + level);
-                                }
-                                thread.scheduleTrimMemory(level);
-                            } catch (RemoteException e) {
-                            }
-                        }
-                        profile.setPendingUiClean(false);
-                    }
                     if (trimMemoryLevel < fgTrimLevel && (thread = app.getThread()) != null) {
                         try {
                             if (DEBUG_SWITCH || DEBUG_OOM_ADJ) {
@@ -1133,28 +1116,36 @@
                     mService.setProcessTrackerStateLOSP(app, trackerMemFactor, now);
                     state.setProcStateChanged(false);
                 }
-                if ((state.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
-                            || state.isSystemNoUi()) && profile.hasPendingUiClean()) {
-                    if (profile.getTrimMemoryLevel() < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
-                            && (thread = app.getThread()) != null) {
-                        try {
-                            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) {
-                                Slog.v(TAG_OOM_ADJ,
-                                        "Trimming memory of ui hidden " + app.processName
-                                        + " to " + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
-                            }
-                            thread.scheduleTrimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
-                        } catch (RemoteException e) {
-                        }
-                    }
-                    profile.setPendingUiClean(false);
-                }
+                trimMemoryUiHiddenIfNecessaryLSP(app);
                 profile.setTrimMemoryLevel(0);
             });
         }
         return allChanged;
     }
 
+    @GuardedBy({"mService", "mProcLock"})
+    private void trimMemoryUiHiddenIfNecessaryLSP(ProcessRecord app) {
+        if ((app.mState.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
+                || app.mState.isSystemNoUi()) && app.mProfile.hasPendingUiClean()) {
+            // If this application is now in the background and it
+            // had done UI, then give it the special trim level to
+            // have it free UI resources.
+            final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
+            IApplicationThread thread;
+            if (app.mProfile.getTrimMemoryLevel() < level && (thread = app.getThread()) != null) {
+                try {
+                    if (DEBUG_SWITCH || DEBUG_OOM_ADJ) {
+                        Slog.v(TAG_OOM_ADJ, "Trimming memory of bg-ui "
+                                + app.processName + " to " + level);
+                    }
+                    thread.scheduleTrimMemory(level);
+                } catch (RemoteException e) {
+                }
+            }
+            app.mProfile.setPendingUiClean(false);
+        }
+    }
+
     @GuardedBy("mProcLock")
     long getLowRamTimeSinceIdleLPr(long now) {
         return mLowRamTimeSinceLastIdle + (mLowRamStartTime > 0 ? (now - mLowRamStartTime) : 0);
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 32d93ab..ed70d2b 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -230,6 +230,10 @@
         return mPendingBroadcast != null && mPendingBroadcast.curApp.getPid() == pid;
     }
 
+    boolean isPendingBroadcastProcessLocked(ProcessRecord app) {
+        return mPendingBroadcast != null && mPendingBroadcast.curApp == app;
+    }
+
     public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
         mParallelBroadcasts.add(r);
         enqueueBroadcastHelper(r);
diff --git a/services/core/java/com/android/server/am/CacheOomRanker.java b/services/core/java/com/android/server/am/CacheOomRanker.java
index bd7ee01..7413808 100644
--- a/services/core/java/com/android/server/am/CacheOomRanker.java
+++ b/services/core/java/com/android/server/am/CacheOomRanker.java
@@ -16,6 +16,8 @@
 
 package com.android.server.am;
 
+import android.os.Process;
+import android.os.SystemClock;
 import android.provider.DeviceConfig;
 import android.util.Slog;
 
@@ -46,6 +48,14 @@
     @VisibleForTesting
     static final int DEFAULT_PRESERVE_TOP_N_APPS = 3;
     @VisibleForTesting
+    static final String KEY_OOM_RE_RANKING_USE_FREQUENT_RSS = "oom_re_ranking_rss_use_frequent_rss";
+    @VisibleForTesting
+    static final boolean DEFAULT_USE_FREQUENT_RSS = true;
+    @VisibleForTesting
+    static final String KEY_OOM_RE_RANKING_RSS_UPDATE_RATE_MS = "oom_re_ranking_rss_update_rate_ms";
+    @VisibleForTesting
+    static final long DEFAULT_RSS_UPDATE_RATE_MS = 10_000; // 10 seconds
+    @VisibleForTesting
     static final String KEY_OOM_RE_RANKING_LRU_WEIGHT = "oom_re_ranking_lru_weight";
     @VisibleForTesting
     static final float DEFAULT_OOM_RE_RANKING_LRU_WEIGHT = 0.35f;
@@ -62,6 +72,8 @@
             new ScoreComparator();
     private static final Comparator<RankedProcessRecord> CACHE_USE_COMPARATOR =
             new CacheUseComparator();
+    private static final Comparator<RankedProcessRecord> RSS_COMPARATOR =
+            new RssComparator();
     private static final Comparator<RankedProcessRecord> LAST_RSS_COMPARATOR =
             new LastRssComparator();
     private static final Comparator<RankedProcessRecord> LAST_ACTIVITY_TIME_COMPARATOR =
@@ -70,6 +82,7 @@
     private final Object mPhenotypeFlagLock = new Object();
 
     private final ActivityManagerService mService;
+    private final ProcessDependencies mProcessDependencies;
     private final ActivityManagerGlobalLock mProcLock;
     private final Object mProfilerLock;
 
@@ -78,6 +91,12 @@
     @GuardedBy("mPhenotypeFlagLock")
     @VisibleForTesting
     int mPreserveTopNApps = DEFAULT_PRESERVE_TOP_N_APPS;
+    @GuardedBy("mPhenotypeFlagLock")
+    @VisibleForTesting
+    boolean mUseFrequentRss = DEFAULT_USE_FREQUENT_RSS;
+    @GuardedBy("mPhenotypeFlagLock")
+    @VisibleForTesting
+    long mRssUpdateRateMs = DEFAULT_RSS_UPDATE_RATE_MS;
     // Weight to apply to the LRU ordering.
     @GuardedBy("mPhenotypeFlagLock")
     @VisibleForTesting
@@ -110,6 +129,10 @@
                                 updateNumberToReRank();
                             } else if (KEY_OOM_RE_RANKING_PRESERVE_TOP_N_APPS.equals(name)) {
                                 updatePreserveTopNApps();
+                            } else if (KEY_OOM_RE_RANKING_USE_FREQUENT_RSS.equals(name)) {
+                                updateUseFrequentRss();
+                            } else if (KEY_OOM_RE_RANKING_RSS_UPDATE_RATE_MS.equals(name)) {
+                                updateRssUpdateRateMs();
                             } else if (KEY_OOM_RE_RANKING_LRU_WEIGHT.equals(name)) {
                                 updateLruWeight();
                             } else if (KEY_OOM_RE_RANKING_USES_WEIGHT.equals(name)) {
@@ -123,9 +146,15 @@
             };
 
     CacheOomRanker(final ActivityManagerService service) {
+        this(service, new ProcessDependenciesImpl());
+    }
+
+    @VisibleForTesting
+    CacheOomRanker(final ActivityManagerService service, ProcessDependencies processDependencies) {
         mService = service;
         mProcLock = service.mProcLock;
         mProfilerLock = service.mAppProfiler.mProfilerLock;
+        mProcessDependencies = processDependencies;
     }
 
     /** Load settings from device config and register a listener for changes. */
@@ -190,6 +219,18 @@
     }
 
     @GuardedBy("mPhenotypeFlagLock")
+    private void updateRssUpdateRateMs() {
+        mRssUpdateRateMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_OOM_RE_RANKING_RSS_UPDATE_RATE_MS, DEFAULT_RSS_UPDATE_RATE_MS);
+    }
+
+    @GuardedBy("mPhenotypeFlagLock")
+    private void updateUseFrequentRss() {
+        mUseFrequentRss = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_OOM_RE_RANKING_USE_FREQUENT_RSS, DEFAULT_USE_FREQUENT_RSS);
+    }
+
+    @GuardedBy("mPhenotypeFlagLock")
     private void updateLruWeight() {
         mLruWeight = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 KEY_OOM_RE_RANKING_LRU_WEIGHT, DEFAULT_OOM_RE_RANKING_LRU_WEIGHT);
@@ -244,6 +285,8 @@
         float usesWeight;
         float rssWeight;
         int preserveTopNApps;
+        boolean useFrequentRss;
+        long rssUpdateRateMs;
         int[] lruPositions;
         RankedProcessRecord[] scoredProcessRecords;
 
@@ -252,6 +295,8 @@
             usesWeight = mUsesWeight;
             rssWeight = mRssWeight;
             preserveTopNApps = mPreserveTopNApps;
+            useFrequentRss = mUseFrequentRss;
+            rssUpdateRateMs = mRssUpdateRateMs;
             lruPositions = mLruPositions;
             scoredProcessRecords = mScoredProcessRecords;
         }
@@ -296,6 +341,32 @@
             }
         }
 
+        if (useFrequentRss) {
+            // Update RSS values for re-ranked apps.
+            long nowMs = SystemClock.elapsedRealtime();
+            for (int i = 0; i < numProcessesReRanked; ++i) {
+                RankedProcessRecord scoredProcessRecord = scoredProcessRecords[i];
+                long sinceUpdateMs =
+                        nowMs - scoredProcessRecord.proc.mState.getCacheOomRankerRssTimeMs();
+                if (scoredProcessRecord.proc.mState.getCacheOomRankerRss() != 0
+                        && sinceUpdateMs < rssUpdateRateMs) {
+                    continue;
+                }
+
+                long[] rss = mProcessDependencies.getRss(scoredProcessRecord.proc.getPid());
+                if (rss == null || rss.length == 0) {
+                    Slog.e(
+                            OomAdjuster.TAG,
+                            "Process.getRss returned bad value, not re-ranking: "
+                                    + Arrays.toString(rss));
+                    return;
+                }
+                // First element is total RSS:
+                // frameworks/base/core/jni/android_util_Process.cpp:1192
+                scoredProcessRecord.proc.mState.setCacheOomRankerRss(rss[0], nowMs);
+            }
+        }
+
         // Add scores for each of the weighted features we want to rank based on.
         if (lruWeight > 0.0f) {
             // This doesn't use the LRU list ordering as after the first re-ranking
@@ -305,8 +376,12 @@
             addToScore(scoredProcessRecords, lruWeight);
         }
         if (rssWeight > 0.0f) {
-            synchronized (mService.mAppProfiler.mProfilerLock) {
-                Arrays.sort(scoredProcessRecords, 0, numProcessesReRanked, LAST_RSS_COMPARATOR);
+            if (useFrequentRss) {
+                Arrays.sort(scoredProcessRecords, 0, numProcessesReRanked, RSS_COMPARATOR);
+            } else {
+                synchronized (mService.mAppProfiler.mProfilerLock) {
+                    Arrays.sort(scoredProcessRecords, 0, numProcessesReRanked, LAST_RSS_COMPARATOR);
+                }
             }
             addToScore(scoredProcessRecords, rssWeight);
         }
@@ -385,6 +460,16 @@
         }
     }
 
+    private static class RssComparator implements Comparator<RankedProcessRecord> {
+        @Override
+        public int compare(RankedProcessRecord o1, RankedProcessRecord o2) {
+            // High RSS first to match least recently used.
+            return Long.compare(
+                    o2.proc.mState.getCacheOomRankerRss(),
+                    o1.proc.mState.getCacheOomRankerRss());
+        }
+    }
+
     private static class LastRssComparator implements Comparator<RankedProcessRecord> {
         @Override
         public int compare(RankedProcessRecord o1, RankedProcessRecord o2) {
@@ -397,4 +482,18 @@
         public ProcessRecord proc;
         public float score;
     }
+
+    /**
+     * Interface for mocking {@link Process} static methods.
+     */
+    interface ProcessDependencies {
+        long[] getRss(int pid);
+    }
+
+    private static class ProcessDependenciesImpl implements ProcessDependencies {
+        @Override
+        public long[] getRss(int pid) {
+            return Process.getRss(pid);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ComponentAliasResolver.java b/services/core/java/com/android/server/am/ComponentAliasResolver.java
index 3577f72..cf3e968 100644
--- a/services/core/java/com/android/server/am/ComponentAliasResolver.java
+++ b/services/core/java/com/android/server/am/ComponentAliasResolver.java
@@ -27,7 +27,9 @@
 import android.content.pm.ServiceInfo;
 import android.os.Binder;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
@@ -38,6 +40,7 @@
 import java.io.PrintWriter;
 import java.util.List;
 import java.util.Objects;
+import java.util.function.Supplier;
 
 /**
  * Manages and handles component aliases, which is an experimental feature.
@@ -72,6 +75,13 @@
     private static final String ALIAS_FILTER_ACTION = "android.intent.action.EXPERIMENTAL_IS_ALIAS";
     private static final String META_DATA_ALIAS_TARGET = "alias_target";
 
+    private static final int PACKAGE_QUERY_FLAGS =
+            PackageManager.MATCH_UNINSTALLED_PACKAGES
+                    | PackageManager.MATCH_ANY_USER
+                    | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                    | PackageManager.GET_META_DATA;
+
     public ComponentAliasResolver(ActivityManagerService service) {
         mAm = service;
         mContext = service.mContext;
@@ -151,24 +161,29 @@
      */
     @GuardedBy("mLock")
     private void loadFromMetadataLocked() {
-        if (DEBUG) Slog.d(TAG, "Scanning aliases...");
+        if (DEBUG) Slog.d(TAG, "Scanning service aliases...");
         Intent i = new Intent(ALIAS_FILTER_ACTION);
 
-        List<ResolveInfo> services = mContext.getPackageManager().queryIntentServicesAsUser(
-                i,
-                PackageManager.MATCH_UNINSTALLED_PACKAGES
-                        | PackageManager.MATCH_ANY_USER
-                        | PackageManager.MATCH_DIRECT_BOOT_AWARE
-                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
-                        | PackageManager.GET_META_DATA,
-                UserHandle.USER_SYSTEM);
+        final List<ResolveInfo> services = mContext.getPackageManager().queryIntentServicesAsUser(
+                i, PACKAGE_QUERY_FLAGS, UserHandle.USER_SYSTEM);
 
-        for (ResolveInfo ri : services) {
+        extractAliases(services);
+
+        if (DEBUG) Slog.d(TAG, "Scanning receiver aliases...");
+        final List<ResolveInfo> receivers = mContext.getPackageManager()
+                .queryBroadcastReceiversAsUser(i, PACKAGE_QUERY_FLAGS, UserHandle.USER_SYSTEM);
+
+        extractAliases(receivers);
+
+        // TODO: Scan for other component types as well.
+    }
+
+    private void extractAliases(List<ResolveInfo> components) {
+        for (ResolveInfo ri : components) {
             final ComponentInfo ci = ri.getComponentInfo();
             final ComponentName from = ci.getComponentName();
-            final ComponentName to = ComponentName.unflattenFromString(
-                    ci.metaData.getString(META_DATA_ALIAS_TARGET));
-            if (!validateComponentName(to)) {
+            final ComponentName to = unflatten(ci.metaData.getString(META_DATA_ALIAS_TARGET));
+            if (to == null) {
                 continue;
             }
             if (DEBUG) {
@@ -176,8 +191,6 @@
             }
             mFromTo.put(from, to);
         }
-
-        // TODO: Scan for other component types as well.
     }
 
     /**
@@ -191,8 +204,11 @@
         if (DEBUG) Slog.d(TAG, "Loading aliases overrides ...");
         for (String line : mOverrideString.split("\\,+")) {
             final String[] fields = line.split("\\:+", 2);
-            final ComponentName from = ComponentName.unflattenFromString(fields[0]);
-            if (!validateComponentName(from)) {
+            if (TextUtils.isEmpty(fields[0])) {
+                continue;
+            }
+            final ComponentName from = unflatten(fields[0]);
+            if (from == null) {
                 continue;
             }
 
@@ -200,8 +216,8 @@
                 if (DEBUG) Slog.d(TAG, "" + from.flattenToShortString() + " [removed]");
                 mFromTo.remove(from);
             } else {
-                final ComponentName to = ComponentName.unflattenFromString(fields[1]);
-                if (!validateComponentName(to)) {
+                final ComponentName to = unflatten(fields[1]);
+                if (to == null) {
                     continue;
                 }
 
@@ -214,12 +230,13 @@
         }
     }
 
-    private boolean validateComponentName(ComponentName cn) {
+    private ComponentName unflatten(String name) {
+        final ComponentName cn = ComponentName.unflattenFromString(name);
         if (cn != null) {
-            return true;
+            return cn;
         }
-        Slog.e(TAG, "Invalid component name detected: " + cn);
-        return false;
+        Slog.e(TAG, "Invalid component name detected: " + name);
+        return null;
     }
 
     /**
@@ -277,10 +294,9 @@
         }
     }
 
-    @Nullable
-    public Resolution<ComponentName> resolveService(
-            @NonNull Intent service, @Nullable String resolvedType,
-            int packageFlags, int userId, int callingUid) {
+    @NonNull
+    public Resolution<ComponentName> resolveComponentAlias(
+            @NonNull Supplier<ComponentName> aliasSupplier) {
         final long identity = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
@@ -288,28 +304,17 @@
                     return new Resolution<>(null, null);
                 }
 
-                PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
-
-                ResolveInfo rInfo = pmi.resolveService(service,
-                        resolvedType, packageFlags, userId, callingUid);
-                ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null;
-                if (sInfo == null) {
-                    return null; // Service not found.
-                }
-                final ComponentName alias =
-                        new ComponentName(sInfo.applicationInfo.packageName, sInfo.name);
+                final ComponentName alias = aliasSupplier.get();
                 final ComponentName target = mFromTo.get(alias);
 
                 if (target != null) {
-                    // It's an alias. Keep the original intent, and rewrite it.
-                    service.setOriginalIntent(new Intent(service));
-
-                    service.setPackage(null);
-                    service.setComponent(target);
-
                     if (DEBUG) {
+                        Exception stacktrace = null;
+                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                            stacktrace = new RuntimeException("STACKTRACE");
+                        }
                         Slog.d(TAG, "Alias resolved: " + alias.flattenToShortString()
-                                + " -> " + target.flattenToShortString());
+                                + " -> " + target.flattenToShortString(), stacktrace);
                     }
                 }
                 return new Resolution<>(alias, target);
@@ -318,4 +323,69 @@
             Binder.restoreCallingIdentity(identity);
         }
     }
+
+    @Nullable
+    public Resolution<ComponentName> resolveService(
+            @NonNull Intent service, @Nullable String resolvedType,
+            int packageFlags, int userId, int callingUid) {
+        Resolution<ComponentName> result = resolveComponentAlias(() -> {
+            PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+
+            ResolveInfo rInfo = pmi.resolveService(service,
+                    resolvedType, packageFlags, userId, callingUid);
+            ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null;
+            if (sInfo == null) {
+                return null; // Service not found.
+            }
+            return new ComponentName(sInfo.applicationInfo.packageName, sInfo.name);
+        });
+
+        // TODO: To make it consistent with resolveReceiver(), let's ensure the target service
+        // is resolvable, and if not, return null.
+
+        if (result != null && result.isAlias()) {
+            // It's an alias. Keep the original intent, and rewrite it.
+            service.setOriginalIntent(new Intent(service));
+
+            service.setPackage(null);
+            service.setComponent(result.getTarget());
+        }
+        return result;
+    }
+
+    @Nullable
+    public Resolution<ResolveInfo> resolveReceiver(@NonNull Intent intent,
+            @NonNull ResolveInfo receiver, @Nullable String resolvedType,
+            int packageFlags, int userId, int callingUid) {
+        // Resolve this alias.
+        final Resolution<ComponentName> resolution = resolveComponentAlias(() ->
+                receiver.activityInfo.getComponentName());
+        final ComponentName target = resolution.getTarget();
+        if (target == null) {
+            return new Resolution<>(receiver, null); // It's not an alias.
+        }
+
+        // Convert the target component name to a ResolveInfo.
+
+        final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+
+        // Rewrite the intent to search the target intent.
+        // - We don't actually rewrite the intent we deliver to the receiver here, which is what
+        //  resolveService() does, because this intent many be send to other receivers as well.
+        // - But we don't have to do that here either, because the actual receiver component
+        //   will be set in BroadcastQueue anyway, before delivering the intent to each receiver.
+        // - However, we're not able to set the original intent either, for the time being.
+        Intent i = new Intent(intent);
+        i.setPackage(null);
+        i.setComponent(resolution.getTarget());
+
+        List<ResolveInfo> resolved = pmi.queryIntentReceivers(i,
+                resolvedType, packageFlags, callingUid, userId);
+        if (resolved == null || resolved.size() == 0) {
+            // Target component not found.
+            Slog.w(TAG, "Alias target " + target.flattenToShortString() + " not found");
+            return null;
+        }
+        return new Resolution<>(receiver, resolved.get(0));
+    }
 }
diff --git a/services/core/java/com/android/server/am/PhantomProcessRecord.java b/services/core/java/com/android/server/am/PhantomProcessRecord.java
index 0156ee5..1a692df 100644
--- a/services/core/java/com/android/server/am/PhantomProcessRecord.java
+++ b/services/core/java/com/android/server/am/PhantomProcessRecord.java
@@ -122,7 +122,7 @@
                     // We'll notify the listener when we're notified it's dead.
                     // Meanwhile, we'd also need handle the case of zombie processes.
                     mKillHandler.postDelayed(mProcKillTimer, this,
-                            ProcessList.PROC_KILL_TIMEOUT);
+                            mService.mConstants.mProcessKillTimeoutMs);
                 }
                 Process.killProcessQuiet(mPid);
                 ProcessList.killProcessGroup(mUid, mPid);
@@ -138,7 +138,7 @@
             synchronized (mLock) {
                 // The process is maybe in either D or Z state.
                 Slog.w(TAG, "Process " + toString() + " is still alive after "
-                        + ProcessList.PROC_KILL_TIMEOUT + "ms");
+                        + mService.mConstants.mProcessKillTimeoutMs + "ms");
                 // Force a cleanup as we can't keep the fd open forever
                 mZombie = true;
                 onProcDied(false);
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 07d9cb2..cf8be63 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -362,11 +362,6 @@
     private static final long LMKD_RECONNECT_DELAY_MS = 1000;
 
     /**
-     * How long between a process kill and we actually receive its death recipient
-     */
-    static final int PROC_KILL_TIMEOUT = 2000; // 2 seconds;
-
-    /**
      * Native heap allocations will now have a non-zero tag in the most significant byte.
      * @see <a href="https://source.android.com/devices/tech/debug/tagged-pointers">Tagged
      * Pointers</a>
@@ -2113,65 +2108,94 @@
             final int[] gids, final int runtimeFlags, int zygotePolicyFlags,
             final int mountExternal, final String requiredAbi, final String instructionSet,
             final String invokeWith, final long startSeq) {
-        // If there is a preceding instance of the process, wait for its death with a timeout.
+        final Runnable startRunnable = () -> {
+            try {
+                final Process.ProcessStartResult startResult = startProcess(app.getHostingRecord(),
+                        entryPoint, app, app.getStartUid(), gids, runtimeFlags, zygotePolicyFlags,
+                        mountExternal, app.getSeInfo(), requiredAbi, instructionSet, invokeWith,
+                        app.getStartTime());
+
+                synchronized (mService) {
+                    handleProcessStartedLocked(app, startResult, startSeq);
+                }
+            } catch (RuntimeException e) {
+                synchronized (mService) {
+                    Slog.e(ActivityManagerService.TAG, "Failure starting process "
+                            + app.processName, e);
+                    mPendingStarts.remove(startSeq);
+                    app.setPendingStart(false);
+                    mService.forceStopPackageLocked(app.info.packageName,
+                            UserHandle.getAppId(app.uid),
+                            false, false, true, false, false, app.userId, "start failure");
+                }
+            }
+        };
         // Use local reference since we are not using locks here
         final ProcessRecord predecessor = app.mPredecessor;
-        int prevPid;
-        if (predecessor != null && (prevPid = predecessor.getDyingPid()) > 0) {
-            long now = System.currentTimeMillis();
-            final long end = now + PROC_KILL_TIMEOUT;
-            final int oldPolicy = StrictMode.getThreadPolicyMask();
-            try {
-                StrictMode.setThreadPolicyMask(0);
-                Process.waitForProcessDeath(prevPid, PROC_KILL_TIMEOUT);
-                // It's killed successfully, but we'd make sure the cleanup work is done.
-                synchronized (predecessor) {
-                    if (app.mPredecessor != null) {
-                        now = System.currentTimeMillis();
-                        if (now < end) {
-                            try {
-                                predecessor.wait(end - now);
-                            } catch (InterruptedException e) {
-                            }
-                            if (System.currentTimeMillis() >= end) {
-                                Slog.w(TAG, predecessor + " " + prevPid
-                                        + " has died but its obituary delivery is slow.");
-                            }
-                        }
-                    }
-                    if (app.mPredecessor != null && app.mPredecessor.getPid() > 0) {
-                        // The cleanup work hasn't be done yet, let's log it and continue.
-                        Slog.w(TAG, predecessor + " " + prevPid
-                                + " has died, but its cleanup isn't done");
-                    }
-                }
-            } catch (Exception e) {
-                // It's still alive... maybe blocked at uninterruptible sleep ?
-                Slog.wtf(TAG, predecessor.toString() + " " + prevPid
-                        + " refused to die, but we need to launch " + app, e);
-            } finally {
-                StrictMode.setThreadPolicyMask(oldPolicy);
+        if (predecessor != null && predecessor.getDyingPid() > 0) {
+            handleProcessStartWithPredecessor(predecessor, startRunnable);
+        } else {
+            // Kick off the process start for real.
+            startRunnable.run();
+        }
+    }
+
+    /**
+     * Handle the case where the given process is killed but still not gone, but we'd need to start
+     * the new instance of it.
+     */
+    private void handleProcessStartWithPredecessor(final ProcessRecord predecessor,
+            final Runnable successorStartRunnable) {
+        // If there is a preceding instance of the process, wait for its death with a timeout.
+        if (predecessor.mSuccessorStartRunnable != null) {
+            // It's been watched already, this shouldn't happen.
+            Slog.wtf(TAG, "We've been watching for the death of " + predecessor);
+            return;
+        }
+        predecessor.mSuccessorStartRunnable = successorStartRunnable;
+        mService.mProcStartHandler.sendMessageDelayed(mService.mProcStartHandler.obtainMessage(
+                ProcStartHandler.MSG_PROCESS_KILL_TIMEOUT, predecessor),
+                mService.mConstants.mProcessKillTimeoutMs);
+    }
+
+    static final class ProcStartHandler extends Handler {
+        static final int MSG_PROCESS_DIED = 1;
+        static final int MSG_PROCESS_KILL_TIMEOUT = 2;
+
+        private final ActivityManagerService mService;
+
+        ProcStartHandler(ActivityManagerService service, Looper looper) {
+            super(looper);
+            mService = service;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_PROCESS_DIED:
+                    mService.mProcessList.handlePredecessorProcDied((ProcessRecord) msg.obj);
+                    break;
+                case MSG_PROCESS_KILL_TIMEOUT:
+                    mService.handleProcessStartOrKillTimeoutLocked((ProcessRecord) msg.obj,
+                            /* isKillTimeout */ true);
+                    break;
             }
         }
-        try {
-            final Process.ProcessStartResult startResult = startProcess(app.getHostingRecord(),
-                    entryPoint, app, app.getStartUid(), gids, runtimeFlags, zygotePolicyFlags,
-                    mountExternal, app.getSeInfo(), requiredAbi, instructionSet, invokeWith,
-                    app.getStartTime());
+    }
 
-            synchronized (mService) {
-                handleProcessStartedLocked(app, startResult, startSeq);
-            }
-        } catch (RuntimeException e) {
-            synchronized (mService) {
-                Slog.e(ActivityManagerService.TAG, "Failure starting process "
-                        + app.processName, e);
-                mPendingStarts.remove(startSeq);
-                app.setPendingStart(false);
-                mService.forceStopPackageLocked(app.info.packageName,
-                        UserHandle.getAppId(app.uid),
-                        false, false, true, false, false, app.userId, "start failure");
-            }
+    /**
+     * Called when the dying process we're waiting for is really gone.
+     */
+    private void handlePredecessorProcDied(ProcessRecord app) {
+        if (DEBUG_PROCESSES) {
+            Slog.i(TAG, app.toString() + " is really gone now");
+        }
+
+        // Now kick off the subsequent process start if there is any.
+        final Runnable start = app.mSuccessorStartRunnable;
+        if (start != null) {
+            app.mSuccessorStartRunnable = null;
+            start.run();
         }
     }
 
@@ -5001,10 +5025,10 @@
             // App has been removed already, meaning cleanup has done.
             Slog.v(TAG, "Got obituary of " + pid + ":" + app.processName);
             app.unlinkDeathRecipient();
-            handlePrecedingAppDiedLocked(app);
             // It's really gone now, let's remove from the dying process list.
             mDyingProcesses.remove(app.processName, app.uid);
             app.setDyingPid(0);
+            handlePrecedingAppDiedLocked(app);
             return true;
         }
         return false;
@@ -5017,23 +5041,25 @@
      */
     @GuardedBy("mService")
     boolean handlePrecedingAppDiedLocked(ProcessRecord app) {
-        synchronized (app) {
-            if (app.mSuccessor != null) {
-                // We don't allow restart with this ProcessRecord now,
-                // because we have created a new one already.
-                // If it's persistent, add the successor to mPersistentStartingProcesses
-                if (app.isPersistent() && !app.isRemoved()) {
-                    if (mService.mPersistentStartingProcesses.indexOf(app.mSuccessor) < 0) {
-                        mService.mPersistentStartingProcesses.add(app.mSuccessor);
-                    }
+        if (app.mSuccessor != null) {
+            // We don't allow restart with this ProcessRecord now,
+            // because we have created a new one already.
+            // If it's persistent, add the successor to mPersistentStartingProcesses
+            if (app.isPersistent() && !app.isRemoved()) {
+                if (mService.mPersistentStartingProcesses.indexOf(app.mSuccessor) < 0) {
+                    mService.mPersistentStartingProcesses.add(app.mSuccessor);
                 }
-                // clean up the field so the successor's proc starter could proceed.
-                app.mSuccessor.mPredecessor = null;
-                app.mSuccessor = null;
-                // Notify if anyone is waiting for it.
-                app.notifyAll();
-                return false;
             }
+            // clean up the field so the successor's proc starter could proceed.
+            app.mSuccessor.mPredecessor = null;
+            app.mSuccessor = null;
+            // Remove any pending timeout msg.
+            mService.mProcStartHandler.removeMessages(
+                    ProcStartHandler.MSG_PROCESS_KILL_TIMEOUT, app);
+            // Kick off the proc start for the succeeding instance
+            mService.mProcStartHandler.obtainMessage(
+                    ProcStartHandler.MSG_PROCESS_DIED, app).sendToTarget();
+            return false;
         }
         return true;
     }
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 9e94d4a..c573615 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -364,6 +364,13 @@
      */
     volatile ProcessRecord mSuccessor;
 
+    /**
+     * The routine to start its successor process.
+     *
+     * <p>Note: It should be accessed from process start thread only.</p>
+     */
+    Runnable mSuccessorStartRunnable;
+
     void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
             long startTime) {
         this.mStartUid = startUid;
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index 7b9a356e..c4ce873 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -360,6 +360,20 @@
     private int mCacheOomRankerUseCount;
 
     /**
+     * Process memory usage (RSS).
+     *
+     * Periodically populated by {@code CacheOomRanker}, stored in this object to cache the values.
+     */
+    @GuardedBy("mService")
+    private long mCacheOomRankerRss;
+
+    /**
+     * The last time, in milliseconds since boot, since {@link #mCacheOomRankerRss} was updated.
+     */
+    @GuardedBy("mService")
+    private long mCacheOomRankerRssTimeMs;
+
+    /**
      * Whether or not this process is reachable from given process.
      */
     @GuardedBy("mService")
@@ -1266,6 +1280,21 @@
         return mLastCanKillOnBgRestrictedAndIdleTime;
     }
 
+    public void setCacheOomRankerRss(long rss, long rssTimeMs) {
+        mCacheOomRankerRss = rss;
+        mCacheOomRankerRssTimeMs = rssTimeMs;
+    }
+
+    @GuardedBy("mService")
+    public long getCacheOomRankerRss() {
+        return mCacheOomRankerRss;
+    }
+
+    @GuardedBy("mService")
+    public long getCacheOomRankerRssTimeMs() {
+        return mCacheOomRankerRssTimeMs;
+    }
+
     @GuardedBy({"mService", "mProcLock"})
     void dump(PrintWriter pw, String prefix, long nowUptime) {
         if (mReportedInteraction || mFgInteractionTime != 0) {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 5ecdfe4..84a3060 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -632,6 +632,37 @@
         sendLMsgNoDelay(MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
     }
 
+    private static final class LeAudioDeviceConnectionInfo {
+        final @NonNull BluetoothDevice mDevice;
+        final @AudioService.BtProfileConnectionState int mState;
+        final boolean mSupprNoisy;
+        final @NonNull String mEventSource;
+
+        LeAudioDeviceConnectionInfo(@NonNull BluetoothDevice device,
+                @AudioService.BtProfileConnectionState int state,
+                boolean suppressNoisyIntent, @NonNull String eventSource) {
+            mDevice = device;
+            mState = state;
+            mSupprNoisy = suppressNoisyIntent;
+            mEventSource = eventSource;
+        }
+    }
+
+    /*package*/ void postBluetoothLeAudioOutDeviceConnectionState(
+            @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
+            boolean suppressNoisyIntent, @NonNull String eventSource) {
+        final LeAudioDeviceConnectionInfo info = new LeAudioDeviceConnectionInfo(
+                device, state, suppressNoisyIntent, eventSource);
+        sendLMsgNoDelay(MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
+    }
+
+    /*package*/ void postBluetoothLeAudioInDeviceConnectionState(
+            @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
+            @NonNull String eventSource) {
+        final LeAudioDeviceConnectionInfo info = new LeAudioDeviceConnectionInfo(
+                device, state, false, eventSource);
+        sendLMsgNoDelay(MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
+    }
 
     /**
      * Current Bluetooth SCO audio active state indicated by BtHelper via setBluetoothScoOn().
@@ -902,6 +933,23 @@
                 delay);
     }
 
+    /*package*/ void postSetLeAudioOutConnectionState(
+            @AudioService.BtProfileConnectionState int state,
+            @NonNull BluetoothDevice device, int delay) {
+        sendILMsg(MSG_IL_SET_LE_AUDIO_OUT_CONNECTION_STATE, SENDMSG_QUEUE,
+                state,
+                device,
+                delay);
+    }
+
+    /*package*/ void postSetLeAudioInConnectionState(
+            @AudioService.BtProfileConnectionState int state,
+            @NonNull BluetoothDevice device) {
+        sendILMsgNoDelay(MSG_IL_SET_LE_AUDIO_IN_CONNECTION_STATE, SENDMSG_QUEUE,
+                state,
+                device);
+    }
+
     /*package*/ void postDisconnectA2dp() {
         sendMsgNoDelay(MSG_DISCONNECT_A2DP, SENDMSG_QUEUE);
     }
@@ -1223,7 +1271,20 @@
                     synchronized (mDeviceStateLock) {
                         mDeviceInventory.onSetHearingAidConnectionState(
                                 (BluetoothDevice) msg.obj, msg.arg1,
-                                mAudioService.getHearingAidStreamType());
+                                mAudioService.getBluetoothContextualVolumeStream());
+                    }
+                    break;
+                case MSG_IL_SET_LE_AUDIO_OUT_CONNECTION_STATE:
+                    synchronized (mDeviceStateLock) {
+                        mDeviceInventory.onSetLeAudioOutConnectionState(
+                                (BluetoothDevice) msg.obj, msg.arg1,
+                                mAudioService.getBluetoothContextualVolumeStream());
+                    }
+                    break;
+                case MSG_IL_SET_LE_AUDIO_IN_CONNECTION_STATE:
+                    synchronized (mDeviceStateLock) {
+                        mDeviceInventory.onSetLeAudioInConnectionState(
+                                (BluetoothDevice) msg.obj, msg.arg1);
                     }
                     break;
                 case MSG_BT_HEADSET_CNCT_FAILED:
@@ -1415,6 +1476,31 @@
                     final int capturePreset = msg.arg1;
                     mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset);
                 } break;
+                case MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT: {
+                    final LeAudioDeviceConnectionInfo info =
+                            (LeAudioDeviceConnectionInfo) msg.obj;
+                    AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+                            "setLeAudioDeviceOutConnectionState state=" + info.mState
+                                    + " addr=" + info.mDevice.getAddress()
+                                    + " supprNoisy=" + info.mSupprNoisy
+                                    + " src=" + info.mEventSource)).printLog(TAG));
+                    synchronized (mDeviceStateLock) {
+                        mDeviceInventory.setBluetoothLeAudioOutDeviceConnectionState(
+                                info.mDevice, info.mState, info.mSupprNoisy);
+                    }
+                } break;
+                case MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT: {
+                    final LeAudioDeviceConnectionInfo info =
+                            (LeAudioDeviceConnectionInfo) msg.obj;
+                    AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+                            "setLeAudioDeviceInConnectionState state=" + info.mState
+                                    + " addr=" + info.mDevice.getAddress()
+                                    + " src=" + info.mEventSource)).printLog(TAG));
+                    synchronized (mDeviceStateLock) {
+                        mDeviceInventory.setBluetoothLeAudioInDeviceConnectionState(info.mDevice,
+                                info.mState);
+                    }
+                } break;
                 default:
                     Log.wtf(TAG, "Invalid message " + msg.what);
             }
@@ -1496,6 +1582,11 @@
     private static final int MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY = 40;
     private static final int MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY = 41;
 
+    private static final int MSG_IL_SET_LE_AUDIO_OUT_CONNECTION_STATE = 42;
+    private static final int MSG_IL_SET_LE_AUDIO_IN_CONNECTION_STATE = 43;
+    private static final int MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT = 44;
+    private static final int MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT = 45;
+
     private static boolean isMessageHandledUnderWakelock(int msgId) {
         switch(msgId) {
             case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
@@ -1511,6 +1602,8 @@
             case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION:
             case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
             case MSG_CHECK_MUTE_MUSIC:
+            case MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT:
+            case MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT:
                 return true;
             default:
                 return false;
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 5944a63..64e620e 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -20,6 +20,7 @@
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothProfile;
 import android.content.Intent;
 import android.media.AudioDeviceAttributes;
@@ -421,6 +422,45 @@
         }
     }
 
+    /*package*/ void onSetLeAudioConnectionState(BluetoothDevice btDevice,
+                @AudioService.BtProfileConnectionState int state, int streamType, int device) {
+        String address = btDevice.getAddress();
+        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+            address = "";
+        }
+        AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+                "onSetLeAudioConnectionState addr=" + address));
+
+        synchronized (mDevicesLock) {
+            DeviceInfo di = null;
+            boolean isConnected = false;
+
+            String key = DeviceInfo.makeDeviceListKey(device, btDevice.getAddress());
+            di = mConnectedDevices.get(key);
+            isConnected = di != null;
+
+            if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
+                makeLeAudioDeviceUnavailable(address, device);
+            } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
+                makeLeAudioDeviceAvailable(address, BtHelper.getName(btDevice), streamType,
+                        device, "onSetLeAudioConnectionState");
+            }
+        }
+    }
+
+    /*package*/ void onSetLeAudioOutConnectionState(BluetoothDevice btDevice,
+                @AudioService.BtProfileConnectionState int state, int streamType) {
+        // TODO: b/198610537 clarify DEVICE_OUT_BLE_HEADSET vs DEVICE_OUT_BLE_SPEAKER criteria
+        onSetLeAudioConnectionState(btDevice, state, streamType,
+                AudioSystem.DEVICE_OUT_BLE_HEADSET);
+    }
+
+    /*package*/ void onSetLeAudioInConnectionState(BluetoothDevice btDevice,
+                @AudioService.BtProfileConnectionState int state) {
+        onSetLeAudioConnectionState(btDevice, state, AudioSystem.STREAM_DEFAULT,
+                AudioSystem.DEVICE_IN_BLE_HEADSET);
+    }
+
     @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
         /*package*/ void onBluetoothA2dpActiveDeviceChange(
             @NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, int event) {
@@ -946,6 +986,28 @@
         }
     }
 
+    /*package*/ int setBluetoothLeAudioOutDeviceConnectionState(
+            @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
+            boolean suppressNoisyIntent) {
+        synchronized (mDevicesLock) {
+            /* Active device become null and it's previous device is not connected anymore */
+            int delay = 0;
+            if (!suppressNoisyIntent) {
+                int intState = (state == BluetoothLeAudio.STATE_CONNECTED) ? 1 : 0;
+                delay = checkSendBecomingNoisyIntentInt(AudioSystem.DEVICE_OUT_BLE_HEADSET,
+                        intState, AudioSystem.DEVICE_NONE);
+            }
+            mDeviceBroker.postSetLeAudioOutConnectionState(state, device, delay);
+            return delay;
+        }
+    }
+
+    /*package*/ void setBluetoothLeAudioInDeviceConnectionState(
+            @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state) {
+        synchronized (mDevicesLock) {
+            mDeviceBroker.postSetLeAudioInConnectionState(state, device);
+        }
+    }
 
     //-------------------------------------------------------------------
     // Internal utilities
@@ -1118,6 +1180,36 @@
     }
 
     @GuardedBy("mDevicesLock")
+    private void makeLeAudioDeviceAvailable(String address, String name, int streamType, int device,
+            String eventSource) {
+        if (device != AudioSystem.DEVICE_NONE) {
+            AudioSystem.setDeviceConnectionState(device, AudioSystem.DEVICE_STATE_AVAILABLE,
+                    address, name, AudioSystem.AUDIO_FORMAT_DEFAULT);
+            mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address),
+                    new DeviceInfo(device, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT));
+            mDeviceBroker.postAccessoryPlugMediaUnmute(device);
+        }
+
+        if (streamType == AudioSystem.STREAM_DEFAULT) {
+            // No need to update volume for input devices
+            return;
+        }
+
+        mDeviceBroker.postApplyVolumeOnDevice(streamType, device, "makeLeAudioDeviceAvailable");
+    }
+
+    @GuardedBy("mDevicesLock")
+    private void makeLeAudioDeviceUnavailable(String address, int device) {
+        if (device != AudioSystem.DEVICE_NONE) {
+            AudioSystem.setDeviceConnectionState(device, AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                    address, "", AudioSystem.AUDIO_FORMAT_DEFAULT);
+            mConnectedDevices.remove(DeviceInfo.makeDeviceListKey(device, address));
+        }
+
+        setCurrentAudioRouteNameIfPossible(null, false /*fromA2dp*/);
+    }
+
+    @GuardedBy("mDevicesLock")
     private void setCurrentAudioRouteNameIfPossible(String name, boolean fromA2dp) {
         synchronized (mCurAudioRoutes) {
             if (TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) {
@@ -1153,6 +1245,7 @@
         BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_HEARING_AID);
         BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
         BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
+        BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_BLE_SET);
     }
 
     // must be called before removing the device from mConnectedDevices
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index f5d29fc..d12cf70 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -2956,7 +2956,7 @@
             if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
                 // only modify the hearing aid attenuation when the stream to modify matches
                 // the one expected by the hearing aid
-                if (streamType == getHearingAidStreamType()) {
+                if (streamType == getBluetoothContextualVolumeStream()) {
                     if (DEBUG_VOL) {
                         Log.d(TAG, "adjustSreamVolume postSetHearingAidVolumeIndex index="
                                 + newIndex + " stream=" + streamType);
@@ -3295,11 +3295,11 @@
         }
     }
 
-    /*package*/ int getHearingAidStreamType() {
-        return getHearingAidStreamType(mMode.get());
+    /*package*/ int getBluetoothContextualVolumeStream() {
+        return getBluetoothContextualVolumeStream(mMode.get());
     }
 
-    private int getHearingAidStreamType(int mode) {
+    private int getBluetoothContextualVolumeStream(int mode) {
         switch (mode) {
             case AudioSystem.MODE_IN_COMMUNICATION:
             case AudioSystem.MODE_IN_CALL:
@@ -3456,7 +3456,7 @@
     }
 
     private void updateHearingAidVolumeOnVoiceActivityUpdate() {
-        final int streamType = getHearingAidStreamType();
+        final int streamType = getBluetoothContextualVolumeStream();
         final int index = getStreamVolume(streamType);
         sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_VOICE_ACTIVITY_HEARING_AID,
                 mVoicePlaybackActive.get(), streamType, index));
@@ -3488,7 +3488,7 @@
                 return;
         }
 
-        int streamType = getHearingAidStreamType(newMode);
+        int streamType = getBluetoothContextualVolumeStream(newMode);
 
         final Set<Integer> deviceTypes = AudioSystem.generateAudioDeviceTypesSet(
                 mAudioSystem.getDevicesForStream(streamType));
@@ -3571,7 +3571,7 @@
             }
 
             if (device == AudioSystem.DEVICE_OUT_HEARING_AID
-                    && streamType == getHearingAidStreamType()) {
+                    && streamType == getBluetoothContextualVolumeStream()) {
                 Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index
                         + " stream=" + streamType);
                 mDeviceBroker.postSetHearingAidVolumeIndex(index, streamType);
@@ -6243,6 +6243,38 @@
                 device, state, suppressNoisyIntent, musicDevice, "AudioService");
     }
 
+    private void setBluetoothLeAudioDeviceConnectionState(@NonNull BluetoothDevice device,
+            @BtProfileConnectionState int state) {
+        if (device == null) {
+            throw new IllegalArgumentException("Illegal null device");
+        }
+        if (state != BluetoothProfile.STATE_CONNECTED
+                && state != BluetoothProfile.STATE_DISCONNECTED) {
+            throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
+                    + " (dis)connection, got " + state);
+        }
+    }
+
+    /**
+     * See AudioManager.setBluetoothLeAudioOutDeviceConnectionState()
+     */
+    public void setBluetoothLeAudioOutDeviceConnectionState(
+            @NonNull BluetoothDevice device, @BtProfileConnectionState int state,
+            boolean suppressNoisyIntent) {
+        setBluetoothLeAudioDeviceConnectionState(device, state);
+        mDeviceBroker.postBluetoothLeAudioOutDeviceConnectionState(device, state,
+                suppressNoisyIntent, "AudioService");
+    }
+
+    /**
+     * See AudioManager.setBluetoothLeAudioInDeviceConnectionState()
+     */
+    public void setBluetoothLeAudioInDeviceConnectionState(
+            @NonNull BluetoothDevice device, @BtProfileConnectionState int state) {
+        setBluetoothLeAudioDeviceConnectionState(device, state);
+        mDeviceBroker.postBluetoothLeAudioInDeviceConnectionState(device, state, "AudioService");
+    }
+
     /**
      * See AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
      */
diff --git a/services/core/java/com/android/server/audio/RotationHelper.java b/services/core/java/com/android/server/audio/RotationHelper.java
index 872b1fe..d4f4245 100644
--- a/services/core/java/com/android/server/audio/RotationHelper.java
+++ b/services/core/java/com/android/server/audio/RotationHelper.java
@@ -17,24 +17,26 @@
 package com.android.server.audio;
 
 import android.content.Context;
+import android.hardware.devicestate.DeviceStateManager;
+import android.hardware.devicestate.DeviceStateManager.FoldStateListener;
 import android.hardware.display.DisplayManager;
 import android.media.AudioSystem;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.util.Log;
-import android.view.Display;
 import android.view.Surface;
 import android.view.WindowManager;
 
 /**
  * Class to handle device rotation events for AudioService, and forward device rotation
- * and current active ID to the audio HALs through AudioSystem.
+ * and folded state to the audio HALs through AudioSystem.
  *
  * The role of this class is to monitor device orientation changes, and upon rotation,
  * verify the UI orientation. In case of a change, send the new orientation, in increments
  * of 90deg, through AudioSystem.
  *
- * Another role of this class is to track current active display ID changes. In case of a
- * change, send the new active display ID through AudioSystem.
+ * Another role of this class is to track device folded state changes. In case of a
+ * change, send the new folded state through AudioSystem.
  *
  * Note that even though we're responding to device orientation events, we always
  * query the display rotation so audio stays in sync with video/dialogs. This is
@@ -47,11 +49,12 @@
     private static final String TAG = "AudioService.RotationHelper";
 
     private static AudioDisplayListener sDisplayListener;
+    private static FoldStateListener sFoldStateListener;
 
     private static final Object sRotationLock = new Object();
-    private static final Object sActiveDisplayLock = new Object();
+    private static final Object sFoldStateLock = new Object();
     private static int sDeviceRotation = Surface.ROTATION_0; // R/W synchronized on sRotationLock
-    private static int sDisplayId = Display.DEFAULT_DISPLAY; // synchronized on sActiveDisplayLock
+    private static boolean sDeviceFold = true; // R/W synchronized on sFoldStateLock
 
     private static Context sContext;
     private static Handler sHandler;
@@ -75,11 +78,17 @@
         ((DisplayManager) sContext.getSystemService(Context.DISPLAY_SERVICE))
                 .registerDisplayListener(sDisplayListener, sHandler);
         updateOrientation();
+
+        sFoldStateListener = new FoldStateListener(sContext, folded -> updateFoldState(folded));
+        sContext.getSystemService(DeviceStateManager.class)
+                .registerCallback(new HandlerExecutor(sHandler), sFoldStateListener);
     }
 
     static void disable() {
         ((DisplayManager) sContext.getSystemService(Context.DISPLAY_SERVICE))
                 .unregisterDisplayListener(sDisplayListener);
+        sContext.getSystemService(DeviceStateManager.class)
+                .unregisterCallback(sFoldStateListener);
     }
 
     /**
@@ -120,13 +129,17 @@
     }
 
     /**
-     * Query current display active id and publish the change if any.
+     * publish the change of device folded state if any.
      */
-    static void updateActiveDisplayId(int displayId) {
-        synchronized (sActiveDisplayLock) {
-            if (displayId != Display.DEFAULT_DISPLAY && sDisplayId != displayId) {
-                sDisplayId = displayId;
-                AudioSystem.setParameters("active_displayId=" + sDisplayId);
+    static void updateFoldState(boolean newFolded) {
+        synchronized (sFoldStateLock) {
+            if (sDeviceFold != newFolded) {
+                sDeviceFold = newFolded;
+                if (newFolded) {
+                    AudioSystem.setParameters("device_folded=on");
+                } else {
+                    AudioSystem.setParameters("device_folded=off");
+                }
             }
         }
     }
@@ -146,7 +159,6 @@
 
         @Override
         public void onDisplayChanged(int displayId) {
-            updateActiveDisplayId(displayId);
             updateOrientation();
         }
     }
diff --git a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
index 0a1c77b..9764a16 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
@@ -26,6 +26,8 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.NoSuchElementException;
 
 /**
@@ -70,26 +72,32 @@
     }
 
     /** Holder for wrapping multiple handlers into a single Callback. */
-    protected static class CompositeCallback implements Callback {
+    public static class CompositeCallback implements Callback {
         @NonNull
-        private final Callback[] mCallbacks;
+        private final List<Callback> mCallbacks;
 
         public CompositeCallback(@NonNull Callback... callbacks) {
-            mCallbacks = callbacks;
+            mCallbacks = new ArrayList<>();
+
+            for (Callback callback : callbacks) {
+                if (callback != null) {
+                    mCallbacks.add(callback);
+                }
+            }
         }
 
         @Override
         public final void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
-            for (int i = 0; i < mCallbacks.length; i++) {
-                mCallbacks[i].onClientStarted(clientMonitor);
+            for (int i = 0; i < mCallbacks.size(); i++) {
+                mCallbacks.get(i).onClientStarted(clientMonitor);
             }
         }
 
         @Override
         public final void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
                 boolean success) {
-            for (int i = mCallbacks.length - 1; i >= 0; i--) {
-                mCallbacks[i].onClientFinished(clientMonitor, success);
+            for (int i = mCallbacks.size() - 1; i >= 0; i--) {
+                mCallbacks.get(i).onClientFinished(clientMonitor, success);
             }
         }
     }
@@ -256,7 +264,7 @@
         return mToken;
     }
 
-    public final int getSensorId() {
+    public int getSensorId() {
         return mSensorId;
     }
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
index a15e14b..9191b8b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
@@ -31,7 +31,7 @@
 /**
  * A class to keep track of the enrollment state for a given client.
  */
-public abstract class EnrollClient<T> extends AcquisitionClient<T> {
+public abstract class EnrollClient<T> extends AcquisitionClient<T> implements EnrollmentModifier {
 
     private static final String TAG = "Biometrics/EnrollClient";
 
@@ -40,6 +40,7 @@
     protected final BiometricUtils mBiometricUtils;
 
     private long mEnrollmentStartTimeMs;
+    private final boolean mHasEnrollmentsBeforeStarting;
 
     /**
      * @return true if the user has already enrolled the maximum number of templates.
@@ -56,6 +57,18 @@
         mBiometricUtils = utils;
         mHardwareAuthToken = Arrays.copyOf(hardwareAuthToken, hardwareAuthToken.length);
         mTimeoutSec = timeoutSec;
+        mHasEnrollmentsBeforeStarting = hasEnrollments();
+    }
+
+    @Override
+    public boolean hasEnrollmentStateChanged() {
+        final boolean hasEnrollmentsNow = hasEnrollments();
+        return hasEnrollmentsNow != mHasEnrollmentsBeforeStarting;
+    }
+
+    @Override
+    public boolean hasEnrollments() {
+        return !mBiometricUtils.getBiometricsForUser(getContext(), getTargetUserId()).isEmpty();
     }
 
     public void onEnrollResult(BiometricAuthenticator.Identifier identifier, int remaining) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/EnrollmentModifier.java b/services/core/java/com/android/server/biometrics/sensors/EnrollmentModifier.java
new file mode 100644
index 0000000..c2f909b
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/EnrollmentModifier.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+/**
+ * Interface for {@link BaseClientMonitor} subclasses that affect the state of enrollment.
+ */
+public interface EnrollmentModifier {
+
+    /**
+     * Callers should typically check this after
+     * {@link BaseClientMonitor.Callback#onClientFinished(BaseClientMonitor, boolean)}
+     *
+     * @return true if the user has gone from:
+     *      1) none-enrolled --> enrolled
+     *      2) enrolled --> none-enrolled
+     *      but NOT any-enrolled --> more-enrolled
+     */
+    boolean hasEnrollmentStateChanged();
+
+    /**
+     * @return true if the user has any enrollments
+     */
+    boolean hasEnrollments();
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
index 282261e..579dfd6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
@@ -40,7 +40,8 @@
  * {@link #onRemoved(BiometricAuthenticator.Identifier, int)} returns true/
  */
 public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Identifier, T>
-        extends HalClientMonitor<T> implements EnumerateConsumer, RemovalConsumer {
+        extends HalClientMonitor<T> implements EnumerateConsumer, RemovalConsumer,
+        EnrollmentModifier {
 
     private static final String TAG = "Biometrics/InternalCleanupClient";
 
@@ -61,6 +62,7 @@
     private final BiometricUtils<S> mBiometricUtils;
     private final Map<Integer, Long> mAuthenticatorIds;
     private final List<S> mEnrolledList;
+    private final boolean mHasEnrollmentsBeforeStarting;
     private BaseClientMonitor mCurrentTask;
 
     private final Callback mEnumerateCallback = new Callback() {
@@ -115,6 +117,7 @@
         mBiometricUtils = utils;
         mAuthenticatorIds = authenticatorIds;
         mEnrolledList = enrolledList;
+        mHasEnrollmentsBeforeStarting = !utils.getBiometricsForUser(context, userId).isEmpty();
     }
 
     private void startCleanupUnknownHalTemplates() {
@@ -166,6 +169,18 @@
     }
 
     @Override
+    public boolean hasEnrollmentStateChanged() {
+        final boolean hasEnrollmentsNow = !mBiometricUtils
+                .getBiometricsForUser(getContext(), getTargetUserId()).isEmpty();
+        return hasEnrollmentsNow != mHasEnrollmentsBeforeStarting;
+    }
+
+    @Override
+    public boolean hasEnrollments() {
+        return !mBiometricUtils.getBiometricsForUser(getContext(), getTargetUserId()).isEmpty();
+    }
+
+    @Override
     public void onEnumerationResult(BiometricAuthenticator.Identifier identifier,
             int remaining) {
         if (!(mCurrentTask instanceof InternalEnumerateClient)) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
index 383efce..2a6677e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
@@ -33,12 +33,13 @@
  * A class to keep track of the remove state for a given client.
  */
 public abstract class RemovalClient<S extends BiometricAuthenticator.Identifier, T>
-        extends HalClientMonitor<T> implements RemovalConsumer {
+        extends HalClientMonitor<T> implements RemovalConsumer, EnrollmentModifier {
 
     private static final String TAG = "Biometrics/RemovalClient";
 
     private final BiometricUtils<S> mBiometricUtils;
     private final Map<Integer, Long> mAuthenticatorIds;
+    private final boolean mHasEnrollmentsBeforeStarting;
 
     public RemovalClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
             @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
@@ -49,6 +50,7 @@
                 BiometricsProtoEnums.CLIENT_UNKNOWN);
         mBiometricUtils = utils;
         mAuthenticatorIds = authenticatorIds;
+        mHasEnrollmentsBeforeStarting = !utils.getBiometricsForUser(context, userId).isEmpty();
     }
 
     @Override
@@ -91,6 +93,18 @@
     }
 
     @Override
+    public boolean hasEnrollmentStateChanged() {
+        final boolean hasEnrollmentsNow = !mBiometricUtils
+                .getBiometricsForUser(getContext(), getTargetUserId()).isEmpty();
+        return hasEnrollmentsNow != mHasEnrollmentsBeforeStarting;
+    }
+
+    @Override
+    public boolean hasEnrollments() {
+        return !mBiometricUtils.getBiometricsForUser(getContext(), getTargetUserId()).isEmpty();
+    }
+
+    @Override
     public int getProtoEnum() {
         return BiometricsProto.CM_REMOVE;
     }
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index fa02c51..af8e8c2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -35,6 +35,7 @@
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
 import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.BiometricsProtoEnums;
@@ -62,11 +63,13 @@
 import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.util.EventLog;
 import android.util.Pair;
@@ -111,6 +114,7 @@
     private final FingerprintServiceWrapper mServiceWrapper;
     @NonNull private final List<ServiceProvider> mServiceProviders;
     @NonNull private final FingerprintStateCallback mFingerprintStateCallback;
+    @NonNull private final Handler mHandler;
 
     @GuardedBy("mLock")
     @NonNull private final RemoteCallbackList<IFingerprintAuthenticatorsRegisteredCallback>
@@ -125,6 +129,37 @@
      */
     public void registerFingerprintStateListener(@NonNull IFingerprintStateListener listener) {
         mFingerprintStateCallback.registerFingerprintStateListener(listener);
+        broadcastCurrentEnrollmentState(listener);
+    }
+
+    /**
+     * @param listener if non-null, notifies only this listener. if null, notifies all listeners
+     *                 in {@link FingerprintStateCallback}. This is slightly ugly, but reduces
+     *                 redundant code.
+     */
+    private void broadcastCurrentEnrollmentState(@Nullable IFingerprintStateListener listener) {
+        final UserManager um = UserManager.get(getContext());
+        synchronized (mLock) {
+            // Update the new listener with current state of all sensors
+            for (FingerprintSensorPropertiesInternal prop : mSensorProps) {
+                final ServiceProvider provider = getProviderForSensor(prop.sensorId);
+                for (UserInfo userInfo : um.getAliveUsers()) {
+                    final boolean enrolled = !provider
+                            .getEnrolledFingerprints(prop.sensorId, userInfo.id).isEmpty();
+
+                    // Defer this work and allow the loop to release the lock sooner
+                    mHandler.post(() -> {
+                        if (listener != null) {
+                            mFingerprintStateCallback.notifyFingerprintEnrollmentStateChanged(
+                                    listener, userInfo.id, prop.sensorId, enrolled);
+                        } else {
+                            mFingerprintStateCallback.notifyAllFingerprintEnrollmentStateChanged(
+                                    userInfo.id, prop.sensorId, enrolled);
+                        }
+                    });
+                }
+            }
+        }
     }
 
     /**
@@ -143,8 +178,7 @@
                 return null;
             }
 
-            return provider.createTestSession(sensorId, callback, mFingerprintStateCallback,
-                    opPackageName);
+            return provider.createTestSession(sensorId, callback, opPackageName);
         }
 
         @Override
@@ -227,7 +261,7 @@
             }
 
             provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId,
-                    receiver, opPackageName, enrollReason, mFingerprintStateCallback);
+                    receiver, opPackageName, enrollReason);
         }
 
         @Override // Binder call
@@ -306,7 +340,7 @@
             }
             return provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
                     0 /* cookie */, new ClientMonitorCallbackConverter(receiver), opPackageName,
-                    restricted, statsClient, isKeyguard, mFingerprintStateCallback);
+                    restricted, statsClient, isKeyguard);
         }
 
         private long authenticateWithPrompt(
@@ -414,7 +448,7 @@
 
             return provider.second.scheduleFingerDetect(provider.first, token, userId,
                     new ClientMonitorCallbackConverter(receiver), opPackageName,
-                    BiometricsProtoEnums.CLIENT_KEYGUARD, mFingerprintStateCallback);
+                    BiometricsProtoEnums.CLIENT_KEYGUARD);
         }
 
         @Override // Binder call
@@ -433,7 +467,7 @@
             provider.scheduleAuthenticate(sensorId, token, operationId, userId, cookie,
                     new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, requestId,
                     restricted, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
-                    allowBackgroundAuthentication, mFingerprintStateCallback);
+                    allowBackgroundAuthentication);
         }
 
         @Override // Binder call
@@ -687,27 +721,6 @@
                     .isEmpty();
         }
 
-        @Override // Binder call
-        public boolean hasEnrolledTemplatesForAnySensor(int userId,
-                @NonNull List<FingerprintSensorPropertiesInternal> sensors,
-                @NonNull String opPackageName) {
-            Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
-
-            for (FingerprintSensorPropertiesInternal prop : sensors) {
-                final ServiceProvider provider = getProviderForSensor(prop.sensorId);
-                if (provider == null) {
-                    Slog.w(TAG, "Null provider for sensorId: " + prop.sensorId
-                            + ", caller: " + opPackageName);
-                    continue;
-                }
-
-                if (!provider.getEnrolledFingerprints(prop.sensorId, userId).isEmpty()) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
         public boolean hasEnrolledFingerprints(int sensorId, int userId, String opPackageName) {
             Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
 
@@ -797,10 +810,12 @@
                         && Settings.Secure.getIntForUser(getContext().getContentResolver(),
                         Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */,
                         UserHandle.USER_CURRENT) != 0) {
-                    fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(), hidlSensor,
+                    fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(),
+                            mFingerprintStateCallback, hidlSensor,
                             mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
                 } else {
-                    fingerprint21 = Fingerprint21.newInstance(getContext(), hidlSensor,
+                    fingerprint21 = Fingerprint21.newInstance(getContext(),
+                            mFingerprintStateCallback, hidlSensor,
                             mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
                 }
                 mServiceProviders.add(fingerprint21);
@@ -823,8 +838,9 @@
                 try {
                     final SensorProps[] props = fp.getSensorProps();
                     final FingerprintProvider provider =
-                            new FingerprintProvider(getContext(), props, instance,
-                                    mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
+                            new FingerprintProvider(getContext(), mFingerprintStateCallback, props,
+                                    instance, mLockoutResetDispatcher,
+                                    mGestureAvailabilityDispatcher);
                     mServiceProviders.add(provider);
                 } catch (RemoteException e) {
                     Slog.e(TAG, "Remote exception in getSensorProps: " + fqName);
@@ -878,6 +894,7 @@
                     }
                 }
 
+                broadcastCurrentEnrollmentState(null); // broadcasts to all listeners
                 broadcastAllAuthenticatorsRegistered();
             });
         }
@@ -975,6 +992,7 @@
         mFingerprintStateCallback = new FingerprintStateCallback();
         mAuthenticatorsRegisteredCallbacks = new RemoteCallbackList<>();
         mSensorProps = new ArrayList<>();
+        mHandler = new Handler(Looper.getMainLooper());
     }
 
     // Notifies the callbacks that all of the authenticators have been registered and removes the
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java
index 5f998d8..0050a89 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java
@@ -23,6 +23,7 @@
 import static android.hardware.fingerprint.FingerprintStateListener.STATE_KEYGUARD_AUTH;
 
 import android.annotation.NonNull;
+import android.content.Context;
 import android.hardware.fingerprint.FingerprintStateListener;
 import android.hardware.fingerprint.IFingerprintStateListener;
 import android.os.RemoteException;
@@ -31,6 +32,9 @@
 import com.android.server.biometrics.Utils;
 import com.android.server.biometrics.sensors.AuthenticationClient;
 import com.android.server.biometrics.sensors.BaseClientMonitor;
+import com.android.server.biometrics.sensors.EnrollClient;
+import com.android.server.biometrics.sensors.EnrollmentModifier;
+import com.android.server.biometrics.sensors.RemovalConsumer;
 import com.android.server.biometrics.sensors.fingerprint.hidl.FingerprintEnrollClient;
 
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -39,9 +43,11 @@
  * A callback for receiving notifications about changes in fingerprint state.
  */
 public class FingerprintStateCallback implements BaseClientMonitor.Callback {
-    private @FingerprintStateListener.State int mFingerprintState;
+
     @NonNull private final CopyOnWriteArrayList<IFingerprintStateListener>
-        mFingerprintStateListeners = new CopyOnWriteArrayList<>();
+            mFingerprintStateListeners = new CopyOnWriteArrayList<>();
+
+    private @FingerprintStateListener.State int mFingerprintState;
 
     public FingerprintStateCallback() {
         mFingerprintState = STATE_IDLE;
@@ -54,8 +60,9 @@
     @Override
     public void onClientStarted(@NonNull BaseClientMonitor client) {
         final int previousFingerprintState = mFingerprintState;
+
         if (client instanceof AuthenticationClient) {
-            AuthenticationClient authClient = (AuthenticationClient) client;
+            final AuthenticationClient<?> authClient = (AuthenticationClient<?>) client;
             if (authClient.isKeyguard()) {
                 mFingerprintState = STATE_KEYGUARD_AUTH;
             } else if (authClient.isBiometricPrompt()) {
@@ -70,6 +77,7 @@
                     "Other authentication client: " + Utils.getClientName(client));
             mFingerprintState = STATE_IDLE;
         }
+
         Slog.d(FingerprintService.TAG, "Fps state updated from " + previousFingerprintState
                 + " to " + mFingerprintState + ", client " + client);
         notifyFingerprintStateListeners(mFingerprintState);
@@ -81,6 +89,18 @@
         Slog.d(FingerprintService.TAG,
                 "Client finished, fps state updated to " + mFingerprintState + ", client "
                         + client);
+
+        if (client instanceof EnrollmentModifier) {
+            EnrollmentModifier enrollmentModifier = (EnrollmentModifier) client;
+            final boolean enrollmentStateChanged = enrollmentModifier.hasEnrollmentStateChanged();
+            Slog.d(FingerprintService.TAG, "Enrollment state changed: " + enrollmentStateChanged);
+            if (enrollmentStateChanged) {
+                notifyAllFingerprintEnrollmentStateChanged(client.getTargetUserId(),
+                        client.getSensorId(),
+                        enrollmentModifier.hasEnrollments());
+            }
+        }
+
         notifyFingerprintStateListeners(mFingerprintState);
     }
 
@@ -95,6 +115,32 @@
     }
 
     /**
+     * This should be invoked when:
+     *  1) Enrolled --> None-enrolled
+     *  2) None-enrolled --> enrolled
+     *  3) HAL becomes ready
+     *  4) Listener is registered
+     */
+    void notifyAllFingerprintEnrollmentStateChanged(int userId, int sensorId,
+            boolean hasEnrollments) {
+        for (IFingerprintStateListener listener : mFingerprintStateListeners) {
+            notifyFingerprintEnrollmentStateChanged(listener, userId, sensorId, hasEnrollments);
+        }
+    }
+
+    /**
+     * Notifies the listener of enrollment state changes.
+     */
+    void notifyFingerprintEnrollmentStateChanged(@NonNull IFingerprintStateListener listener,
+            int userId, int sensorId, boolean hasEnrollments) {
+        try {
+            listener.onEnrollmentsChanged(userId, sensorId, hasEnrollments);
+        } catch (RemoteException e) {
+            Slog.e(FingerprintService.TAG, "Remote exception", e);
+        }
+    }
+
+    /**
      * Enables clients to register a FingerprintStateListener. Used by FingerprintService to forward
      * updates in fingerprint sensor state to the SideFpNsEventHandler
      * @param listener
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
index b9fcd8e..1772f81 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
@@ -90,27 +90,23 @@
      */
     void scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken,
             int userId, @NonNull IFingerprintServiceReceiver receiver,
-            @NonNull String opPackageName, @FingerprintManager.EnrollReason int enrollReason,
-            @NonNull FingerprintStateCallback fingerprintStateCallback);
+            @NonNull String opPackageName, @FingerprintManager.EnrollReason int enrollReason);
 
     void cancelEnrollment(int sensorId, @NonNull IBinder token);
 
     long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
             @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName,
-            int statsClient,
-            @NonNull FingerprintStateCallback fingerprintStateCallback);
+            int statsClient);
 
     void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
             int cookie, @NonNull ClientMonitorCallbackConverter callback,
             @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
-            boolean allowBackgroundAuthentication,
-            @NonNull FingerprintStateCallback fingerprintStateCallback);
+            boolean allowBackgroundAuthentication);
 
     long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
             int cookie, @NonNull ClientMonitorCallbackConverter callback,
             @NonNull String opPackageName, boolean restricted, int statsClient,
-            boolean allowBackgroundAuthentication,
-            @NonNull FingerprintStateCallback fingerprintStateCallback);
+            boolean allowBackgroundAuthentication);
 
     void startPreparedClient(int sensorId, int cookie);
 
@@ -169,6 +165,5 @@
 
     @NonNull
     ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
-            @NonNull FingerprintStateCallback fingerprintStateCallback,
             @NonNull String opPackageName);
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java
index 29f2f20..2b50b96 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java
@@ -143,8 +143,7 @@
         Utils.checkPermission(mContext, TEST_BIOMETRIC);
 
         mProvider.scheduleEnroll(mSensorId, new Binder(), new byte[69], userId, mReceiver,
-                mContext.getOpPackageName(), FingerprintManager.ENROLL_ENROLL,
-                mFingerprintStateCallback);
+                mContext.getOpPackageName(), FingerprintManager.ENROLL_ENROLL);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index 377feca..ca83dda 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -82,6 +82,7 @@
     private boolean mTestHalEnabled;
 
     @NonNull private final Context mContext;
+    @NonNull private final FingerprintStateCallback mFingerprintStateCallback;
     @NonNull private final String mHalInstanceName;
     @NonNull @VisibleForTesting
     final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports
@@ -130,10 +131,13 @@
         }
     }
 
-    public FingerprintProvider(@NonNull Context context, @NonNull SensorProps[] props,
-            @NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher,
+    public FingerprintProvider(@NonNull Context context,
+            @NonNull FingerprintStateCallback fingerprintStateCallback,
+            @NonNull SensorProps[] props, @NonNull String halInstanceName,
+            @NonNull LockoutResetDispatcher lockoutResetDispatcher,
             @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
         mContext = context;
+        mFingerprintStateCallback = fingerprintStateCallback;
         mHalInstanceName = halInstanceName;
         mSensors = new SparseArray<>();
         mHandler = new Handler(Looper.getMainLooper());
@@ -335,8 +339,7 @@
     public void scheduleEnroll(int sensorId, @NonNull IBinder token,
             @NonNull byte[] hardwareAuthToken, int userId,
             @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName,
-            @FingerprintManager.EnrollReason int enrollReason,
-            @NonNull FingerprintStateCallback fingerprintStateCallback) {
+            @FingerprintManager.EnrollReason int enrollReason) {
         mHandler.post(() -> {
             final int maxTemplatesPerUser = mSensors.get(sensorId).getSensorProperties()
                     .maxEnrollmentsPerUser;
@@ -350,13 +353,13 @@
 
                 @Override
                 public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
-                    fingerprintStateCallback.onClientStarted(clientMonitor);
+                    mFingerprintStateCallback.onClientStarted(clientMonitor);
                 }
 
                 @Override
                 public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
                         boolean success) {
-                    fingerprintStateCallback.onClientFinished(clientMonitor, success);
+                    mFingerprintStateCallback.onClientFinished(clientMonitor, success);
                     if (success) {
                         scheduleLoadAuthenticatorIdsForUser(sensorId, userId);
                         scheduleInvalidationRequest(sensorId, userId);
@@ -374,17 +377,15 @@
     @Override
     public long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
             @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName,
-            int statsClient,
-            @NonNull FingerprintStateCallback fingerprintStateCallback) {
+            int statsClient) {
         final long id = mRequestCounter.incrementAndGet();
-
         mHandler.post(() -> {
             final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
             final FingerprintDetectClient client = new FingerprintDetectClient(mContext,
                     mSensors.get(sensorId).getLazySession(), token, id, callback, userId,
                     opPackageName, sensorId, mUdfpsOverlayController, isStrongBiometric,
                     statsClient);
-            scheduleForSensor(sensorId, client, fingerprintStateCallback);
+            scheduleForSensor(sensorId, client, mFingerprintStateCallback);
         });
 
         return id;
@@ -394,8 +395,7 @@
     public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
             int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
             @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
-            boolean allowBackgroundAuthentication,
-            @NonNull FingerprintStateCallback fingerprintStateCallback) {
+            boolean allowBackgroundAuthentication) {
         mHandler.post(() -> {
             final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
             final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
@@ -405,7 +405,7 @@
                     mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
                     mUdfpsOverlayController, allowBackgroundAuthentication,
                     mSensors.get(sensorId).getSensorProperties());
-            scheduleForSensor(sensorId, client, fingerprintStateCallback);
+            scheduleForSensor(sensorId, client, mFingerprintStateCallback);
         });
     }
 
@@ -413,13 +413,11 @@
     public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
             int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
             @NonNull String opPackageName, boolean restricted, int statsClient,
-            boolean allowBackgroundAuthentication,
-            @NonNull FingerprintStateCallback fingerprintStateCallback) {
+            boolean allowBackgroundAuthentication) {
         final long id = mRequestCounter.incrementAndGet();
 
         scheduleAuthenticate(sensorId, token, operationId, userId, cookie, callback,
-                opPackageName, id, restricted, statsClient, allowBackgroundAuthentication,
-                fingerprintStateCallback);
+                opPackageName, id, restricted, statsClient, allowBackgroundAuthentication);
 
         return id;
     }
@@ -466,7 +464,7 @@
                     new ClientMonitorCallbackConverter(receiver), fingerprintIds, userId,
                     opPackageName, FingerprintUtils.getInstance(sensorId), sensorId,
                     mSensors.get(sensorId).getAuthenticatorIds());
-            scheduleForSensor(sensorId, client);
+            scheduleForSensor(sensorId, client, mFingerprintStateCallback);
         });
     }
 
@@ -481,7 +479,8 @@
                             mContext.getOpPackageName(), sensorId, enrolledList,
                             FingerprintUtils.getInstance(sensorId),
                             mSensors.get(sensorId).getAuthenticatorIds());
-            scheduleForSensor(sensorId, client, callback);
+            scheduleForSensor(sensorId, client, new BaseClientMonitor.CompositeCallback(callback,
+                    mFingerprintStateCallback));
         });
     }
 
@@ -626,9 +625,8 @@
     @NonNull
     @Override
     public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
-            @NonNull FingerprintStateCallback fingerprintStateCallback,
             @NonNull String opPackageName) {
-        return mSensors.get(sensorId).createTestSession(callback, fingerprintStateCallback);
+        return mSensors.get(sensorId).createTestSession(callback, mFingerprintStateCallback);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java
index c00daff..79c6b1b3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java
@@ -143,8 +143,7 @@
         Utils.checkPermission(mContext, TEST_BIOMETRIC);
 
         mFingerprint21.scheduleEnroll(mSensorId, new Binder(), new byte[69], userId, mReceiver,
-                mContext.getOpPackageName(), FingerprintManager.ENROLL_ENROLL,
-                mFingerprintStateCallback);
+                mContext.getOpPackageName(), FingerprintManager.ENROLL_ENROLL);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index f17bcc8..d2882aa 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -102,6 +102,7 @@
     private boolean mTestHalEnabled;
 
     final Context mContext;
+    @NonNull private final FingerprintStateCallback mFingerprintStateCallback;
     private final ActivityTaskManager mActivityTaskManager;
     @NonNull private final FingerprintSensorPropertiesInternal mSensorProperties;
     private final BiometricScheduler mScheduler;
@@ -317,11 +318,13 @@
     }
 
     Fingerprint21(@NonNull Context context,
+            @NonNull FingerprintStateCallback fingerprintStateCallback,
             @NonNull FingerprintSensorPropertiesInternal sensorProps,
             @NonNull BiometricScheduler scheduler, @NonNull Handler handler,
             @NonNull LockoutResetDispatcher lockoutResetDispatcher,
             @NonNull HalResultController controller) {
         mContext = context;
+        mFingerprintStateCallback = fingerprintStateCallback;
 
         mSensorProperties = sensorProps;
         mSensorId = sensorProps.sensorId;
@@ -351,6 +354,7 @@
     }
 
     public static Fingerprint21 newInstance(@NonNull Context context,
+            @NonNull FingerprintStateCallback fingerprintStateCallback,
             @NonNull FingerprintSensorPropertiesInternal sensorProps,
             @NonNull LockoutResetDispatcher lockoutResetDispatcher,
             @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
@@ -362,8 +366,8 @@
         final HalResultController controller = new HalResultController(sensorProps.sensorId,
                 context, handler,
                 scheduler);
-        return new Fingerprint21(context, sensorProps, scheduler, handler, lockoutResetDispatcher,
-                controller);
+        return new Fingerprint21(context, fingerprintStateCallback, sensorProps, scheduler, handler,
+                lockoutResetDispatcher, controller);
     }
 
     @Override
@@ -557,8 +561,7 @@
     public void scheduleEnroll(int sensorId, @NonNull IBinder token,
             @NonNull byte[] hardwareAuthToken, int userId,
             @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName,
-            @FingerprintManager.EnrollReason int enrollReason,
-            @NonNull FingerprintStateCallback fingerprintStateCallback) {
+            @FingerprintManager.EnrollReason int enrollReason) {
         mHandler.post(() -> {
             scheduleUpdateActiveUserWithoutHandler(userId);
 
@@ -570,13 +573,13 @@
             mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() {
                 @Override
                 public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
-                    fingerprintStateCallback.onClientStarted(clientMonitor);
+                    mFingerprintStateCallback.onClientStarted(clientMonitor);
                 }
 
                 @Override
                 public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
                         boolean success) {
-                    fingerprintStateCallback.onClientFinished(clientMonitor, success);
+                    mFingerprintStateCallback.onClientFinished(clientMonitor, success);
                     if (success) {
                         // Update authenticatorIds
                         scheduleUpdateActiveUserWithoutHandler(clientMonitor.getTargetUserId(),
@@ -597,10 +600,8 @@
     @Override
     public long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
             @NonNull ClientMonitorCallbackConverter listener, @NonNull String opPackageName,
-            int statsClient,
-            @NonNull FingerprintStateCallback fingerprintStateCallback) {
+            int statsClient) {
         final long id = mRequestCounter.incrementAndGet();
-
         mHandler.post(() -> {
             scheduleUpdateActiveUserWithoutHandler(userId);
 
@@ -609,7 +610,7 @@
                     mLazyDaemon, token, id, listener, userId, opPackageName,
                     mSensorProperties.sensorId, mUdfpsOverlayController, isStrongBiometric,
                     statsClient);
-            mScheduler.scheduleClientMonitor(client, fingerprintStateCallback);
+            mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
         });
 
         return id;
@@ -619,8 +620,7 @@
     public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
             int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener,
             @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
-            boolean allowBackgroundAuthentication,
-            @NonNull FingerprintStateCallback fingerprintStateCallback) {
+            boolean allowBackgroundAuthentication) {
         mHandler.post(() -> {
             scheduleUpdateActiveUserWithoutHandler(userId);
 
@@ -631,7 +631,7 @@
                     mSensorProperties.sensorId, isStrongBiometric, statsClient,
                     mTaskStackListener, mLockoutTracker, mUdfpsOverlayController,
                     allowBackgroundAuthentication, mSensorProperties);
-            mScheduler.scheduleClientMonitor(client, fingerprintStateCallback);
+            mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
         });
     }
 
@@ -639,13 +639,11 @@
     public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
             int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener,
             @NonNull String opPackageName, boolean restricted, int statsClient,
-            boolean allowBackgroundAuthentication,
-            @NonNull FingerprintStateCallback fingerprintStateCallback) {
+            boolean allowBackgroundAuthentication) {
         final long id = mRequestCounter.incrementAndGet();
 
         scheduleAuthenticate(sensorId, token, operationId, userId, cookie, listener,
-                opPackageName, id, restricted, statsClient, allowBackgroundAuthentication,
-                fingerprintStateCallback);
+                opPackageName, id, restricted, statsClient, allowBackgroundAuthentication);
 
         return id;
     }
@@ -672,7 +670,7 @@
                     mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), fingerId,
                     userId, opPackageName, FingerprintUtils.getLegacyInstance(mSensorId),
                     mSensorProperties.sensorId, mAuthenticatorIds);
-            mScheduler.scheduleClientMonitor(client);
+            mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
         });
     }
 
@@ -689,7 +687,7 @@
                     0 /* fingerprintId */, userId, opPackageName,
                     FingerprintUtils.getLegacyInstance(mSensorId),
                     mSensorProperties.sensorId, mAuthenticatorIds);
-            mScheduler.scheduleClientMonitor(client);
+            mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
         });
     }
 
@@ -711,7 +709,8 @@
     @Override
     public void scheduleInternalCleanup(int sensorId, int userId,
             @Nullable BaseClientMonitor.Callback callback) {
-        scheduleInternalCleanup(userId, callback);
+        scheduleInternalCleanup(userId, new BaseClientMonitor.CompositeCallback(callback,
+                mFingerprintStateCallback));
     }
 
     @Override
@@ -919,9 +918,8 @@
     @NonNull
     @Override
     public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
-            @NonNull FingerprintStateCallback fingerprintStateCallback,
             @NonNull String opPackageName) {
         return new BiometricTestSessionImpl(mContext, mSensorProperties.sensorId, callback,
-                fingerprintStateCallback, this, mHalResultController);
+                mFingerprintStateCallback, this, mHalResultController);
     }
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
index 24ce867..79ad8e1 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
@@ -26,6 +26,7 @@
 import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
 import android.hardware.fingerprint.FingerprintSensorProperties;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.hardware.fingerprint.FingerprintStateListener;
 import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.os.Handler;
 import android.os.IBinder;
@@ -42,6 +43,7 @@
 import com.android.server.biometrics.sensors.BiometricScheduler;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
 import com.android.server.biometrics.sensors.LockoutResetDispatcher;
+import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback;
 import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
 
 import java.util.ArrayList;
@@ -270,6 +272,7 @@
     }
 
     public static Fingerprint21UdfpsMock newInstance(@NonNull Context context,
+            @NonNull FingerprintStateCallback fingerprintStateCallback,
             @NonNull FingerprintSensorPropertiesInternal sensorProps,
             @NonNull LockoutResetDispatcher lockoutResetDispatcher,
             @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
@@ -280,8 +283,8 @@
                 new TestableBiometricScheduler(TAG, gestureAvailabilityDispatcher);
         final MockHalResultController controller =
                 new MockHalResultController(sensorProps.sensorId, context, handler, scheduler);
-        return new Fingerprint21UdfpsMock(context, sensorProps, scheduler, handler,
-                lockoutResetDispatcher, controller);
+        return new Fingerprint21UdfpsMock(context, fingerprintStateCallback, sensorProps, scheduler,
+                handler, lockoutResetDispatcher, controller);
     }
 
     private static abstract class FakeFingerRunnable implements Runnable {
@@ -400,17 +403,19 @@
             // internal preemption logic is not run.
             mFingerprint21.scheduleAuthenticate(mFingerprint21.mSensorProperties.sensorId, token,
                     operationId, user, cookie, listener, opPackageName, restricted, statsClient,
-                    isKeyguard, null /* fingerprintStateCallback */);
+                    isKeyguard);
         }
     }
 
     private Fingerprint21UdfpsMock(@NonNull Context context,
+            @NonNull FingerprintStateCallback fingerprintStateCallback,
             @NonNull FingerprintSensorPropertiesInternal sensorProps,
             @NonNull TestableBiometricScheduler scheduler,
             @NonNull Handler handler,
             @NonNull LockoutResetDispatcher lockoutResetDispatcher,
             @NonNull MockHalResultController controller) {
-        super(context, sensorProps, scheduler, handler, lockoutResetDispatcher, controller);
+        super(context, fingerprintStateCallback, sensorProps, scheduler, handler,
+                lockoutResetDispatcher, controller);
         mScheduler = scheduler;
         mScheduler.init(this);
         mHandler = handler;
diff --git a/services/core/java/com/android/server/connectivity/PacProxyService.java b/services/core/java/com/android/server/connectivity/PacProxyService.java
index b2df535..3a97765 100644
--- a/services/core/java/com/android/server/connectivity/PacProxyService.java
+++ b/services/core/java/com/android/server/connectivity/PacProxyService.java
@@ -34,7 +34,6 @@
 import android.net.TrafficStats;
 import android.net.Uri;
 import android.os.Handler;
-import android.os.HandlerExecutor;
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.RemoteCallbackList;
@@ -42,6 +41,7 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
 
@@ -357,8 +357,9 @@
                 }
             }
         };
-        mContext.bindService(intent, mConnection,
-                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE);
+        mContext.bindServiceAsUser(intent, mConnection,
+                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
+                UserHandle.SYSTEM);
 
         intent = new Intent();
         intent.setClassName(PROXY_PACKAGE, PROXY_SERVICE);
@@ -398,9 +399,9 @@
                 }
             }
         };
-        mContext.bindService(intent,
+        mContext.bindServiceAsUser(intent, mProxyConnection,
                 Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
-                new HandlerExecutor(mNetThreadHandler), mProxyConnection);
+                mNetThreadHandler, UserHandle.SYSTEM);
     }
 
     private void unbind() {
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index 383b392..806a5dd 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -19,7 +19,6 @@
 import static android.Manifest.permission.CONTROL_DEVICE_STATE;
 import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE;
 import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
-import static android.os.Process.THREAD_PRIORITY_DISPLAY;
 
 import static com.android.server.devicestate.OverrideRequestController.STATUS_ACTIVE;
 import static com.android.server.devicestate.OverrideRequestController.STATUS_CANCELED;
@@ -36,7 +35,6 @@
 import android.hardware.devicestate.IDeviceStateManagerCallback;
 import android.os.Binder;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -48,8 +46,8 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.DisplayThread;
 import com.android.server.LocalServices;
-import com.android.server.ServiceThread;
 import com.android.server.SystemService;
 import com.android.server.policy.DeviceStatePolicyImpl;
 import com.android.server.wm.ActivityTaskManagerInternal;
@@ -93,10 +91,9 @@
     private static final boolean DEBUG = false;
 
     private final Object mLock = new Object();
-    // Internal system service thread used to dispatch calls to the policy and to registered
+    // Handler on the {@link DisplayThread} used to dispatch calls to the policy and to registered
     // callbacks though its handler (mHandler). Provides a guarantee of callback order when
     // leveraging mHandler and also enables posting messages with the service lock held.
-    private final HandlerThread mHandlerThread;
     private final Handler mHandler;
     @NonNull
     private final DeviceStatePolicy mDeviceStatePolicy;
@@ -149,11 +146,10 @@
     @VisibleForTesting
     DeviceStateManagerService(@NonNull Context context, @NonNull DeviceStatePolicy policy) {
         super(context);
-        // Service thread assigned THREAD_PRIORITY_DISPLAY because this service indirectly drives
+        // We use the DisplayThread because this service indirectly drives
         // display (on/off) and window (position) events through its callbacks.
-        mHandlerThread = new ServiceThread(TAG, THREAD_PRIORITY_DISPLAY, false /* allowIo */);
-        mHandlerThread.start();
-        mHandler = mHandlerThread.getThreadHandler();
+        DisplayThread displayThread = DisplayThread.get();
+        mHandler = new Handler(displayThread.getLooper());
         mOverrideRequestController = new OverrideRequestController(
                 this::onOverrideRequestStatusChangedLocked);
         mDeviceStatePolicy = policy;
@@ -552,7 +548,7 @@
             }
 
             ProcessRecord record = new ProcessRecord(callback, pid, this::handleProcessDied,
-                    mHandlerThread.getThreadHandler());
+                    mHandler);
             try {
                 callback.asBinder().linkToDeath(record, 0);
             } catch (RemoteException ex) {
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 806bcc2..def9685 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -206,6 +206,13 @@
             DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) {}
 
     /**
+     * Sets the user preferred display mode. Removes the user preferred display mode and sets
+     * default display mode as the mode chosen by HAL, if 'mode' is null
+     * Returns true if the mode set by user is supported by the display.
+     */
+    public void setUserPreferredDisplayModeLocked(Display.Mode mode) { }
+
+    /**
      * Sets the requested color mode.
      */
     public void setRequestedColorModeLocked(int colorMode) {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 73bcea6..c964e37 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -130,6 +130,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicLong;
@@ -213,6 +214,9 @@
     private int[] mUserDisabledHdrTypes = {};
     private boolean mAreUserDisabledHdrTypesAllowed = true;
 
+    // Display mode chosen by user.
+    private Display.Mode mUserPreferredMode;
+
     // The synchronization root for the display manager.
     // This lock guards most of the display manager's state.
     // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call
@@ -581,6 +585,7 @@
             updateSettingsLocked();
 
             updateUserDisabledHdrTypesFromSettingsLocked();
+            updateUserPreferredDisplayModeSettingsLocked();
         }
 
         mDisplayModeDirector.setDesiredDisplayModeSpecsListener(
@@ -795,9 +800,8 @@
                     mUserDisabledHdrTypes[i] = Integer.parseInt(userDisabledHdrTypeStrings[i]);
                 }
             } catch (NumberFormatException e) {
-                Slog.e(TAG,
-                        "Failed to parse USER_DISABLED_HDR_FORMATS. "
-                                + "Clearing the setting.", e);
+                Slog.e(TAG, "Failed to parse USER_DISABLED_HDR_FORMATS. "
+                        + "Clearing the setting.", e);
                 clearUserDisabledHdrTypesLocked();
             }
         } else {
@@ -813,6 +817,17 @@
         }
     }
 
+    private void updateUserPreferredDisplayModeSettingsLocked() {
+        final float refreshRate = Settings.Global.getFloat(mContext.getContentResolver(),
+                Settings.Global.USER_PREFERRED_REFRESH_RATE, 0.0f);
+        final int height = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.USER_PREFERRED_RESOLUTION_HEIGHT, -1);
+        final int width = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.USER_PREFERRED_RESOLUTION_WIDTH, -1);
+        Display.Mode mode = new Display.Mode(height, width, refreshRate);
+        mUserPreferredMode = isResolutionAndRefreshRateValid(mode) ? mode : null;
+    }
+
     private DisplayInfo getDisplayInfoForFrameRateOverride(DisplayEventReceiver.FrameRateOverride[]
             frameRateOverrides, DisplayInfo info, int callingUid) {
         float frameRateHz = 0;
@@ -1259,6 +1274,9 @@
             recordStableDisplayStatsIfNeededLocked(display);
             recordTopInsetLocked(display);
         }
+        if (mUserPreferredMode != null) {
+            device.setUserPreferredDisplayModeLocked(mUserPreferredMode);
+        }
         addDisplayPowerControllerLocked(display);
         mDisplayStates.append(displayId, Display.STATE_UNKNOWN);
 
@@ -1429,6 +1447,39 @@
         return mWideColorSpace.getId();
     }
 
+    void setUserPreferredDisplayModeInternal(Display.Mode mode) {
+        synchronized (mSyncRoot) {
+            if (Objects.equals(mUserPreferredMode, mode)) {
+                return;
+            }
+
+            if (mode != null && !isResolutionAndRefreshRateValid(mode)) {
+                throw new IllegalArgumentException("width, height and refresh rate of mode should "
+                        + "be greater than 0");
+            }
+            mUserPreferredMode = mode;
+
+            final int resolutionHeight = mode == null ? -1 : mode.getPhysicalHeight();
+            final int resolutionWidth = mode == null ? -1 : mode.getPhysicalWidth();
+            final float refreshRate = mode == null ? 0.0f : mode.getRefreshRate();
+            Settings.Global.putFloat(mContext.getContentResolver(),
+                    Settings.Global.USER_PREFERRED_REFRESH_RATE, refreshRate);
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Global.USER_PREFERRED_RESOLUTION_HEIGHT, resolutionHeight);
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Global.USER_PREFERRED_RESOLUTION_WIDTH, resolutionWidth);
+            mDisplayDeviceRepo.forEachLocked((DisplayDevice device) -> {
+                device.setUserPreferredDisplayModeLocked(mode);
+            });
+        }
+    }
+
+    private Display.Mode getUserPreferredDisplayModeInternal() {
+        synchronized (mSyncRoot) {
+            return mUserPreferredMode;
+        }
+    }
+
     void setShouldAlwaysRespectAppRequestedModeInternal(boolean enabled) {
         mDisplayModeDirector.setShouldAlwaysRespectAppRequestedMode(enabled);
     }
@@ -2019,6 +2070,10 @@
             pw.println("  mStableDisplaySize=" + mStableDisplaySize);
             pw.println("  mMinimumBrightnessCurve=" + mMinimumBrightnessCurve);
 
+            if (mUserPreferredMode != null) {
+                pw.println(mUserPreferredMode.toString());
+            }
+
             pw.println();
             if (!mAreUserDisabledHdrTypesAllowed) {
                 pw.println("  mUserDisabledHdrTypes: size=" + mUserDisabledHdrTypes.length);
@@ -2097,6 +2152,11 @@
         return floatArray;
     }
 
+    private static boolean isResolutionAndRefreshRateValid(Display.Mode mode) {
+        return mode.getPhysicalWidth() > 0 && mode.getPhysicalHeight() > 0
+                && mode.getRefreshRate() > 0.0f;
+    }
+
     /**
      * This is the object that everything in the display manager locks on.
      * We make it an inner class within the {@link DisplayManagerService} to so that it is
@@ -3084,6 +3144,29 @@
         }
 
         @Override // Binder call
+        public void setUserPreferredDisplayMode(Display.Mode mode) {
+            mContext.enforceCallingOrSelfPermission(
+                    Manifest.permission.WRITE_SECURE_SETTINGS,
+                    "Permission required to set the user preferred display mode.");
+            final long token = Binder.clearCallingIdentity();
+            try {
+                setUserPreferredDisplayModeInternal(mode);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override // Binder call
+        public Display.Mode getUserPreferredDisplayMode() {
+            final long token = Binder.clearCallingIdentity();
+            try {
+                return getUserPreferredDisplayModeInternal();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override // Binder call
         public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
             mContext.enforceCallingOrSelfPermission(
                     Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index e16a241..fce3fd5 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -36,9 +36,14 @@
 import android.hardware.fingerprint.IUdfpsHbmListener;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.IThermalEventListener;
+import android.os.IThermalService;
 import android.os.Looper;
 import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.Temperature;
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
 import android.provider.DeviceConfigInterface;
@@ -92,8 +97,6 @@
     // specific display.
     private static final int GLOBAL_ID = -1;
 
-    private static final int INVALID_DISPLAY_MODE_ID = -1;
-
     private static final float FLOAT_TOLERANCE = RefreshRateRange.FLOAT_TOLERANCE;
 
     private final Object mLock = new Object();
@@ -108,6 +111,7 @@
     private final UdfpsObserver mUdfpsObserver;
     private final SensorObserver mSensorObserver;
     private final HbmObserver mHbmObserver;
+    private final SkinThermalStatusObserver mSkinThermalStatusObserver;
     private final DeviceConfigInterface mDeviceConfig;
     private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
 
@@ -156,6 +160,7 @@
         };
         mSensorObserver = new SensorObserver(context, ballotBox, injector);
         mHbmObserver = new HbmObserver(injector, ballotBox, BackgroundThread.getHandler());
+        mSkinThermalStatusObserver = new SkinThermalStatusObserver(injector, ballotBox);
         mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
         mDeviceConfig = injector.getDeviceConfig();
         mAlwaysRespectAppRequest = false;
@@ -174,6 +179,7 @@
         mBrightnessObserver.observe(sensorManager);
         mSensorObserver.observe();
         mHbmObserver.observe();
+        mSkinThermalStatusObserver.observe();
         synchronized (mLock) {
             // We may have a listener already registered before the call to start, so go ahead and
             // notify them to pick up our newly initialized state.
@@ -606,6 +612,7 @@
             mUdfpsObserver.dumpLocked(pw);
             mSensorObserver.dumpLocked(pw);
             mHbmObserver.dumpLocked(pw);
+            mSkinThermalStatusObserver.dumpLocked(pw);
         }
     }
 
@@ -714,7 +721,6 @@
         return mUdfpsObserver;
     }
 
-
     @VisibleForTesting
     DesiredDisplayModeSpecs getDesiredDisplayModeSpecsWithInjectedFpsSettings(
             float minRefreshRate, float peakRefreshRate, float defaultRefreshRate) {
@@ -950,16 +956,19 @@
         // user seeing the display flickering when the switches occur.
         public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 8;
 
+        // Force display to [0, 60HZ] if skin temperature is at or above CRITICAL.
+        public static final int PRIORITY_SKIN_TEMPERATURE = 9;
+
         // High-brightness-mode may need a specific range of refresh-rates to function properly.
-        public static final int PRIORITY_HIGH_BRIGHTNESS_MODE = 9;
+        public static final int PRIORITY_HIGH_BRIGHTNESS_MODE = 10;
 
         // The proximity sensor needs the refresh rate to be locked in order to function, so this is
         // set to a high priority.
-        public static final int PRIORITY_PROXIMITY = 10;
+        public static final int PRIORITY_PROXIMITY = 11;
 
         // The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order
         // to function, so this needs to be the highest priority of all votes.
-        public static final int PRIORITY_UDFPS = 11;
+        public static final int PRIORITY_UDFPS = 12;
 
         // Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and
         // APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString.
@@ -1054,6 +1063,8 @@
                     return "PRIORITY_PROXIMITY";
                 case PRIORITY_LOW_POWER_MODE:
                     return "PRIORITY_LOW_POWER_MODE";
+                case PRIORITY_SKIN_TEMPERATURE:
+                    return "PRIORITY_SKIN_TEMPERATURE";
                 case PRIORITY_UDFPS:
                     return "PRIORITY_UDFPS";
                 case PRIORITY_USER_SETTING_MIN_REFRESH_RATE:
@@ -2311,6 +2322,52 @@
         }
     }
 
+    private final class SkinThermalStatusObserver extends IThermalEventListener.Stub {
+        private final BallotBox mBallotBox;
+        private final Injector mInjector;
+
+        private @Temperature.ThrottlingStatus int mStatus = -1;
+
+        SkinThermalStatusObserver(Injector injector, BallotBox ballotBox) {
+            mInjector = injector;
+            mBallotBox = ballotBox;
+        }
+
+        @Override
+        public void notifyThrottling(Temperature temp) {
+            mStatus = temp.getStatus();
+            if (mLoggingEnabled) {
+                Slog.d(TAG, "New thermal throttling status "
+                        + ", current thermal status = " + mStatus);
+            }
+            final Vote vote;
+            if (mStatus >= Temperature.THROTTLING_CRITICAL) {
+                vote = Vote.forRefreshRates(0f, 60f);
+            } else {
+                vote = null;
+            }
+            mBallotBox.vote(GLOBAL_ID, Vote.PRIORITY_SKIN_TEMPERATURE, vote);
+        }
+
+        public void observe() {
+            IThermalService thermalService = mInjector.getThermalService();
+            if (thermalService == null) {
+                Slog.w(TAG, "Could not observe thermal status. Service not available");
+                return;
+            }
+            try {
+                thermalService.registerThermalEventListenerWithType(this, Temperature.TYPE_SKIN);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to register thermal status listener", e);
+            }
+        }
+
+        void dumpLocked(PrintWriter writer) {
+            writer.println("  SkinThermalStatusObserver:");
+            writer.println("    mStatus: " + mStatus);
+        }
+    }
+
     private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener {
         public DeviceConfigDisplaySettings() {
         }
@@ -2472,6 +2529,8 @@
         BrightnessInfo getBrightnessInfo(int displayId);
 
         boolean isDozeState(Display d);
+
+        IThermalService getThermalService();
     }
 
     @VisibleForTesting
@@ -2532,6 +2591,12 @@
             return Display.isDozeState(d.getState());
         }
 
+        @Override
+        public IThermalService getThermalService() {
+            return IThermalService.Stub.asInterface(
+                    ServiceManager.getService(Context.THERMAL_SERVICE));
+        }
+
         private DisplayManager getDisplayManager() {
             if (mDisplayManager == null) {
                 mDisplayManager = mContext.getSystemService(DisplayManager.class);
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 06d331a..dbe17b7 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -16,6 +16,8 @@
 
 package com.android.server.display;
 
+import static android.view.Display.Mode.INVALID_MODE_ID;
+
 import android.app.ActivityThread;
 import android.content.Context;
 import android.content.res.Resources;
@@ -65,8 +67,6 @@
 
     private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
 
-    private static final int NO_DISPLAY_MODE_ID = 0;
-
     private final LongSparseArray<LocalDisplayDevice> mDevices = new LongSparseArray<>();
 
     private final Injector mInjector;
@@ -191,9 +191,11 @@
         // This is only set in the runnable returned from requestDisplayStateLocked.
         private float mBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
         private float mSdrBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
-        private int mDefaultModeId;
+        private int mDefaultModeId = INVALID_MODE_ID;
         private int mDefaultModeGroup;
-        private int mActiveModeId;
+        private int mUserPreferredModeId = INVALID_MODE_ID;
+        private Display.Mode mUserPreferredMode;
+        private int mActiveModeId = INVALID_MODE_ID;
         private DisplayModeDirector.DesiredDisplayModeSpecs mDisplayModeSpecs =
                 new DisplayModeDirector.DesiredDisplayModeSpecs();
         private boolean mDisplayModeSpecsInvalid;
@@ -323,7 +325,7 @@
 
             // Check whether SurfaceFlinger or the display device changed the active mode out from
             // under us.
-            if (mActiveModeId != NO_DISPLAY_MODE_ID
+            if (mActiveModeId != INVALID_MODE_ID
                     && mActiveModeId != activeRecord.mMode.getModeId()) {
                 Slog.d(TAG, "The active mode was changed from SurfaceFlinger or the display"
                         + " device to " + activeRecord.mMode);
@@ -334,12 +336,12 @@
 
             // Check whether surface flinger spontaneously changed display config specs out from
             // under us. If so, schedule a traversal to reapply our display config specs.
-            if (mDisplayModeSpecs.baseModeId != NO_DISPLAY_MODE_ID) {
+            if (mDisplayModeSpecs.baseModeId != INVALID_MODE_ID) {
                 int activeBaseMode = findMatchingModeIdLocked(modeSpecs.defaultMode);
                 // If we can't map the defaultMode index to a mode, then the physical display
                 // modes must have changed, and the code below for handling changes to the
                 // list of available modes will take care of updating display mode specs.
-                if (activeBaseMode == NO_DISPLAY_MODE_ID
+                if (activeBaseMode == INVALID_MODE_ID
                         || mDisplayModeSpecs.baseModeId != activeBaseMode
                         || mDisplayModeSpecs.primaryRefreshRateRange.min
                                 != modeSpecs.primaryRefreshRateMin
@@ -366,7 +368,7 @@
             }
 
             // For a new display, we need to initialize the default mode ID.
-            if (mDefaultModeId == NO_DISPLAY_MODE_ID) {
+            if (mDefaultModeId == INVALID_MODE_ID) {
                 mDefaultModeId = activeRecord.mMode.getModeId();
                 mDefaultModeGroup = mActiveSfDisplayMode.group;
             } else if (modesAdded && activeModeChanged) {
@@ -383,7 +385,7 @@
 
             // Determine whether the display mode specs' base mode is still there.
             if (mSupportedModes.indexOfKey(mDisplayModeSpecs.baseModeId) < 0) {
-                if (mDisplayModeSpecs.baseModeId != NO_DISPLAY_MODE_ID) {
+                if (mDisplayModeSpecs.baseModeId != INVALID_MODE_ID) {
                     Slog.w(TAG,
                             "DisplayModeSpecs base mode no longer available, using currently"
                                     + " active mode.");
@@ -392,13 +394,17 @@
                 mDisplayModeSpecsInvalid = true;
             }
 
+            if (mUserPreferredMode != null) {
+                mUserPreferredModeId = findUserPreferredModeIdLocked(mUserPreferredMode);
+            }
+
             // Determine whether the active mode is still there.
             if (mSupportedModes.indexOfKey(mActiveModeId) < 0) {
-                if (mActiveModeId != NO_DISPLAY_MODE_ID) {
+                if (mActiveModeId != INVALID_MODE_ID) {
                     Slog.w(TAG, "Active display mode no longer available, reverting to default"
                             + " mode.");
                 }
-                mActiveModeId = mDefaultModeId;
+                mActiveModeId = getPreferredModeId();
             }
 
             // Schedule traversals so that we apply pending changes.
@@ -414,6 +420,12 @@
             return mDisplayDeviceConfig;
         }
 
+        private int getPreferredModeId() {
+            return mUserPreferredModeId != INVALID_MODE_ID
+                    ? mUserPreferredModeId
+                    : mDefaultModeId;
+        }
+
         private void loadDisplayDeviceConfig() {
             // Load display device config
             final Context context = getOverlayContext();
@@ -561,7 +573,7 @@
                 mInfo.width = mActiveSfDisplayMode.width;
                 mInfo.height = mActiveSfDisplayMode.height;
                 mInfo.modeId = mActiveModeId;
-                mInfo.defaultModeId = mDefaultModeId;
+                mInfo.defaultModeId = getPreferredModeId();
                 mInfo.supportedModes = getDisplayModes(mSupportedModes);
                 mInfo.colorMode = mActiveColorMode;
                 mInfo.allmSupported = mAllmSupported;
@@ -601,8 +613,6 @@
                             && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
                         mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;
                     }
-                    mInfo.roundedCorners = RoundedCorners.fromResources(
-                            res, mInfo.width, mInfo.height);
                 } else {
                     if (!res.getBoolean(
                                 com.android.internal.R.bool.config_localDisplaysMirrorContent)) {
@@ -620,6 +630,9 @@
                 mInfo.displayCutout = DisplayCutout.fromResourcesRectApproximation(res,
                         mInfo.uniqueId, mInfo.width, mInfo.height);
 
+                mInfo.roundedCorners = RoundedCorners.fromResources(
+                        res, mInfo.uniqueId, mInfo.width, mInfo.height);
+
                 if (mStaticDisplayInfo.isInternal) {
                     mInfo.type = Display.TYPE_INTERNAL;
                     mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
@@ -822,6 +835,17 @@
         }
 
         @Override
+        public void setUserPreferredDisplayModeLocked(Display.Mode mode) {
+            final int oldModeId = getPreferredModeId();
+            mUserPreferredMode = mode;
+            mUserPreferredModeId = findUserPreferredModeIdLocked(mode);
+
+            if (oldModeId != getPreferredModeId()) {
+                updateDeviceInfoLocked();
+            }
+        }
+
+        @Override
         public void setRequestedColorModeLocked(int colorMode) {
             requestColorModeLocked(colorMode);
         }
@@ -902,7 +926,7 @@
             }
             mActiveSfDisplayMode = getModeById(mSfDisplayModes, activeSfModeId);
             mActiveModeId = findMatchingModeIdLocked(activeSfModeId);
-            if (mActiveModeId == NO_DISPLAY_MODE_ID) {
+            if (mActiveModeId == INVALID_MODE_ID) {
                 Slog.w(TAG, "In unknown mode after setting allowed modes"
                         + ", activeModeId=" + activeSfModeId);
             }
@@ -987,6 +1011,7 @@
             pw.println("mActiveModeId=" + mActiveModeId);
             pw.println("mActiveColorMode=" + mActiveColorMode);
             pw.println("mDefaultModeId=" + mDefaultModeId);
+            pw.println("mUserPreferredModeId=" + mUserPreferredModeId);
             pw.println("mState=" + Display.stateToString(mState));
             pw.println("mBrightnessState=" + mBrightnessState);
             pw.println("mBacklightAdapter=" + mBacklightAdapter);
@@ -1009,13 +1034,12 @@
         }
 
         private int findDisplayModeIdLocked(int modeId, int modeGroup) {
-            int matchingModeId = SurfaceControl.DisplayMode.INVALID_DISPLAY_MODE_ID;
+            int matchingModeId = INVALID_MODE_ID;
             DisplayModeRecord record = mSupportedModes.get(modeId);
             if (record != null) {
                 for (SurfaceControl.DisplayMode mode : mSfDisplayModes) {
                     if (record.hasMatchingMode(mode)) {
-                        if (matchingModeId
-                                == SurfaceControl.DisplayMode.INVALID_DISPLAY_MODE_ID) {
+                        if (matchingModeId == INVALID_MODE_ID) {
                             matchingModeId = mode.id;
                         }
 
@@ -1029,11 +1053,25 @@
             return matchingModeId;
         }
 
+        private int findUserPreferredModeIdLocked(Display.Mode userPreferredMode) {
+            if (userPreferredMode != null) {
+                for (int i = 0; i < mSupportedModes.size(); i++) {
+                    Display.Mode supportedMode = mSupportedModes.valueAt(i).mMode;
+                    if (userPreferredMode.matches(supportedMode.getPhysicalWidth(),
+                            supportedMode.getPhysicalHeight(),
+                            supportedMode.getRefreshRate())) {
+                        return supportedMode.getModeId();
+                    }
+                }
+            }
+            return INVALID_MODE_ID;
+        }
+
         private int findMatchingModeIdLocked(int sfModeId) {
             SurfaceControl.DisplayMode mode = getModeById(mSfDisplayModes, sfModeId);
             if (mode == null) {
                 Slog.e(TAG, "Invalid display mode ID " + sfModeId);
-                return NO_DISPLAY_MODE_ID;
+                return INVALID_MODE_ID;
             }
             for (int i = 0; i < mSupportedModes.size(); i++) {
                 DisplayModeRecord record = mSupportedModes.valueAt(i);
@@ -1041,7 +1079,7 @@
                     return record.mMode.getModeId();
                 }
             }
-            return NO_DISPLAY_MODE_ID;
+            return INVALID_MODE_ID;
         }
 
         private void updateDeviceInfoLocked() {
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 34d2b01..a592192 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -303,6 +303,9 @@
 
         @Override
         public Point getDisplaySurfaceDefaultSize() {
+            if (mSurface == null) {
+                return null;
+            }
             return mSurface.getDefaultSize();
         }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
index e52e32a..a9b5214 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
@@ -92,6 +92,9 @@
         pw.println("      Sets the System Audio Mode feature on or off on TV devices");
         pw.println("  setarc [on|off]");
         pw.println("      Sets the ARC feature on or off on TV devices");
+        pw.println("  deviceselect <device id>");
+        pw.println("      Switch to device with given id");
+        pw.println("      The device's id is represented by its logical address.");
     }
 
     private int handleShellCommand(String cmd) throws RemoteException {
@@ -110,12 +113,30 @@
                 return setSystemAudioMode(pw);
             case "setarc":
                 return setArcMode(pw);
+            case "deviceselect":
+                return deviceSelect(pw);
         }
 
         getErrPrintWriter().println("Unhandled command: " + cmd);
         return 1;
     }
 
+    private int deviceSelect(PrintWriter pw) throws RemoteException {
+        if (getRemainingArgsCount() != 1) {
+            throw new IllegalArgumentException("Expected exactly 1 argument.");
+        }
+        int deviceId = Integer.parseInt(getNextArg());
+
+        pw.print("Sending Device Select...");
+        mBinderService.deviceSelect(deviceId, mHdmiControlCallback);
+
+        if (!receiveCallback("Device Select")) {
+            return 1;
+        }
+
+        return mCecResult.get() == HdmiControlManager.RESULT_SUCCESS ? 0 : 1;
+    }
+
     private int oneTouchPlay(PrintWriter pw) throws RemoteException {
         pw.print("Sending One Touch Play...");
         mBinderService.oneTouchPlay(mHdmiControlCallback);
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index c905fe0..eb457c9 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -665,12 +665,10 @@
      */
     @Override // Binder call
     public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) {
-        if (keyCodes == null) {
-            throw new IllegalArgumentException("keyCodes must not be null.");
-        }
-        if (keyExists == null || keyExists.length < keyCodes.length) {
-            throw new IllegalArgumentException("keyExists must not be null and must be at "
-                    + "least as large as keyCodes.");
+        Objects.requireNonNull(keyCodes, "keyCodes must not be null");
+        Objects.requireNonNull(keyExists, "keyExists must not be null");
+        if (keyExists.length < keyCodes.length) {
+            throw new IllegalArgumentException("keyExists must be at least as large as keyCodes");
         }
 
         return nativeHasKeys(mPtr, deviceId, sourceMask, keyCodes, keyExists);
@@ -685,7 +683,7 @@
      */
     public boolean transferTouch(IBinder destChannelToken) {
         // TODO(b/162194035): Replace this with a SPY window
-        Objects.requireNonNull(destChannelToken, "destChannelToken must not be null.");
+        Objects.requireNonNull(destChannelToken, "destChannelToken must not be null");
         return nativeTransferTouch(mPtr, destChannelToken);
     }
 
@@ -696,9 +694,7 @@
      * @return The input channel.
      */
     public InputChannel monitorInput(String inputChannelName, int displayId) {
-        if (inputChannelName == null) {
-            throw new IllegalArgumentException("inputChannelName must not be null.");
-        }
+        Objects.requireNonNull(inputChannelName, "inputChannelName not be null");
 
         if (displayId < Display.DEFAULT_DISPLAY) {
             throw new IllegalArgumentException("displayId must >= 0.");
@@ -722,7 +718,6 @@
                 "monitorInputRegion()")) {
             throw new SecurityException("Requires MONITOR_INPUT permission");
         }
-
         Objects.requireNonNull(inputChannelName, "inputChannelName must not be null.");
 
         if (displayId < Display.DEFAULT_DISPLAY) {
@@ -755,10 +750,7 @@
      * @param connectionToken The input channel to unregister.
      */
     public void removeInputChannel(IBinder connectionToken) {
-        if (connectionToken == null) {
-            throw new IllegalArgumentException("connectionToken must not be null.");
-        }
-
+        Objects.requireNonNull(connectionToken, "connectionToken must not be null");
         nativeRemoveInputChannel(mPtr, connectionToken);
     }
 
@@ -830,9 +822,7 @@
     }
 
     private boolean injectInputEventInternal(InputEvent event, int mode) {
-        if (event == null) {
-            throw new IllegalArgumentException("event must not be null");
-        }
+        Objects.requireNonNull(event, "event must not be null");
         if (mode != InputEventInjectionSync.NONE
                 && mode != InputEventInjectionSync.WAIT_FOR_FINISHED
                 && mode != InputEventInjectionSync.WAIT_FOR_RESULT) {
@@ -900,6 +890,7 @@
 
     @Override // Binder call
     public VerifiedInputEvent verifyInputEvent(InputEvent event) {
+        Objects.requireNonNull(event, "event must not be null");
         return nativeVerifyInputEvent(mPtr, event);
     }
 
@@ -976,9 +967,7 @@
 
     @Override // Binder call
     public void registerInputDevicesChangedListener(IInputDevicesChangedListener listener) {
-        if (listener == null) {
-            throw new IllegalArgumentException("listener must not be null");
-        }
+        Objects.requireNonNull(listener, "listener must not be null");
 
         synchronized (mInputDevicesLock) {
             int callingPid = Binder.getCallingPid();
@@ -1173,9 +1162,7 @@
     @Override // Binder call & native callback
     public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor,
             int surfaceRotation) {
-        if (inputDeviceDescriptor == null) {
-            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
-        }
+        Objects.requireNonNull(inputDeviceDescriptor, "inputDeviceDescriptor must not be null");
 
         synchronized (mDataStore) {
             return mDataStore.getTouchCalibration(inputDeviceDescriptor, surfaceRotation);
@@ -1189,12 +1176,8 @@
                 "setTouchCalibrationForInputDevice()")) {
             throw new SecurityException("Requires SET_INPUT_CALIBRATION permission");
         }
-        if (inputDeviceDescriptor == null) {
-            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
-        }
-        if (calibration == null) {
-            throw new IllegalArgumentException("calibration must not be null");
-        }
+        Objects.requireNonNull(inputDeviceDescriptor, "inputDeviceDescriptor must not be null");
+        Objects.requireNonNull(calibration, "calibration must not be null");
         if (surfaceRotation < Surface.ROTATION_0 || surfaceRotation > Surface.ROTATION_270) {
             throw new IllegalArgumentException("surfaceRotation value out of bounds");
         }
@@ -1231,9 +1214,7 @@
                 "registerTabletModeChangedListener()")) {
             throw new SecurityException("Requires TABLET_MODE_LISTENER permission");
         }
-        if (listener == null) {
-            throw new IllegalArgumentException("listener must not be null");
-        }
+        Objects.requireNonNull(listener, "event must not be null");
 
         synchronized (mTabletModeLock) {
             final int callingPid = Binder.getCallingPid();
@@ -1417,9 +1398,8 @@
 
     @Override // Binder call
     public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
-        if (keyboardLayoutDescriptor == null) {
-            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
-        }
+        Objects.requireNonNull(keyboardLayoutDescriptor,
+                "keyboardLayoutDescriptor must not be null");
 
         final KeyboardLayout[] result = new KeyboardLayout[1];
         visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
@@ -1566,9 +1546,8 @@
      * descriptor for ids that aren't useful (such as the default 0, 0).
      */
     private String getLayoutDescriptor(InputDeviceIdentifier identifier) {
-        if (identifier == null || identifier.getDescriptor() == null) {
-            throw new IllegalArgumentException("identifier and descriptor must not be null");
-        }
+        Objects.requireNonNull(identifier, "identifier must not be null");
+        Objects.requireNonNull(identifier.getDescriptor(), "descriptor must not be null");
 
         if (identifier.getVendorId() == 0 && identifier.getProductId() == 0) {
             return identifier.getDescriptor();
@@ -1606,9 +1585,9 @@
                 "setCurrentKeyboardLayoutForInputDevice()")) {
             throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
         }
-        if (keyboardLayoutDescriptor == null) {
-            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
-        }
+
+        Objects.requireNonNull(keyboardLayoutDescriptor,
+                "keyboardLayoutDescriptor must not be null");
 
         String key = getLayoutDescriptor(identifier);
         synchronized (mDataStore) {
@@ -1645,9 +1624,8 @@
                 "addKeyboardLayoutForInputDevice()")) {
             throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
         }
-        if (keyboardLayoutDescriptor == null) {
-            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
-        }
+        Objects.requireNonNull(keyboardLayoutDescriptor,
+                "keyboardLayoutDescriptor must not be null");
 
         String key = getLayoutDescriptor(identifier);
         synchronized (mDataStore) {
@@ -1674,9 +1652,8 @@
                 "removeKeyboardLayoutForInputDevice()")) {
             throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
         }
-        if (keyboardLayoutDescriptor == null) {
-            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
-        }
+        Objects.requireNonNull(keyboardLayoutDescriptor,
+                "keyboardLayoutDescriptor must not be null");
 
         String key = getLayoutDescriptor(identifier);
         synchronized (mDataStore) {
@@ -1762,9 +1739,7 @@
 
     @Override
     public void requestPointerCapture(IBinder inputChannelToken, boolean enabled) {
-        if (inputChannelToken == null) {
-            return;
-        }
+        Objects.requireNonNull(inputChannelToken, "event must not be null");
 
         nativeRequestPointerCapture(mPtr, inputChannelToken, enabled);
     }
@@ -2368,10 +2343,7 @@
             Slog.d(TAG, "registerSensorListener: listener=" + listener + " callingPid="
                     + Binder.getCallingPid());
         }
-        if (listener == null) {
-            Slog.e(TAG, "listener must not be null");
-            return false;
-        }
+        Objects.requireNonNull(listener, "listener must not be null");
 
         synchronized (mInputDevicesLock) {
             int callingPid = Binder.getCallingPid();
@@ -2403,9 +2375,7 @@
                     + Binder.getCallingPid());
         }
 
-        if (listener == null) {
-            throw new IllegalArgumentException("listener must not be null");
-        }
+        Objects.requireNonNull(listener, "listener must not be null");
 
         synchronized (mInputDevicesLock) {
             int callingPid = Binder.getCallingPid();
@@ -3244,9 +3214,7 @@
 
         @Override
         public void sendInputEvent(InputEvent event, int policyFlags) {
-            if (event == null) {
-                throw new IllegalArgumentException("event must not be null");
-            }
+            Objects.requireNonNull(event, "event must not be null");
 
             synchronized (mInputFilterLock) {
                 if (!mDisconnected) {
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index 27a78dd..a491eb7 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -359,7 +359,10 @@
      * @return the IContextHubWrapper interface
      */
     private IContextHubWrapper getContextHubWrapper() {
-        IContextHubWrapper wrapper = IContextHubWrapper.maybeConnectTo1_2();
+        IContextHubWrapper wrapper = IContextHubWrapper.maybeConnectToAidl();
+        if (wrapper == null) {
+            wrapper = IContextHubWrapper.maybeConnectTo1_2();
+        }
         if (wrapper == null) {
             wrapper = IContextHubWrapper.maybeConnectTo1_1();
         }
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java b/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java
index df6cc05..1de749b 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java
@@ -33,6 +33,7 @@
 import android.util.Log;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
@@ -45,6 +46,11 @@
     private static final String CONTEXT_HUB_PERMISSION = Manifest.permission.ACCESS_CONTEXT_HUB;
 
     /**
+     * A host endpoint that is reserved to identify a broadcasted message.
+     */
+    private static final char HOST_ENDPOINT_BROADCAST = 0xFFFF;
+
+    /**
      * Creates a ConcurrentHashMap of the Context Hub ID to the ContextHubInfo object given an
      * ArrayList of HIDL ContextHub objects.
      *
@@ -110,11 +116,11 @@
     }
 
     /**
-     * Generates the Context Hub HAL's NanoAppBinary object from the client-facing
+     * Generates the Context Hub HAL's HIDL NanoAppBinary object from the client-facing
      * android.hardware.location.NanoAppBinary object.
      *
      * @param nanoAppBinary the client-facing NanoAppBinary object
-     * @return the Context Hub HAL's NanoAppBinary object
+     * @return the Context Hub HAL's HIDL NanoAppBinary object
      */
     /* package */
     static android.hardware.contexthub.V1_0.NanoAppBinary createHidlNanoAppBinary(
@@ -142,6 +148,29 @@
     }
 
     /**
+     * Generates the Context Hub HAL's AIDL NanoAppBinary object from the client-facing
+     * android.hardware.location.NanoAppBinary object.
+     *
+     * @param nanoAppBinary the client-facing NanoAppBinary object
+     * @return the Context Hub HAL's AIDL NanoAppBinary object
+     */
+    /* package */
+    static android.hardware.contexthub.NanoappBinary createAidlNanoAppBinary(
+            NanoAppBinary nanoAppBinary) {
+        android.hardware.contexthub.NanoappBinary aidlNanoAppBinary =
+                new android.hardware.contexthub.NanoappBinary();
+
+        aidlNanoAppBinary.nanoappId = nanoAppBinary.getNanoAppId();
+        aidlNanoAppBinary.nanoappVersion = nanoAppBinary.getNanoAppVersion();
+        aidlNanoAppBinary.flags = nanoAppBinary.getFlags();
+        aidlNanoAppBinary.targetChreApiMajorVersion = nanoAppBinary.getTargetChreApiMajorVersion();
+        aidlNanoAppBinary.targetChreApiMinorVersion = nanoAppBinary.getTargetChreApiMinorVersion();
+        aidlNanoAppBinary.customBinary = nanoAppBinary.getBinaryNoHeader();
+
+        return aidlNanoAppBinary;
+    }
+
+    /**
      * Generates a client-facing NanoAppState array from a HAL HubAppInfo array.
      *
      * @param nanoAppInfoList the array of HubAppInfo objects
@@ -154,7 +183,26 @@
         for (HubAppInfo appInfo : nanoAppInfoList) {
             nanoAppStateList.add(
                     new NanoAppState(appInfo.info_1_0.appId, appInfo.info_1_0.version,
-                                     appInfo.info_1_0.enabled, appInfo.permissions));
+                            appInfo.info_1_0.enabled, appInfo.permissions));
+        }
+
+        return nanoAppStateList;
+    }
+
+    /**
+     * Generates a client-facing NanoAppState array from a AIDL NanoappInfo array.
+     *
+     * @param nanoAppInfoList the array of NanoappInfo objects
+     * @return the corresponding array of NanoAppState objects
+     */
+    /* package */
+    static List<NanoAppState> createNanoAppStateList(
+            android.hardware.contexthub.NanoappInfo[] nanoAppInfoList) {
+        ArrayList<NanoAppState> nanoAppStateList = new ArrayList<>();
+        for (android.hardware.contexthub.NanoappInfo appInfo : nanoAppInfoList) {
+            nanoAppStateList.add(
+                    new NanoAppState(appInfo.nanoappId, appInfo.nanoappVersion,
+                            appInfo.enabled, new ArrayList<>(Arrays.asList(appInfo.permissions))));
         }
 
         return nanoAppStateList;
@@ -180,6 +228,29 @@
     }
 
     /**
+     * Creates an AIDL ContextHubMessage object to send to a nanoapp.
+     *
+     * @param hostEndPoint the ID of the client sending the message
+     * @param message      the client-facing NanoAppMessage object describing the message
+     * @return the AIDL ContextHubMessage object
+     */
+    /* package */
+    static android.hardware.contexthub.ContextHubMessage createAidlContextHubMessage(
+            short hostEndPoint, NanoAppMessage message) {
+        android.hardware.contexthub.ContextHubMessage aidlMessage =
+                new android.hardware.contexthub.ContextHubMessage();
+
+        aidlMessage.nanoappId = message.getNanoAppId();
+        aidlMessage.hostEndPoint = (char) hostEndPoint;
+        aidlMessage.messageType = message.getMessageType();
+        aidlMessage.messageBody = message.getMessageBody();
+        // This explicit definition is required to avoid erroneous behavior at the binder.
+        aidlMessage.permissions = new String[0];
+
+        return aidlMessage;
+    }
+
+    /**
      * Creates a client-facing NanoAppMessage object to send to a client.
      *
      * @param message the HIDL ContextHubMsg object from a nanoapp
@@ -195,6 +266,20 @@
     }
 
     /**
+     * Creates a client-facing NanoAppMessage object to send to a client.
+     *
+     * @param message the AIDL ContextHubMessage object from a nanoapp
+     * @return the NanoAppMessage object
+     */
+    /* package */
+    static NanoAppMessage createNanoAppMessage(
+            android.hardware.contexthub.ContextHubMessage message) {
+        return NanoAppMessage.createMessageFromNanoApp(
+                message.nanoappId, message.messageType, message.messageBody,
+                message.hostEndPoint == HOST_ENDPOINT_BROADCAST);
+    }
+
+    /**
      * Checks for location hardware permissions.
      *
      * @param context the context of the service
@@ -274,4 +359,21 @@
                 return ContextHubService.CONTEXT_HUB_EVENT_UNKNOWN;
         }
     }
+
+    /**
+     * Converts an AIDL AsyncEventType to the corresponding ContextHubService.CONTEXT_HUB_EVENT_*.
+     *
+     * @param aidlEventType The AsyncEventType value.
+     * @return The converted event type.
+     */
+    /* package */
+    static int toContextHubEventFromAidl(int aidlEventType) {
+        switch (aidlEventType) {
+            case android.hardware.contexthub.AsyncEventType.RESTARTED:
+                return ContextHubService.CONTEXT_HUB_EVENT_RESTARTED;
+            default:
+                Log.e(TAG, "toContextHubEventFromAidl: Unknown event type: " + aidlEventType);
+                return ContextHubService.CONTEXT_HUB_EVENT_UNKNOWN;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
index d733db0..6c70d9d 100644
--- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
+++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
@@ -30,13 +30,17 @@
 import android.hardware.location.NanoAppMessage;
 import android.hardware.location.NanoAppState;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.util.Log;
 import android.util.Pair;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.NoSuchElementException;
+import java.util.Set;
 
 /**
  * @hide
@@ -141,6 +145,29 @@
     }
 
     /**
+     * Attempts to connect to the Contexthub HAL AIDL service, if it exists.
+     *
+     * @return A valid IContextHubWrapper if the connection was successful, null otherwise.
+     */
+    @Nullable
+    public static IContextHubWrapper maybeConnectToAidl() {
+        android.hardware.contexthub.IContextHub proxy = null;
+        final String aidlServiceName =
+                android.hardware.contexthub.IContextHub.class.getCanonicalName() + "/default";
+        if (ServiceManager.isDeclared(aidlServiceName)) {
+            proxy = android.hardware.contexthub.IContextHub.Stub.asInterface(
+                    ServiceManager.waitForService(aidlServiceName));
+            if (proxy == null) {
+                Log.e(TAG, "Context Hub AIDL service was declared but was not found");
+            }
+        } else {
+            Log.d(TAG, "Context Hub AIDL service is not declared");
+        }
+
+        return (proxy == null) ? null : new ContextHubWrapperAidl(proxy);
+    }
+
+    /**
      * Calls the appropriate getHubs function depending on the HAL version.
      */
     public abstract Pair<List<ContextHubInfo>, List<String>> getHubs() throws RemoteException;
@@ -258,6 +285,137 @@
     public abstract void registerCallback(int contextHubId, @NonNull ICallback callback)
             throws RemoteException;
 
+    private static class ContextHubWrapperAidl extends IContextHubWrapper {
+        private android.hardware.contexthub.IContextHub mHub;
+
+        private ICallback mCallback = null;
+
+        private ContextHubAidlCallback mAidlCallback = new ContextHubAidlCallback();
+
+        private class ContextHubAidlCallback extends
+                android.hardware.contexthub.IContextHubCallback.Stub {
+            public void handleNanoappInfo(android.hardware.contexthub.NanoappInfo[] appInfo) {
+                List<NanoAppState> nanoAppStateList =
+                        ContextHubServiceUtil.createNanoAppStateList(appInfo);
+                mCallback.handleNanoappInfo(nanoAppStateList);
+            }
+
+            public void handleContextHubMessage(android.hardware.contexthub.ContextHubMessage msg,
+                    String[] msgContentPerms) {
+                mCallback.handleNanoappMessage(
+                        (short) msg.hostEndPoint,
+                        ContextHubServiceUtil.createNanoAppMessage(msg),
+                        new ArrayList<>(Arrays.asList(msg.permissions)),
+                        new ArrayList<>(Arrays.asList(msgContentPerms)));
+            }
+
+            public void handleContextHubAsyncEvent(int evt) {
+                mCallback.handleContextHubEvent(
+                        ContextHubServiceUtil.toContextHubEventFromAidl(evt));
+            }
+
+            public void handleTransactionResult(int transactionId, boolean success) {
+                mCallback.handleTransactionResult(transactionId, success);
+            }
+        }
+
+        ContextHubWrapperAidl(android.hardware.contexthub.IContextHub hub) {
+            mHub = hub;
+        }
+
+        public Pair<List<ContextHubInfo>, List<String>> getHubs() throws RemoteException {
+            Set<String> supportedPermissions = new HashSet<>();
+            ArrayList<ContextHubInfo> hubInfoList = new ArrayList<>();
+            for (android.hardware.contexthub.ContextHubInfo hub : mHub.getContextHubs()) {
+                hubInfoList.add(new ContextHubInfo(hub));
+                for (String permission : hub.supportedPermissions) {
+                    supportedPermissions.add(permission);
+                }
+            }
+            return new Pair(hubInfoList, new ArrayList<String>(supportedPermissions));
+        }
+
+        // TODO(b/194285834): Implement settings logic
+        public boolean supportsLocationSettingNotifications() {
+            return false;
+        }
+
+        public boolean supportsWifiSettingNotifications() {
+            return false;
+        }
+
+        public boolean supportsAirplaneModeSettingNotifications() {
+            return false;
+        }
+
+        public boolean supportsMicrophoneDisableSettingNotifications() {
+            return false;
+        }
+
+        public void onLocationSettingChanged(boolean enabled) {
+        }
+
+        public void onWifiSettingChanged(boolean enabled) {
+        }
+
+        public void onAirplaneModeSettingChanged(boolean enabled) {
+        }
+
+        public void onMicrophoneDisableSettingChanged(boolean enabled) {
+        }
+
+        @ContextHubTransaction.Result
+        public int sendMessageToContextHub(
+                short hostEndpointId, int contextHubId, NanoAppMessage message)
+                throws RemoteException {
+            return toTransactionResult(mHub.sendMessageToHub(contextHubId,
+                    ContextHubServiceUtil.createAidlContextHubMessage(hostEndpointId, message)));
+        }
+
+        @ContextHubTransaction.Result
+        public int loadNanoapp(int contextHubId, NanoAppBinary binary,
+                int transactionId) throws RemoteException {
+            android.hardware.contexthub.NanoappBinary aidlNanoAppBinary =
+                    ContextHubServiceUtil.createAidlNanoAppBinary(binary);
+            return toTransactionResult(
+                    mHub.loadNanoapp(contextHubId, aidlNanoAppBinary, transactionId));
+        }
+
+        @ContextHubTransaction.Result
+        public int unloadNanoapp(int contextHubId, long nanoappId, int transactionId)
+                throws RemoteException {
+            return toTransactionResult(mHub.unloadNanoapp(contextHubId, nanoappId, transactionId));
+        }
+
+        @ContextHubTransaction.Result
+        public int enableNanoapp(int contextHubId, long nanoappId, int transactionId)
+                throws RemoteException {
+            return toTransactionResult(mHub.enableNanoapp(contextHubId, nanoappId, transactionId));
+        }
+
+        @ContextHubTransaction.Result
+        public int disableNanoapp(int contextHubId, long nanoappId, int transactionId)
+                throws RemoteException {
+            return toTransactionResult(mHub.disableNanoapp(contextHubId, nanoappId, transactionId));
+        }
+
+        @ContextHubTransaction.Result
+        public int queryNanoapps(int contextHubId) throws RemoteException {
+            return toTransactionResult(mHub.queryNanoapps(contextHubId));
+        }
+
+        public void registerCallback(int contextHubId, ICallback callback) throws RemoteException {
+            mCallback = callback;
+            mHub.registerCallback(contextHubId, mAidlCallback);
+        }
+
+        @ContextHubTransaction.Result
+        private int toTransactionResult(boolean success) {
+            return success ? ContextHubTransaction.RESULT_SUCCESS
+                    : ContextHubTransaction.RESULT_FAILED_UNKNOWN;
+        }
+    }
+
     /**
      * An abstract call that defines methods common to all HIDL IContextHubWrappers.
      */
diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index 206682e..8750e2a 100644
--- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -16,6 +16,7 @@
 
 package com.android.server.location.gnss;
 
+import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
 import static android.location.provider.ProviderProperties.ACCURACY_FINE;
 import static android.location.provider.ProviderProperties.POWER_USAGE_HIGH;
 
@@ -43,6 +44,8 @@
 import static com.android.server.location.gnss.hal.GnssNative.GNSS_POSITION_MODE_STANDALONE;
 import static com.android.server.location.gnss.hal.GnssNative.GNSS_POSITION_RECURRENCE_PERIODIC;
 
+import static java.lang.Math.abs;
+import static java.lang.Math.max;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
 import android.app.AlarmManager;
@@ -83,6 +86,7 @@
 import android.telephony.TelephonyManager;
 import android.telephony.gsm.GsmCellLocation;
 import android.text.TextUtils;
+import android.text.format.DateUtils;
 import android.util.Log;
 import android.util.TimeUtils;
 
@@ -101,7 +105,9 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
@@ -147,6 +153,10 @@
     private static final long LOCATION_UPDATE_DURATION_MILLIS = 10 * 1000;
     // Update duration extension multiplier for emergency REQUEST_LOCATION.
     private static final int EMERGENCY_LOCATION_UPDATE_DURATION_MULTIPLIER = 3;
+    // maximum length gnss batching may go for (1 day)
+    private static final int MIN_BATCH_INTERVAL_MS = (int) DateUtils.SECOND_IN_MILLIS;
+    private static final long MAX_BATCH_LENGTH_MS = DateUtils.DAY_IN_MILLIS;
+    private static final long MAX_BATCH_TIMESTAMP_DELTA_MS = 500;
 
     // Threadsafe class to hold stats reported in the Extras Bundle
     private static class LocationExtras {
@@ -236,6 +246,7 @@
     private boolean mShutdown;
     private boolean mStarted;
     private boolean mBatchingStarted;
+    private AlarmManager.OnAlarmListener mBatchingAlarm;
     private long mStartedChangedElapsedRealtime;
     private int mFixInterval = 1000;
 
@@ -834,18 +845,15 @@
                 mFixInterval = Integer.MAX_VALUE;
             }
 
-            // requested batch size, or zero to disable batching
-            long batchSize =
-                    mBatchingEnabled ? mProviderRequest.getMaxUpdateDelayMillis() / Math.max(
-                            mFixInterval, 1) : 0;
-            if (batchSize < getBatchSize()) {
-                batchSize = 0;
-            }
+            int batchIntervalMs = max(mFixInterval, MIN_BATCH_INTERVAL_MS);
+            long batchLengthMs = Math.min(mProviderRequest.getMaxUpdateDelayMillis(),
+                    MAX_BATCH_LENGTH_MS);
 
             // apply request to GPS engine
-            if (batchSize > 0) {
+            if (mBatchingEnabled && batchLengthMs / 2 >= batchIntervalMs) {
                 stopNavigating();
-                startBatching();
+                mFixInterval = batchIntervalMs;
+                startBatching(batchLengthMs);
             } else {
                 stopBatching();
 
@@ -864,7 +872,7 @@
                     if (mFixInterval >= NO_FIX_TIMEOUT) {
                         // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
                         // and our fix interval is not short
-                        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                        mAlarmManager.set(ELAPSED_REALTIME_WAKEUP,
                                 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, TAG,
                                 mTimeoutListener, mHandler);
                     }
@@ -1055,7 +1063,7 @@
                 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
                 // and our fix interval is not short
                 if (mFixInterval >= NO_FIX_TIMEOUT) {
-                    mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                    mAlarmManager.set(ELAPSED_REALTIME_WAKEUP,
                             SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, TAG, mTimeoutListener,
                             mHandler);
                 }
@@ -1079,12 +1087,37 @@
         mAlarmManager.cancel(mWakeupListener);
     }
 
-    private void startBatching() {
+    private void startBatching(long batchLengthMs) {
+        long batchSize = batchLengthMs / mFixInterval;
+
         if (DEBUG) {
-            Log.d(TAG, "startBatching " + mFixInterval);
+            Log.d(TAG, "startBatching " + mFixInterval + " " + batchLengthMs);
         }
         if (mGnssNative.startBatch(MILLISECONDS.toNanos(mFixInterval), true)) {
             mBatchingStarted = true;
+
+            if (batchSize < getBatchSize()) {
+                // if the batch size is smaller than the hardware batch size, use an alarm to flush
+                // locations as appropriate
+                mBatchingAlarm = () -> {
+                    boolean flush = false;
+                    synchronized (mLock) {
+                        if (mBatchingAlarm != null) {
+                            flush = true;
+                            mAlarmManager.setExact(ELAPSED_REALTIME_WAKEUP,
+                                    SystemClock.elapsedRealtime() + batchLengthMs, TAG,
+                                    mBatchingAlarm, FgThread.getHandler());
+                        }
+                    }
+
+                    if (flush) {
+                        mGnssNative.flushBatch();
+                    }
+                };
+                mAlarmManager.setExact(ELAPSED_REALTIME_WAKEUP,
+                        SystemClock.elapsedRealtime() + batchLengthMs, TAG,
+                        mBatchingAlarm, FgThread.getHandler());
+            }
         } else {
             Log.e(TAG, "native_start_batch failed in startBatching()");
         }
@@ -1093,6 +1126,10 @@
     private void stopBatching() {
         if (DEBUG) Log.d(TAG, "stopBatching");
         if (mBatchingStarted) {
+            if (mBatchingAlarm != null) {
+                mAlarmManager.cancel(mBatchingAlarm);
+                mBatchingAlarm = null;
+            }
             mGnssNative.stopBatch();
             mBatchingStarted = false;
         }
@@ -1109,7 +1146,7 @@
         // stop GPS until our next fix interval arrives
         stopNavigating();
         long now = SystemClock.elapsedRealtime();
-        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, TAG,
+        mAlarmManager.set(ELAPSED_REALTIME_WAKEUP, now + mFixInterval, TAG,
                 mWakeupListener, mHandler);
     }
 
@@ -1419,16 +1456,50 @@
             Log.d(TAG, "Location batch of size " + locations.length + " reported");
         }
 
+        if (locations.length > 0) {
+            // attempt to fix up timestamps if necessary
+            if (locations.length > 1) {
+                // check any realtimes outside of expected bounds
+                boolean fixRealtime = false;
+                for (int i = locations.length - 2; i >= 0; i--) {
+                    long timeDeltaMs = locations[i + 1].getTime() - locations[i].getTime();
+                    long realtimeDeltaMs = locations[i + 1].getElapsedRealtimeMillis()
+                            - locations[i].getElapsedRealtimeMillis();
+                    if (abs(timeDeltaMs - realtimeDeltaMs) > MAX_BATCH_TIMESTAMP_DELTA_MS) {
+                        fixRealtime = true;
+                        break;
+                    }
+                }
+
+                if (fixRealtime) {
+                    // sort for monotonically increasing time before fixing realtime - realtime will
+                    // thus also be monotonically increasing
+                    Arrays.sort(locations,
+                            Comparator.comparingLong(Location::getTime));
+
+                    long expectedDeltaMs =
+                            locations[locations.length - 1].getTime()
+                                    - locations[locations.length - 1].getElapsedRealtimeMillis();
+                    for (int i = locations.length - 2; i >= 0; i--) {
+                        locations[i].setElapsedRealtimeNanos(
+                                MILLISECONDS.toNanos(
+                                        max(locations[i].getTime() - expectedDeltaMs, 0)));
+                    }
+                } else {
+                    // sort for monotonically increasing realttime
+                    Arrays.sort(locations,
+                            Comparator.comparingLong(Location::getElapsedRealtimeNanos));
+                }
+            }
+
+            reportLocation(LocationResult.wrap(locations).validate());
+        }
+
         Runnable[] listeners;
         synchronized (mLock) {
             listeners = mFlushListeners.toArray(new Runnable[0]);
             mFlushListeners.clear();
         }
-
-        if (locations.length > 0) {
-            reportLocation(LocationResult.wrap(locations).validate());
-        }
-
         for (Runnable listener : listeners) {
             listener.run();
         }
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index 8955c28..62d8c32 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -1078,7 +1078,7 @@
         }
 
         private void onTransportFailure(Exception e) {
-            if (e instanceof RemoteException) {
+            if (e instanceof PendingIntent.CanceledException) {
                 Log.w(TAG, mName + " provider registration " + getIdentity() + " removed", e);
                 synchronized (mLock) {
                     remove();
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 65a3ad0..31a82a3 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -1063,7 +1063,8 @@
                         // TODO(jaewan): Implement
                     }
                 } else if (mCurrentFullUserRecord.mLastMediaButtonReceiverHolder != null) {
-                    String packageName = mLastMediaButtonReceiverHolder.getPackageName();
+                    String packageName =
+                            mCurrentFullUserRecord.mLastMediaButtonReceiverHolder.getPackageName();
                     callback.onMediaKeyEventSessionChanged(packageName, null);
                 } else {
                     callback.onMediaKeyEventSessionChanged("", null);
diff --git a/services/core/java/com/android/server/notification/NotificationShellCmd.java b/services/core/java/com/android/server/notification/NotificationShellCmd.java
index 7112ae1..628a322 100644
--- a/services/core/java/com/android/server/notification/NotificationShellCmd.java
+++ b/services/core/java/com/android/server/notification/NotificationShellCmd.java
@@ -22,6 +22,7 @@
 import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
 import static android.app.NotificationManager.INTERRUPTION_FILTER_UNKNOWN;
 
+import android.annotation.SuppressLint;
 import android.app.ActivityManager;
 import android.app.INotificationManager;
 import android.app.Notification;
@@ -44,6 +45,8 @@
 import android.os.RemoteException;
 import android.os.ShellCommand;
 import android.os.UserHandle;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.util.Slog;
 
@@ -392,19 +395,28 @@
                                     + "--context <snooze-criterion-id>) <key>");
                             return 1;
                     }
-                    if (null == mDirectService.getNotificationRecord(key)) {
-                        pw.println("error: no notification matching key: " + key);
-                        return 1;
-                    }
                     if (duration > 0 || criterion != null) {
+                        ShellNls nls = new ShellNls();
+                        nls.registerAsSystemService(mDirectService.getContext(),
+                                new ComponentName(nls.getClass().getPackageName(),
+                                        nls.getClass().getName()),
+                                ActivityManager.getCurrentUser());
+                        if (!waitForBind(nls)) {
+                            pw.println("error: could not bind a listener in time");
+                            return 1;
+                        }
                         if (duration > 0) {
                             pw.println(String.format("snoozing <%s> until time: %s", key,
                                     new Date(System.currentTimeMillis() + duration)));
+                            nls.snoozeNotification(key, duration);
                         } else {
                             pw.println(String.format("snoozing <%s> until criterion: %s", key,
                                     criterion));
+                            nls.snoozeNotification(key, criterion);
                         }
-                        mDirectService.snoozeNotificationInt(key, duration, criterion, null);
+                        waitForSnooze(nls, key);
+                        nls.unregisterAsSystemService();
+                        waitForUnbind(nls);
                     } else {
                         pw.println("error: invalid value for --" + subflag + ": " + flagarg);
                         return 1;
@@ -527,14 +539,17 @@
                     final PendingIntent pi;
                     if ("broadcast".equals(intentKind)) {
                         pi = PendingIntent.getBroadcastAsUser(
-                                context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED,
+                                context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT
+                                        | PendingIntent.FLAG_MUTABLE_UNAUDITED,
                                 UserHandle.CURRENT);
                     } else if ("service".equals(intentKind)) {
                         pi = PendingIntent.getService(
-                                context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
+                                context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT
+                                        | PendingIntent.FLAG_MUTABLE_UNAUDITED);
                     } else {
                         pi = PendingIntent.getActivityAsUser(
-                                context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED, null,
+                                context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT
+                                        | PendingIntent.FLAG_MUTABLE_UNAUDITED, null,
                                 UserHandle.CURRENT);
                     }
                     builder.setContentIntent(pi);
@@ -685,9 +700,79 @@
         return 0;
     }
 
+    private void waitForSnooze(ShellNls nls, String key) {
+        for (int i = 0; i < 20; i++) {
+            StatusBarNotification[] sbns = nls.getSnoozedNotifications();
+            for (StatusBarNotification sbn : sbns) {
+                if (sbn.getKey().equals(key)) {
+                    return;
+                }
+            }
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+        return;
+    }
+
+    private boolean waitForBind(ShellNls nls) {
+        for (int i = 0; i < 20; i++) {
+            if (nls.isConnected) {
+                Slog.i(TAG, "Bound Shell NLS");
+                return true;
+            } else {
+                try {
+                    Thread.sleep(100);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return false;
+    }
+
+    private void waitForUnbind(ShellNls nls) {
+        for (int i = 0; i < 10; i++) {
+            if (!nls.isConnected) {
+                Slog.i(TAG, "Unbound Shell NLS");
+                return;
+            } else {
+                try {
+                    Thread.sleep(100);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
     @Override
     public void onHelp() {
         getOutPrintWriter().println(USAGE);
     }
+
+    @SuppressLint("OverrideAbstract")
+    private static class ShellNls extends NotificationListenerService {
+        private static ShellNls
+                sNotificationListenerInstance = null;
+        boolean isConnected;
+
+        @Override
+        public void onListenerConnected() {
+            super.onListenerConnected();
+            sNotificationListenerInstance = this;
+            isConnected = true;
+        }
+        @Override
+        public void onListenerDisconnected() {
+            isConnected = false;
+        }
+
+        public static ShellNls getInstance() {
+            return sNotificationListenerInstance;
+        }
+    }
 }
 
diff --git a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
index 117136a..a3f1435 100644
--- a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
+++ b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
@@ -199,6 +199,30 @@
                     .addDataType("video/*")
                     .build();
 
+    // TODO(b/199068419): Remove once GEM enables the intent for Googlers
+    /** Pick images can be forwarded to work profile. */
+    private static final DefaultCrossProfileIntentFilter ACTION_PICK_IMAGES_TO_PROFILE =
+            new DefaultCrossProfileIntentFilter.Builder(
+                    DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
+                    /* flags= */ 0,
+                    /* letsPersonalDataIntoProfile= */ true)
+                    .addAction(MediaStore.ACTION_PICK_IMAGES)
+                    .addCategory(Intent.CATEGORY_DEFAULT)
+                    .build();
+    // TODO(b/199068419): Remove once GEM enables the intent for Googlers
+    /** Pick images can be forwarded to work profile. */
+    private static final DefaultCrossProfileIntentFilter
+            ACTION_PICK_IMAGES_WITH_DATA_TYPES_TO_PROFILE =
+            new DefaultCrossProfileIntentFilter.Builder(
+                    DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
+                    /* flags= */ 0,
+                    /* letsPersonalDataIntoProfile= */ true)
+                    .addAction(MediaStore.ACTION_PICK_IMAGES)
+                    .addCategory(Intent.CATEGORY_DEFAULT)
+                    .addDataType("image/*")
+                    .addDataType("video/*")
+                    .build();
+
     /** Open document intent can be forwarded to parent user. */
     private static final DefaultCrossProfileIntentFilter OPEN_DOCUMENT =
             new DefaultCrossProfileIntentFilter.Builder(
@@ -236,7 +260,7 @@
     private static final DefaultCrossProfileIntentFilter RECOGNIZE_SPEECH =
             new DefaultCrossProfileIntentFilter.Builder(
                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
-                    /* flags= */0,
+                    /* flags= */ ONLY_IF_NO_MATCH_FOUND,
                     /* letsPersonalDataIntoProfile= */ false)
                     .addAction(ACTION_RECOGNIZE_SPEECH)
                     .addCategory(Intent.CATEGORY_DEFAULT)
@@ -312,6 +336,8 @@
                 ACTION_PICK_DATA,
                 ACTION_PICK_IMAGES,
                 ACTION_PICK_IMAGES_WITH_DATA_TYPES,
+                ACTION_PICK_IMAGES_TO_PROFILE,
+                ACTION_PICK_IMAGES_WITH_DATA_TYPES_TO_PROFILE,
                 OPEN_DOCUMENT,
                 GET_CONTENT,
                 USB_DEVICE_ATTACHED,
diff --git a/services/core/java/com/android/server/pm/InstallParams.java b/services/core/java/com/android/server/pm/InstallParams.java
index 934775a..4a8c76b 100644
--- a/services/core/java/com/android/server/pm/InstallParams.java
+++ b/services/core/java/com/android/server/pm/InstallParams.java
@@ -1071,13 +1071,14 @@
 
             try {
                 PackageSetting pkgSetting;
+                AndroidPackage oldPackage;
                 synchronized (mPm.mLock) {
                     pkgSetting = mPm.mSettings.getPackageLPr(pkgName);
+                    oldPackage = mPm.mPackages.get(pkgName);
                 }
                 boolean isUpdatedSystemAppFromExistingSetting = pkgSetting != null
                         && pkgSetting.getPkgState().isUpdatedSystemApp();
                 final String abiOverride = deriveAbiOverride(args.mAbiOverride);
-                AndroidPackage oldPackage = mPm.mPackages.get(pkgName);
                 boolean isUpdatedSystemAppInferred = oldPackage != null && oldPackage.isSystem();
                 final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths>
                         derivedAbi = mPm.mInjector.getAbiHelper().derivePackageAbi(parsedPackage,
@@ -1108,38 +1109,37 @@
                 freezePackageForInstall(pkgName, installFlags, "installPackageLI");
         boolean shouldCloseFreezerBeforeReturn = true;
         try {
-            final AndroidPackage existingPackage;
-            String renamedPackage = null;
+            final AndroidPackage oldPackage;
+            String renamedPackage;
             boolean sysPkg = false;
             int targetScanFlags = scanFlags;
             int targetParseFlags = parseFlags;
             final PackageSetting ps;
             final PackageSetting disabledPs;
             if (replace) {
+                final String pkgName11 = parsedPackage.getPackageName();
+                synchronized (mPm.mLock) {
+                    oldPackage = mPm.mPackages.get(pkgName11);
+                }
                 if (parsedPackage.isStaticSharedLibrary()) {
                     // Static libs have a synthetic package name containing the version
                     // and cannot be updated as an update would get a new package name,
                     // unless this is installed from adb which is useful for development.
-                    AndroidPackage existingPkg = mPm.mPackages.get(parsedPackage.getPackageName());
-                    if (existingPkg != null
+                    if (oldPackage != null
                             && (installFlags & PackageManager.INSTALL_FROM_ADB) == 0) {
                         throw new PrepareFailure(INSTALL_FAILED_DUPLICATE_PACKAGE,
-                                "Packages declaring "
-                                        + "static-shared libs cannot be updated");
+                            "Packages declaring "
+                                + "static-shared libs cannot be updated");
                     }
                 }
 
                 final boolean isInstantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
 
-                final AndroidPackage oldPackage;
-                final String pkgName11 = parsedPackage.getPackageName();
                 final int[] allUsers;
                 final int[] installedUsers;
                 final int[] uninstalledUsers;
 
                 synchronized (mPm.mLock) {
-                    oldPackage = mPm.mPackages.get(pkgName11);
-                    existingPackage = oldPackage;
                     if (DEBUG_INSTALL) {
                         Slog.d(TAG,
                                 "replacePackageLI: new=" + parsedPackage + ", old=" + oldPackage);
@@ -1305,7 +1305,7 @@
                 ps = null;
                 disabledPs = null;
                 replace = false;
-                existingPackage = null;
+                oldPackage = null;
                 // Remember this for later, in case we need to rollback this install
                 String pkgName1 = parsedPackage.getPackageName();
 
@@ -1336,7 +1336,7 @@
             shouldCloseFreezerBeforeReturn = false;
 
             return new PrepareResult(replace, targetScanFlags, targetParseFlags,
-                    existingPackage, parsedPackage, replace /* clearCodeCache */, sysPkg,
+                oldPackage, parsedPackage, replace /* clearCodeCache */, sysPkg,
                     ps, disabledPs);
         } finally {
             res.mFreezer = freezer;
@@ -1364,13 +1364,14 @@
         // "updating same package" could also involve key-rotation.
 
         final PackageSetting sourcePackageSetting;
+        final KeySetManagerService ksms;
         synchronized (mPm.mLock) {
             sourcePackageSetting = mPm.mSettings.getPackageLPr(sourcePackageName);
+            ksms = mPm.mSettings.getKeySetManagerService();
         }
 
         final SigningDetails sourceSigningDetails = (sourcePackageSetting == null
                 ? SigningDetails.UNKNOWN : sourcePackageSetting.getSigningDetails());
-        final KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService();
         if (sourcePackageName.equals(parsedPackage.getPackageName())
                 && (ksms.shouldCheckUpgradeKeySetLocked(
                 sourcePackageSetting, scanFlags))) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 08c95c2..ceee0fa 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -349,8 +349,9 @@
     private boolean mSealed = false;
     @GuardedBy("mLock")
     private boolean mShouldBeSealed = false;
-    @GuardedBy("mLock")
-    private boolean mCommitted = false;
+
+    private final AtomicBoolean mCommitted = new AtomicBoolean(false);
+
     @GuardedBy("mLock")
     private boolean mRelinquished = false;
 
@@ -693,11 +694,10 @@
                     return;
                 }
                 mDestroyed = true;
-                boolean isCommitted = mCommitted;
                 List<PackageInstallerSession> childSessions = getChildSessionsLocked();
                 r = () -> {
                     assertNotLocked("abandonStaged");
-                    if (isCommitted) {
+                    if (mCommitted.get()) {
                         mStagingManager.abortCommittedSession(this);
                     }
                     cleanStageDir(childSessions);
@@ -1070,7 +1070,7 @@
         }
 
         mPrepared = prepared;
-        mCommitted = committed;
+        mCommitted.set(committed);
         mDestroyed = destroyed;
         mStagedSession = params.isStaged ? new StagedSession(isReady, isApplied, isFailed,
                 stagedSessionErrorCode, stagedSessionErrorMessage) : null;
@@ -1140,7 +1140,7 @@
                     mResolvedBaseFile.getAbsolutePath() : null;
             info.progress = mProgress;
             info.sealed = mSealed;
-            info.isCommitted = mCommitted;
+            info.isCommitted = mCommitted.get();
             info.active = mActiveCount.get() > 0;
 
             info.mode = params.mode;
@@ -1196,9 +1196,7 @@
 
     /** {@hide} */
     boolean isCommitted() {
-        synchronized (mLock) {
-            return mCommitted;
-        }
+        return mCommitted.get();
     }
 
     /** {@hide} */
@@ -1236,7 +1234,7 @@
     @GuardedBy("mLock")
     private void assertPreparedAndNotCommittedOrDestroyedLocked(String cookie) {
         assertPreparedAndNotDestroyedLocked(cookie);
-        if (mCommitted) {
+        if (mCommitted.get()) {
             throw new SecurityException(cookie + " not allowed after commit");
         }
     }
@@ -1277,7 +1275,7 @@
 
     @GuardedBy("mProgressLock")
     private void computeProgressLocked(boolean forcePublish) {
-        if (!isIncrementalInstallation() || !mCommitted) {
+        if (!isIncrementalInstallation() || !mCommitted.get()) {
             mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f)
                     + MathUtils.constrain(mInternalProgress * 0.2f, 0f, 0.2f);
         } else {
@@ -2005,7 +2003,7 @@
         //             single / child sessions.
         try {
             synchronized (mLock) {
-                if (mCommitted) {
+                if (mCommitted.get()) {
                     return true;
                 }
                 // Read transfers from the original owner stay open, but as the session's data
@@ -2038,7 +2036,13 @@
                 // will probably close their end.
                 mActiveCount.incrementAndGet();
 
-                mCommitted = true;
+                if (!mCommitted.compareAndSet(false /*expect*/, true /*update*/)) {
+                    throw new PackageManagerException(
+                            INSTALL_FAILED_INTERNAL_ERROR,
+                            TextUtils.formatSimple(
+                                    "The mCommitted of session %d should be false originally",
+                                    sessionId));
+                }
                 committedMillis = System.currentTimeMillis();
             }
             return true;
@@ -4112,7 +4116,8 @@
     private boolean canBeAddedAsChild(int parentCandidate) {
         synchronized (mLock) {
             return (!hasParentSessionId() || mParentSessionId == parentCandidate)
-                    && !mCommitted && !mDestroyed;
+                    && !mCommitted.get()
+                    && !mDestroyed;
         }
     }
 
@@ -4556,7 +4561,7 @@
                 writeStringAttribute(out, ATTR_SESSION_STAGE_CID, stageCid);
             }
             writeBooleanAttribute(out, ATTR_PREPARED, mPrepared);
-            writeBooleanAttribute(out, ATTR_COMMITTED, mCommitted);
+            writeBooleanAttribute(out, ATTR_COMMITTED, mCommitted.get());
             writeBooleanAttribute(out, ATTR_DESTROYED, mDestroyed);
             writeBooleanAttribute(out, ATTR_SEALED, mSealed);
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 098a9b6..de51128 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -23460,6 +23460,37 @@
         return new IntentSender(target);
     }
 
+    @Override
+    public boolean mayPackageQuery(String sourcePackageName, String targetPackageName, int userId) {
+        if (!mUserManager.exists(userId)) return false;
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/,
+                false /*checkShell*/, "may package query");
+        synchronized (mLock) {
+            final PackageSetting sourceSetting = getPackageSetting(sourcePackageName);
+            final PackageSetting targetSetting = getPackageSetting(targetPackageName);
+            if (sourceSetting == null || targetSetting == null) {
+                throw new ParcelableException(new PackageManager.NameNotFoundException("Package(s) "
+                        + (sourceSetting == null ? sourcePackageName + " " : "")
+                        + (targetSetting == null ? targetPackageName + " " : "")
+                        + "not found."));
+            }
+            final boolean filterSource =
+                    shouldFilterApplicationLocked(sourceSetting, callingUid, userId);
+            final boolean filterTarget =
+                    shouldFilterApplicationLocked(targetSetting, callingUid, userId);
+            // The caller must have visibility of the both packages
+            if (filterSource || filterTarget) {
+                throw new ParcelableException(new PackageManager.NameNotFoundException("Package(s) "
+                        + (filterSource ? sourcePackageName + " " : "")
+                        + (filterTarget ? targetPackageName + " " : "")
+                        + "not found."));
+            }
+            final int sourcePackageUid = UserHandle.getUid(userId, sourceSetting.appId);
+            return !shouldFilterApplicationLocked(targetSetting, sourcePackageUid, userId);
+        }
+    }
+
     private static class TempUserState {
         public final int enabledState;
         @Nullable
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index dab980a..010c284 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -557,11 +557,14 @@
         grantPermissionsToSystemPackage(pm, verifier, userId, PHONE_PERMISSIONS, SMS_PERMISSIONS);
 
         // SetupWizard
-        grantPermissionsToSystemPackage(pm,
-                ArrayUtils.firstOrNull(getKnownPackages(
-                        PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId)), userId,
-                PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS,
-                CAMERA_PERMISSIONS);
+        final String setupWizardPackage = ArrayUtils.firstOrNull(getKnownPackages(
+                        PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId));
+        grantPermissionsToSystemPackage(pm, setupWizardPackage, userId, PHONE_PERMISSIONS,
+                CONTACTS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS, CAMERA_PERMISSIONS);
+        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH, 0)) {
+            grantPermissionsToSystemPackage(
+                    pm, setupWizardPackage, userId, NEARBY_DEVICES_PERMISSIONS);
+        }
 
         // Camera
         grantPermissionsToSystemPackage(pm,
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 1a51394..ccd9709 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -390,12 +390,6 @@
     // Assigned on main thread, accessed on UI thread
     volatile VrManagerInternal mVrManagerInternal;
 
-    // Vibrator pattern for haptic feedback of a long press.
-    long[] mLongPressVibePattern;
-
-    // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar.
-    long[] mCalendarDateVibePattern;
-
     // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
     long[] mSafeModeEnabledVibePattern;
 
@@ -1804,10 +1798,6 @@
         context.registerReceiver(mMultiuserReceiver, filter);
 
         mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
-        mLongPressVibePattern = getLongIntArray(mContext.getResources(),
-                com.android.internal.R.array.config_longPressVibePattern);
-        mCalendarDateVibePattern = getLongIntArray(mContext.getResources(),
-                com.android.internal.R.array.config_calendarDateVibePattern);
         mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
                 com.android.internal.R.array.config_safeModeEnabledVibePattern);
 
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index a564624..e7b2756 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -654,15 +654,11 @@
     @WorkerThread
     private void onPackageReplaced(String packageName) {
         assertInWorkerThread();
-        // TODO: Could this end up incorrectly deleting a rollback for a
-        // package that is about to be installed?
         long installedVersion = getInstalledPackageVersion(packageName);
-
         Iterator<Rollback> iter = mRollbacks.iterator();
         while (iter.hasNext()) {
             Rollback rollback = iter.next();
-            // TODO: Should we remove rollbacks in the ENABLING state here?
-            if ((rollback.isEnabling() || rollback.isAvailable())
+            if ((rollback.isAvailable())
                     && rollback.includesPackageWithDifferentVersion(packageName,
                     installedVersion)) {
                 iter.remove();
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 2cfc785..f973f5c 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -43,7 +43,6 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.PrintWriter;
 import java.nio.file.Files;
 import java.text.ParseException;
 import java.time.Instant;
@@ -323,9 +322,8 @@
                     "extensionVersions", extensionVersionsToJson(rollback.getExtensionVersions()));
 
             fos = file.startWrite();
-            PrintWriter pw = new PrintWriter(fos);
-            pw.println(dataJson.toString());
-            pw.close();
+            fos.write(dataJson.toString().getBytes());
+            fos.flush();
             file.finishWrite(fos);
         } catch (JSONException | IOException e) {
             Slog.e(TAG, "Unable to save rollback for: " + rollback.info.getRollbackId(), e);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index b58ca1f..7ac9110 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -21,7 +21,9 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityManagerInternal;
 import android.app.ActivityThread;
 import android.app.ITransientNotificationCallback;
 import android.app.Notification;
@@ -31,7 +33,11 @@
 import android.compat.annotation.EnabledSince;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Icon;
 import android.hardware.biometrics.BiometricAuthenticator.Modality;
 import android.hardware.biometrics.BiometricManager.BiometricMultiSensorMode;
 import android.hardware.biometrics.IBiometricSysuiReceiver;
@@ -53,6 +59,7 @@
 import android.os.ShellCallback;
 import android.os.UserHandle;
 import android.service.notification.NotificationStats;
+import android.service.quicksettings.TileService;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -68,6 +75,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.inputmethod.SoftInputShowHideReason;
 import com.android.internal.os.TransferPipe;
+import com.android.internal.statusbar.IAddTileResultCallback;
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
@@ -123,7 +131,9 @@
 
     private final Object mLock = new Object();
     private final DeathRecipient mDeathRecipient = new DeathRecipient();
+    private final ActivityManagerInternal mActivityManagerInternal;
     private final ActivityTaskManagerInternal mActivityTaskManager;
+    private final PackageManagerInternal mPackageManagerInternal;
     private int mCurrentUserId;
     private boolean mTracingEnabled;
 
@@ -227,6 +237,8 @@
                 (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
         displayManager.registerDisplayListener(this, mHandler);
         mActivityTaskManager = LocalServices.getService(ActivityTaskManagerInternal.class);
+        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
+        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
     }
 
     @Override
@@ -1640,6 +1652,96 @@
         }
     }
 
+    private void checkCallingUidPackage(String packageName, int callingUid, int userId) {
+        int packageUid = mPackageManagerInternal.getPackageUid(packageName, 0, userId);
+        if (UserHandle.getAppId(callingUid) != UserHandle.getAppId(packageUid)) {
+            throw new SecurityException("Package " + packageName
+                    + " does not belong to the calling uid " + callingUid);
+        }
+    }
+
+    private ResolveInfo isComponentValidTileService(ComponentName componentName, int userId) {
+        Intent intent = new Intent(TileService.ACTION_QS_TILE);
+        intent.setComponent(componentName);
+        ResolveInfo r = mPackageManagerInternal.resolveService(intent,
+                intent.resolveTypeIfNeeded(mContext.getContentResolver()), 0, userId,
+                Process.myUid());
+        int enabled = mPackageManagerInternal.getComponentEnabledSetting(
+                componentName, Process.myUid(), userId);
+        if (r != null
+                && r.serviceInfo != null
+                && resolveEnabledComponent(r.serviceInfo.enabled, enabled)
+                && Manifest.permission.BIND_QUICK_SETTINGS_TILE.equals(r.serviceInfo.permission)) {
+            return r;
+        } else {
+            return null;
+        }
+    }
+
+    private boolean resolveEnabledComponent(boolean defaultValue, int pmResult) {
+        if (pmResult == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+            return true;
+        }
+        if (pmResult == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
+            return defaultValue;
+        }
+        return false;
+    }
+
+    @Override
+    public int requestAddTile(
+            @NonNull ComponentName componentName,
+            @NonNull CharSequence label,
+            @NonNull Icon icon,
+            int userId,
+            @NonNull IAddTileResultCallback callback
+    ) {
+        int callingUid = Binder.getCallingUid();
+        String packageName = componentName.getPackageName();
+
+        // Check calling user can act on behalf of current user
+        mActivityManagerInternal.handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
+                false, ActivityManagerInternal.ALLOW_NON_FULL, "requestAddTile", packageName);
+
+        // Check calling uid matches package
+        checkCallingUidPackage(packageName, callingUid, userId);
+
+        int currentUser = mActivityManagerInternal.getCurrentUserId();
+
+        // Check current user
+        if (userId != currentUser) {
+            return StatusBarManager.TILE_ADD_REQUEST_ANSWER_FAILED_NOT_CURRENT_USER;
+        }
+
+        // We've checked that the package, component name and uid all match.
+        ResolveInfo r = isComponentValidTileService(componentName, userId);
+        if (r == null) {
+            return StatusBarManager.TILE_ADD_REQUEST_ANSWER_FAILED_BAD_COMPONENT;
+        }
+
+        IAddTileResultCallback proxyCallback = new IAddTileResultCallback.Stub() {
+            @Override
+            public void onTileRequest(int i) throws RemoteException {
+                if (i == StatusBarManager.TILE_ADD_REQUEST_RESULT_DIALOG_DISMISSED) {
+                    i = StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED;
+                }
+                callback.onTileRequest(i);
+            }
+        };
+
+        CharSequence appName = r.serviceInfo.applicationInfo
+                .loadLabel(mContext.getPackageManager());
+        if (mBar != null) {
+            try {
+                mBar.requestAddTile(componentName, appName, label, icon, proxyCallback);
+                return StatusBarManager.TILE_ADD_REQUEST_ANSWER_SUCCESS;
+            } catch (RemoteException e) {
+                Slog.e(TAG, "requestAddTile", e);
+            }
+        }
+        return StatusBarManager.TILE_ADD_REQUEST_ANSWER_FAILED_UNKNOWN_REASON;
+    }
+
     public String[] getStatusBarIcons() {
         return mContext.getResources().getStringArray(R.array.config_statusBarIcons);
     }
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
index 382398a..e0cc8e1 100644
--- a/services/core/java/com/android/server/vcn/Vcn.java
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -352,7 +352,7 @@
     }
 
     private void handleSafeModeStatusChanged() {
-        logDbg("VcnGatewayConnection safe mode status changed");
+        logVdbg("VcnGatewayConnection safe mode status changed");
         boolean hasSafeModeGatewayConnection = false;
 
         // If any VcnGatewayConnection is in safe mode, mark the entire VCN as being in safe mode
@@ -368,7 +368,7 @@
                 hasSafeModeGatewayConnection ? VCN_STATUS_CODE_SAFE_MODE : VCN_STATUS_CODE_ACTIVE;
         if (oldStatus != mCurrentStatus) {
             mVcnCallback.onSafeModeStatusChanged(hasSafeModeGatewayConnection);
-            logDbg(
+            logInfo(
                     "Safe mode "
                             + (mCurrentStatus == VCN_STATUS_CODE_SAFE_MODE ? "entered" : "exited"));
         }
@@ -539,6 +539,16 @@
         Slog.d(TAG, getLogPrefix() + msg, tr);
     }
 
+    private void logInfo(String msg) {
+        Slog.i(TAG, getLogPrefix() + msg);
+        LOCAL_LOG.log(getLogPrefix() + "INFO: " + msg);
+    }
+
+    private void logInfo(String msg, Throwable tr) {
+        Slog.i(TAG, getLogPrefix() + msg, tr);
+        LOCAL_LOG.log(getLogPrefix() + "INFO: " + msg + tr);
+    }
+
     private void logErr(String msg) {
         Slog.e(TAG, getLogPrefix() + msg);
         LOCAL_LOG.log(getLogPrefix() + "ERR: " + msg);
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 450257f..7dec4e7 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -1677,10 +1677,8 @@
             mFailedAttempts = 0;
             cancelSafeModeAlarm();
 
-            if (mIsInSafeMode) {
-                mIsInSafeMode = false;
-                mGatewayStatusCallback.onSafeModeStatusChanged();
-            }
+            mIsInSafeMode = false;
+            mGatewayStatusCallback.onSafeModeStatusChanged();
         }
 
         protected void applyTransform(
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index 4f48442..95305ba 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -51,8 +51,6 @@
 final class VibrationSettings {
     private static final String TAG = "VibrationSettings";
 
-    private static final long[] DOUBLE_CLICK_EFFECT_FALLBACK_TIMINGS = {0, 30, 100, 30};
-
     /** Listener for changes on vibration settings. */
     interface OnVibratorSettingsChanged {
         /** Callback triggered when any of the vibrator settings change. */
@@ -120,8 +118,8 @@
 
         VibrationEffect clickEffect = createEffectFromResource(
                 com.android.internal.R.array.config_virtualKeyVibePattern);
-        VibrationEffect doubleClickEffect = VibrationEffect.createWaveform(
-                DOUBLE_CLICK_EFFECT_FALLBACK_TIMINGS, -1 /*repeatIndex*/);
+        VibrationEffect doubleClickEffect = createEffectFromResource(
+                com.android.internal.R.array.config_doubleClickVibePattern);
         VibrationEffect heavyClickEffect = createEffectFromResource(
                 com.android.internal.R.array.config_longPressVibePattern);
         VibrationEffect tickEffect = createEffectFromResource(
@@ -468,12 +466,14 @@
                 UserHandle.USER_ALL);
     }
 
+    @Nullable
     private VibrationEffect createEffectFromResource(int resId) {
         long[] timings = getLongIntArray(mContext.getResources(), resId);
         return createEffectFromTimings(timings);
     }
 
-    private static VibrationEffect createEffectFromTimings(long[] timings) {
+    @Nullable
+    private static VibrationEffect createEffectFromTimings(@Nullable long[] timings) {
         if (timings == null || timings.length == 0) {
             return null;
         } else if (timings.length == 1) {
diff --git a/services/core/java/com/android/server/vr/Vr2dDisplay.java b/services/core/java/com/android/server/vr/Vr2dDisplay.java
index a713e5b..39d7a15 100644
--- a/services/core/java/com/android/server/vr/Vr2dDisplay.java
+++ b/services/core/java/com/android/server/vr/Vr2dDisplay.java
@@ -302,7 +302,8 @@
             builder.setUniqueId(UNIQUE_DISPLAY_ID);
             builder.setFlags(flags);
             mVirtualDisplay = mDisplayManager.createVirtualDisplay(null /* projection */,
-                    builder.build(), null /* callback */, null /* handler */);
+                    builder.build(), null /* callback */, null /* handler */,
+                    null /* windowContext */);
 
             if (mVirtualDisplay != null) {
                 updateDisplayId(mVirtualDisplay.getDisplay().getDisplayId());
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index e48593c..6d89daa 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -208,7 +208,7 @@
      * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
      * every time the wallpaper is changed.
      */
-    private class WallpaperObserver extends FileObserver {
+    class WallpaperObserver extends FileObserver {
 
         final int mUserId;
         final WallpaperData mWallpaper;
@@ -226,7 +226,7 @@
             mWallpaperLockFile = new File(mWallpaperDir, WALLPAPER_LOCK_ORIG);
         }
 
-        private WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) {
+        WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) {
             WallpaperData wallpaper = null;
             synchronized (mLock) {
                 if (lockChanged) {
@@ -309,9 +309,18 @@
                             }
                             wallpaper.imageWallpaperPending = false;
                             if (sysWallpaperChanged) {
+                                IRemoteCallback.Stub callback = new IRemoteCallback.Stub() {
+                                    @Override
+                                    public void sendResult(Bundle data) throws RemoteException {
+                                        if (DEBUG) {
+                                            Slog.d(TAG, "publish system wallpaper changed!");
+                                        }
+                                        notifyWallpaperChanged(wallpaper);
+                                    }
+                                };
                                 // If this was the system wallpaper, rebind...
                                 bindWallpaperComponentLocked(mImageWallpaper, true,
-                                        false, wallpaper, null);
+                                        false, wallpaper, callback);
                                 notifyColorsWhich |= FLAG_SYSTEM;
                             }
                             if (lockWallpaperChanged
@@ -331,15 +340,9 @@
                             }
 
                             saveSettingsLocked(wallpaper.userId);
-
-                            // Publish completion *after* we've persisted the changes
-                            if (wallpaper.setComplete != null) {
-                                try {
-                                    wallpaper.setComplete.onWallpaperChanged();
-                                } catch (RemoteException e) {
-                                    // if this fails we don't really care; the setting app may just
-                                    // have crashed and that sort of thing is a fact of life.
-                                }
+                            // Notify the client immediately if only lockscreen wallpaper changed.
+                            if (lockWallpaperChanged && !sysWallpaperChanged) {
+                                notifyWallpaperChanged(wallpaper);
                             }
                         }
                     }
@@ -353,6 +356,18 @@
         }
     }
 
+    private void notifyWallpaperChanged(WallpaperData wallpaper) {
+        // Publish completion *after* we've persisted the changes
+        if (wallpaper.setComplete != null) {
+            try {
+                wallpaper.setComplete.onWallpaperChanged();
+            } catch (RemoteException e) {
+                // if this fails we don't really care; the setting app may just
+                // have crashed and that sort of thing is a fact of life.
+            }
+        }
+    }
+
     private void notifyLockWallpaperChanged() {
         final IWallpaperManagerCallback cb = mKeyguardListener;
         if (cb != null) {
@@ -364,7 +379,7 @@
         }
     }
 
-    private void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper, int which) {
+    void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper, int which) {
         if (wallpaper.connection != null) {
             wallpaper.connection.forEachDisplayConnector(connector -> {
                 notifyWallpaperColorsChangedOnDisplay(wallpaper, which, connector.mDisplayId);
@@ -568,7 +583,7 @@
      * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
      * for display.
      */
-    private void generateCrop(WallpaperData wallpaper) {
+    void generateCrop(WallpaperData wallpaper) {
         boolean success = false;
 
         // Only generate crop for default display.
@@ -2834,7 +2849,7 @@
         return false;
     }
 
-    private boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
+    boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
             boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
         if (DEBUG_LIVE) {
             Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
@@ -3121,7 +3136,7 @@
         return new JournaledFile(new File(base), new File(base + ".tmp"));
     }
 
-    private void saveSettingsLocked(int userId) {
+    void saveSettingsLocked(int userId) {
         JournaledFile journal = makeJournaledFile(userId);
         FileOutputStream fstream = null;
         try {
@@ -3270,7 +3285,7 @@
      * Important: this method loads settings to initialize the given user's wallpaper data if
      * there is no current in-memory state.
      */
-    private WallpaperData getWallpaperSafeLocked(int userId, int which) {
+    WallpaperData getWallpaperSafeLocked(int userId, int which) {
         // We're setting either just system (work with the system wallpaper),
         // both (also work with the system wallpaper), or just the lock
         // wallpaper (update against the existing lock wallpaper if any).
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 63ab1bb..042f4f6 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -285,7 +285,6 @@
 import android.os.SystemClock;
 import android.os.Trace;
 import android.os.UserHandle;
-import android.os.storage.StorageManager;
 import android.service.contentcapture.ActivityEvent;
 import android.service.dreams.DreamActivity;
 import android.service.dreams.DreamManagerInternal;
@@ -317,7 +316,7 @@
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManager.TransitionOldType;
 import android.view.animation.Animation;
-import android.window.IRemoteTransition;
+import android.window.RemoteTransition;
 import android.window.SizeConfigurationBuckets;
 import android.window.SplashScreen;
 import android.window.SplashScreenView;
@@ -491,7 +490,7 @@
     private ActivityOptions mPendingOptions;
     /** Non-null if {@link #mPendingOptions} specifies the remote animation. */
     private RemoteAnimationAdapter mPendingRemoteAnimation;
-    private IRemoteTransition mPendingRemoteTransition;
+    private RemoteTransition mPendingRemoteTransition;
     ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
     AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
     ActivityServiceConnectionsHolder mServiceConnectionsHolder; // Service connections.
@@ -730,7 +729,7 @@
     // TODO: rename to mNoDisplay
     @VisibleForTesting
     boolean noDisplay;
-    boolean mShowForAllUsers;
+    final boolean mShowForAllUsers;
     // TODO: Make this final
     int mTargetSdk;
 
@@ -1022,7 +1021,8 @@
             pw.println(mPendingRemoteAnimation.getCallingPid());
         }
         if (mPendingRemoteTransition != null) {
-            pw.print(prefix + " pendingRemoteTransition=" + mPendingRemoteTransition);
+            pw.print(prefix + " pendingRemoteTransition="
+                    + mPendingRemoteTransition.getRemoteTransition());
         }
         if (appTimeTracker != null) {
             appTimeTracker.dumpWithHeader(pw, prefix, false);
@@ -3505,6 +3505,11 @@
         finishing = true;
         final TaskFragment taskFragment = getTaskFragment();
         if (taskFragment != null) {
+            final Task task = taskFragment.getTask();
+            if (task != null && task.isClearingToReuseTask()
+                    && taskFragment.getTopNonFinishingActivity() == null) {
+                taskFragment.mClearedTaskForReuse = true;
+            }
             taskFragment.sendTaskFragmentInfoChanged();
         }
         if (stopped) {
@@ -4579,8 +4584,8 @@
         return opts;
     }
 
-    IRemoteTransition takeRemoteTransition() {
-        IRemoteTransition out = mPendingRemoteTransition;
+    RemoteTransition takeRemoteTransition() {
+        RemoteTransition out = mPendingRemoteTransition;
         mPendingRemoteTransition = null;
         return out;
     }
@@ -4897,7 +4902,12 @@
         // dispatchTaskInfoChangedIfNeeded() right after ActivityRecord#setVisibility() can report
         // the stale visible state, because the state will be updated after the app transition.
         // So tries to report the actual visible state again where the state is changed.
-        if (task != null) task.dispatchTaskInfoChangedIfNeeded(false /* force */);
+        if (!mTaskSupervisor.inActivityVisibilityUpdate()) {
+            final Task task = getOrganizedTask();
+            if (task != null) {
+                task.dispatchTaskInfoChangedIfNeeded(false /* force */);
+            }
+        }
         ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                 "commitVisibility: %s: visible=%b mVisibleRequested=%b", this,
                 isVisible(), mVisibleRequested);
@@ -5305,7 +5315,7 @@
 
     void updateVisibilityIgnoringKeyguard(boolean behindFullscreenActivity) {
         visibleIgnoringKeyguard = (!behindFullscreenActivity || mLaunchTaskBehind)
-                && okToShowLocked();
+                && showToCurrentUser();
     }
 
     boolean shouldBeVisible() {
@@ -6208,11 +6218,7 @@
         // TODO(shell-transitions): Remove mDeferHidingClient once everything is shell-transitions.
         //                          pip activities should just remain in clientVisible.
         if (!clientVisible && mDeferHidingClient) return;
-        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                "setClientVisible: %s clientVisible=%b Callers=%s", this, clientVisible,
-                Debug.getCallers(5));
         super.setClientVisible(clientVisible);
-        sendAppVisibilityToClients();
     }
 
     /**
@@ -6342,22 +6348,8 @@
         return this;
     }
 
-    /** Checks whether the activity should be shown for current user. */
-    public boolean okToShowLocked() {
-        // We cannot show activities when the device is locked and the application is not
-        // encryption aware.
-        if (!StorageManager.isUserKeyUnlocked(mUserId)
-                && !info.applicationInfo.isEncryptionAware()) {
-            return false;
-        }
-
-        return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0
-                || (mTaskSupervisor.isCurrentProfileLocked(mUserId)
-                && mAtmService.mAmInternal.isUserRunning(mUserId, 0 /* flags */));
-    }
-
     boolean canBeTopRunning() {
-        return !finishing && okToShowLocked();
+        return !finishing && showToCurrentUser();
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index af53827..3b43e48 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -115,7 +115,7 @@
 import android.util.DebugUtils;
 import android.util.Pools.SynchronizedPool;
 import android.util.Slog;
-import android.window.IRemoteTransition;
+import android.window.RemoteTransition;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.HeavyWeightSwitcherActivity;
@@ -1568,7 +1568,7 @@
         final Transition newTransition = (!mService.getTransitionController().isCollecting()
                 && mService.getTransitionController().getTransitionPlayer() != null)
                 ? mService.getTransitionController().createTransition(TRANSIT_OPEN) : null;
-        IRemoteTransition remoteTransition = r.takeRemoteTransition();
+        RemoteTransition remoteTransition = r.takeRemoteTransition();
         if (newTransition != null && remoteTransition != null) {
             newTransition.setRemoteTransition(remoteTransition);
         }
@@ -2357,7 +2357,7 @@
         // of this in the record so that we can skip it when trying to find
         // the top running activity.
         mDoResume = doResume;
-        if (!doResume || !r.okToShowLocked() || mLaunchTaskBehind) {
+        if (!doResume || !r.showToCurrentUser() || mLaunchTaskBehind) {
             r.delayedResume = true;
             mDoResume = false;
         }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 19cf14f..808d138 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4065,6 +4065,9 @@
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
+                // Window configuration is unrelated to persistent configuration (e.g. font scale,
+                // locale). Unset it to avoid affecting the current display configuration.
+                values.windowConfiguration.setToDefaults();
                 updateConfigurationLocked(values, null, false, true, userId,
                         false /* deferResume */);
             }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index ea242bb..e6aa4fc 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -1872,12 +1872,6 @@
         mHandler.obtainMessage(LAUNCH_TASK_BEHIND_COMPLETE, token).sendToTarget();
     }
 
-    /** Checks whether the userid is a profile of the current user. */
-    boolean isCurrentProfileLocked(int userId) {
-        if (userId == mRootWindowContainer.mCurrentUser) return true;
-        return mService.mAmInternal.isCurrentProfile(userId);
-    }
-
     /**
      * Processes the activities to be stopped or destroyed. This should be called when the resumed
      * activities are idle or drawn.
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 7a42351..1e3b194 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -844,7 +844,7 @@
 
         final AccessibilityController accessibilityController =
                 mDisplayContent.mWmService.mAccessibilityController;
-        if (accessibilityController != null) {
+        if (accessibilityController.hasCallbacks()) {
             accessibilityController.onAppWindowTransition(mDisplayContent.getDisplayId(), transit);
         }
     }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index db5e3d0..21fe96b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -61,7 +61,6 @@
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN;
@@ -87,6 +86,7 @@
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LAYER_MIRRORING;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
@@ -301,7 +301,8 @@
     @VisibleForTesting IBinder mTokenToMirror = null;
 
     /**
-     * The surface for mirroring the contents of this hierarchy.
+     * The surface for mirroring the contents of this hierarchy, or null if layer mirroring is
+     * temporarily disabled.
      */
     private SurfaceControl mMirroredSurface = null;
 
@@ -310,6 +311,11 @@
      */
     private Rect mLastMirroredDisplayAreaBounds = null;
 
+    /**
+     * The last state of the display.
+     */
+    private int mLastDisplayState;
+
     // Contains all IME window containers. Note that the z-ordering of the IME windows will depend
     // on the IME target. We mainly have this container grouping so we can keep track of all the IME
     // window containers together and move them in-sync if/when needed. We use a subclass of
@@ -1136,10 +1142,6 @@
         if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Creating display=" + display);
 
         mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this);
-
-        // Check if this DisplayContent is for a new VirtualDisplay, that should use layer mirroring
-        // to capture the contents of a DisplayArea.
-        startMirrorIfNeeded();
     }
 
     boolean isReady() {
@@ -1274,7 +1276,7 @@
 
         addWindowToken(token.token, token);
 
-        if (mWmService.mAccessibilityController != null) {
+        if (mWmService.mAccessibilityController.hasCallbacks()) {
             final int prevDisplayId = prevDc != null ? prevDc.getDisplayId() : INVALID_DISPLAY;
             mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(prevDisplayId,
                     getDisplayId());
@@ -2498,19 +2500,42 @@
 
         // Update mirroring surface for MediaProjection, if this DisplayContent is being used
         // for layer mirroring.
-        if (mMirroredSurface != null) {
-            // Retrieve the size of the DisplayArea to mirror, and continue with the update if the
-            // bounds have changed.
+        if (isCurrentlyMirroring() && mLastMirroredDisplayAreaBounds != null) {
+            // Mirroring has already begun, but update mirroring since the display is now on.
             final WindowContainer wc = mWmService.mWindowContextListenerController.getContainer(
                     mTokenToMirror);
-            if (wc != null && mLastMirroredDisplayAreaBounds != null) {
-                // Retrieve the size of the DisplayArea to mirror, and continue with the update
-                // if the bounds or orientation has changed.
-                final Rect displayAreaBounds = wc.getDisplayContent().getBounds();
-                int displayAreaOrientation = wc.getDisplayContent().getOrientation();
-                if (!mLastMirroredDisplayAreaBounds.equals(displayAreaBounds)
-                        || lastOrientation != displayAreaOrientation) {
-                    updateMirroredSurface(mWmService.mTransactionFactory.get(), displayAreaBounds);
+            if (wc == null) {
+                ProtoLog.v(WM_DEBUG_LAYER_MIRRORING,
+                        "Unable to retrieve window container to update layer mirroring for "
+                                + "display %d",
+                        mDisplayId);
+                return;
+            }
+
+            ProtoLog.v(WM_DEBUG_LAYER_MIRRORING,
+                    "Display %d was already layer mirroring, so apply transformations if necessary",
+                    mDisplayId);
+            // Retrieve the size of the DisplayArea to mirror, and continue with the update
+            // if the bounds or orientation has changed.
+            final Rect displayAreaBounds = wc.getDisplayContent().getBounds();
+            int displayAreaOrientation = wc.getDisplayContent().getOrientation();
+            if (!mLastMirroredDisplayAreaBounds.equals(displayAreaBounds)
+                    || lastOrientation != displayAreaOrientation) {
+                Point surfaceSize = fetchSurfaceSizeIfPresent();
+                if (surfaceSize != null) {
+                    ProtoLog.v(WM_DEBUG_LAYER_MIRRORING,
+                            "Going ahead with updating layer mirroring for display %d to new "
+                                    + "bounds %s and/or orientation %d.",
+                            mDisplayId, displayAreaBounds, displayAreaOrientation);
+                    updateMirroredSurface(mWmService.mTransactionFactory.get(),
+                            displayAreaBounds, surfaceSize);
+                } else {
+                    // If the surface removed, do nothing. We will handle this via onDisplayChanged
+                    // (the display will be off if the surface is removed).
+                    ProtoLog.v(WM_DEBUG_LAYER_MIRRORING,
+                            "Unable to update layer mirroring for display %d to new bounds %s"
+                            + " and/or orientation %d, since the surface is not available.",
+                            mDisplayId, displayAreaBounds, displayAreaOrientation);
                 }
             }
         }
@@ -3514,7 +3539,7 @@
         // focused one starts firing events.
         // TODO(b/151179149) investigate what info accessibility service needs before input can
         // dispatch focus to clients.
-        if (mWmService.mAccessibilityController != null) {
+        if (mWmService.mAccessibilityController.hasCallbacks()) {
             mWmService.mH.sendMessage(PooledLambda.obtainMessage(
                     this::updateAccessibilityOnWindowFocusChanged,
                     mWmService.mAccessibilityController));
@@ -4399,6 +4424,7 @@
                     mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing,
                     true /* inTraversal, must call performTraversalInTrans... below */);
         }
+        // If the display now has content, or no longer has content, update layer mirroring.
         updateMirroring();
 
         final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible();
@@ -5148,7 +5174,7 @@
         }
         if (!mLocationInParentWindow.equals(x, y)) {
             mLocationInParentWindow.set(x, y);
-            if (mWmService.mAccessibilityController != null) {
+            if (mWmService.mAccessibilityController.hasCallbacks()) {
                 mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(mDisplayId);
             }
             notifyLocationInParentDisplayChanged();
@@ -5465,6 +5491,15 @@
             } else if (displayState == Display.STATE_ON) {
                 mOffTokenAcquirer.release(mDisplayId);
             }
+            ProtoLog.v(WM_DEBUG_LAYER_MIRRORING,
+                    "Display %d state is now (%d), so update layer mirroring?",
+                    mDisplayId, displayState);
+            if (mLastDisplayState != displayState) {
+                // If state is on due to surface being added, then start layer mirroring.
+                // If state is off due to surface being removed, then stop layer mirroring.
+                updateMirroring();
+            }
+            mLastDisplayState = displayState;
         }
         mWmService.requestTraversal();
     }
@@ -5654,7 +5689,8 @@
         final Configuration currOverrideConfig = getRequestedOverrideConfiguration();
         final int currRotation = currOverrideConfig.windowConfiguration.getRotation();
         final int overrideRotation = overrideConfiguration.windowConfiguration.getRotation();
-        if (currRotation != ROTATION_UNDEFINED && currRotation != overrideRotation) {
+        if (currRotation != ROTATION_UNDEFINED && overrideRotation != ROTATION_UNDEFINED
+                && currRotation != overrideRotation) {
             applyRotationAndFinishFixedRotation(currRotation, overrideRotation);
         }
         mCurrentOverrideConfigurationChanges = currOverrideConfig.diff(overrideConfiguration);
@@ -5668,7 +5704,7 @@
     @Override
     void onResize() {
         super.onResize();
-        if (mWmService.mAccessibilityController != null) {
+        if (mWmService.mAccessibilityController.hasCallbacks()) {
             mWmService.mAccessibilityController.onDisplaySizeChanged(this);
         }
     }
@@ -5943,31 +5979,48 @@
      * back to original MediaProjection approach.
      */
     private void startMirrorIfNeeded() {
-        // Only mirror if this display does not have its own content.
-        if (mLastHasContent) {
+        // Only mirror if this display does not have its own content, is not mirroring already,
+        // and if this display is on (it has a surface to write output to).
+        if (mLastHasContent || isCurrentlyMirroring() || mDisplay.getState() == Display.STATE_OFF) {
             return;
         }
+
         // Given the WindowToken of the DisplayArea to mirror, retrieve the associated
         // SurfaceControl.
         IBinder tokenToMirror = mWmService.mDisplayManagerInternal.getWindowTokenClientToMirror(
                 mDisplayId);
-
         if (tokenToMirror == null) {
             // This DisplayContent instance is not involved in layer mirroring. If the display
             // has been created for capturing, fall back to prior MediaProjection approach.
             return;
         }
+
         final WindowContainer wc = mWmService.mWindowContextListenerController.getContainer(
                 tokenToMirror);
         if (wc == null) {
             // Un-set the window token to mirror for this VirtualDisplay, to fall back to the
             // original MediaProjection approach.
             mWmService.mDisplayManagerInternal.setWindowTokenClientToMirror(mDisplayId, null);
+            ProtoLog.v(WM_DEBUG_LAYER_MIRRORING,
+                    "Unable to retrieve window container to start layer mirroring for display %d",
+                    mDisplayId);
             return;
         }
-        SurfaceControl sc = wc.getDisplayContent().getSurfaceControl();
+
+        Point surfaceSize = fetchSurfaceSizeIfPresent();
+        if (surfaceSize == null) {
+            ProtoLog.v(WM_DEBUG_LAYER_MIRRORING,
+                    "Unable to start layer mirroring for display %d since the surface is not "
+                            + "available.",
+                    mDisplayId);
+            return;
+        }
+        ProtoLog.v(WM_DEBUG_LAYER_MIRRORING,
+                "Display %d has no content and is on, so start layer mirroring for state %d",
+                mDisplayId, mDisplay.getState());
 
         // Create a mirrored hierarchy for the SurfaceControl of the DisplayArea to capture.
+        SurfaceControl sc = wc.getDisplayContent().getSurfaceControl();
         mMirroredSurface = SurfaceControl.mirrorSurface(sc);
         SurfaceControl.Transaction transaction = mWmService.mTransactionFactory.get()
                 // Set the mMirroredSurface's parent to the root SurfaceControl for this
@@ -5980,7 +6033,7 @@
                 // VirtualDisplay will show up as part of the mirrored content.
                 .reparent(mWindowingLayer, null);
         // Retrieve the size of the DisplayArea to mirror.
-        updateMirroredSurface(transaction, wc.getDisplayContent().getBounds());
+        updateMirroredSurface(transaction, wc.getDisplayContent().getBounds(), surfaceSize);
         mTokenToMirror = tokenToMirror;
 
         // No need to clean up. In SurfaceFlinger, parents hold references to their children. The
@@ -5990,11 +6043,18 @@
     }
 
     /**
-     * Start or stop mirroring if this DisplayContent now has content, or no longer has content.
+     * Start mirroring if this DisplayContent no longer has content. Stop mirroring if it now
+     * has content or the display is not on.
      */
     private void updateMirroring() {
-        if (mLastHasContent && mMirroredSurface != null) {
-            // Display now has content, so stop mirroring to it.
+        if (isCurrentlyMirroring() && (mLastHasContent
+                || mDisplay.getState() == Display.STATE_OFF)) {
+            ProtoLog.v(WM_DEBUG_LAYER_MIRRORING,
+                    "Display %d has content (%b) so disable layer mirroring", mDisplayId,
+                    mLastHasContent);
+            // If the display is not on and it is a virtual display, then it no longer has an
+            // associated surface to write output to.
+            // If the display now has content, stop mirroring to it.
             mWmService.mTransactionFactory.get()
                     // Remove the reference to mMirroredSurface, to clean up associated memory.
                     .remove(mMirroredSurface)
@@ -6005,8 +6065,9 @@
             // Stop mirroring by destroying the reference to the mirrored layer.
             mMirroredSurface = null;
             // Do not un-set the token, in case content is removed and mirroring should begin again.
-        } else if (!mLastHasContent && mMirroredSurface == null) {
-            // Display no longer has content, so start mirroring to it.
+        } else {
+            // Display no longer has content, or now has a surface to write to, so try to start
+            // mirroring to it.
             startMirrorIfNeeded();
         }
     }
@@ -6015,21 +6076,15 @@
      * Apply transformations to the mirrored surface to ensure the captured contents are scaled to
      * fit and centred in the output surface.
      *
-     * @param transaction            the transaction to include transformations of mMirroredSurface
-     *                               to. Transaction is not applied before returning.
-     * @param displayAreaBounds      bounds of the DisplayArea to mirror to the surface provided by
-     *                               the app.
+     * @param transaction       the transaction to include transformations of mMirroredSurface
+     *                          to. Transaction is not applied before returning.
+     * @param displayAreaBounds bounds of the DisplayArea to mirror to the surface provided by
+     *                          the app.
+     * @param surfaceSize       the default size of the surface to write the display area content to
      */
     @VisibleForTesting
     void updateMirroredSurface(SurfaceControl.Transaction transaction,
-            Rect displayAreaBounds) {
-        // Retrieve the default size of the surface the app provided to
-        // MediaProjection#createVirtualDisplay. Note the app is the consumer of the surface,
-        // since it reads out buffers from the surface, and SurfaceFlinger is the producer since
-        // it writes the mirrored layers to the buffers.
-        final Point surfaceSize = mWmService.mDisplayManagerInternal.getDisplaySurfaceDefaultSize(
-                mDisplayId);
-
+            Rect displayAreaBounds, Point surfaceSize) {
         // Calculate the scale to apply to the root mirror SurfaceControl to fit the size of the
         // output surface.
         float scaleX = surfaceSize.x / (float) displayAreaBounds.width();
@@ -6064,6 +6119,36 @@
         mLastMirroredDisplayAreaBounds = new Rect(displayAreaBounds);
     }
 
+    /**
+     * Returns a non-null {@link Point} if the surface is present, or null otherwise
+     */
+    Point fetchSurfaceSizeIfPresent() {
+        // Retrieve the default size of the surface the app provided to
+        // MediaProjection#createVirtualDisplay. Note the app is the consumer of the surface,
+        // since it reads out buffers from the surface, and SurfaceFlinger is the producer since
+        // it writes the mirrored layers to the buffers.
+        Point surfaceSize = mWmService.mDisplayManagerInternal.getDisplaySurfaceDefaultSize(
+                mDisplayId);
+        if (surfaceSize == null) {
+            // Layer mirroring started with a null surface, so do not apply any transformations yet.
+            // State of virtual display will change to 'ON' when the surface is set.
+            // will get event DISPLAY_DEVICE_EVENT_CHANGED
+            ProtoLog.v(WM_DEBUG_LAYER_MIRRORING,
+                    "Provided surface for layer mirroring on display %d is not present, so do not"
+                            + " update the surface",
+                    mDisplayId);
+            return null;
+        }
+        return surfaceSize;
+    }
+
+    /**
+     * Returns {@code true} if this DisplayContent is currently layer mirroring.
+     */
+    boolean isCurrentlyMirroring() {
+        return mTokenToMirror != null && mMirroredSurface != null;
+    }
+
     /** The entry for proceeding to handle {@link #mFixedRotationLaunchingApp}. */
     class FixedRotationTransitionListener extends WindowManagerInternal.AppTransitionListener {
 
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 3c8827e..322024d 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -483,7 +483,8 @@
                             if (mStatusBar != null) {
                                 requestTransientBars(mStatusBar);
                             }
-                            checkAltBarSwipeForTransientBars(ALT_BAR_TOP);
+                            checkAltBarSwipeForTransientBars(ALT_BAR_TOP,
+                                    false /* allowForAllPositions */);
                         }
                     }
 
@@ -494,7 +495,8 @@
                                     && mNavigationBarPosition == NAV_BAR_BOTTOM) {
                                 requestTransientBars(mNavigationBar);
                             }
-                            checkAltBarSwipeForTransientBars(ALT_BAR_BOTTOM);
+                            checkAltBarSwipeForTransientBars(ALT_BAR_BOTTOM,
+                                    false /* allowForAllPositions */);
                         }
                     }
 
@@ -504,13 +506,13 @@
                         synchronized (mLock) {
                             mDisplayContent.calculateSystemGestureExclusion(
                                     excludedRegion, null /* outUnrestricted */);
-                            final boolean excluded =
-                                    mSystemGestures.currentGestureStartedInRegion(excludedRegion);
+                            final boolean allowSideSwipe = mNavigationBarAlwaysShowOnSideGesture &&
+                                    !mSystemGestures.currentGestureStartedInRegion(excludedRegion);
                             if (mNavigationBar != null && (mNavigationBarPosition == NAV_BAR_RIGHT
-                                    || !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
+                                    || allowSideSwipe)) {
                                 requestTransientBars(mNavigationBar);
                             }
-                            checkAltBarSwipeForTransientBars(ALT_BAR_RIGHT);
+                            checkAltBarSwipeForTransientBars(ALT_BAR_RIGHT, allowSideSwipe);
                         }
                         excludedRegion.recycle();
                     }
@@ -521,13 +523,13 @@
                         synchronized (mLock) {
                             mDisplayContent.calculateSystemGestureExclusion(
                                     excludedRegion, null /* outUnrestricted */);
-                            final boolean excluded =
-                                    mSystemGestures.currentGestureStartedInRegion(excludedRegion);
+                            final boolean allowSideSwipe = mNavigationBarAlwaysShowOnSideGesture &&
+                                    !mSystemGestures.currentGestureStartedInRegion(excludedRegion);
                             if (mNavigationBar != null && (mNavigationBarPosition == NAV_BAR_LEFT
-                                    || !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
+                                    || allowSideSwipe)) {
                                 requestTransientBars(mNavigationBar);
                             }
-                            checkAltBarSwipeForTransientBars(ALT_BAR_LEFT);
+                            checkAltBarSwipeForTransientBars(ALT_BAR_LEFT, allowSideSwipe);
                         }
                         excludedRegion.recycle();
                     }
@@ -681,17 +683,19 @@
         mHandler.post(mGestureNavigationSettingsObserver::register);
     }
 
-    private void checkAltBarSwipeForTransientBars(@WindowManagerPolicy.AltBarPosition int pos) {
-        if (mStatusBarAlt != null && mStatusBarAltPosition == pos) {
+    private void checkAltBarSwipeForTransientBars(@WindowManagerPolicy.AltBarPosition int pos,
+            boolean allowForAllPositions) {
+        if (mStatusBarAlt != null && (mStatusBarAltPosition == pos || allowForAllPositions)) {
             requestTransientBars(mStatusBarAlt);
         }
-        if (mNavigationBarAlt != null && mNavigationBarAltPosition == pos) {
+        if (mNavigationBarAlt != null
+                && (mNavigationBarAltPosition == pos || allowForAllPositions)) {
             requestTransientBars(mNavigationBarAlt);
         }
-        if (mClimateBarAlt != null && mClimateBarAltPosition == pos) {
+        if (mClimateBarAlt != null && (mClimateBarAltPosition == pos || allowForAllPositions)) {
             requestTransientBars(mClimateBarAlt);
         }
-        if (mExtraNavBarAlt != null && mExtraNavBarAltPosition == pos) {
+        if (mExtraNavBarAlt != null && (mExtraNavBarAltPosition == pos || allowForAllPositions)) {
             requestTransientBars(mExtraNavBarAlt);
         }
     }
@@ -1207,6 +1211,12 @@
             default:
                 if (attrs.providesInsetsTypes != null) {
                     for (@InternalInsetsType int insetsType : attrs.providesInsetsTypes) {
+                        final TriConsumer<DisplayFrames, WindowState, Rect> imeFrameProvider =
+                                !attrs.providedInternalImeInsets.equals(Insets.NONE)
+                                    ? (displayFrames, windowState, inOutFrame) ->
+                                            inOutFrame.inset(windowState.getLayoutingAttrs(
+                                                displayFrames.mRotation).providedInternalImeInsets)
+                                    : null;
                         switch (insetsType) {
                             case ITYPE_STATUS_BAR:
                                 mStatusBarAlt = win;
@@ -1226,12 +1236,13 @@
                                 break;
                         }
                         if (!INSETS_LAYOUT_GENERALIZATION) {
-                            mDisplayContent.setInsetProvider(insetsType, win, null);
+                            mDisplayContent.setInsetProvider(insetsType, win, null,
+                                    imeFrameProvider);
                         } else {
                             mDisplayContent.setInsetProvider(insetsType, win, (displayFrames,
                                     windowState, inOutFrame) -> inOutFrame.inset(
                                             windowState.getLayoutingAttrs(displayFrames.mRotation)
-                                                    .providedInternalInsets));
+                                                    .providedInternalInsets), imeFrameProvider);
                         }
                     }
                 }
@@ -2430,7 +2441,7 @@
      */
     float getWindowCornerRadius() {
         return mDisplayContent.getDisplay().getType() == TYPE_INTERNAL
-                ? ScreenDecorationsUtils.getWindowCornerRadius(mContext.getResources()) : 0f;
+                ? ScreenDecorationsUtils.getWindowCornerRadius(mContext) : 0f;
     }
 
     boolean isShowingDreamLw() {
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java
index 8fcdf2e..4a70fa3 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java
@@ -264,8 +264,14 @@
 
     @NonNull
     private static AtomicFile getVendorSettingsFile() {
-        final File vendorFile = new File(Environment.getVendorDirectory(),
+        // First look under product path for treblized builds.
+        File vendorFile = new File(Environment.getProductDirectory(),
                 VENDOR_DISPLAY_SETTINGS_FILE_PATH);
+        if (!vendorFile.exists()) {
+            // Try and look in vendor path.
+            vendorFile = new File(Environment.getVendorDirectory(),
+                VENDOR_DISPLAY_SETTINGS_FILE_PATH);
+        }
         return new AtomicFile(vendorFile, WM_DISPLAY_COMMIT_TAG);
     }
 
diff --git a/services/core/java/com/android/server/wm/DockedTaskDividerController.java b/services/core/java/com/android/server/wm/DockedTaskDividerController.java
index fb9d064..925a6d8 100644
--- a/services/core/java/com/android/server/wm/DockedTaskDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedTaskDividerController.java
@@ -46,7 +46,7 @@
     void setTouchRegion(Rect touchRegion) {
         mTouchRegion.set(touchRegion);
         // We need to report touchable region changes to accessibility.
-        if (mDisplayContent.mWmService.mAccessibilityController != null) {
+        if (mDisplayContent.mWmService.mAccessibilityController.hasCallbacks()) {
             mDisplayContent.mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(
                     mDisplayContent.getDisplayId());
         }
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 450c2c1..3d19f54 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -43,8 +43,10 @@
 import android.view.InsetsSourceControl;
 import android.view.InsetsState;
 import android.view.InsetsState.InternalInsetsType;
+import android.view.InternalInsetsAnimationController;
 import android.view.SurfaceControl;
 import android.view.SyncRtSurfaceTransactionApplier;
+import android.view.WindowInsets.Type;
 import android.view.WindowInsetsAnimation;
 import android.view.WindowInsetsAnimation.Bounds;
 import android.view.WindowInsetsAnimationControlListener;
@@ -335,7 +337,7 @@
 
     private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin,
             boolean fake) {
-        if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1 && !fake) {
+        if (!fake && isShowingTransientTypes(Type.statusBars())) {
             return mDummyControlTarget;
         }
         final WindowState notificationShade = mPolicy.getNotificationShade();
@@ -385,7 +387,7 @@
             // Force showing navigation bar while IME is visible.
             return null;
         }
-        if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1 && !fake) {
+        if (!fake && isShowingTransientTypes(Type.navigationBars())) {
             return mDummyControlTarget;
         }
         if (focusedWin == mPolicy.getNotificationShade()) {
@@ -411,6 +413,16 @@
         return focusedWin;
     }
 
+    private boolean isShowingTransientTypes(@Type.InsetsType int types) {
+        final IntArray showingTransientTypes = mShowingTransientTypes;
+        for (int i = showingTransientTypes.size() - 1; i >= 0; i--) {
+            if ((InsetsState.toPublicType(showingTransientTypes.get(i)) & types) != 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * Determines whether the remote insets controller should take control of system bars for all
      * windows.
@@ -585,7 +597,7 @@
             }
 
             @Override
-            public <T extends InsetsAnimationControlRunner & WindowInsetsAnimationController>
+            public <T extends InsetsAnimationControlRunner & InternalInsetsAnimationController>
             void startAnimation(T runner, WindowInsetsAnimationControlListener listener, int types,
                     WindowInsetsAnimation animation,
                     Bounds bounds) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 079868d..6c2322b 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1965,7 +1965,7 @@
 
     private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,
             WindowProcessController app, ActivityRecord top) {
-        if (r.finishing || !r.okToShowLocked() || !r.visibleIgnoringKeyguard || r.app != null
+        if (r.finishing || !r.showToCurrentUser() || !r.visibleIgnoringKeyguard || r.app != null
                 || app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) {
             return false;
         }
diff --git a/services/core/java/com/android/server/wm/ShellRoot.java b/services/core/java/com/android/server/wm/ShellRoot.java
index be6a5d2..6ed59e9 100644
--- a/services/core/java/com/android/server/wm/ShellRoot.java
+++ b/services/core/java/com/android/server/wm/ShellRoot.java
@@ -197,7 +197,7 @@
                 mAccessibilityWindow = null;
             }
         }
-        if (mDisplayContent.mWmService.mAccessibilityController != null) {
+        if (mDisplayContent.mWmService.mAccessibilityController.hasCallbacks()) {
             mDisplayContent.mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(
                     mDisplayContent.getDisplayId());
         }
diff --git a/services/core/java/com/android/server/wm/SurfaceFreezer.java b/services/core/java/com/android/server/wm/SurfaceFreezer.java
index e0a791e..fce2f8d 100644
--- a/services/core/java/com/android/server/wm/SurfaceFreezer.java
+++ b/services/core/java/com/android/server/wm/SurfaceFreezer.java
@@ -117,7 +117,7 @@
         SurfaceControl leash = mLeash;
         mLeash = null;
         final boolean scheduleAnim = SurfaceAnimator.removeLeash(t, mAnimatable, leash,
-                false /* destroy */);
+                true /* destroy */);
         if (scheduleAnim) {
             mWmService.scheduleAnimationLocked();
         }
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 567936d..e6e51b8 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -165,6 +165,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.Trace;
@@ -570,7 +571,9 @@
             mRoot = r;
 
             // Only end search if we are ignore relinquishing identity or we are not relinquishing.
-            return ignoreRelinquishIdentity || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
+            return ignoreRelinquishIdentity
+                    || mNeverRelinquishIdentity
+                    || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
         }
     }
 
@@ -1009,7 +1012,14 @@
     private void setIntent(Intent _intent, ActivityInfo info) {
         if (!isLeafTask()) return;
 
-        mNeverRelinquishIdentity = (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
+        if (info.applicationInfo.uid == Process.SYSTEM_UID
+                || info.applicationInfo.isSystemApp()) {
+            // Only allow the apps that pre-installed on the system image to apply
+            // relinquishTaskIdentity
+            mNeverRelinquishIdentity = (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
+        } else {
+            mNeverRelinquishIdentity = true;
+        }
         affinity = info.taskAffinity;
         if (intent == null) {
             // If this task already has an intent associated with it, don't set the root
@@ -1990,14 +2000,7 @@
             taskDisplayArea.onRootTaskWindowingModeChanged(this);
         }
 
-        if (mDisplayContent == null) {
-            return;
-        }
-
-        // Use override windowing mode to prevent extra bounds changes if inheriting the mode.
-        final int overrideWindowingMode = getRequestedOverrideWindowingMode();
-        if (overrideWindowingMode != WINDOWING_MODE_PINNED
-                && !getRequestedOverrideBounds().isEmpty()) {
+        if (!isOrganized() && !getRequestedOverrideBounds().isEmpty() && mDisplayContent != null) {
             // If the parent (display) has rotated, rotate our bounds to best-fit where their
             // bounds were on the pre-rotated display.
             final int newRotation = getWindowConfiguration().getRotation();
@@ -5159,7 +5162,7 @@
                 }
 
                 final ActivityRecord prev = baseTask.getActivity(
-                        a -> a.mStartingData != null && a.okToShowLocked());
+                        a -> a.mStartingData != null && a.showToCurrentUser());
                 r.showStartingWindow(prev, newTask, isTaskSwitch,
                         true /* startActivity */, sourceRecord);
             }
@@ -5530,7 +5533,7 @@
 
             // Don't refocus if invisible to current user
             final ActivityRecord top = tr.getTopNonFinishingActivity();
-            if (top == null || !top.okToShowLocked()) {
+            if (top == null || !top.showToCurrentUser()) {
                 positionChildAtTop(tr);
                 if (top != null) {
                     mTaskSupervisor.mRecentTasks.add(top.getTask());
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 1b72826..ca1d83e 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -174,6 +174,12 @@
     boolean mTaskFragmentAppearedSent;
 
     /**
+     * The last running activity of the TaskFragment was finished due to clear task while launching
+     * an activity in the Task.
+     */
+    boolean mClearedTaskForReuse;
+
+    /**
      * When we are in the process of pausing an activity, before starting the
      * next one, this variable holds the activity that is currently being paused.
      *
@@ -655,7 +661,6 @@
      * @param includingEmbeddedTask whether the activity in a task that being embedded from this
      *                              one should be included.
      * @see #topRunningActivity(boolean, boolean)
-     * @see ActivityRecord#okToShowLocked()
      */
     ActivityRecord getTopNonFinishingActivity(boolean includeOverlays,
             boolean includingEmbeddedTask) {
@@ -1588,6 +1593,8 @@
 
     @Override
     void addChild(WindowContainer child, int index) {
+        mClearedTaskForReuse = false;
+
         boolean isAddingActivity = child.asActivityRecord() != null;
         final Task task = isAddingActivity ? getTask() : null;
 
@@ -2080,15 +2087,22 @@
         }
         final Point positionInParent = new Point();
         getRelativePosition(positionInParent);
+        final int[] runningActivityCount = new int[1];
+        forAllActivities(a -> {
+            if (!a.finishing) {
+                runningActivityCount[0]++;
+            }
+        });
         return new TaskFragmentInfo(
                 mFragmentToken,
                 mRemoteToken.toWindowContainerToken(),
                 getConfiguration(),
                 getChildCount() == 0,
-                hasRunningActivity(this),
+                runningActivityCount[0],
                 isVisible(),
                 childActivities,
-                positionInParent);
+                positionInParent,
+                mClearedTaskForReuse);
     }
 
     @Nullable
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 07f0197..6b93364 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -70,7 +70,7 @@
 import android.util.Slog;
 import android.view.SurfaceControl;
 import android.view.animation.Animation;
-import android.window.IRemoteTransition;
+import android.window.RemoteTransition;
 import android.window.TransitionInfo;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -123,7 +123,7 @@
     private @TransitionFlags int mFlags;
     private final TransitionController mController;
     private final BLASTSyncEngine mSyncEngine;
-    private IRemoteTransition mRemoteTransition = null;
+    private RemoteTransition mRemoteTransition = null;
 
     /** Only use for clean-up after binder death! */
     private SurfaceControl.Transaction mStartTransaction = null;
@@ -436,11 +436,11 @@
         mSyncEngine.abort(mSyncId);
     }
 
-    void setRemoteTransition(IRemoteTransition remoteTransition) {
+    void setRemoteTransition(RemoteTransition remoteTransition) {
         mRemoteTransition = remoteTransition;
     }
 
-    IRemoteTransition getRemoteTransition() {
+    RemoteTransition getRemoteTransition() {
         return mRemoteTransition;
     }
 
@@ -565,7 +565,7 @@
         if (mFinishTransaction != null) {
             mFinishTransaction.apply();
         }
-        finishTransition();
+        mController.finishTransition(this);
     }
 
     /** @see RecentsAnimationController#attachNavigationBarToApp */
@@ -978,7 +978,7 @@
             // Wallpaper must be the top (regardless of how nested it is in DisplayAreas).
             boolean skipIntermediateReports = isWallpaper(wc);
             for (WindowContainer p = wc.getParent(); p != null; p = p.getParent()) {
-                if (!p.isAttached() || !changes.get(p).hasChanged(p)) {
+                if (!p.isAttached() || changes.get(p) == null || !changes.get(p).hasChanged(p)) {
                     // Again, we're skipping no-ops
                     break;
                 }
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 419b4c3..69e6a54 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -34,6 +34,7 @@
 import android.view.WindowManager;
 import android.window.IRemoteTransition;
 import android.window.ITransitionPlayer;
+import android.window.RemoteTransition;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
 
@@ -223,7 +224,7 @@
     @Nullable
     Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
             @WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger,
-            @NonNull WindowContainer readyGroupRef, @Nullable IRemoteTransition remoteTransition) {
+            @NonNull WindowContainer readyGroupRef, @Nullable RemoteTransition remoteTransition) {
         if (mTransitionPlayer == null) {
             return null;
         }
@@ -252,7 +253,7 @@
     /** Asks the transition player (shell) to start a created but not yet started transition. */
     @NonNull
     Transition requestStartTransition(@NonNull Transition transition, @Nullable Task startTask,
-            @Nullable IRemoteTransition remoteTransition) {
+            @Nullable RemoteTransition remoteTransition) {
         try {
             ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                     "Requesting StartTransition: %s", transition);
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index eb32486..4a43f4f 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -164,7 +164,7 @@
                 final DisplayContent dc = root.getDisplayContent(displayId);
 
                 dc.checkAppWindowsReadyToShow();
-                if (accessibilityController != null) {
+                if (accessibilityController.hasCallbacks()) {
                     accessibilityController.drawMagnifiedRegionBorderIfNeeded(displayId,
                             mTransaction);
                 }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 8e3fd0a..31bf49d 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1381,6 +1381,7 @@
         }
     }
 
+    /** Returns whether the window should be shown for current user. */
     boolean showToCurrentUser() {
         return true;
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9458511..8ac32ab 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -46,6 +46,8 @@
 import static android.provider.Settings.Global.DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_270;
 import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
 import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
@@ -153,6 +155,7 @@
 import android.app.IAssistDataReceiver;
 import android.app.WindowConfiguration;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -162,6 +165,7 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.TestUtilityService;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
@@ -323,11 +327,13 @@
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.Set;
 import java.util.function.Function;
 import java.util.function.Supplier;
 
@@ -630,7 +636,7 @@
     /** List of window currently causing non-system overlay windows to be hidden. */
     private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>();
 
-    AccessibilityController mAccessibilityController;
+    final AccessibilityController mAccessibilityController;
     private RecentsAnimationController mRecentsAnimationController;
 
     Watermark mWatermark;
@@ -1376,6 +1382,7 @@
         mStartingSurfaceController = new StartingSurfaceController(this);
 
         mBlurController = new BlurController(mContext, mPowerManager);
+        mAccessibilityController = new AccessibilityController(this);
     }
 
     DisplayAreaPolicy.Provider getDisplayAreaPolicyProvider() {
@@ -2155,7 +2162,7 @@
                     mWindowPlacerLocked.performSurfacePlacement();
 
                     // We need to report touchable region changes to accessibility.
-                    if (mAccessibilityController != null) {
+                    if (mAccessibilityController.hasCallbacks()) {
                         mAccessibilityController.onSomeWindowResizedOrMovedWithCallingUid(
                                 uid, w.getDisplayContent().getDisplayId());
                     }
@@ -2168,7 +2175,7 @@
 
     public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
         synchronized (mGlobalLock) {
-            if (mAccessibilityController != null) {
+            if (mAccessibilityController.hasCallbacks()) {
                 WindowState window = mWindowMap.get(token);
                 if (window != null) {
                     mAccessibilityController.onRectangleOnScreenRequested(
@@ -2258,7 +2265,7 @@
                     win.mActivityRecord.checkKeyguardFlagsChanged();
                 }
                 if (((attrChanges & LayoutParams.ACCESSIBILITY_TITLE_CHANGED) != 0)
-                        && (mAccessibilityController != null)) {
+                        && (mAccessibilityController.hasCallbacks())) {
                     // No move or resize, but the controller checks for title changes as well
                     mAccessibilityController.onSomeWindowResizedOrMovedWithCallingUid(
                             uid, win.getDisplayContent().getDisplayId());
@@ -2580,7 +2587,7 @@
             win.mDestroying = true;
             win.destroySurface(false, stopped);
         }
-        if (mAccessibilityController != null) {
+        if (mAccessibilityController.hasCallbacks()) {
             mAccessibilityController.onWindowTransition(win, transit);
         }
 
@@ -6370,7 +6377,7 @@
 
         mInputManagerCallback.dump(pw, "  ");
         mTaskSnapshotController.dump(pw, "  ");
-        if (mAccessibilityController != null) {
+        if (mAccessibilityController.hasCallbacks()) {
             mAccessibilityController.dump(pw, "  ");
         }
 
@@ -7390,7 +7397,7 @@
         @Override
         public void setMagnificationSpec(int displayId, MagnificationSpec spec) {
             synchronized (mGlobalLock) {
-                if (mAccessibilityController != null) {
+                if (mAccessibilityController.hasCallbacks()) {
                     mAccessibilityController.setMagnificationSpec(displayId, spec);
                 } else {
                     throw new IllegalStateException("Magnification callbacks not set!");
@@ -7401,7 +7408,7 @@
         @Override
         public void setForceShowMagnifiableBounds(int displayId, boolean show) {
             synchronized (mGlobalLock) {
-                if (mAccessibilityController != null) {
+                if (mAccessibilityController.hasCallbacks()) {
                     mAccessibilityController.setForceShowMagnifiableBounds(displayId, show);
                 } else {
                     throw new IllegalStateException("Magnification callbacks not set!");
@@ -7412,7 +7419,7 @@
         @Override
         public void getMagnificationRegion(int displayId, @NonNull Region magnificationRegion) {
             synchronized (mGlobalLock) {
-                if (mAccessibilityController != null) {
+                if (mAccessibilityController.hasCallbacks()) {
                     mAccessibilityController.getMagnificationRegion(displayId, magnificationRegion);
                 } else {
                     throw new IllegalStateException("Magnification callbacks not set!");
@@ -7428,7 +7435,7 @@
                     return null;
                 }
                 MagnificationSpec spec = null;
-                if (mAccessibilityController != null) {
+                if (mAccessibilityController.hasCallbacks()) {
                     spec = mAccessibilityController.getMagnificationSpecForWindow(windowState);
                 }
                 if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
@@ -7447,16 +7454,7 @@
         public boolean setMagnificationCallbacks(int displayId,
                 @Nullable MagnificationCallbacks callbacks) {
             synchronized (mGlobalLock) {
-                if (mAccessibilityController == null) {
-                    mAccessibilityController = new AccessibilityController(
-                            WindowManagerService.this);
-                }
-                boolean result = mAccessibilityController.setMagnificationCallbacks(
-                        displayId, callbacks);
-                if (!mAccessibilityController.hasCallbacks()) {
-                    mAccessibilityController = null;
-                }
-                return result;
+                return mAccessibilityController.setMagnificationCallbacks(displayId, callbacks);
             }
         }
 
@@ -7464,15 +7462,7 @@
         public void setWindowsForAccessibilityCallback(int displayId,
                 WindowsForAccessibilityCallback callback) {
             synchronized (mGlobalLock) {
-                if (mAccessibilityController == null) {
-                    mAccessibilityController = new AccessibilityController(
-                            WindowManagerService.this);
-                }
-                mAccessibilityController.setWindowsForAccessibilityCallback(
-                        displayId, callback);
-                if (!mAccessibilityController.hasCallbacks()) {
-                    mAccessibilityController = null;
-                }
+                mAccessibilityController.setWindowsForAccessibilityCallback(displayId, callback);
             }
         }
 
@@ -7645,13 +7635,7 @@
 
         @Override
         public void computeWindowsForAccessibility(int displayId) {
-            final AccessibilityController accessibilityController;
-            synchronized (mGlobalLock) {
-                accessibilityController = mAccessibilityController;
-            }
-            if (accessibilityController != null) {
-                accessibilityController.performComputeChangedWindowsNot(displayId, true);
-            }
+            mAccessibilityController.performComputeChangedWindowsNot(displayId, true);
         }
 
         @Override
@@ -8454,6 +8438,65 @@
         }
     }
 
+    @Override
+    public List<DisplayInfo> getPossibleDisplayInfo(int displayId, String packageName) {
+        final int callingUid = Binder.getCallingUid();
+        final long origId = Binder.clearCallingIdentity();
+        try {
+            synchronized (mGlobalLock) {
+                if (packageName == null || !isRecentsComponent(packageName, callingUid)) {
+                    Slog.e(TAG, "Unable to verify uid for package " + packageName
+                            + " for getPossibleMaximumWindowMetrics");
+                    return new ArrayList<>();
+                }
+                // TODO(181127261) DisplayInfo should be pushed from DisplayManager.
+                final DisplayContent dc = mRoot.getDisplayContent(displayId);
+                if (dc == null) {
+                    Slog.e(TAG, "Invalid displayId " + displayId
+                            + " for getPossibleMaximumWindowMetrics");
+                    return new ArrayList<>();
+                }
+
+                // TODO(181127261) DisplayManager should provide a DisplayInfo for each rotation
+                DisplayInfo currentDisplayInfo = dc.getDisplayInfo();
+                Set<DisplayInfo> displayInfoSet = new HashSet<>();
+                for (int rotation = ROTATION_0; rotation <= ROTATION_270; rotation++) {
+                    currentDisplayInfo.rotation = rotation;
+                    // TODO(181127261) Retrieve the device state from display stack.
+                    displayInfoSet.add(new DisplayInfo(currentDisplayInfo));
+                }
+                return new ArrayList<DisplayInfo>(displayInfoSet);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    /**
+     * Returns {@code true} when the calling package is the recents component.
+     */
+    boolean isRecentsComponent(@NonNull String callingPackageName, int callingUid) {
+        String recentsPackage;
+        try {
+            String recentsComponent = mContext.getResources().getString(
+                    R.string.config_recentsComponentName);
+            if (recentsComponent == null) {
+                return false;
+            }
+            recentsPackage = ComponentName.unflattenFromString(recentsComponent).getPackageName();
+        } catch (Resources.NotFoundException e) {
+            Slog.e(TAG, "Unable to verify if recents component", e);
+            return false;
+        }
+        try {
+            return callingUid == mContext.getPackageManager().getPackageUid(callingPackageName, 0)
+                    && callingPackageName.equals(recentsPackage);
+        } catch (PackageManager.NameNotFoundException e) {
+            Slog.e(TAG, "Unable to verify if recents component", e);
+            return false;
+        }
+    }
+
     void grantEmbeddedWindowFocus(Session session, IBinder inputToken, boolean grantFocus) {
         synchronized (mGlobalLock) {
             final EmbeddedWindowController.EmbeddedWindow embeddedWindow =
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index b568774..8bcd62d 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -275,8 +275,6 @@
                 syncId = startSyncWithOrganizer(callback);
                 applyTransaction(t, syncId, null /* transition */, caller);
                 setSyncReady(syncId);
-                mService.mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY)
-                        .executeAppTransition();
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -653,18 +651,10 @@
                     options = activityOptions.toBundle();
                 }
 
-                int res = mService.mAmInternal.sendIntentSender(hop.getPendingIntent().getTarget(),
+                mService.mAmInternal.sendIntentSender(hop.getPendingIntent().getTarget(),
                         hop.getPendingIntent().getWhitelistToken(), 0 /* code */,
                         hop.getActivityIntent(), resolvedType, null /* finishReceiver */,
                         null /* requiredPermission */, options);
-                if (res != ActivityManager.START_SUCCESS
-                        && res != ActivityManager.START_TASK_TO_FRONT) {
-                    if (!mTransitionController.isShellTransitionsEnabled()) {
-                        final DisplayContent dc =
-                                mService.mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY);
-                        dc.cancelAppTransition();
-                    }
-                }
                 break;
             case HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT:
                 final TaskFragmentCreationParams taskFragmentCreationOptions =
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 22db297..f848c22 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2212,7 +2212,7 @@
                         mWmService.mAccessibilityController;
                 final int winTransit = TRANSIT_EXIT;
                 mWinAnimator.applyAnimationLocked(winTransit, false /* isEntrance */);
-                if (accessibilityController != null) {
+                if (accessibilityController.hasCallbacks()) {
                     accessibilityController.onWindowTransition(this, winTransit);
                 }
             }
@@ -2233,7 +2233,7 @@
         }
         if (isVisibleNow() && animateExit) {
             mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
-            if (mWmService.mAccessibilityController != null) {
+            if (mWmService.mAccessibilityController.hasCallbacks()) {
                 mWmService.mAccessibilityController.onWindowTransition(this, TRANSIT_EXIT);
             }
             changed = true;
@@ -2283,7 +2283,7 @@
             startMoveAnimation(left, top);
         }
 
-        if (mWmService.mAccessibilityController != null) {
+        if (mWmService.mAccessibilityController.hasCallbacks()) {
             mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(getDisplayId());
         }
         updateLocationInParentDisplayIfNeeded();
@@ -2569,7 +2569,7 @@
                         setDisplayLayoutNeeded();
                         mWmService.requestTraversal();
                     }
-                    if (mWmService.mAccessibilityController != null) {
+                    if (mWmService.mAccessibilityController.hasCallbacks()) {
                         mWmService.mAccessibilityController.onWindowTransition(this, transit);
                     }
                 }
@@ -3589,7 +3589,7 @@
         if (mAttrs.type >= FIRST_SYSTEM_WINDOW && mAttrs.type != TYPE_TOAST) {
             mWmService.mAtmService.mActiveUids.onNonAppSurfaceVisibilityChanged(mOwnerUid, shown);
         }
-        if (mIsImWindow && mWmService.mAccessibilityController != null) {
+        if (mIsImWindow && mWmService.mAccessibilityController.hasCallbacks()) {
             mWmService.mAccessibilityController.onImeSurfaceShownChanged(this, shown);
         }
     }
@@ -3933,7 +3933,7 @@
                         "Requested redraw for orientation change: %s", this);
             }
 
-            if (mWmService.mAccessibilityController != null) {
+            if (mWmService.mAccessibilityController.hasCallbacks()) {
                 mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(displayId);
             }
             updateLocationInParentDisplayIfNeeded();
@@ -5059,7 +5059,7 @@
         if (isAnimating()) {
             return;
         }
-        if (mWmService.mAccessibilityController != null) {
+        if (mWmService.mAccessibilityController.hasCallbacks()) {
             mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(getDisplayId());
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index f25706a..81f06d9 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -682,7 +682,7 @@
             applyAnimationLocked(transit, true);
         }
 
-        if (mService.mAccessibilityController != null) {
+        if (mService.mAccessibilityController.hasCallbacks()) {
             mService.mAccessibilityController.onWindowTransition(mWin, transit);
         }
     }
diff --git a/services/core/lint-baseline.xml b/services/core/lint-baseline.xml
new file mode 100644
index 0000000..c5b0549
--- /dev/null
+++ b/services/core/lint-baseline.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 7.1.0-dev" type="baseline" client="" dependencies="true" name="" variant="all" version="7.1.0-dev">
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="            return Settings.Secure.getInt(context.getContentResolver(),"
+        errorLine2="                   ~~~~~~">
+        <location
+            file="frameworks/base/services/core/java/com/android/server/biometrics/BiometricService.java"
+            line="1106"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="            return Settings.Secure.getInt(context.getContentResolver(),"
+        errorLine2="                   ~~~~~~">
+        <location
+            file="frameworks/base/services/core/java/com/android/server/biometrics/BiometricService.java"
+            line="1111"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="            return Settings.Secure.getString(mContentResolver, mKey);"
+        errorLine2="                                   ~~~~~~~~~">
+        <location
+            file="frameworks/base/services/core/java/com/android/server/CertBlacklister.java"
+            line="73"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        }"
+        errorLine2="      ^">
+        <location
+            file="frameworks/base/services/core/java/com/android/server/clipboard/ClipboardService.java"
+            line="973"
+            column="7"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="            boolean accessibilityEnabled = Settings.Secure.getInt(cr,"
+        errorLine2="                                                           ~~~~~~">
+        <location
+            file="frameworks/base/services/core/java/com/android/server/DockObserver.java"
+            line="176"
+            column="60"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="            String mediaButtonReceiverInfo = Settings.Secure.getString(mContentResolver,"
+        errorLine2="                                             ~~~~~~~~~">
+        <location
+            file="frameworks/base/services/core/java/com/android/server/media/MediaSessionService.java"
+            line="928"
+            column="46"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="            final boolean isSecureFrpEnabled ="
+        errorLine2="                                   ~~~~~~">
+        <location
+            file="frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java"
+            line="1959"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="    private int getUnknownSourcesSettings() {"
+        errorLine2="                                      ~~~~~~">
+        <location
+            file="frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java"
+            line="16741"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="            String inputMethodComponent = Settings.Secure.getString(mContext.getContentResolver(),"
+        errorLine2="                                  ~~~~~~~~~">
+        <location
+            file="frameworks/base/services/core/java/com/android/server/SensorPrivacyService.java"
+            line="489"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="            return Settings.Secure.getString(getContentResolverAsUser(userId), key);"
+        errorLine2="           ~~~~~~~~~">
+        <location
+            file="frameworks/base/services/core/java/com/android/server/connectivity/Vpn.java"
+            line="1994"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="            return Settings.Secure.getInt(getContentResolverAsUser(userId), key, def);"
+        errorLine2="           ~~~~~~">
+        <location
+            file="frameworks/base/services/core/java/com/android/server/connectivity/Vpn.java"
+            line="2001"
+            column="12"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="                        if (Settings.Secure.getInt(mContext.getContentResolver(),"
+        errorLine2="                                            ~~~~~~">
+        <location
+            file="frameworks/base/services/core/java/com/android/server/notification/ZenModeHelper.java"
+            line="980"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="                &amp;&amp; Settings.Secure.getInt(mContext.getContentResolver(),"
+        errorLine2="                                   ~~~~~~">
+        <location
+            file="frameworks/base/services/core/java/com/android/server/notification/ZenModeHelper.java"
+            line="1442"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="                &amp;&amp; Settings.Secure.getInt(mContext.getContentResolver(),"
+        errorLine2="                                   ~~~~~~">
+        <location
+            file="frameworks/base/services/core/java/com/android/server/notification/ZenModeHelper.java"
+            line="1444"
+            column="36"/>
+    </issue>
+
+</issues>
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a9ddd35..5b205cd 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -16966,6 +16966,19 @@
     }
 
     @Override
+    public void clearOrganizationIdForUser(int userHandle) {
+        Preconditions.checkCallAuthorization(
+                hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
+
+        synchronized (getLockObject()) {
+            final ActiveAdmin owner = getDeviceOrProfileOwnerAdminLocked(userHandle);
+            owner.mOrganizationId = null;
+            owner.mEnrollmentSpecificId = null;
+            saveSettingsLocked(userHandle);
+        }
+    }
+
+    @Override
     public UserHandle createAndProvisionManagedProfile(
             @NonNull ManagedProfileProvisioningParams provisioningParams,
             @NonNull String callerPackage) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index fe3a77e..aa5b209 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -302,6 +302,8 @@
             "com.android.clockwork.power.WearPowerService";
     private static final String WEAR_SIDEKICK_SERVICE_CLASS =
             "com.google.android.clockwork.sidekick.SidekickService";
+    private static final String WEAR_DISPLAYOFFLOAD_SERVICE_CLASS =
+            "com.google.android.clockwork.displayoffload.DisplayOffloadService";
     private static final String WEAR_DISPLAY_SERVICE_CLASS =
             "com.google.android.clockwork.display.WearDisplayService";
     private static final String WEAR_LEFTY_SERVICE_CLASS =
@@ -1119,6 +1121,13 @@
         mSystemServiceManager.startService(LightsService.class);
         t.traceEnd();
 
+        t.traceBegin("StartDisplayOffloadService");
+        // Package manager isn't started yet; need to use SysProp not hardware feature
+        if (SystemProperties.getBoolean("config.enable_display_offload", false)) {
+            mSystemServiceManager.startService(WEAR_DISPLAYOFFLOAD_SERVICE_CLASS);
+        }
+        t.traceEnd();
+
         t.traceBegin("StartSidekickService");
         // Package manager isn't started yet; need to use SysProp not hardware feature
         if (SystemProperties.getBoolean("config.enable_sidekick_graphics", false)) {
@@ -2078,14 +2087,11 @@
             mSystemServiceManager.startService(DockObserver.class);
             t.traceEnd();
 
-            // TODO(b/191495635): re-enable thermal observer after fixing b/191375904.
-            /*
             if (isWatch) {
                 t.traceBegin("StartThermalObserver");
                 mSystemServiceManager.startService(THERMAL_OBSERVER_CLASS);
                 t.traceEnd();
             }
-            */
 
             t.traceBegin("StartWiredAccessoryManager");
             try {
@@ -2436,8 +2442,6 @@
             t.traceEnd();
         }
 
-        // TODO(b/191495635): Re-enable these services after fixing b/191375904.
-       /*
        if (isWatch) {
             // Must be started before services that depend it, e.g. WearConnectivityService
             t.traceBegin("StartWearPowerService");
@@ -2466,7 +2470,6 @@
             mSystemServiceManager.startService(WEAR_GLOBAL_ACTIONS_SERVICE_CLASS);
             t.traceEnd();
         }
-        */
 
         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_SLICES_DISABLED)) {
             t.traceBegin("StartSliceManagerService");
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index fd364ae7..51fa851 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -37,6 +37,8 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.content.pm.VersionedPackage;
 import android.os.Bundle;
 import android.os.RecoverySystem;
@@ -83,6 +85,8 @@
     private static final String CALLING_PACKAGE1 = "com.package.name1";
     private static final String CALLING_PACKAGE2 = "com.package.name2";
     private static final String CALLING_PACKAGE3 = "com.package.name3";
+    private static final String PERSISTENT_PACKAGE = "com.persistent.package";
+    private static final String NON_PERSISTENT_PACKAGE = "com.nonpersistent.package";
     private static final String NAMESPACE1 = "namespace1";
     private static final String NAMESPACE2 = "namespace2";
     private static final String NAMESPACE3 = "namespace3";
@@ -103,6 +107,8 @@
     private PackageWatchdog mMockPackageWatchdog;
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private ContentResolver mMockContentResolver;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private PackageManager mPackageManager;
 
     @Captor
     private ArgumentCaptor<RemoteCallback> mMonitorCallbackCaptor;
@@ -129,6 +135,17 @@
         mNamespacesWiped = new HashSet<>();
 
         when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
+        when(mMockContext.getPackageManager()).thenReturn(mPackageManager);
+        ApplicationInfo persistentApplicationInfo = new ApplicationInfo();
+        persistentApplicationInfo.flags |=
+                ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_PERSISTENT;
+
+        // If the package name is PERSISTENT_PACKAGE, then set the flags to be persistent and
+        // system. Don't set any flags otherwise.
+        when(mPackageManager.getApplicationInfo(eq(PERSISTENT_PACKAGE),
+                anyInt())).thenReturn(persistentApplicationInfo);
+        when(mPackageManager.getApplicationInfo(eq(NON_PERSISTENT_PACKAGE),
+                anyInt())).thenReturn(new ApplicationInfo());
         // Reset observer instance to get new mock context on every run
         RescuePartyObserver.reset();
 
@@ -241,29 +258,53 @@
 
     @Test
     public void testPersistentAppCrashDetectionWithExecutionForAllRescueLevels() {
-        notePersistentAppCrash(1);
+        noteAppCrash(1, true);
 
         verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, /*resetNamespaces=*/ null,
                 /*configResetVerifiedTimesMap=*/ null);
 
-        notePersistentAppCrash(2);
+        noteAppCrash(2, true);
 
         verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_CHANGES, /*resetNamespaces=*/ null,
                 /*configResetVerifiedTimesMap=*/ null);
 
-        notePersistentAppCrash(3);
+        noteAppCrash(3, true);
 
         verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS, /*resetNamespaces=*/ null,
                 /*configResetVerifiedTimesMap=*/ null);
 
-        notePersistentAppCrash(4);
+        noteAppCrash(4, true);
         assertTrue(RescueParty.isRebootPropertySet());
 
-        notePersistentAppCrash(5);
+        noteAppCrash(5, true);
         assertTrue(RescueParty.isFactoryResetPropertySet());
     }
 
     @Test
+    public void testNonPersistentAppOnlyPerformsFlagResets() {
+        noteAppCrash(1, false);
+
+        verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, /*resetNamespaces=*/ null,
+                /*configResetVerifiedTimesMap=*/ null);
+
+        noteAppCrash(2, false);
+
+        verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_CHANGES, /*resetNamespaces=*/ null,
+                /*configResetVerifiedTimesMap=*/ null);
+
+        noteAppCrash(3, false);
+
+        verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS, /*resetNamespaces=*/ null,
+                /*configResetVerifiedTimesMap=*/ null);
+
+        noteAppCrash(4, false);
+        assertFalse(RescueParty.isRebootPropertySet());
+
+        noteAppCrash(5, false);
+        assertFalse(RescueParty.isFactoryResetPropertySet());
+    }
+
+    @Test
     public void testNonPersistentAppCrashDetectionWithScopedResets() {
         RescueParty.onSettingsProviderPublished(mMockContext);
         verify(() -> Settings.Config.registerMonitorCallback(eq(mMockContentResolver),
@@ -311,11 +352,11 @@
 
         observer.execute(new VersionedPackage(
                 CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 4);
-        assertTrue(RescueParty.isRebootPropertySet());
+        assertFalse(RescueParty.isRebootPropertySet());
 
         observer.execute(new VersionedPackage(
                 CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 5);
-        assertTrue(RescueParty.isFactoryResetPropertySet());
+        assertFalse(RescueParty.isFactoryResetPropertySet());
     }
 
     @Test
@@ -376,11 +417,11 @@
 
         observer.execute(new VersionedPackage(
                 CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 4);
-        assertTrue(RescueParty.isRebootPropertySet());
+        assertFalse(RescueParty.isRebootPropertySet());
 
         observer.execute(new VersionedPackage(
                 CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 5);
-        assertTrue(RescueParty.isFactoryResetPropertySet());
+        assertFalse(RescueParty.isFactoryResetPropertySet());
     }
 
     @Test
@@ -627,9 +668,10 @@
         RescuePartyObserver.getInstance(mMockContext).executeBootLoopMitigation(mitigationCount);
     }
 
-    private void notePersistentAppCrash(int mitigationCount) {
+    private void noteAppCrash(int mitigationCount, boolean isPersistent) {
+        String packageName = isPersistent ? PERSISTENT_PACKAGE : NON_PERSISTENT_PACKAGE;
         RescuePartyObserver.getInstance(mMockContext).execute(new VersionedPackage(
-                "com.package.name", 1), PackageWatchdog.FAILURE_REASON_APP_CRASH, mitigationCount);
+                packageName, 1), PackageWatchdog.FAILURE_REASON_APP_CRASH, mitigationCount);
     }
 
     private Bundle getConfigAccessBundle(String callingPackage, String namespace) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java
index d0c9242..609768c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java
@@ -57,6 +57,9 @@
 import java.time.ZoneOffset;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
@@ -67,6 +70,7 @@
  * Build/Install/Run:
  * atest FrameworksMockingServicesTests:CacheOomRankerTest
  */
+@SuppressWarnings("GuardedBy") // No tests are concurrent, so no need to test locking.
 @RunWith(MockitoJUnitRunner.class)
 public class CacheOomRankerTest {
     private static final Instant NOW = LocalDate.of(2021, 1, 1).atStartOfDay(
@@ -91,6 +95,7 @@
     private int mNextUid = 30000;
     private int mNextPackageUid = 40000;
     private int mNextPackageName = 1;
+    private Map<Integer, Long> mPidToRss;
 
     private TestExecutor mExecutor = new TestExecutor();
     private CacheOomRanker mCacheOomRanker;
@@ -116,7 +121,15 @@
         LocalServices.removeServiceForTest(PackageManagerInternal.class);
         LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt);
 
-        mCacheOomRanker = new CacheOomRanker(mAms);
+        mPidToRss = new HashMap<>();
+        mCacheOomRanker = new CacheOomRanker(
+                mAms,
+                pid -> {
+                    Long rss = mPidToRss.get(pid);
+                    assertThat(rss).isNotNull();
+                    return new long[]{rss};
+                }
+        );
         mCacheOomRanker.init(mExecutor);
     }
 
@@ -184,6 +197,8 @@
     public void reRankLruCachedApps_lruImpactsOrdering() throws InterruptedException {
         setConfig(/* numberToReRank= */ 5,
                 /* preserveTopNApps= */ 0,
+                /* useFrequentRss= */ true,
+                /* rssUpdateRateMs= */ 0,
                 /* usesWeight= */ 0.0f,
                 /* pssWeight= */ 0.0f,
                 /* lruWeight= */1.0f);
@@ -223,6 +238,8 @@
     public void reRankLruCachedApps_rssImpactsOrdering() throws InterruptedException {
         setConfig(/* numberToReRank= */ 6,
                 /* preserveTopNApps= */ 0,
+                /* useFrequentRss= */ true,
+                /* rssUpdateRateMs= */ 0,
                 /* usesWeight= */ 0.0f,
                 /* pssWeight= */ 1.0f,
                 /* lruWeight= */ 0.0f);
@@ -261,9 +278,128 @@
     }
 
     @Test
+    public void reRankLruCachedApps_rssImpactsOrdering_cachedRssValues()
+            throws InterruptedException {
+        setConfig(/* numberToReRank= */ 6,
+                /* preserveTopNApps= */ 0,
+                /* useFrequentRss= */ true,
+                /* rssUpdateRateMs= */ 10000000,
+                /* usesWeight= */ 0.0f,
+                /* pssWeight= */ 1.0f,
+                /* lruWeight= */ 0.0f);
+
+        ProcessList list = new ProcessList();
+        ArrayList<ProcessRecord> processList = list.getLruProcessesLSP();
+        ProcessRecord rss10k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
+                NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000);
+        processList.add(rss10k);
+        ProcessRecord rss20k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
+                NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000);
+        processList.add(rss20k);
+        ProcessRecord rss1k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
+                NOW.minus(60, ChronoUnit.MINUTES).toEpochMilli(), 1024L, 10000);
+        processList.add(rss1k);
+        ProcessRecord rss100k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
+                NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10);
+        processList.add(rss100k);
+        ProcessRecord rss2k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
+                NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20);
+        processList.add(rss2k);
+        ProcessRecord rss15k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
+                NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 20);
+        processList.add(rss15k);
+        // Only re-ranking 6 entries so this should stay in most recent position.
+        ProcessRecord rss16k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
+                NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 20);
+        processList.add(rss16k);
+        list.setLruProcessServiceStartLSP(processList.size());
+
+        mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
+        // First 6 ordered by largest pss, then last processes position unchanged.
+        assertThat(processList).containsExactly(rss100k, rss20k, rss15k, rss10k, rss2k, rss1k,
+                rss16k).inOrder();
+
+        // Clear mPidToRss so that Process.getRss calls fail.
+        mPidToRss.clear();
+        // Mix up the process list to ensure that CacheOomRanker actually re-ranks.
+        Collections.swap(processList, 0, 1);
+
+        mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
+        // Re ranking is the same.
+        assertThat(processList).containsExactly(rss100k, rss20k, rss15k, rss10k, rss2k, rss1k,
+                rss16k).inOrder();
+    }
+
+    @Test
+    public void reRankLruCachedApps_rssImpactsOrdering_profileRss()
+            throws InterruptedException {
+        setConfig(/* numberToReRank= */ 6,
+                /* preserveTopNApps= */ 0,
+                /* useFrequentRss= */ false,
+                /* rssUpdateRateMs= */ 10000000,
+                /* usesWeight= */ 0.0f,
+                /* pssWeight= */ 1.0f,
+                /* lruWeight= */ 0.0f);
+
+        ProcessList list = new ProcessList();
+        ArrayList<ProcessRecord> processList = list.getLruProcessesLSP();
+        ProcessRecord rss10k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
+                NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 0L, 1000);
+        rss10k.mProfile.setLastRss(10 * 1024L);
+        processList.add(rss10k);
+        ProcessRecord rss20k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
+                NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 0L, 2000);
+        rss20k.mProfile.setLastRss(20 * 1024L);
+        processList.add(rss20k);
+        ProcessRecord rss1k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
+                NOW.minus(60, ChronoUnit.MINUTES).toEpochMilli(), 0L, 10000);
+        rss1k.mProfile.setLastRss(1024L);
+        processList.add(rss1k);
+        ProcessRecord rss100k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
+                NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 0L, 10);
+        rss100k.mProfile.setLastRss(100 * 1024L);
+        processList.add(rss100k);
+        ProcessRecord rss2k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
+                NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 0L, 20);
+        rss2k.mProfile.setLastRss(2 * 1024L);
+        processList.add(rss2k);
+        ProcessRecord rss15k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
+                NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 20);
+        rss15k.mProfile.setLastRss(15 * 1024L);
+        processList.add(rss15k);
+        // Only re-ranking 6 entries so this should stay in most recent position.
+        ProcessRecord rss16k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
+                NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 20);
+        rss16k.mProfile.setLastRss(16 * 1024L);
+        processList.add(rss16k);
+        list.setLruProcessServiceStartLSP(processList.size());
+
+        // This should not be used, as RSS values are taken from mProfile.
+        mPidToRss.clear();
+
+        mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
+        // First 6 ordered by largest pss, then last processes position unchanged.
+        assertThat(processList).containsExactly(rss100k, rss20k, rss15k, rss10k, rss2k, rss1k,
+                rss16k).inOrder();
+
+        // Clear mPidToRss so that Process.getRss calls fail.
+        mPidToRss.clear();
+        // Mix up the process list to ensure that CacheOomRanker actually re-ranks.
+        Collections.swap(processList, 0, 1);
+
+        mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
+        // Re ranking is the same.
+        assertThat(processList).containsExactly(rss100k, rss20k, rss15k, rss10k, rss2k, rss1k,
+                rss16k).inOrder();
+    }
+
+
+    @Test
     public void reRankLruCachedApps_usesImpactsOrdering() throws InterruptedException {
         setConfig(/* numberToReRank= */ 4,
                 /* preserveTopNApps= */ 0,
+                /* useFrequentRss= */ true,
+                /* rssUpdateRateMs= */ 0,
                 /* usesWeight= */ 1.0f,
                 /* pssWeight= */ 0.0f,
                 /* lruWeight= */ 0.0f);
@@ -302,6 +438,8 @@
     public void reRankLruCachedApps_fewProcesses() throws InterruptedException {
         setConfig(/* numberToReRank= */ 4,
                 /* preserveTopNApps= */ 0,
+                /* useFrequentRss= */ true,
+                /* rssUpdateRateMs= */ 0,
                 /* usesWeight= */ 1.0f,
                 /* pssWeight= */ 0.0f,
                 /* lruWeight= */ 0.0f);
@@ -339,6 +477,8 @@
     public void reRankLruCachedApps_fewNonServiceProcesses() throws InterruptedException {
         setConfig(/* numberToReRank= */ 4,
                 /* preserveTopNApps= */ 0,
+                /* useFrequentRss= */ true,
+                /* rssUpdateRateMs= */ 0,
                 /* usesWeight= */ 1.0f,
                 /* pssWeight= */ 0.0f,
                 /* lruWeight= */ 0.0f);
@@ -376,6 +516,8 @@
     public void reRankLruCachedApps_manyProcessesThenFew() throws InterruptedException {
         setConfig(/* numberToReRank= */ 6,
                 /* preserveTopNApps= */ 0,
+                /* useFrequentRss= */ true,
+                /* rssUpdateRateMs= */ 0,
                 /* usesWeight= */ 1.0f,
                 /* pssWeight= */ 0.0f,
                 /* lruWeight= */ 0.0f);
@@ -439,6 +581,8 @@
     public void reRankLruCachedApps_preservesTopNApps() throws InterruptedException {
         setConfig(/* numberToReRank= */ 6,
                 /* preserveTopNApps= */ 3,
+                /* useFrequentRss= */ true,
+                /* rssUpdateRateMs= */ 0,
                 /* usesWeight= */ 1.0f,
                 /* pssWeight= */ 0.0f,
                 /* lruWeight= */ 0.0f);
@@ -478,6 +622,8 @@
             throws InterruptedException {
         setConfig(/* numberToReRank= */ 6,
                 /* preserveTopNApps= */ 100,
+                /* useFrequentRss= */ true,
+                /* rssUpdateRateMs= */ 0,
                 /* usesWeight= */ 1.0f,
                 /* pssWeight= */ 0.0f,
                 /* lruWeight= */ 0.0f);
@@ -516,6 +662,8 @@
             throws InterruptedException {
         setConfig(/* numberToReRank= */ 6,
                 /* preserveTopNApps= */ -100,
+                /* useFrequentRss= */ true,
+                /* rssUpdateRateMs= */ 0,
                 /* usesWeight= */ 1.0f,
                 /* pssWeight= */ 0.0f,
                 /* lruWeight= */ 0.0f);
@@ -550,8 +698,8 @@
                 used200).inOrder();
     }
 
-    private void setConfig(int numberToReRank, int preserveTopNApps, float usesWeight,
-            float pssWeight, float lruWeight)
+    private void setConfig(int numberToReRank, int preserveTopNApps, boolean useFrequentRss,
+            long rssUpdateRateMs, float usesWeight, float pssWeight, float lruWeight)
             throws InterruptedException {
         mExecutor.init(4);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -563,6 +711,14 @@
                 Integer.toString(preserveTopNApps),
                 false);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                CacheOomRanker.KEY_OOM_RE_RANKING_USE_FREQUENT_RSS,
+                Boolean.toString(useFrequentRss),
+                false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                CacheOomRanker.KEY_OOM_RE_RANKING_RSS_UPDATE_RATE_MS,
+                Long.toString(rssUpdateRateMs),
+                false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 CacheOomRanker.KEY_OOM_RE_RANKING_LRU_WEIGHT,
                 Float.toString(lruWeight),
                 false);
@@ -576,6 +732,8 @@
                 false);
         mExecutor.waitForLatch();
         assertThat(mCacheOomRanker.getNumberToReRank()).isEqualTo(numberToReRank);
+        assertThat(mCacheOomRanker.mUseFrequentRss).isEqualTo(useFrequentRss);
+        assertThat(mCacheOomRanker.mRssUpdateRateMs).isEqualTo(rssUpdateRateMs);
         assertThat(mCacheOomRanker.mRssWeight).isEqualTo(pssWeight);
         assertThat(mCacheOomRanker.mUsesWeight).isEqualTo(usesWeight);
         assertThat(mCacheOomRanker.mLruWeight).isEqualTo(lruWeight);
@@ -592,7 +750,7 @@
         app.mState.setSetProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
         app.mState.setCurAdj(setAdj);
         app.setLastActivityTime(lastActivityTime);
-        app.mProfile.setLastRss(lastRss);
+        mPidToRss.put(app.getPid(), lastRss);
         app.mState.setCached(false);
         for (int i = 0; i < wentToForegroundCount; ++i) {
             app.mState.setSetProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 34856e2..b5ad459 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -142,6 +142,12 @@
                 .thenReturn(mockArray);
         when(mMockedResources.obtainTypedArray(R.array.config_waterfallCutoutArray))
                 .thenReturn(mockArray);
+        when(mMockedResources.obtainTypedArray(R.array.config_roundedCornerRadiusArray))
+                .thenReturn(mockArray);
+        when(mMockedResources.obtainTypedArray(R.array.config_roundedCornerTopRadiusArray))
+                .thenReturn(mockArray);
+        when(mMockedResources.obtainTypedArray(R.array.config_roundedCornerBottomRadiusArray))
+                .thenReturn(mockArray);
     }
 
     @After
@@ -330,6 +336,62 @@
     }
 
     @Test
+    public void testAfterDisplayChange_DefaultDisplayModeIsUpdated() throws Exception {
+        SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(0, 1920, 1080, 60f);
+        SurfaceControl.DisplayMode[] modes =
+                new SurfaceControl.DisplayMode[]{displayMode};
+        FakeDisplay display = new FakeDisplay(PORT_A, modes, 0);
+        setUpDisplay(display);
+        updateAvailableDisplays();
+        mAdapter.registerLocked();
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+
+        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
+        assertThat(mListener.changedDisplays).isEmpty();
+
+        DisplayDeviceInfo displayDeviceInfo = mListener.addedDisplays.get(
+                0).getDisplayDeviceInfoLocked();
+
+        assertThat(displayDeviceInfo.supportedModes.length).isEqualTo(modes.length);
+        assertModeIsSupported(displayDeviceInfo.supportedModes, displayMode);
+
+        Display.Mode defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
+        assertThat(matches(defaultMode, displayMode)).isTrue();
+
+        // Set the display mode to an unsupported mode
+        SurfaceControl.DisplayMode displayMode2 = createFakeDisplayMode(1, 1920, 1080, 120f);
+        mListener.addedDisplays.get(0).setUserPreferredDisplayModeLocked(
+                new Display.Mode(displayMode2.width, displayMode2.height,
+                        displayMode2.refreshRate));
+        updateAvailableDisplays();
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+        defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
+        assertThat(matches(defaultMode, displayMode2)).isFalse();
+
+        // Change the display
+        modes = new SurfaceControl.DisplayMode[]{displayMode, displayMode2};
+        display.dynamicInfo.supportedDisplayModes = modes;
+        setUpDisplay(display);
+        mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
+        waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+
+        assertTrue(mListener.traversalRequested);
+        assertThat(mListener.addedDisplays.size()).isEqualTo(1);
+        assertThat(mListener.changedDisplays.size()).isEqualTo(1);
+
+        DisplayDevice displayDevice = mListener.changedDisplays.get(0);
+        displayDevice.applyPendingDisplayDeviceInfoChangesLocked();
+        displayDeviceInfo = mListener.addedDisplays.get(0).getDisplayDeviceInfoLocked();
+
+        assertThat(displayDeviceInfo.supportedModes.length).isEqualTo(modes.length);
+        assertModeIsSupported(displayDeviceInfo.supportedModes, displayMode);
+        assertModeIsSupported(displayDeviceInfo.supportedModes, displayMode2);
+
+        defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
+        assertThat(matches(defaultMode, displayMode2)).isTrue();
+    }
+
+    @Test
     public void testAfterDisplayChange_DisplayModesAreUpdated() throws Exception {
         SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(0, 1920, 1080, 60f);
         SurfaceControl.DisplayMode[] modes =
@@ -350,12 +412,10 @@
         assertModeIsSupported(displayDeviceInfo.supportedModes, displayMode);
 
         Display.Mode defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
-        assertThat(defaultMode.matches(displayMode.width, displayMode.height,
-                displayMode.refreshRate)).isTrue();
+        assertThat(matches(defaultMode, displayMode)).isTrue();
 
         Display.Mode activeMode = getModeById(displayDeviceInfo, displayDeviceInfo.modeId);
-        assertThat(activeMode.matches(displayMode.width, displayMode.height,
-                displayMode.refreshRate)).isTrue();
+        assertThat(matches(activeMode, displayMode)).isTrue();
 
         // Change the display
         SurfaceControl.DisplayMode addedDisplayInfo = createFakeDisplayMode(1, 3840, 2160, 60f);
@@ -379,12 +439,10 @@
         assertModeIsSupported(displayDeviceInfo.supportedModes, addedDisplayInfo);
 
         activeMode = getModeById(displayDeviceInfo, displayDeviceInfo.modeId);
-        assertThat(activeMode.matches(addedDisplayInfo.width, addedDisplayInfo.height,
-                addedDisplayInfo.refreshRate)).isTrue();
+        assertThat(matches(activeMode, addedDisplayInfo)).isTrue();
 
         defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
-        assertThat(defaultMode.matches(addedDisplayInfo.width, addedDisplayInfo.height,
-                addedDisplayInfo.refreshRate)).isTrue();
+        assertThat(matches(defaultMode, addedDisplayInfo)).isTrue();
     }
 
     @Test
@@ -912,4 +970,9 @@
         });
         return mockArray;
     }
+
+    private boolean matches(Display.Mode a, SurfaceControl.DisplayMode b) {
+        return a.getPhysicalWidth() == b.width && a.getPhysicalHeight() == b.height
+                && Float.floatToIntBits(a.getRefreshRate()) == Float.floatToIntBits(b.refreshRate);
+    }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
index 53483f6..fe23c14 100644
--- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
@@ -18,13 +18,18 @@
 
 import static android.app.WallpaperManager.COMMAND_REAPPLY;
 import static android.app.WallpaperManager.FLAG_SYSTEM;
+import static android.os.FileObserver.CLOSE_WRITE;
+import static android.os.UserHandle.USER_SYSTEM;
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
 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.spyOn;
+import static com.android.server.wallpaper.WallpaperManagerService.WALLPAPER;
+import static com.android.server.wallpaper.WallpaperManagerService.WALLPAPER_CROP;
 
 import static org.hamcrest.core.IsNot.not;
 import static org.junit.Assert.assertEquals;
@@ -34,6 +39,7 @@
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeThat;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.reset;
@@ -41,6 +47,7 @@
 
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.WallpaperColors;
 import android.app.WallpaperManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -49,8 +56,10 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ServiceInfo;
+import android.graphics.Color;
 import android.hardware.display.DisplayManager;
-import android.os.UserHandle;
+import android.os.RemoteException;
+import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
 import android.service.wallpaper.IWallpaperConnection;
 import android.service.wallpaper.IWallpaperEngine;
@@ -242,13 +251,13 @@
      */
     @Test
     public void testDataCorrectAfterBoot() {
-        mService.switchUser(UserHandle.USER_SYSTEM, null);
+        mService.switchUser(USER_SYSTEM, null);
 
         final WallpaperData fallbackData = mService.mFallbackWallpaper;
         assertEquals("Fallback wallpaper component should be ImageWallpaper.",
                 sImageWallpaperComponentName, fallbackData.wallpaperComponent);
 
-        verifyLastWallpaperData(UserHandle.USER_SYSTEM, sDefaultWallpaperComponent);
+        verifyLastWallpaperData(USER_SYSTEM, sDefaultWallpaperComponent);
         verifyDisplayData();
     }
 
@@ -261,7 +270,7 @@
         assumeThat(sDefaultWallpaperComponent,
                 not(CoreMatchers.equalTo(sImageWallpaperComponentName)));
 
-        final int testUserId = UserHandle.USER_SYSTEM;
+        final int testUserId = USER_SYSTEM;
         mService.switchUser(testUserId, null);
         verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent);
         verifyCurrentSystemData(testUserId);
@@ -281,7 +290,7 @@
      */
     @Test
     public void testSetCurrentComponent() throws Exception {
-        final int testUserId = UserHandle.USER_SYSTEM;
+        final int testUserId = USER_SYSTEM;
         mService.switchUser(testUserId, null);
         verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent);
         verifyCurrentSystemData(testUserId);
@@ -387,6 +396,42 @@
         assertEquals(systemWallpaperData.primaryColors, shouldMatchSystem.primaryColors);
     }
 
+    @Test
+    public void testWallpaperManagerCallbackInRightOrder() throws RemoteException {
+        WallpaperData wallpaper = new WallpaperData(
+                USER_SYSTEM, mService.getWallpaperDir(USER_SYSTEM), WALLPAPER, WALLPAPER_CROP);
+        wallpaper.primaryColors = new WallpaperColors(Color.valueOf(Color.RED),
+                Color.valueOf(Color.BLUE), null);
+
+        spyOn(wallpaper);
+        doReturn(wallpaper).when(mService).getWallpaperSafeLocked(wallpaper.userId, FLAG_SYSTEM);
+        doNothing().when(mService).switchWallpaper(any(), any());
+        doReturn(true).when(mService)
+                .bindWallpaperComponentLocked(any(), anyBoolean(), anyBoolean(), any(), any());
+        doNothing().when(mService).saveSettingsLocked(wallpaper.userId);
+        doNothing().when(mService).generateCrop(wallpaper);
+
+        // timestamps of {ACTION_WALLPAPER_CHANGED, onWallpaperColorsChanged}
+        final long[] timestamps = new long[2];
+        doAnswer(invocation -> timestamps[0] = SystemClock.elapsedRealtime())
+                .when(sContext).sendBroadcastAsUser(any(), any());
+        doAnswer(invocation -> timestamps[1] = SystemClock.elapsedRealtime())
+                .when(mService).notifyWallpaperColorsChanged(wallpaper, FLAG_SYSTEM);
+
+        assertNull(wallpaper.wallpaperObserver);
+        mService.switchUser(wallpaper.userId, null);
+        assertNotNull(wallpaper.wallpaperObserver);
+        // We will call onEvent directly, so stop watching the file.
+        wallpaper.wallpaperObserver.stopWatching();
+
+        spyOn(wallpaper.wallpaperObserver);
+        doReturn(wallpaper).when(wallpaper.wallpaperObserver).dataForEvent(true, false);
+        wallpaper.wallpaperObserver.onEvent(CLOSE_WRITE, WALLPAPER);
+
+        // ACTION_WALLPAPER_CHANGED should be invoked before onWallpaperColorsChanged.
+        assertTrue(timestamps[1] > timestamps[0]);
+    }
+
     // Verify that after continue switch user from userId 0 to lastUserId, the wallpaper data for
     // non-current user must not bind to wallpaper service.
     private void verifyNoConnectionBeforeLastUser(int lastUserId) {
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 11e1230..ef9248a 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -86,7 +86,6 @@
 
     // These are not normally accessible from apps so they must be explicitly included.
     jni_libs: [
-        "libbacktrace",
         "libbase",
         "libbinder",
         "libc++",
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
index e612d12..086e3c0 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
@@ -53,6 +53,7 @@
 import static org.junit.Assert.assertThat;
 import static org.junit.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.eq;
@@ -92,7 +93,7 @@
 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
 
 import com.android.server.accessibility.AccessibilityWindowManager.RemoteAccessibilityConnection;
-import com.android.server.accessibility.magnification.FullScreenMagnificationController;
+import com.android.server.accessibility.magnification.MagnificationProcessor;
 import com.android.server.accessibility.test.MessageCapturingHandler;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -170,7 +171,7 @@
     @Mock private IAccessibilityInteractionConnection mMockIA11yInteractionConnection;
     @Mock private IAccessibilityInteractionConnectionCallback mMockCallback;
     @Mock private FingerprintGestureDispatcher mMockFingerprintGestureDispatcher;
-    @Mock private FullScreenMagnificationController mMockFullScreenMagnificationController;
+    @Mock private MagnificationProcessor mMockMagnificationProcessor;
     @Mock private RemoteCallback.OnResultListener mMockListener;
 
     @Before
@@ -181,8 +182,8 @@
         when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mMockKeyEventDispatcher);
         when(mMockSystemSupport.getFingerprintGestureDispatcher())
                 .thenReturn(mMockFingerprintGestureDispatcher);
-        when(mMockSystemSupport.getFullScreenMagnificationController())
-                .thenReturn(mMockFullScreenMagnificationController);
+        when(mMockSystemSupport.getMagnificationProcessor())
+                .thenReturn(mMockMagnificationProcessor);
 
         PowerManager powerManager =
                 new PowerManager(mMockContext, mMockIPowerManager, mMockIThermalService, mHandler);
@@ -558,7 +559,7 @@
     public void getMagnificationScale() {
         final int displayId = 1;
         final float scale = 2.0f;
-        when(mMockFullScreenMagnificationController.getScale(displayId)).thenReturn(scale);
+        when(mMockMagnificationProcessor.getScale(displayId)).thenReturn(scale);
 
         final float result = mServiceConnection.getMagnificationScale(displayId);
         assertThat(result, is(scale));
@@ -568,7 +569,7 @@
     public void getMagnificationScale_serviceNotBelongCurrentUser_returnNoScale() {
         final int displayId = 1;
         final float scale = 2.0f;
-        when(mMockFullScreenMagnificationController.getScale(displayId)).thenReturn(scale);
+        when(mMockMagnificationProcessor.getScale(displayId)).thenReturn(scale);
         when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
 
         final float result = mServiceConnection.getMagnificationScale(displayId);
@@ -576,31 +577,14 @@
     }
 
     @Test
-    public void getMagnificationRegion_notRegistered_shouldRegisterThenUnregister() {
-        final int displayId = 1;
-        final Region region = new Region(10, 20, 100, 200);
-        doAnswer((invocation) -> {
-            ((Region) invocation.getArguments()[1]).set(region);
-            return null;
-        }).when(mMockFullScreenMagnificationController).getMagnificationRegion(eq(displayId),
-                any());
-        when(mMockFullScreenMagnificationController.isRegistered(displayId)).thenReturn(false);
-
-        final Region result = mServiceConnection.getMagnificationRegion(displayId);
-        assertThat(result, is(region));
-        verify(mMockFullScreenMagnificationController).register(displayId);
-        verify(mMockFullScreenMagnificationController).unregister(displayId);
-    }
-
-    @Test
     public void getMagnificationRegion_serviceNotBelongCurrentUser_returnEmptyRegion() {
         final int displayId = 1;
         final Region region = new Region(10, 20, 100, 200);
         doAnswer((invocation) -> {
             ((Region) invocation.getArguments()[1]).set(region);
             return null;
-        }).when(mMockFullScreenMagnificationController).getMagnificationRegion(eq(displayId),
-                any());
+        }).when(mMockMagnificationProcessor).getMagnificationRegion(eq(displayId),
+                any(), anyBoolean());
         when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
 
         final Region result = mServiceConnection.getMagnificationRegion(displayId);
@@ -608,23 +592,11 @@
     }
 
     @Test
-    public void getMagnificationCenterX_notRegistered_shouldRegisterThenUnregister() {
-        final int displayId = 1;
-        final float centerX = 480.0f;
-        when(mMockFullScreenMagnificationController.getCenterX(displayId)).thenReturn(centerX);
-        when(mMockFullScreenMagnificationController.isRegistered(displayId)).thenReturn(false);
-
-        final float result = mServiceConnection.getMagnificationCenterX(displayId);
-        assertThat(result, is(centerX));
-        verify(mMockFullScreenMagnificationController).register(displayId);
-        verify(mMockFullScreenMagnificationController).unregister(displayId);
-    }
-
-    @Test
     public void getMagnificationCenterX_serviceNotBelongCurrentUser_returnZero() {
         final int displayId = 1;
         final float centerX = 480.0f;
-        when(mMockFullScreenMagnificationController.getCenterX(displayId)).thenReturn(centerX);
+        when(mMockMagnificationProcessor.getCenterX(displayId, /* canControlMagnification= */
+                true)).thenReturn(centerX);
         when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
 
         final float result = mServiceConnection.getMagnificationCenterX(displayId);
@@ -632,23 +604,11 @@
     }
 
     @Test
-    public void getMagnificationCenterY_notRegistered_shouldRegisterThenUnregister() {
-        final int displayId = 1;
-        final float centerY = 640.0f;
-        when(mMockFullScreenMagnificationController.getCenterY(displayId)).thenReturn(centerY);
-        when(mMockFullScreenMagnificationController.isRegistered(displayId)).thenReturn(false);
-
-        final float result = mServiceConnection.getMagnificationCenterY(displayId);
-        assertThat(result, is(centerY));
-        verify(mMockFullScreenMagnificationController).register(displayId);
-        verify(mMockFullScreenMagnificationController).unregister(displayId);
-    }
-
-    @Test
     public void getMagnificationCenterY_serviceNotBelongCurrentUser_returnZero() {
         final int displayId = 1;
         final float centerY = 640.0f;
-        when(mMockFullScreenMagnificationController.getCenterY(displayId)).thenReturn(centerY);
+        when(mMockMagnificationProcessor.getCenterY(displayId, /* canControlMagnification= */
+                true)).thenReturn(centerY);
         when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
 
         final float result = mServiceConnection.getMagnificationCenterY(displayId);
@@ -658,7 +618,7 @@
     @Test
     public void resetMagnification() {
         final int displayId = 1;
-        when(mMockFullScreenMagnificationController.reset(displayId, true)).thenReturn(true);
+        when(mMockMagnificationProcessor.reset(displayId, true)).thenReturn(true);
 
         final boolean result = mServiceConnection.resetMagnification(displayId, true);
         assertThat(result, is(true));
@@ -667,7 +627,7 @@
     @Test
     public void resetMagnification_cantControlMagnification_returnFalse() {
         final int displayId = 1;
-        when(mMockFullScreenMagnificationController.reset(displayId, true)).thenReturn(true);
+        when(mMockMagnificationProcessor.reset(displayId, true)).thenReturn(true);
         when(mMockSecurityPolicy.canControlMagnification(mServiceConnection)).thenReturn(false);
 
         final boolean result = mServiceConnection.resetMagnification(displayId, true);
@@ -677,7 +637,7 @@
     @Test
     public void resetMagnification_serviceNotBelongCurrentUser_returnFalse() {
         final int displayId = 1;
-        when(mMockFullScreenMagnificationController.reset(displayId, true)).thenReturn(true);
+        when(mMockMagnificationProcessor.reset(displayId, true)).thenReturn(true);
         when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
 
         final boolean result = mServiceConnection.resetMagnification(displayId, true);
@@ -685,28 +645,12 @@
     }
 
     @Test
-    public void setMagnificationScaleAndCenter_notRegistered_shouldRegister() {
-        final int displayId = 1;
-        final float scale = 1.8f;
-        final float centerX = 50.5f;
-        final float centerY = 100.5f;
-        when(mMockFullScreenMagnificationController.setScaleAndCenter(displayId,
-                scale, centerX, centerY, true, SERVICE_ID)).thenReturn(true);
-        when(mMockFullScreenMagnificationController.isRegistered(displayId)).thenReturn(false);
-
-        final boolean result = mServiceConnection.setMagnificationScaleAndCenter(
-                displayId, scale, centerX, centerY, true);
-        assertThat(result, is(true));
-        verify(mMockFullScreenMagnificationController).register(displayId);
-    }
-
-    @Test
     public void setMagnificationScaleAndCenter_cantControlMagnification_returnFalse() {
         final int displayId = 1;
         final float scale = 1.8f;
         final float centerX = 50.5f;
         final float centerY = 100.5f;
-        when(mMockFullScreenMagnificationController.setScaleAndCenter(displayId,
+        when(mMockMagnificationProcessor.setScaleAndCenter(displayId,
                 scale, centerX, centerY, true, SERVICE_ID)).thenReturn(true);
         when(mMockSecurityPolicy.canControlMagnification(mServiceConnection)).thenReturn(false);
 
@@ -721,7 +665,7 @@
         final float scale = 1.8f;
         final float centerX = 50.5f;
         final float centerY = 100.5f;
-        when(mMockFullScreenMagnificationController.setScaleAndCenter(displayId,
+        when(mMockMagnificationProcessor.setScaleAndCenter(displayId,
                 scale, centerX, centerY, true, SERVICE_ID)).thenReturn(true);
         when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
 
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterTest.java
index 554f0a4..464fee2 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterTest.java
@@ -53,9 +53,9 @@
 
 import com.android.server.LocalServices;
 import com.android.server.accessibility.gestures.TouchExplorer;
-import com.android.server.accessibility.magnification.FullScreenMagnificationController;
 import com.android.server.accessibility.magnification.FullScreenMagnificationGestureHandler;
 import com.android.server.accessibility.magnification.MagnificationGestureHandler;
+import com.android.server.accessibility.magnification.MagnificationProcessor;
 import com.android.server.accessibility.magnification.WindowMagnificationGestureHandler;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -96,7 +96,7 @@
 
     @Mock private WindowManagerInternal.AccessibilityControllerInternal mMockA11yController;
     @Mock private WindowManagerInternal mMockWindowManagerService;
-    @Mock private FullScreenMagnificationController mMockFullScreenMagnificationController;
+    @Mock private MagnificationProcessor mMockMagnificationProcessor;
     private AccessibilityManagerService mAms;
     private AccessibilityInputFilter mA11yInputFilter;
     private EventCaptor mCaptor1;
@@ -152,8 +152,7 @@
         mA11yInputFilter.onInstalled();
 
         doReturn(mDisplayList).when(mAms).getValidDisplayList();
-        doReturn(mMockFullScreenMagnificationController).when(mAms)
-                .getFullScreenMagnificationController();
+        doReturn(mMockMagnificationProcessor).when(mAms).getMagnificationProcessor();
     }
 
     @After
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
index 432a500..e93e544 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
@@ -45,7 +45,7 @@
 import android.testing.DexmakerShareClassLoaderRule;
 import android.view.Display;
 
-import com.android.server.accessibility.magnification.FullScreenMagnificationController;
+import com.android.server.accessibility.magnification.MagnificationProcessor;
 import com.android.server.accessibility.test.MessageCapturingHandler;
 import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
@@ -91,7 +91,7 @@
     @Mock SystemActionPerformer mMockSystemActionPerformer;
     @Mock KeyEventDispatcher mMockKeyEventDispatcher;
     @Mock
-    FullScreenMagnificationController mMockFullScreenMagnificationController;
+    MagnificationProcessor mMockMagnificationProcessor;
     @Mock IBinder mMockIBinder;
     @Mock IAccessibilityServiceClient mMockServiceClient;
     @Mock MotionEventInjector mMockMotionEventInjector;
@@ -102,8 +102,8 @@
     public void setup() {
         MockitoAnnotations.initMocks(this);
         when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mMockKeyEventDispatcher);
-        when(mMockSystemSupport.getFullScreenMagnificationController())
-                .thenReturn(mMockFullScreenMagnificationController);
+        when(mMockSystemSupport.getMagnificationProcessor())
+                .thenReturn(mMockMagnificationProcessor);
         when(mMockSystemSupport.getMotionEventInjectorForDisplayLocked(
                 Display.DEFAULT_DISPLAY)).thenReturn(mMockMotionEventInjector);
 
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
new file mode 100644
index 0000000..c412b94
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.graphics.Region;
+
+import com.android.server.accessibility.magnification.FullScreenMagnificationController;
+import com.android.server.accessibility.magnification.MagnificationController;
+import com.android.server.accessibility.magnification.MagnificationProcessor;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+
+/**
+ * Tests for the {@link MagnificationProcessor}
+ */
+public class MagnificationProcessorTest {
+
+    private static final int TEST_DISPLAY = 0;
+
+    private MagnificationProcessor mMagnificationProcessor;
+    @Mock
+    private MagnificationController mMockMagnificationController;
+    @Mock
+    private FullScreenMagnificationController mMockFullScreenMagnificationController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mMockMagnificationController.getFullScreenMagnificationController()).thenReturn(
+                mMockFullScreenMagnificationController);
+        mMagnificationProcessor = new MagnificationProcessor(mMockMagnificationController);
+    }
+
+    @Test
+    public void getScale() {
+        final float result = 2;
+        when(mMockFullScreenMagnificationController.getScale(TEST_DISPLAY)).thenReturn(result);
+
+        float scale = mMagnificationProcessor.getScale(TEST_DISPLAY);
+
+        assertEquals(scale, result, 0);
+    }
+
+    @Test
+    public void getCenterX_canControlMagnification_returnCenterX() {
+        final float result = 200;
+        when(mMockFullScreenMagnificationController.getCenterX(TEST_DISPLAY)).thenReturn(result);
+
+        float centerX = mMagnificationProcessor.getCenterX(
+                TEST_DISPLAY,  /* canControlMagnification= */true);
+
+        assertEquals(centerX, result, 0);
+    }
+
+    @Test
+    public void getCenterY_canControlMagnification_returnCenterY() {
+        final float result = 300;
+        when(mMockFullScreenMagnificationController.getCenterY(TEST_DISPLAY)).thenReturn(result);
+
+        float centerY = mMagnificationProcessor.getCenterY(
+                TEST_DISPLAY,  /* canControlMagnification= */false);
+
+        assertEquals(centerY, result, 0);
+    }
+
+    @Test
+    public void getMagnificationRegion_canControlMagnification_returnRegion() {
+        final Region region = new Region(10, 20, 100, 200);
+        mMagnificationProcessor.getMagnificationRegion(TEST_DISPLAY,
+                region,  /* canControlMagnification= */true);
+
+        verify(mMockFullScreenMagnificationController).getMagnificationRegion(eq(TEST_DISPLAY),
+                eq(region));
+    }
+
+    @Test
+    public void getMagnificationRegion_notRegistered_shouldRegisterThenUnregister() {
+        final Region region = new Region(10, 20, 100, 200);
+        doAnswer((invocation) -> {
+            ((Region) invocation.getArguments()[1]).set(region);
+            return null;
+        }).when(mMockFullScreenMagnificationController).getMagnificationRegion(eq(TEST_DISPLAY),
+                any());
+        when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
+
+        final Region result = new Region();
+        mMagnificationProcessor.getMagnificationRegion(TEST_DISPLAY,
+                result, /* canControlMagnification= */true);
+        assertEquals(region, result);
+        verify(mMockFullScreenMagnificationController).register(TEST_DISPLAY);
+        verify(mMockFullScreenMagnificationController).unregister(TEST_DISPLAY);
+    }
+
+    @Test
+    public void getMagnificationCenterX_notRegistered_shouldRegisterThenUnregister() {
+        final float centerX = 480.0f;
+        when(mMockFullScreenMagnificationController.getCenterX(TEST_DISPLAY)).thenReturn(centerX);
+        when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
+
+        final float result = mMagnificationProcessor.getCenterX(
+                TEST_DISPLAY,  /* canControlMagnification= */ true);
+        assertEquals(centerX, result, 0);
+        verify(mMockFullScreenMagnificationController).register(TEST_DISPLAY);
+        verify(mMockFullScreenMagnificationController).unregister(TEST_DISPLAY);
+    }
+
+    @Test
+    public void getMagnificationCenterY_notRegistered_shouldRegisterThenUnregister() {
+        final float centerY = 640.0f;
+        when(mMockFullScreenMagnificationController.getCenterY(TEST_DISPLAY)).thenReturn(centerY);
+        when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
+
+        final float result = mMagnificationProcessor.getCenterY(
+                TEST_DISPLAY,  /* canControlMagnification= */ true);
+        assertEquals(centerY, result, 0);
+        verify(mMockFullScreenMagnificationController).register(TEST_DISPLAY);
+        verify(mMockFullScreenMagnificationController).unregister(TEST_DISPLAY);
+    }
+
+    @Test
+    public void setMagnificationScaleAndCenter_notRegistered_shouldRegister() {
+        final int serviceId = 42;
+        final float scale = 1.8f;
+        final float centerX = 50.5f;
+        final float centerY = 100.5f;
+        when(mMockFullScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY,
+                scale, centerX, centerY, true, serviceId)).thenReturn(true);
+        when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
+
+        final boolean result = mMagnificationProcessor.setScaleAndCenter(
+                TEST_DISPLAY, scale, centerX, centerY, true, serviceId);
+        assertTrue(result);
+        verify(mMockFullScreenMagnificationController).register(TEST_DISPLAY);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/CompositeCallbackTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CompositeCallbackTest.java
new file mode 100644
index 0000000..09b5c5c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CompositeCallbackTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+@Presubmit
+@SmallTest
+public class CompositeCallbackTest {
+
+    @Test
+    public void testNullCallback() {
+        BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class);
+        BaseClientMonitor.Callback callback2 = mock(BaseClientMonitor.Callback.class);
+        BaseClientMonitor.Callback callback3 = null;
+
+        BaseClientMonitor.CompositeCallback callback = new BaseClientMonitor.CompositeCallback(
+                callback1, callback2, callback3);
+
+        BaseClientMonitor clientMonitor = mock(BaseClientMonitor.class);
+
+        callback.onClientStarted(clientMonitor);
+        verify(callback1).onClientStarted(eq(clientMonitor));
+        verify(callback2).onClientStarted(eq(clientMonitor));
+
+        callback.onClientFinished(clientMonitor, true /* success */);
+        verify(callback1).onClientFinished(eq(clientMonitor), eq(true));
+        verify(callback2).onClientFinished(eq(clientMonitor), eq(true));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallbackTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallbackTest.java
new file mode 100644
index 0000000..38e8dfa
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallbackTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.fingerprint;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.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.hardware.fingerprint.FingerprintStateListener;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.biometrics.sensors.AuthenticationClient;
+import com.android.server.biometrics.sensors.EnrollClient;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@Presubmit
+@SmallTest
+public class FingerprintStateCallbackTest {
+
+    private FingerprintStateCallback mCallback;
+
+    @Mock
+    FingerprintStateListener mFingerprintStateListener;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+
+        mCallback = new FingerprintStateCallback();
+        mCallback.registerFingerprintStateListener(mFingerprintStateListener);
+    }
+
+    @Test
+    public void testNoEnrollmentsToEnrollments_callbackNotified() {
+        testEnrollmentCallback(true /* changed */, true /* isNowEnrolled */,
+                true /* expectCallback */, true /* expectedCallbackValue */);
+    }
+
+    @Test
+    public void testEnrollmentsToNoEnrollments_callbackNotified() {
+        testEnrollmentCallback(true /* changed */, false /* isNowEnrolled */,
+                true /* expectCallback */, false /* expectedCallbackValue */);
+    }
+
+    @Test
+    public void testEnrollmentsToEnrollments_callbackNotNotified() {
+        testEnrollmentCallback(false /* changed */, true /* isNowEnrolled */,
+                false /* expectCallback */, false /* expectedCallbackValue */);
+    }
+
+    private void testEnrollmentCallback(boolean changed, boolean isNowEnrolled,
+            boolean expectCallback, boolean expectedCallbackValue) {
+        EnrollClient<?> client = mock(EnrollClient.class);
+
+        final int userId = 10;
+        final int sensorId = 100;
+
+        when(client.hasEnrollmentStateChanged()).thenReturn(changed);
+        when(client.hasEnrollments()).thenReturn(isNowEnrolled);
+        when(client.getTargetUserId()).thenReturn(userId);
+        when(client.getSensorId()).thenReturn(sensorId);
+
+        mCallback.onClientFinished(client, true /* success */);
+        if (expectCallback) {
+            verify(mFingerprintStateListener).onEnrollmentsChanged(eq(userId), eq(sensorId),
+                    eq(expectedCallbackValue));
+        } else {
+            verify(mFingerprintStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(),
+                    anyBoolean());
+        }
+    }
+
+    @Test
+    public void testAuthentication_enrollmentCallbackNeverNotified() {
+        AuthenticationClient<?> client = mock(AuthenticationClient.class);
+        mCallback.onClientFinished(client, true /* success */);
+        verify(mFingerprintStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(),
+                anyBoolean());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
index 35c37ef..b51918e 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
@@ -37,6 +37,7 @@
 import com.android.server.biometrics.sensors.BiometricScheduler;
 import com.android.server.biometrics.sensors.HalClientMonitor;
 import com.android.server.biometrics.sensors.LockoutResetDispatcher;
+import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback;
 import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
 
 import org.junit.Before;
@@ -58,6 +59,8 @@
     private UserManager mUserManager;
     @Mock
     private GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
+    @Mock
+    private FingerprintStateCallback mFingerprintStateCallback;
 
     private SensorProps[] mSensorProps;
     private LockoutResetDispatcher mLockoutResetDispatcher;
@@ -87,8 +90,8 @@
 
         mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
 
-        mFingerprintProvider = new TestableFingerprintProvider(mContext, mSensorProps, TAG,
-                mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
+        mFingerprintProvider = new TestableFingerprintProvider(mContext, mFingerprintStateCallback,
+                mSensorProps, TAG, mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
     }
 
     @SuppressWarnings("rawtypes")
@@ -133,11 +136,12 @@
 
     private static class TestableFingerprintProvider extends FingerprintProvider {
         public TestableFingerprintProvider(@NonNull Context context,
+                @NonNull FingerprintStateCallback fingerprintStateCallback,
                 @NonNull SensorProps[] props,
                 @NonNull String halInstanceName,
                 @NonNull LockoutResetDispatcher lockoutResetDispatcher,
                 @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
-            super(context, props, halInstanceName, lockoutResetDispatcher,
+            super(context, fingerprintStateCallback, props, halInstanceName, lockoutResetDispatcher,
                     gestureAvailabilityDispatcher);
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
index 0a0dcc9..f6b9209 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
@@ -41,6 +41,7 @@
 import com.android.internal.R;
 import com.android.server.biometrics.sensors.BiometricScheduler;
 import com.android.server.biometrics.sensors.LockoutResetDispatcher;
+import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -67,6 +68,8 @@
     Fingerprint21.HalResultController mHalResultController;
     @Mock
     private BiometricScheduler mScheduler;
+    @Mock
+    private FingerprintStateCallback mFingerprintStateCallback;
 
     private LockoutResetDispatcher mLockoutResetDispatcher;
     private Fingerprint21 mFingerprint21;
@@ -96,8 +99,9 @@
                         componentInfo, FingerprintSensorProperties.TYPE_UNKNOWN,
                         resetLockoutRequiresHardwareAuthToken);
 
-        mFingerprint21 = new TestableFingerprint21(mContext, sensorProps, mScheduler,
-                new Handler(Looper.getMainLooper()), mLockoutResetDispatcher, mHalResultController);
+        mFingerprint21 = new TestableFingerprint21(mContext, mFingerprintStateCallback, sensorProps,
+                mScheduler, new Handler(Looper.getMainLooper()), mLockoutResetDispatcher,
+                mHalResultController);
     }
 
     @Test
@@ -118,11 +122,13 @@
     private static class TestableFingerprint21 extends Fingerprint21 {
 
         TestableFingerprint21(@NonNull Context context,
+                @NonNull FingerprintStateCallback fingerprintStateCallback,
                 @NonNull FingerprintSensorPropertiesInternal sensorProps,
                 @NonNull BiometricScheduler scheduler, @NonNull Handler handler,
                 @NonNull LockoutResetDispatcher lockoutResetDispatcher,
                 @NonNull HalResultController controller) {
-            super(context, sensorProps, scheduler, handler, lockoutResetDispatcher, controller);
+            super(context, fingerprintStateCallback, sensorProps, scheduler, handler,
+                    lockoutResetDispatcher, controller);
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index 1ac28ab..4564296 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -56,7 +56,11 @@
 import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
 import android.hardware.fingerprint.IUdfpsHbmListener;
 import android.os.Handler;
+import android.os.IThermalEventListener;
+import android.os.IThermalService;
 import android.os.Looper;
+import android.os.RemoteException;
+import android.os.Temperature;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.test.mock.MockContentResolver;
@@ -116,6 +120,8 @@
     public SensorManagerInternal mSensorManagerInternalMock;
     @Mock
     public DisplayManagerInternal mDisplayManagerInternalMock;
+    @Mock
+    public IThermalService mThermalServiceMock;
 
     @Before
     public void setUp() throws Exception {
@@ -124,6 +130,7 @@
         final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContext);
         when(mContext.getContentResolver()).thenReturn(resolver);
         mInjector = spy(new FakesInjector());
+        when(mInjector.getThermalService()).thenReturn(mThermalServiceMock);
         mHandler = new Handler(Looper.getMainLooper());
 
         LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
@@ -1547,12 +1554,52 @@
         assertNull(vote);
     }
 
+    @Test
+    public void testSkinTemperature() throws RemoteException {
+        DisplayModeDirector director =
+                createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0);
+        director.start(createMockSensorManager());
+
+        ArgumentCaptor<IThermalEventListener> thermalEventListener =
+                ArgumentCaptor.forClass(IThermalEventListener.class);
+
+        verify(mThermalServiceMock).registerThermalEventListenerWithType(
+            thermalEventListener.capture(), eq(Temperature.TYPE_SKIN));
+        final IThermalEventListener listener = thermalEventListener.getValue();
+
+        // Verify that there is no skin temperature vote initially.
+        Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE);
+        assertNull(vote);
+
+        // Set the skin temperature to critical and verify that we added a vote.
+        listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_CRITICAL));
+        vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE);
+        assertVoteForRefreshRateRange(vote, 0f, 60.f);
+
+        // Set the skin temperature to severe and verify that the vote is gone.
+        listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_SEVERE));
+        vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE);
+        assertNull(vote);
+    }
+
+    private Temperature getSkinTemp(@Temperature.ThrottlingStatus int status) {
+        return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status);
+    }
+
     private void assertVoteForRefreshRate(Vote vote, float refreshRate) {
         assertThat(vote).isNotNull();
         final RefreshRateRange expectedRange = new RefreshRateRange(refreshRate, refreshRate);
         assertThat(vote.refreshRateRange).isEqualTo(expectedRange);
     }
 
+    private void assertVoteForRefreshRateRange(
+            Vote vote, float refreshRateLow, float refreshRateHigh) {
+        assertThat(vote).isNotNull();
+        final RefreshRateRange expectedRange =
+                new RefreshRateRange(refreshRateLow, refreshRateHigh);
+        assertThat(vote.refreshRateRange).isEqualTo(expectedRange);
+    }
+
     public static class FakeDeviceConfig extends FakeDeviceConfigInterface {
         @Override
         public String getProperty(String namespace, String name) {
@@ -1748,6 +1795,11 @@
             return false;
         }
 
+        @Override
+        public IThermalService getThermalService() {
+            return null;
+        }
+
         void notifyPeakRefreshRateChanged() {
             if (mPeakRefreshRateObserver != null) {
                 mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/,
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 1ba414e..2128a08 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -58,7 +58,6 @@
     jni_libs: [
         "libdexmakerjvmtiagent",
         "libmultiplejvmtiagentsinterferenceagent",
-        "libbacktrace",
         "libbase",
         "libbinder",
         "libc++",
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 14dc33e..4ee0c60 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -25,6 +25,7 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
 import static android.os.Build.VERSION_CODES.P;
 import static android.os.Build.VERSION_CODES.Q;
 import static android.view.Display.DEFAULT_DISPLAY;
@@ -111,6 +112,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.hardware.display.VirtualDisplay;
 import android.metrics.LogMaker;
 import android.os.Binder;
 import android.os.IBinder;
@@ -2292,7 +2294,7 @@
         float yScale = 2f;
         Rect displayAreaBounds = new Rect(0, 0, Math.round(surfaceSize.x * xScale),
                 Math.round(surfaceSize.y * yScale));
-        virtualDisplay.updateMirroredSurface(mTransaction, displayAreaBounds);
+        virtualDisplay.updateMirroredSurface(mTransaction, displayAreaBounds, surfaceSize);
 
         // THEN content in the captured DisplayArea is scaled to fit the surface size.
         verify(mTransaction, atLeastOnce()).setMatrix(mirroredSurface, 1.0f / yScale, 0, 0,
@@ -2305,6 +2307,72 @@
         mockSession.finishMocking();
     }
 
+    @Test
+    public void testVirtualDisplayContent_withoutSurface() {
+        MockitoSession mockSession = mockitoSession()
+                .initMocks(this)
+                .spyStatic(SurfaceControl.class)
+                .strictness(Strictness.LENIENT)
+                .startMocking();
+
+        // GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
+        // mirror.
+        setUpDefaultTaskDisplayAreaWindowToken();
+
+        // GIVEN SurfaceControl can successfully mirror the provided surface.
+        Point surfaceSize = new Point(
+                mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().width(),
+                mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().height());
+        surfaceControlMirrors(surfaceSize);
+
+        // GIVEN a new VirtualDisplay with an associated surface.
+        final VirtualDisplay display = createVirtualDisplay(surfaceSize, null /* surface */);
+        final int displayId = display.getDisplay().getDisplayId();
+        mWm.mRoot.onDisplayAdded(displayId);
+
+        // WHEN getting the DisplayContent for the new virtual display.
+        DisplayContent actualDC = mWm.mRoot.getDisplayContent(displayId);
+
+        // THEN mirroring is not started, since a null surface indicates the VirtualDisplay is off.
+        assertThat(actualDC.mTokenToMirror).isNull();
+
+        display.release();
+        mockSession.finishMocking();
+    }
+
+    @Test
+    public void testVirtualDisplayContent_withSurface() {
+        MockitoSession mockSession = mockitoSession()
+                .initMocks(this)
+                .spyStatic(SurfaceControl.class)
+                .strictness(Strictness.LENIENT)
+                .startMocking();
+
+        // GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
+        // mirror.
+        final IBinder tokenToMirror = setUpDefaultTaskDisplayAreaWindowToken();
+
+        // GIVEN SurfaceControl can successfully mirror the provided surface.
+        Point surfaceSize = new Point(
+                mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().width(),
+                mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().height());
+        surfaceControlMirrors(surfaceSize);
+
+        // GIVEN a new VirtualDisplay with an associated surface.
+        final VirtualDisplay display = createVirtualDisplay(surfaceSize, new Surface());
+        final int displayId = display.getDisplay().getDisplayId();
+        mWm.mRoot.onDisplayAdded(displayId);
+
+        // WHEN getting the DisplayContent for the new virtual display.
+        DisplayContent actualDC = mWm.mRoot.getDisplayContent(displayId);
+
+        // THEN mirroring is initiated for the default display's DisplayArea.
+        assertThat(actualDC.mTokenToMirror).isEqualTo(tokenToMirror);
+
+        display.release();
+        mockSession.finishMocking();
+    }
+
     private class TestToken extends Binder {
     }
 
@@ -2342,6 +2410,11 @@
         return mirroredSurface;
     }
 
+    private VirtualDisplay createVirtualDisplay(Point size, Surface surface) {
+        return mWm.mDisplayManager.createVirtualDisplay("VirtualDisplay", size.x, size.y,
+                DisplayMetrics.DENSITY_140, surface, VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR);
+    }
+
     private void removeRootTaskTests(Runnable runnable) {
         final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
         final Task rootTask1 = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index f2eb709..4069f0f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -1008,33 +1008,31 @@
 
     @Test
     public void testLockAllProfileTasks() {
-        // Make an activity visible with the user id set to 0
-        final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
-        final int taskId = task.mTaskId;
-        final ActivityRecord activity = task.getTopMostActivity();
+        final int profileUid = UserHandle.PER_USER_RANGE + UserHandle.MIN_SECONDARY_USER_ID;
+        final int profileUserId = UserHandle.getUserId(profileUid);
+        // Create an activity belonging to the profile user.
+        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true)
+                .setUid(profileUid).build();
+        final Task task = activity.getTask();
 
-        // Create another activity on top and the user id is 1
-        final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task)
-                .setUid(UserHandle.PER_USER_RANGE + 1).build();
-        doReturn(true).when(topActivity).okToShowLocked();
+        // Create another activity belonging to current user on top.
+        final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build();
         topActivity.intent.setAction(Intent.ACTION_MAIN);
 
         // Make sure the listeners will be notified for putting the task to locked state
         TaskChangeNotificationController controller = mAtm.getTaskChangeNotificationController();
         spyOn(controller);
-        mWm.mRoot.lockAllProfileTasks(0);
-        verify(controller).notifyTaskProfileLocked(eq(taskId), eq(0));
+        mWm.mRoot.lockAllProfileTasks(profileUserId);
+        verify(controller).notifyTaskProfileLocked(eq(task.mTaskId), eq(profileUserId));
 
         // Create the work lock activity on top of the task
-        final ActivityRecord workLockActivity = new ActivityBuilder(mAtm).setTask(task)
-                .setUid(UserHandle.PER_USER_RANGE + 1).build();
-        doReturn(true).when(workLockActivity).okToShowLocked();
+        final ActivityRecord workLockActivity = new ActivityBuilder(mAtm).setTask(task).build();
         workLockActivity.intent.setAction(ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER);
         doReturn(workLockActivity.mActivityComponent).when(mAtm).getSysUiServiceComponentLocked();
 
         // Make sure the listener won't be notified again.
         clearInvocations(controller);
-        mWm.mRoot.lockAllProfileTasks(0);
+        mWm.mRoot.lockAllProfileTasks(profileUserId);
         verify(controller, never()).notifyTaskProfileLocked(anyInt(), anyInt());
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 8e7ba4bc..5bc45d7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -271,7 +271,6 @@
         doNothing().when(amInternal).cleanUpServices(anyInt(), any(), any());
         doReturn(UserHandle.USER_SYSTEM).when(amInternal).getCurrentUserId();
         doReturn(TEST_USER_PROFILE_IDS).when(amInternal).getCurrentProfileIds();
-        doReturn(true).when(amInternal).isCurrentProfile(anyInt());
         doReturn(true).when(amInternal).isUserRunning(anyInt(), anyInt());
         doReturn(true).when(amInternal).hasStartedUserState(anyInt());
         doReturn(false).when(amInternal).shouldConfirmCredentials(anyInt());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 67e8c87..ce568f1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -898,7 +898,8 @@
 
     /**
      * Test that root activity index is reported correctly when looking for the 'effective root' in
-     * case when bottom activities are relinquishing task identity or finishing.
+     * case when bottom activity is finishing. Ignore the relinquishing task identity if it's not a
+     * system activity even with the FLAG_RELINQUISH_TASK_IDENTITY.
      */
     @Test
     public void testFindRootIndex_effectiveRoot_finishingAndRelinquishing() {
@@ -912,7 +913,7 @@
         new ActivityBuilder(mAtm).setTask(task).build();
 
         assertEquals("The first non-finishing activity and non-relinquishing task identity "
-                + "must be reported.", task.getChildAt(2), task.getRootActivity(
+                + "must be reported.", task.getChildAt(0), task.getRootActivity(
                 false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/));
     }
 
@@ -932,8 +933,8 @@
     }
 
     /**
-     * Test that the topmost activity index is reported correctly when looking for the
-     * 'effective root' for the case when all activities have relinquishTaskIdentity set.
+     * Test that the root activity index is reported correctly when looking for the
+     * 'effective root' for the case when all non-system activities have relinquishTaskIdentity set.
      */
     @Test
     public void testFindRootIndex_effectiveRoot_relinquishingMultipleActivities() {
@@ -944,9 +945,9 @@
         final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build();
         activity1.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
 
-        assertEquals("The topmost activity in the task must be reported.",
-                task.getChildAt(task.getChildCount() - 1), task.getRootActivity(
-                        false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/));
+        assertEquals("The topmost activity in the task must be reported.", task.getChildAt(0),
+                task.getRootActivity(false /*ignoreRelinquishIdentity*/,
+                        true /*setToBottomIfNone*/));
     }
 
     /** Test that bottom-most activity is reported in {@link Task#getRootActivity()}. */
@@ -1084,8 +1085,8 @@
     }
 
     /**
-     * Test {@link ActivityRecord#getTaskForActivityLocked(IBinder, boolean)} with activity that
-     * relinquishes task identity.
+     * Test {@link ActivityRecord#getTaskForActivityLocked(IBinder, boolean)} with non-system
+     * activity that relinquishes task identity.
      */
     @Test
     public void testGetTaskForActivity_onlyRoot_relinquishTaskIdentity() {
@@ -1100,7 +1101,7 @@
 
         assertEquals(task.mTaskId,
                 ActivityRecord.getTaskForActivityLocked(activity0.appToken, true /* onlyRoot */));
-        assertEquals(task.mTaskId,
+        assertEquals("No task must be reported for activity that is above root", INVALID_TASK_ID,
                 ActivityRecord.getTaskForActivityLocked(activity1.appToken, true /* onlyRoot */));
         assertEquals("No task must be reported for activity that is above root", INVALID_TASK_ID,
                 ActivityRecord.getTaskForActivityLocked(activity2.appToken, true /* onlyRoot */));
diff --git a/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java b/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java
index 49ea9df..0c65cc4 100644
--- a/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java
+++ b/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java
@@ -45,6 +45,7 @@
 import android.service.usb.UsbUserPermissionsManagerProto;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
+import android.util.EventLog;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
 import android.util.TypedXmlPullParser;
@@ -74,6 +75,8 @@
     private static final String TAG = UsbUserPermissionManager.class.getSimpleName();
     private static final boolean DEBUG = false;
 
+    private static final int SNET_EVENT_LOG_ID = 0x534e4554;
+
     @GuardedBy("mLock")
     /** Mapping of USB device name to list of UIDs with permissions for the device
      * Each entry lasts until device is disconnected*/
@@ -691,6 +694,7 @@
             if (aInfo.uid != uid) {
                 Slog.w(TAG, "package " + packageName
                         + " does not match caller's uid " + uid);
+                EventLog.writeEvent(SNET_EVENT_LOG_ID, "180104273", -1, "");
                 throw new IllegalArgumentException("package " + packageName
                         + " not found");
             }
diff --git a/services/usb/lint-baseline.xml b/services/usb/lint-baseline.xml
new file mode 100644
index 0000000..c2c0a35
--- /dev/null
+++ b/services/usb/lint-baseline.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 7.1.0-dev" type="baseline" client="" dependencies="true" name="" variant="all" version="7.1.0-dev">
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        int isDisabled = Settings.Secure.getInt(mContext.getContentResolver(),"
+        errorLine2="                                         ~~~~~~">
+        <location
+            file="frameworks/base/services/usb/java/com/android/server/usb/UsbAlsaManager.java"
+            line="150"
+            column="42"/>
+    </issue>
+
+</issues>
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index c365648..cac716e 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -81,7 +81,8 @@
  * <pre>
  * {@code
  * <service android:name="your.package.YourInCallServiceImplementation"
- *          android:permission="android.permission.BIND_INCALL_SERVICE">
+ *          android:permission="android.permission.BIND_INCALL_SERVICE"
+ *          android:exported="true">
  *      <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
  *      <meta-data android:name="android.telecom.IN_CALL_SERVICE_RINGING"
  *          android:value="true" />
@@ -91,6 +92,10 @@
  * </service>
  * }
  * </pre>
+ *
+ * <em>Note: You should NOT mark your {@link InCallService} with the attribute
+ * {@code android:exported="false"}; doing so can result in a failure to bind to your implementation
+ * during calls.</em>
  * <p>
  * In addition to implementing the {@link InCallService} API, you must also declare an activity in
  * your manifest which handles the {@link Intent#ACTION_DIAL} intent.  The example below illustrates
diff --git a/telephony/OWNERS b/telephony/OWNERS
index 4df8a4b..f248fd5 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -8,10 +8,10 @@
 tgunn@google.com
 jminjie@google.com
 shuoq@google.com
-nazaninb@google.com
 sarahchin@google.com
 xiaotonj@google.com
 huiwang@google.com
 jayachandranc@google.com
 chinmayd@google.com
 amruthr@google.com
+sasindran@google.com
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0e4c44e..7d354a8 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -5167,6 +5167,16 @@
             "display_no_data_notification_on_permanent_failure_bool";
 
     /**
+     * Boolean indicating if the VoNR setting is visible in the Call Settings menu.
+     * If true, the VoNR setting menu will be visible. If false, the menu will be gone.
+     *
+     * Disabled by default.
+     *
+     * @hide
+     */
+    public static final String KEY_VONR_SETTING_VISIBILITY_BOOL = "vonr_setting_visibility_bool";
+
+    /**
      * Determine whether unthrottle data retry when tracking area code (TAC/LAC) from cell changes
      *
      * @hide
@@ -5781,6 +5791,7 @@
         sDefaults.putString(KEY_CARRIER_PROVISIONING_APP_STRING, "");
         sDefaults.putBoolean(KEY_DISPLAY_NO_DATA_NOTIFICATION_ON_PERMANENT_FAILURE_BOOL, false);
         sDefaults.putBoolean(KEY_UNTHROTTLE_DATA_RETRY_WHEN_TAC_CHANGES_BOOL, false);
+        sDefaults.putBoolean(KEY_VONR_SETTING_VISIBILITY_BOOL, false);
     }
 
     /**
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index a51b5c1..484eb1f 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -444,7 +444,9 @@
         mArfcnRsrpBoost = s.mArfcnRsrpBoost;
         synchronized (mNetworkRegistrationInfos) {
             mNetworkRegistrationInfos.clear();
-            mNetworkRegistrationInfos.addAll(s.getNetworkRegistrationInfoList());
+            for (NetworkRegistrationInfo nri : s.getNetworkRegistrationInfoList()) {
+                mNetworkRegistrationInfos.add(new NetworkRegistrationInfo(nri));
+            }
         }
         mNrFrequencyRange = s.mNrFrequencyRange;
         mOperatorAlphaLongRaw = s.mOperatorAlphaLongRaw;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 39cb04a..e21d0ad 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -12140,6 +12140,100 @@
     }
 
     /**
+     * No error. Operation succeeded.
+     * @hide
+     */
+    public static final int ENABLE_VONR_SUCCESS = 0;
+
+    /**
+     * Radio is not available.
+     * @hide
+     */
+    public static final int ENABLE_VONR_RADIO_NOT_AVAILABLE = 2;
+
+    /**
+     * Internal Radio error.
+     * @hide
+     */
+    public static final int ENABLE_VONR_RADIO_ERROR = 3;
+
+    /**
+     * Voice over NR enable/disable request is received when system is in invalid state.
+     * @hide
+     */
+    public static final int ENABLE_VONR_RADIO_INVALID_STATE = 4;
+
+    /**
+     * Voice over NR enable/disable request is not supported.
+     * @hide
+     */
+    public static final int ENABLE_VONR_REQUEST_NOT_SUPPORTED = 5;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"EnableVoNrResult"}, value = {
+            ENABLE_VONR_SUCCESS,
+            ENABLE_VONR_RADIO_NOT_AVAILABLE,
+            ENABLE_VONR_RADIO_ERROR,
+            ENABLE_VONR_RADIO_INVALID_STATE,
+            ENABLE_VONR_REQUEST_NOT_SUPPORTED})
+    public @interface EnableVoNrResult {}
+
+    /**
+     * Enable or disable Voice over NR (VoNR)
+     *
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     *
+     * @param enabled  enable or disable VoNR.
+     * @throws IllegalStateException if the Telephony process is not currently available.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public @EnableVoNrResult int setVoNrEnabled(boolean enabled) {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                return service.setVoNrEnabled(
+                        getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enabled);
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling ITelephony#setVoNrEnabled", e);
+        }
+
+        return ENABLE_VONR_RADIO_INVALID_STATE;
+    }
+
+    /**
+     * Is Voice over NR (VoNR) enabled.
+     * @return true if Voice over NR (VoNR) is enabled else false. Enabled state does not mean
+     *  voice call over NR is active or voice ove NR is available. It means the device is allowed to
+     *  register IMS over NR.
+     * @throws IllegalStateException if the Telephony process is not currently available.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public boolean isVoNrEnabled() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.isVoNrEnabled(getSubId());
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "isVoNrEnabled RemoteException", ex);
+            ex.rethrowFromSystemServer();
+        }
+        return false;
+    }
+
+    /**
      * Carrier action to start or stop reporting default network available events.
      *
      * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
index 0aff997..dfe5e6c 100755
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -766,7 +766,10 @@
      * The method is only valid to call when the session state is in
      * {@link ImsCallSession.State#IDLE}.
      *
-     * @param callee dialed string to make the call to
+     * @param callee dial string to make the call to.  The platform passes the dialed number
+     *               entered by the user as-is.  The {@link ImsService} should ensure that the
+     *               number is formatted in SIP messages appropriately (e.g. using
+     *               {@link android.telephony.PhoneNumberUtils#formatNumberToE164(String, String)}).
      * @param profile call profile to make the call with the specified service type,
      *      call type and media information
      * @see Listener#callSessionStarted, Listener#callSessionStartFailed
@@ -788,7 +791,10 @@
      * The method is only valid to call when the session state is in
      * {@link ImsCallSession.State#IDLE}.
      *
-     * @param participants participant list to initiate an IMS conference call
+     * @param participants participant list to initiate an IMS conference call.  The platform passes
+     *               the dialed numbers entered by the user as-is.  The {@link ImsService} should
+     *               ensure that the number is formatted in SIP messages appropriately (e.g. using
+     *               {@link android.telephony.PhoneNumberUtils#formatNumberToE164(String, String)}).
      * @param profile call profile to make the call with the specified service type,
      *      call type and media information
      * @see Listener#callSessionStarted, Listener#callSessionStartFailed
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 4f3b4cb..d99fb85 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2224,6 +2224,20 @@
     List<String> getEquivalentHomePlmns(int subId, String callingPackage, String callingFeatureId);
 
     /**
+     * Enable or disable Voice over NR (VoNR)
+     * @param subId the subscription ID that this action applies to.
+     * @param enabled enable or disable VoNR.
+     * @return operation result.
+     */
+    int setVoNrEnabled(int subId, boolean enabled);
+
+    /**
+     * Is voice over NR enabled
+     * @return true if VoNR is enabled else false
+     */
+    boolean isVoNrEnabled(int subId);
+
+    /**
      * Enable/Disable E-UTRA-NR Dual Connectivity
      * @return operation result. See TelephonyManager.EnableNrDualConnectivityResult for
      * details
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index fe8e671..fadc23b 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -528,6 +528,8 @@
     int RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP = 222;
     int RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP = 223;
     int RIL_REQUEST_GET_SLICING_CONFIG = 224;
+    int RIL_REQUEST_ENABLE_VONR = 225;
+    int RIL_REQUEST_IS_VONR_ENABLED = 225;
 
     /* Responses begin */
     int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index 7a1dda3..49daad3 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -573,11 +573,26 @@
 
     /** @hide */
     @Override
+    @SystemApi
+    public Intent registerReceiverForAllUsers(BroadcastReceiver receiver,
+            IntentFilter filter, String broadcastPermission, Handler scheduler, int flags) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** @hide */
+    @Override
     public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
             IntentFilter filter, String broadcastPermission, Handler scheduler) {
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+            IntentFilter filter, String broadcastPermission, Handler scheduler, int flags) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public void unregisterReceiver(BroadcastReceiver receiver) {
         throw new UnsupportedOperationException();
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
index c06f8fd..46d3a3d 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
@@ -63,7 +63,7 @@
                 "uniform shader bitmapShader;\n"
                 + "uniform float param1;\n"
                 + "half4 main(float2 xy) {\n"
-                + "  return half4(sample(bitmapShader, xy).rgb, param1);\n"
+                + "  return half4(bitmapShader.eval(xy).rgb, param1);\n"
                 + "}\n";
 
         BitmapsView(Context c) {
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java
index d925541..83e2de9 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java
@@ -91,7 +91,7 @@
                 + "    d = rand(float2(x, y)) > density ? d : d * .2;\n"
                 + "    d = d * rand(float2(fraction, x * y));\n"
                 + "    float alpha = 1. - pow(fraction, 3.);\n"
-                + "    return float4(sample(in_paintColor, p).rgb, d * alpha);\n"
+                + "    return float4(in_paintColor.eval(p).rgb, d * alpha);\n"
                 + "}";
 
         RippleView(Context c) {
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java
index 3307c36..fcdee63 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java
@@ -532,6 +532,6 @@
             + "    uv.y = outV;\n"
             + "    coord.x = uv.x * viewportWidth;\n"
             + "    coord.y = uv.y * viewportHeight;\n"
-            + "    return sample(uContentTexture, coord);\n"
+            + "    return uContentTexture.eval(coord);\n"
             + "}";
 }
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index 7a668a5..cbdcb88 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -16,7 +16,6 @@
 
 package com.android.tests.rollback;
 
-import static com.android.cts.install.lib.InstallUtils.processUserData;
 import static com.android.cts.rollback.lib.RollbackInfoSubject.assertThat;
 import static com.android.cts.rollback.lib.RollbackUtils.getUniqueRollbackInfoForPackage;
 import static com.android.cts.rollback.lib.RollbackUtils.waitForAvailableRollback;
@@ -34,7 +33,6 @@
 import android.content.rollback.RollbackInfo;
 import android.content.rollback.RollbackManager;
 import android.os.UserManager;
-import android.provider.DeviceConfig;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -69,12 +67,6 @@
 
     private static final String INSTRUMENTED_APP = "com.android.tests.rollback";
 
-    // copied from PackageManagerService#PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS
-    // TODO: find a better place for the property so that it can be imported in tests
-    // maybe android.content.pm.PackageManager?
-    private static final String PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS =
-            "enable_rollback_timeout";
-
     private static boolean hasRollbackInclude(List<RollbackInfo> rollbacks, String packageName) {
         return rollbacks.stream().anyMatch(
                 ri -> ri.getPackages().stream().anyMatch(
@@ -201,355 +193,6 @@
         }
     }
 
-    /**
-     * Test the scheduling aspect of rollback expiration.
-     */
-    @Test
-    public void testRollbackExpiresAfterLifetime() throws Exception {
-        long expirationTime = TimeUnit.SECONDS.toMillis(30);
-        long defaultExpirationTime = TimeUnit.HOURS.toMillis(48);
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.TEST_MANAGE_ROLLBACKS,
-                    Manifest.permission.WRITE_DEVICE_CONFIG);
-
-            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
-                    RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS,
-                    Long.toString(expirationTime), false /* makeDefault*/);
-
-            // Uninstall TestApp.A
-            Uninstall.packages(TestApp.A);
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
-
-            // Install v1 of the app (without rollbacks enabled).
-            Install.single(TestApp.A1).commit();
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-
-            // Upgrade from v1 to v2, with rollbacks enabled.
-            Install.single(TestApp.A2).setEnableRollback().commit();
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
-            // Check that the rollback data has not expired
-            Thread.sleep(1000);
-            RollbackInfo rollback = waitForAvailableRollback(TestApp.A);
-            assertThat(rollback).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1));
-
-            // Give it a little more time, but still not long enough to expire
-            Thread.sleep(expirationTime / 2);
-            rollback = getUniqueRollbackInfoForPackage(
-                    rm.getAvailableRollbacks(), TestApp.A);
-            assertThat(rollback).isNotNull();
-            assertThat(rollback).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1));
-
-            // Check that the data has expired after the expiration time (with a buffer of 1 second)
-            Thread.sleep(expirationTime / 2);
-            rollback = getUniqueRollbackInfoForPackage(
-                    rm.getAvailableRollbacks(), TestApp.A);
-            assertThat(rollback).isNull();
-
-        } finally {
-            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
-                    RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS,
-                    Long.toString(defaultExpirationTime), false /* makeDefault*/);
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
-     * Test that available rollbacks should expire correctly when the property
-     * {@link RollbackManager#PROPERTY_ROLLBACK_LIFETIME_MILLIS} is changed
-     */
-    @Test
-    public void testRollbackExpiresWhenLifetimeChanges() throws Exception {
-        long defaultExpirationTime = TimeUnit.HOURS.toMillis(48);
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.TEST_MANAGE_ROLLBACKS,
-                    Manifest.permission.WRITE_DEVICE_CONFIG);
-
-            Uninstall.packages(TestApp.A);
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
-            Install.single(TestApp.A1).commit();
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-            Install.single(TestApp.A2).setEnableRollback().commit();
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-            RollbackInfo rollback = waitForAvailableRollback(TestApp.A);
-            assertThat(rollback).packagesContainsExactly(Rollback.from(TestApp.A2).to(TestApp.A1));
-
-            // Change the lifetime to 0 which should expire rollbacks immediately
-            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
-                    RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS,
-                    Long.toString(0), false /* makeDefault*/);
-
-            // Keep polling until device config changes has happened (which might take more than
-            // 5 sec depending how busy system_server is) and rollbacks have expired
-            for (int i = 0; i < 30; ++i) {
-                if (hasRollbackInclude(rm.getAvailableRollbacks(), TestApp.A)) {
-                    Thread.sleep(1000);
-                }
-            }
-            rollback = getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A);
-            assertThat(rollback).isNull();
-        } finally {
-            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
-                    RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS,
-                    Long.toString(defaultExpirationTime), false /* makeDefault*/);
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
-     * Test that changing time on device does not affect the duration of time that we keep
-     * rollback available
-     */
-    @Test
-    public void testTimeChangeDoesNotAffectLifetime() throws Exception {
-        long expirationTime = TimeUnit.SECONDS.toMillis(30);
-        long defaultExpirationTime = TimeUnit.HOURS.toMillis(48);
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.TEST_MANAGE_ROLLBACKS,
-                    Manifest.permission.WRITE_DEVICE_CONFIG,
-                    Manifest.permission.SET_TIME);
-
-            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
-                    RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS,
-                    Long.toString(expirationTime), false /* makeDefault*/);
-
-            // Install app A with rollback enabled
-            Uninstall.packages(TestApp.A);
-            Install.single(TestApp.A1).commit();
-            Install.single(TestApp.A2).setEnableRollback().commit();
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
-            Thread.sleep(expirationTime / 2);
-
-            // Install app B with rollback enabled
-            Uninstall.packages(TestApp.B);
-            Install.single(TestApp.B1).commit();
-            Install.single(TestApp.B2).setEnableRollback().commit();
-            assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
-            // 1 second buffer
-            Thread.sleep(1000);
-
-            try {
-                // Change the time
-                RollbackUtils.forwardTimeBy(expirationTime);
-
-                // 1 second buffer to allow Rollback Manager to handle time change before loading
-                // persisted data
-                Thread.sleep(1000);
-
-                // Load timestamps from storage
-                rm.reloadPersistedData();
-
-                // Wait until rollback for app A has expired
-                // This will trigger an expiration run that should expire app A but not B
-                Thread.sleep(expirationTime / 2);
-                RollbackInfo rollbackA =
-                        getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A);
-                Log.i(TAG, "Checking if the rollback for TestApp.A is null");
-
-                // Rollback for app B should not be expired
-                RollbackInfo rollbackB1 = getUniqueRollbackInfoForPackage(
-                        rm.getAvailableRollbacks(), TestApp.B);
-
-                // Wait until rollback for app B has expired
-                Thread.sleep(expirationTime / 2);
-                RollbackInfo rollbackB2 = getUniqueRollbackInfoForPackage(
-                        rm.getAvailableRollbacks(), TestApp.B);
-
-                assertThat(rollbackA).isNull();
-                assertThat(rollbackB1).isNotNull();
-                assertThat(rollbackB1).packagesContainsExactly(
-                        Rollback.from(TestApp.B2).to(TestApp.B1));
-                assertThat(rollbackB2).isNull();
-            } finally {
-                RollbackUtils.forwardTimeBy(-expirationTime);
-            }
-        } finally {
-            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
-                    RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS,
-                    Long.toString(defaultExpirationTime), false /* makeDefault*/);
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
-     * Test explicit expiration of rollbacks.
-     * Does not test the scheduling aspects of rollback expiration.
-     */
-    @Test
-    public void testRollbackExpiration() throws Exception {
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
-
-            RollbackManager rm = RollbackUtils.getRollbackManager();
-            Uninstall.packages(TestApp.A);
-            Install.single(TestApp.A1).commit();
-            Install.single(TestApp.A2).setEnableRollback().commit();
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
-            // The app should now be available for rollback.
-            RollbackInfo rollback = waitForAvailableRollback(TestApp.A);
-            assertThat(rollback).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1));
-
-            // Expire the rollback.
-            rm.expireRollbackForPackage(TestApp.A);
-
-            // The rollback should no longer be available.
-            assertThat(getUniqueRollbackInfoForPackage(
-                        rm.getAvailableRollbacks(), TestApp.A)).isNull();
-        } finally {
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
-     * Test that app user data is rolled back.
-     */
-    @Test
-    public void testUserDataRollback() throws Exception {
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
-
-            Uninstall.packages(TestApp.A);
-            Install.single(TestApp.A1).commit();
-            processUserData(TestApp.A);
-            Install.single(TestApp.A2).setEnableRollback().commit();
-            processUserData(TestApp.A);
-
-            RollbackInfo rollback = waitForAvailableRollback(TestApp.A);
-            RollbackUtils.rollback(rollback.getRollbackId());
-            processUserData(TestApp.A);
-        } finally {
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
-     * Test rollback of apks involving splits.
-     */
-    @Test
-    public void testRollbackWithSplits() throws Exception {
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
-
-            Uninstall.packages(TestApp.A);
-            Install.single(TestApp.ASplit1).commit();
-            processUserData(TestApp.A);
-
-            Install.single(TestApp.ASplit2).setEnableRollback().commit();
-            processUserData(TestApp.A);
-
-            RollbackInfo rollback = waitForAvailableRollback(TestApp.A);
-            RollbackUtils.rollback(rollback.getRollbackId());
-            processUserData(TestApp.A);
-        } finally {
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
-     * Test restrictions on rollback broadcast sender.
-     * A random app should not be able to send a ROLLBACK_COMMITTED broadcast.
-     */
-    @Test
-    public void testRollbackBroadcastRestrictions() throws Exception {
-        RollbackBroadcastReceiver broadcastReceiver = new RollbackBroadcastReceiver();
-        Intent broadcast = new Intent(Intent.ACTION_ROLLBACK_COMMITTED);
-        try {
-            InstrumentationRegistry.getContext().sendBroadcast(broadcast);
-            fail("Succeeded in sending restricted broadcast from app context.");
-        } catch (SecurityException se) {
-            // Expected behavior.
-        }
-
-        // Confirm that we really haven't received the broadcast.
-        // TODO: How long to wait for the expected timeout?
-        assertThat(broadcastReceiver.poll(5, TimeUnit.SECONDS)).isNull();
-
-        // TODO: Do we need to do this? Do we need to ensure this is always
-        // called, even when the test fails?
-        broadcastReceiver.unregister();
-    }
-
-    /**
-     * Regression test for rollback in the case when multiple apps are
-     * available for rollback at the same time.
-     */
-    @Test
-    public void testMultipleRollbackAvailable() throws Exception {
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
-
-            // Prep installation of the test apps.
-            Uninstall.packages(TestApp.A);
-            Install.single(TestApp.A1).commit();
-            Install.single(TestApp.A2).setEnableRollback().commit();
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
-            Uninstall.packages(TestApp.B);
-            Install.single(TestApp.B1).commit();
-            Install.single(TestApp.B2).setEnableRollback().commit();
-            assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
-            // Both test apps should now be available for rollback, and the
-            // RollbackInfo returned for the rollbacks should be correct.
-            RollbackInfo rollbackA = waitForAvailableRollback(TestApp.A);
-            assertThat(rollbackA).packagesContainsExactly(
-                    Rollback.from(TestApp.A2).to(TestApp.A1));
-
-            RollbackInfo rollbackB = waitForAvailableRollback(TestApp.B);
-            assertThat(rollbackB).packagesContainsExactly(
-                    Rollback.from(TestApp.B2).to(TestApp.B1));
-
-            // Executing rollback should roll back the correct package.
-            RollbackUtils.rollback(rollbackA.getRollbackId());
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-            assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
-            Uninstall.packages(TestApp.A);
-            Install.single(TestApp.A1).commit();
-            Install.single(TestApp.A2).setEnableRollback().commit();
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
-            RollbackUtils.rollback(rollbackB.getRollbackId());
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-            assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
-        } finally {
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
-
     @Test
     @Ignore("b/120200473")
     /**
@@ -687,90 +330,4 @@
             InstallUtils.dropShellPermissionIdentity();
         }
     }
-
-    @Test
-    public void testEnableRollbackTimeoutFailsRollback() throws Exception {
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.TEST_MANAGE_ROLLBACKS,
-                    Manifest.permission.MANAGE_ROLLBACKS,
-                    Manifest.permission.WRITE_DEVICE_CONFIG);
-
-            //setting the timeout to a very short amount that will definitely be triggered
-            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
-                    PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
-                    Long.toString(0), false /* makeDefault*/);
-            RollbackManager rm = RollbackUtils.getRollbackManager();
-
-            Uninstall.packages(TestApp.A);
-            Install.single(TestApp.A1).commit();
-            waitForUnavailableRollback(TestApp.A);
-
-            // Block the RollbackManager to make extra sure it will not be
-            // able to enable the rollback in time.
-            rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(1));
-            Install.single(TestApp.A2).setEnableRollback().commit();
-
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
-            // Give plenty of time for RollbackManager to unblock and attempt
-            // to make the rollback available before asserting that the
-            // rollback was not made available.
-            Thread.sleep(TimeUnit.SECONDS.toMillis(2));
-            assertThat(
-                getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull();
-        } finally {
-            //setting the timeout back to default
-            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
-                    PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
-                    null, false /* makeDefault*/);
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    public void testEnableRollbackTimeoutFailsRollback_MultiPackage() throws Exception {
-        try {
-            InstallUtils.adoptShellPermissionIdentity(
-                    Manifest.permission.INSTALL_PACKAGES,
-                    Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.TEST_MANAGE_ROLLBACKS,
-                    Manifest.permission.MANAGE_ROLLBACKS,
-                    Manifest.permission.WRITE_DEVICE_CONFIG);
-
-            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
-                    PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
-                    Long.toString(5000), false /* makeDefault*/);
-            RollbackManager rm = RollbackUtils.getRollbackManager();
-
-            Uninstall.packages(TestApp.A, TestApp.B);
-            Install.multi(TestApp.A1, TestApp.B1).commit();
-            waitForUnavailableRollback(TestApp.A);
-
-            // Block the 2nd session for 10s so it will not be able to enable the rollback in time.
-            rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(0));
-            rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(10));
-            Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit();
-
-            assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-            assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
-            // Give plenty of time for RollbackManager to unblock and attempt
-            // to make the rollback available before asserting that the
-            // rollback was not made available.
-            Thread.sleep(TimeUnit.SECONDS.toMillis(2));
-
-            List<RollbackInfo> available = rm.getAvailableRollbacks();
-            assertThat(getUniqueRollbackInfoForPackage(available, TestApp.A)).isNull();
-            assertThat(getUniqueRollbackInfoForPackage(available, TestApp.B)).isNull();
-        } finally {
-            //setting the timeout back to default
-            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
-                    PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
-                    null, false /* makeDefault*/);
-            InstallUtils.dropShellPermissionIdentity();
-        }
-    }
 }
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index a283aa9..539090b 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -22,12 +22,10 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.Manifest;
-import android.content.Context;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.rollback.RollbackInfo;
 import android.content.rollback.RollbackManager;
-import android.os.storage.StorageManager;
 import android.provider.DeviceConfig;
 
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -82,155 +80,6 @@
         InstallUtils.dropShellPermissionIdentity();
     }
 
-    /**
-     * Test rollbacks of staged installs involving only apks with bad update.
-     * Enable rollback phase.
-     */
-    @Test
-    public void testBadApkOnly_Phase1_Install() throws Exception {
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
-
-        Install.single(TestApp.A1).commit();
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-        InstallUtils.processUserData(TestApp.A);
-
-        Install.single(TestApp.ACrashing2).setEnableRollback().setStaged().commit();
-    }
-
-    /**
-     * Test rollbacks of staged installs involving only apks with bad update.
-     * Confirm that rollback was successfully enabled.
-     */
-    @Test
-    public void testBadApkOnly_Phase2_VerifyInstall() throws Exception {
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-        InstallUtils.processUserData(TestApp.A);
-
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-        RollbackInfo rollback = getUniqueRollbackInfoForPackage(
-                rm.getAvailableRollbacks(), TestApp.A);
-        assertThat(rollback).isNotNull();
-        assertThat(rollback).packagesContainsExactly(
-                Rollback.from(TestApp.A2).to(TestApp.A1));
-        assertThat(rollback.isStaged()).isTrue();
-
-        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
-                PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT,
-                Integer.toString(5), false);
-        RollbackUtils.sendCrashBroadcast(TestApp.A, 4);
-        // Sleep for a while to make sure we don't trigger rollback
-        Thread.sleep(TimeUnit.SECONDS.toMillis(30));
-    }
-
-    /**
-     * Test rollbacks of staged installs involving only apks.
-     * Confirm rollback phase.
-     */
-    @Test
-    public void testBadApkOnly_Phase3_VerifyRollback() throws Exception {
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-        InstallUtils.processUserData(TestApp.A);
-
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-        RollbackInfo rollback = getUniqueRollbackInfoForPackage(
-                rm.getRecentlyCommittedRollbacks(), TestApp.A);
-        assertThat(rollback).isNotNull();
-        assertThat(rollback).packagesContainsExactly(
-                Rollback.from(TestApp.A2).to(TestApp.A1));
-        assertThat(rollback).causePackagesContainsExactly(TestApp.ACrashing2);
-        assertThat(rollback).isStaged();
-        assertThat(rollback.getCommittedSessionId()).isNotEqualTo(-1);
-    }
-
-    /**
-     * Stage install an apk with rollback that will be later triggered by unattributable crash.
-     */
-    @Test
-    public void testNativeWatchdogTriggersRollback_Phase1_Install() throws Exception {
-        Install.single(TestApp.A1).commit();
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-
-        Install.single(TestApp.A2).setEnableRollback().setStaged().commit();
-    }
-
-    /**
-     * Verify the rollback is available.
-     */
-    @Test
-    public void testNativeWatchdogTriggersRollback_Phase2_VerifyInstall() throws Exception {
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
-                TestApp.A)).isNotNull();
-    }
-
-    /**
-     * Verify the rollback is committed after crashing.
-     */
-    @Test
-    public void testNativeWatchdogTriggersRollback_Phase3_VerifyRollback() throws Exception {
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-        assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
-                TestApp.A)).isNotNull();
-    }
-
-    /**
-     * Stage install an apk with rollback that will be later triggered by unattributable crash.
-     */
-    @Test
-    public void testNativeWatchdogTriggersRollbackForAll_Phase1_InstallA() throws Exception {
-        Install.single(TestApp.A1).commit();
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-
-        Install.single(TestApp.A2).setEnableRollback().setStaged().commit();
-    }
-
-    /**
-     * Verify the rollback is available and then install another package with rollback.
-     */
-    @Test
-    public void testNativeWatchdogTriggersRollbackForAll_Phase2_InstallB() throws Exception {
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
-                TestApp.A)).isNotNull();
-
-        // Install another package with rollback
-        Install.single(TestApp.B1).commit();
-        assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
-
-        Install.single(TestApp.B2).setEnableRollback().setStaged().commit();
-    }
-
-    /**
-     * Verify the rollbacks are available.
-     */
-    @Test
-    public void testNativeWatchdogTriggersRollbackForAll_Phase3_VerifyInstall() throws Exception {
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-        assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
-                TestApp.A)).isNotNull();
-        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
-                TestApp.B)).isNotNull();
-    }
-
-    /**
-     * Verify the rollbacks are committed after crashing.
-     */
-    @Test
-    public void testNativeWatchdogTriggersRollbackForAll_Phase4_VerifyRollback() throws Exception {
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-        assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-        assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
-                TestApp.A)).isNotNull();
-        assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
-                TestApp.B)).isNotNull();
-    }
-
     @Test
     public void testPreviouslyAbandonedRollbacks_Phase1_InstallAndAbandon() throws Exception {
         Install.single(TestApp.A1).commit();
@@ -315,51 +164,6 @@
             "TestApexWithApkV2Crashing", APK_IN_APEX_TESTAPEX_NAME, 2, /*isApex*/true,
             APK_IN_APEX_TESTAPEX_NAME + "_v2Crashing.apex");
 
-    @Test
-    public void testRollbackApexWithApk_Phase1_Install() throws Exception {
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-        InstallUtils.processUserData(TestApp.A);
-
-        int sessionId = Install.single(TEST_APEX_WITH_APK_V2).setStaged().setEnableRollback()
-                .commit();
-        InstallUtils.waitForSessionReady(sessionId);
-    }
-
-    @Test
-    public void testRollbackApexWithApk_Phase2_Rollback() throws Exception {
-        assertThat(InstallUtils.getInstalledVersion(APK_IN_APEX_TESTAPEX_NAME)).isEqualTo(2);
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-        InstallUtils.processUserData(TestApp.A);
-
-        RollbackInfo available = RollbackUtils.getAvailableRollback(APK_IN_APEX_TESTAPEX_NAME);
-        assertThat(available).isStaged();
-        assertThat(available).packagesContainsExactly(
-                Rollback.from(TEST_APEX_WITH_APK_V2).to(TEST_APEX_WITH_APK_V1),
-                Rollback.from(TestApp.A, 0).to(TestApp.A1));
-
-        RollbackUtils.rollback(available.getRollbackId(), TEST_APEX_WITH_APK_V2);
-        RollbackInfo committed = RollbackUtils.getCommittedRollbackById(available.getRollbackId());
-        assertThat(committed).isNotNull();
-        assertThat(committed).isStaged();
-        assertThat(committed).packagesContainsExactly(
-                Rollback.from(TEST_APEX_WITH_APK_V2).to(TEST_APEX_WITH_APK_V1),
-                Rollback.from(TestApp.A, 0).to(TestApp.A1));
-        assertThat(committed).causePackagesContainsExactly(TEST_APEX_WITH_APK_V2);
-        assertThat(committed.getCommittedSessionId()).isNotEqualTo(-1);
-
-        // Note: The app is not rolled back until after the rollback is staged
-        // and the device has been rebooted.
-        InstallUtils.waitForSessionReady(committed.getCommittedSessionId());
-        assertThat(InstallUtils.getInstalledVersion(APK_IN_APEX_TESTAPEX_NAME)).isEqualTo(2);
-    }
-
-    @Test
-    public void testRollbackApexWithApk_Phase3_VerifyRollback() throws Exception {
-        assertThat(InstallUtils.getInstalledVersion(APK_IN_APEX_TESTAPEX_NAME)).isEqualTo(1);
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-        InstallUtils.processUserData(TestApp.A);
-    }
-
     /**
      * Installs an apex with an apk that can crash.
      */
@@ -398,52 +202,6 @@
     }
 
     @Test
-    public void testRollbackApexDataDirectories_Phase1_Install() throws Exception {
-        int sessionId = Install.single(TEST_APEX_WITH_APK_V2).setStaged().setEnableRollback()
-                .commit();
-        InstallUtils.waitForSessionReady(sessionId);
-    }
-
-    @Test
-    public void testRollbackApexDataDirectories_Phase2_Rollback() throws Exception {
-        RollbackInfo available = RollbackUtils.getAvailableRollback(APK_IN_APEX_TESTAPEX_NAME);
-
-        RollbackUtils.rollback(available.getRollbackId(), TEST_APEX_WITH_APK_V2);
-        RollbackInfo committed = RollbackUtils.getCommittedRollbackById(available.getRollbackId());
-
-        // Note: The app is not rolled back until after the rollback is staged
-        // and the device has been rebooted.
-        InstallUtils.waitForSessionReady(committed.getCommittedSessionId());
-    }
-
-    @Test
-    public void testRollbackApkDataDirectories_Phase1_InstallV1() throws Exception {
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
-        Install.single(TestApp.A1).commit();
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-    }
-
-    @Test
-    public void testRollbackApkDataDirectories_Phase2_InstallV2() throws Exception {
-        Install.single(TestApp.A2).setStaged().setEnableRollback().commit();
-    }
-
-    @Test
-    public void testRollbackApkDataDirectories_Phase3_Rollback() throws Exception {
-        RollbackInfo available = RollbackUtils.getAvailableRollback(TestApp.A);
-        RollbackUtils.rollback(available.getRollbackId(), TestApp.A2);
-        RollbackInfo committed = RollbackUtils.getCommittedRollbackById(available.getRollbackId());
-        InstallUtils.waitForSessionReady(committed.getCommittedSessionId());
-    }
-
-    @Test
-    public void isCheckpointSupported() {
-        Context context = InstrumentationRegistry.getInstrumentation().getContext();
-        StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
-        assertThat(sm.isCheckpointSupported()).isTrue();
-    }
-
-    @Test
     public void testWatchdogMonitorsAcrossReboots_Phase1_Install() throws Exception {
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
         Install.single(TestApp.A1).commit();
@@ -483,33 +241,6 @@
     }
 
     @Test
-    public void testExpireSession_Phase1_Install() throws Exception {
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
-        Install.single(TestApp.A1).commit();
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-        Install.single(TestApp.A2).setEnableRollback().setStaged().commit();
-    }
-
-    @Test
-    public void testExpireSession_Phase2_VerifyInstall() throws Exception {
-        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-        RollbackInfo rollback = getUniqueRollbackInfoForPackage(
-                rm.getAvailableRollbacks(), TestApp.A);
-        assertThat(rollback).isNotNull();
-        assertThat(rollback).packagesContainsExactly(Rollback.from(TestApp.A2).to(TestApp.A1));
-        assertThat(rollback.isStaged()).isTrue();
-    }
-
-    @Test
-    public void testExpireSession_Phase3_VerifyRollback() throws Exception {
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-        RollbackInfo rollback = getUniqueRollbackInfoForPackage(
-                rm.getAvailableRollbacks(), TestApp.A);
-        assertThat(rollback).isNotNull();
-    }
-
-    @Test
     public void hasMainlineModule() throws Exception {
         String pkgName = getModuleMetadataPackageName();
         boolean existed =  InstrumentationRegistry.getInstrumentation().getContext()
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 1c2f244..293f159 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -21,13 +21,9 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
-import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.ddmlib.Log;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.IFileEntry;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 import com.android.tradefed.util.CommandResult;
@@ -40,12 +36,7 @@
 import org.junit.runner.RunWith;
 
 import java.io.File;
-import java.time.Instant;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
 import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
 
 /**
  * Runs the staged rollback tests.
@@ -72,17 +63,6 @@
     private static final String APK_IN_APEX_TESTAPEX_NAME = "com.android.apex.apkrollback.test";
     private static final String TESTAPP_A = "com.android.cts.install.lib.testapp.A";
 
-    private static final String TEST_SUBDIR = "/subdir/";
-
-    private static final String TEST_FILENAME_1 = "test_file.txt";
-    private static final String TEST_STRING_1 = "hello this is a test";
-    private static final String TEST_FILENAME_2 = "another_file.txt";
-    private static final String TEST_STRING_2 = "this is a different file";
-    private static final String TEST_FILENAME_3 = "also.xyz";
-    private static final String TEST_STRING_3 = "also\n a\n test\n string";
-    private static final String TEST_FILENAME_4 = "one_more.test";
-    private static final String TEST_STRING_4 = "once more unto the test";
-
     private static final String REASON_APP_CRASH = "REASON_APP_CRASH";
     private static final String REASON_NATIVE_CRASH = "REASON_NATIVE_CRASH";
 
@@ -153,98 +133,6 @@
     }
 
     /**
-     * Tests watchdog triggered staged rollbacks involving only apks.
-     */
-    @Test
-    public void testBadApkOnly() throws Exception {
-        runPhase("testBadApkOnly_Phase1_Install");
-        getDevice().reboot();
-        runPhase("testBadApkOnly_Phase2_VerifyInstall");
-
-        // Launch the app to crash to trigger rollback
-        startActivity(TESTAPP_A);
-        // Wait for reboot to happen
-        waitForDeviceNotAvailable(2, TimeUnit.MINUTES);
-
-        getDevice().waitForDeviceAvailable();
-
-        runPhase("testBadApkOnly_Phase3_VerifyRollback");
-
-        assertThat(mLogger).eventOccurred(ROLLBACK_INITIATE, null, REASON_APP_CRASH, TESTAPP_A);
-        assertThat(mLogger).eventOccurred(ROLLBACK_BOOT_TRIGGERED, null, null, null);
-        assertThat(mLogger).eventOccurred(ROLLBACK_SUCCESS, null, null, null);
-    }
-
-    @Test
-    public void testNativeWatchdogTriggersRollback() throws Exception {
-        runPhase("testNativeWatchdogTriggersRollback_Phase1_Install");
-
-        // Reboot device to activate staged package
-        getDevice().reboot();
-
-        runPhase("testNativeWatchdogTriggersRollback_Phase2_VerifyInstall");
-
-        // crash system_server enough times to trigger a rollback
-        crashProcess("system_server", NATIVE_CRASHES_THRESHOLD);
-
-        // Rollback should be committed automatically now.
-        // Give time for rollback to be committed. This could take a while,
-        // because we need all of the following to happen:
-        // 1. system_server comes back up and boot completes.
-        // 2. Rollback health observer detects updatable crashing signal.
-        // 3. Staged rollback session becomes ready.
-        // 4. Device actually reboots.
-        // So we give a generous timeout here.
-        waitForDeviceNotAvailable(5, TimeUnit.MINUTES);
-        getDevice().waitForDeviceAvailable();
-
-        // verify rollback committed
-        runPhase("testNativeWatchdogTriggersRollback_Phase3_VerifyRollback");
-
-        assertThat(mLogger).eventOccurred(ROLLBACK_INITIATE, null, REASON_NATIVE_CRASH, null);
-        assertThat(mLogger).eventOccurred(ROLLBACK_BOOT_TRIGGERED, null, null, null);
-        assertThat(mLogger).eventOccurred(ROLLBACK_SUCCESS, null, null, null);
-    }
-
-    @Test
-    public void testNativeWatchdogTriggersRollbackForAll() throws Exception {
-        // This test requires committing multiple staged rollbacks
-        assumeTrue(isCheckpointSupported());
-
-        // Install a package with rollback enabled.
-        runPhase("testNativeWatchdogTriggersRollbackForAll_Phase1_InstallA");
-        getDevice().reboot();
-
-        // Once previous staged install is applied, install another package
-        runPhase("testNativeWatchdogTriggersRollbackForAll_Phase2_InstallB");
-        getDevice().reboot();
-
-        // Verify the new staged install has also been applied successfully.
-        runPhase("testNativeWatchdogTriggersRollbackForAll_Phase3_VerifyInstall");
-
-        // crash system_server enough times to trigger a rollback
-        crashProcess("system_server", NATIVE_CRASHES_THRESHOLD);
-
-        // Rollback should be committed automatically now.
-        // Give time for rollback to be committed. This could take a while,
-        // because we need all of the following to happen:
-        // 1. system_server comes back up and boot completes.
-        // 2. Rollback health observer detects updatable crashing signal.
-        // 3. Staged rollback session becomes ready.
-        // 4. Device actually reboots.
-        // So we give a generous timeout here.
-        waitForDeviceNotAvailable(5, TimeUnit.MINUTES);
-        getDevice().waitForDeviceAvailable();
-
-        // verify all available rollbacks have been committed
-        runPhase("testNativeWatchdogTriggersRollbackForAll_Phase4_VerifyRollback");
-
-        assertThat(mLogger).eventOccurred(ROLLBACK_INITIATE, null, REASON_NATIVE_CRASH, null);
-        assertThat(mLogger).eventOccurred(ROLLBACK_BOOT_TRIGGERED, null, null, null);
-        assertThat(mLogger).eventOccurred(ROLLBACK_SUCCESS, null, null, null);
-    }
-
-    /**
      * Tests rolling back user data where there are multiple rollbacks for that package.
      */
     @Test
@@ -268,19 +156,6 @@
     }
 
     /**
-     * Tests that userdata of apk-in-apex is restored when apex is rolled back.
-     */
-    @Test
-    public void testRollbackApexWithApk() throws Exception {
-        pushTestApex();
-        runPhase("testRollbackApexWithApk_Phase1_Install");
-        getDevice().reboot();
-        runPhase("testRollbackApexWithApk_Phase2_Rollback");
-        getDevice().reboot();
-        runPhase("testRollbackApexWithApk_Phase3_VerifyRollback");
-    }
-
-    /**
      * Tests that RollbackPackageHealthObserver is observing apk-in-apex.
      */
     @Test
@@ -306,242 +181,6 @@
     }
 
     /**
-     * Tests that data in DE_sys apex data directory is restored when apex is rolled back.
-     */
-    @Test
-    public void testRollbackApexDataDirectories_DeSys() throws Exception {
-        List<String> before = getSnapshotDirectories("/data/misc/apexrollback");
-        pushTestApex();
-
-        // Push files to apex data directory
-        String oldFilePath1 = apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + "/" + TEST_FILENAME_1;
-        String oldFilePath2 =
-                apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + TEST_SUBDIR + TEST_FILENAME_2;
-        runAsRoot(() -> {
-            pushString(TEST_STRING_1, oldFilePath1);
-            pushString(TEST_STRING_2, oldFilePath2);
-        });
-
-        // Install new version of the APEX with rollback enabled
-        runPhase("testRollbackApexDataDirectories_Phase1_Install");
-        getDevice().reboot();
-
-        // Replace files in data directory
-        String newFilePath3 = apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + "/" + TEST_FILENAME_3;
-        String newFilePath4 =
-                apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + TEST_SUBDIR + TEST_FILENAME_4;
-        runAsRoot(() -> {
-            getDevice().deleteFile(oldFilePath1);
-            getDevice().deleteFile(oldFilePath2);
-            pushString(TEST_STRING_3, newFilePath3);
-            pushString(TEST_STRING_4, newFilePath4);
-        });
-
-        // Roll back the APEX
-        runPhase("testRollbackApexDataDirectories_Phase2_Rollback");
-        getDevice().reboot();
-
-        // Verify that old files have been restored and new files are gone
-        runAsRoot(() -> {
-            assertFileContents(TEST_STRING_1, oldFilePath1);
-            assertFileContents(TEST_STRING_2, oldFilePath2);
-            assertFileNotExists(newFilePath3);
-            assertFileNotExists(newFilePath4);
-        });
-
-        // Verify snapshots are deleted after restoration
-        List<String> after = getSnapshotDirectories("/data/misc/apexrollback");
-        // Only check directories newly created during the test
-        after.removeAll(before);
-        // There should be only one /data/misc/apexrollback/<rollbackId> created during test
-        assertThat(after).hasSize(1);
-        assertDirectoryIsEmpty(after.get(0));
-    }
-
-    /**
-     * Tests that data in DE (user) apex data directory is restored when apex is rolled back.
-     */
-    @Test
-    public void testRollbackApexDataDirectories_DeUser() throws Exception {
-        List<String> before = getSnapshotDirectories("/data/misc_de/0/apexrollback");
-        pushTestApex();
-
-        // Push files to apex data directory
-        String oldFilePath1 = apexDataDirDeUser(
-                APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1;
-        String oldFilePath2 =
-                apexDataDirDeUser(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2;
-        runAsRoot(() -> {
-            pushString(TEST_STRING_1, oldFilePath1);
-            pushString(TEST_STRING_2, oldFilePath2);
-        });
-
-        // Install new version of the APEX with rollback enabled
-        runPhase("testRollbackApexDataDirectories_Phase1_Install");
-        getDevice().reboot();
-
-        // Replace files in data directory
-        String newFilePath3 =
-                apexDataDirDeUser(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_3;
-        String newFilePath4 =
-                apexDataDirDeUser(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_4;
-        runAsRoot(() -> {
-            getDevice().deleteFile(oldFilePath1);
-            getDevice().deleteFile(oldFilePath2);
-            pushString(TEST_STRING_3, newFilePath3);
-            pushString(TEST_STRING_4, newFilePath4);
-        });
-
-        // Roll back the APEX
-        runPhase("testRollbackApexDataDirectories_Phase2_Rollback");
-        getDevice().reboot();
-
-        // Verify that old files have been restored and new files are gone
-        runAsRoot(() -> {
-            assertFileContents(TEST_STRING_1, oldFilePath1);
-            assertFileContents(TEST_STRING_2, oldFilePath2);
-            assertFileNotExists(newFilePath3);
-            assertFileNotExists(newFilePath4);
-        });
-
-        // Verify snapshots are deleted after restoration
-        List<String> after = getSnapshotDirectories("/data/misc_de/0/apexrollback");
-        // Only check directories newly created during the test
-        after.removeAll(before);
-        // There should be only one /data/misc_de/0/apexrollback/<rollbackId> created during test
-        assertThat(after).hasSize(1);
-        assertDirectoryIsEmpty(after.get(0));
-    }
-
-    /**
-     * Tests that data in CE apex data directory is restored when apex is rolled back.
-     */
-    @Test
-    public void testRollbackApexDataDirectories_Ce() throws Exception {
-        List<String> before = getSnapshotDirectories("/data/misc_ce/0/apexrollback");
-        pushTestApex();
-
-        // Push files to apex data directory
-        String oldFilePath1 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1;
-        String oldFilePath2 =
-                apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2;
-        runAsRoot(() -> {
-            pushString(TEST_STRING_1, oldFilePath1);
-            pushString(TEST_STRING_2, oldFilePath2);
-        });
-
-        // Install new version of the APEX with rollback enabled
-        runPhase("testRollbackApexDataDirectories_Phase1_Install");
-        getDevice().reboot();
-
-        // Replace files in data directory
-        String newFilePath3 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_3;
-        String newFilePath4 =
-                apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_4;
-        runAsRoot(() -> {
-            getDevice().deleteFile(oldFilePath1);
-            getDevice().deleteFile(oldFilePath2);
-            pushString(TEST_STRING_3, newFilePath3);
-            pushString(TEST_STRING_4, newFilePath4);
-        });
-
-        // Roll back the APEX
-        runPhase("testRollbackApexDataDirectories_Phase2_Rollback");
-        getDevice().reboot();
-
-        // Verify that old files have been restored and new files are gone
-        runAsRoot(() -> {
-            assertFileContents(TEST_STRING_1, oldFilePath1);
-            assertFileContents(TEST_STRING_2, oldFilePath2);
-            assertFileNotExists(newFilePath3);
-            assertFileNotExists(newFilePath4);
-        });
-
-        // Verify snapshots are deleted after restoration
-        List<String> after = getSnapshotDirectories("/data/misc_ce/0/apexrollback");
-        // Only check directories newly created during the test
-        after.removeAll(before);
-        // There should be only one /data/misc_ce/0/apexrollback/<rollbackId> created during test
-        assertThat(after).hasSize(1);
-        assertDirectoryIsEmpty(after.get(0));
-    }
-
-    /**
-     * Tests that data in DE apk data directory is restored when apk is rolled back.
-     */
-    @Test
-    public void testRollbackApkDataDirectories_De() throws Exception {
-        // Install version 1 of TESTAPP_A
-        runPhase("testRollbackApkDataDirectories_Phase1_InstallV1");
-
-        // Push files to apk data directory
-        String oldFilePath1 = apkDataDirDe(TESTAPP_A, 0) + "/" + TEST_FILENAME_1;
-        String oldFilePath2 = apkDataDirDe(TESTAPP_A, 0) + TEST_SUBDIR + TEST_FILENAME_2;
-        runAsRoot(() -> {
-            pushString(TEST_STRING_1, oldFilePath1);
-            pushString(TEST_STRING_2, oldFilePath2);
-        });
-
-        // Install version 2 of TESTAPP_A with rollback enabled
-        runPhase("testRollbackApkDataDirectories_Phase2_InstallV2");
-        getDevice().reboot();
-
-        // Replace files in data directory
-        String newFilePath3 = apkDataDirDe(TESTAPP_A, 0) + "/" + TEST_FILENAME_3;
-        String newFilePath4 = apkDataDirDe(TESTAPP_A, 0) + TEST_SUBDIR + TEST_FILENAME_4;
-        runAsRoot(() -> {
-            getDevice().deleteFile(oldFilePath1);
-            getDevice().deleteFile(oldFilePath2);
-            pushString(TEST_STRING_3, newFilePath3);
-            pushString(TEST_STRING_4, newFilePath4);
-        });
-
-        // Roll back the APK
-        runPhase("testRollbackApkDataDirectories_Phase3_Rollback");
-        getDevice().reboot();
-
-        // Verify that old files have been restored and new files are gone
-        runAsRoot(() -> {
-            assertFileContents(TEST_STRING_1, oldFilePath1);
-            assertFileContents(TEST_STRING_2, oldFilePath2);
-            assertFileNotExists(newFilePath3);
-            assertFileNotExists(newFilePath4);
-        });
-    }
-
-    @Test
-    public void testExpireApexRollback() throws Exception {
-        List<String> before = getSnapshotDirectories("/data/misc_ce/0/apexrollback");
-        pushTestApex();
-
-        // Push files to apex data directory
-        String oldFilePath1 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1;
-        String oldFilePath2 =
-                apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2;
-        runAsRoot(() -> {
-            pushString(TEST_STRING_1, oldFilePath1);
-            pushString(TEST_STRING_2, oldFilePath2);
-        });
-
-        // Install new version of the APEX with rollback enabled
-        runPhase("testRollbackApexDataDirectories_Phase1_Install");
-        getDevice().reboot();
-
-        List<String> after = getSnapshotDirectories("/data/misc_ce/0/apexrollback");
-        // Only check directories newly created during the test
-        after.removeAll(before);
-        // There should be only one /data/misc_ce/0/apexrollback/<rollbackId> created during test
-        assertThat(after).hasSize(1);
-        // Expire all rollbacks and check CE snapshot directories are deleted
-        runPhase("expireRollbacks");
-        runAsRoot(() -> {
-            for (String dir : after) {
-                assertFileNotExists(dir);
-            }
-        });
-    }
-
-    /**
      * Tests that packages are monitored across multiple reboots.
      */
     @Test
@@ -565,27 +204,6 @@
         runPhase("testWatchdogMonitorsAcrossReboots_Phase3_VerifyRollback");
     }
 
-    /**
-     * Tests an available rollback shouldn't be deleted when its session expires.
-     */
-    @Test
-    public void testExpireSession() throws Exception {
-        runPhase("testExpireSession_Phase1_Install");
-        getDevice().reboot();
-        runPhase("testExpireSession_Phase2_VerifyInstall");
-
-        // Advance system clock by 7 days to expire the staged session
-        Instant t1 = Instant.ofEpochMilli(getDevice().getDeviceDate());
-        Instant t2 = t1.plusMillis(TimeUnit.DAYS.toMillis(7));
-        runAsRoot(() -> getDevice().setDate(Date.from(t2)));
-
-        // Somehow we need to wait for a while before reboot. Otherwise the change to the
-        // system clock will be reset after reboot.
-        Thread.sleep(3000);
-        getDevice().reboot();
-        runPhase("testExpireSession_Phase3_VerifyRollback");
-    }
-
     private void pushTestApex() throws Exception {
         CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild());
         final String fileName = APK_IN_APEX_TESTAPEX_NAME + "_v1.apex";
@@ -600,101 +218,20 @@
         getDevice().reboot();
     }
 
-    private void pushString(String contents, String path) throws Exception {
-        assertWithMessage("Failed to push file to device, content=%s path=%s", contents, path)
-                .that(getDevice().pushString(contents, path)).isTrue();
-    }
-
-    private void assertFileContents(String expectedContents, String path) throws Exception {
-        String actualContents = getDevice().pullFileContents(path);
-        assertWithMessage("Failed to retrieve file=%s", path).that(actualContents).isNotNull();
-        assertWithMessage("Mismatched file contents, path=%s", path)
-                .that(actualContents).isEqualTo(expectedContents);
-    }
-
-    private void assertFileNotExists(String path) throws Exception {
-        assertWithMessage("File shouldn't exist, path=%s", path)
-                .that(getDevice().getFileEntry(path)).isNull();
-    }
-
     private static String apexDataDirDeSys(String apexName) {
         return String.format("/data/misc/apexdata/%s", apexName);
     }
 
-    private static String apexDataDirDeUser(String apexName, int userId) {
-        return String.format("/data/misc_de/%d/apexdata/%s", userId, apexName);
-    }
-
     private static String apexDataDirCe(String apexName, int userId) {
         return String.format("/data/misc_ce/%d/apexdata/%s", userId, apexName);
     }
 
-    private static String apkDataDirDe(String apexName, int userId) {
-        return String.format("/data/user_de/%d/%s", userId, apexName);
-    }
-
-    private List<String> getSnapshotDirectories(String baseDir) throws Exception {
-        try {
-            getDevice().enableAdbRoot();
-            IFileEntry f = getDevice().getFileEntry(baseDir);
-            if (f == null) {
-                Log.d(TAG, "baseDir doesn't exist: " + baseDir);
-                return Collections.EMPTY_LIST;
-            }
-            List<String> list = f.getChildren(false)
-                    .stream().filter(entry -> entry.getName().matches("\\d+(-prerestore)?"))
-                    .map(entry -> entry.getFullPath())
-                    .collect(Collectors.toList());
-            Log.d(TAG, "getSnapshotDirectories=" + list);
-            return list;
-        } finally {
-            getDevice().disableAdbRoot();
-        }
-    }
-
-    private void assertDirectoryIsEmpty(String path) throws Exception {
-        try {
-            getDevice().enableAdbRoot();
-            IFileEntry file = getDevice().getFileEntry(path);
-            assertWithMessage("Not a directory: " + path).that(file.isDirectory()).isTrue();
-            assertWithMessage("Directory not empty: " + path)
-                    .that(file.getChildren(false)).isEmpty();
-        } catch (DeviceNotAvailableException e) {
-            fail("Can't access directory: " + path);
-        } finally {
-            getDevice().disableAdbRoot();
-        }
-    }
-
     private void startActivity(String packageName) throws Exception {
         String cmd = "am start -S -a android.intent.action.MAIN "
                 + "-c android.intent.category.LAUNCHER " + packageName;
         getDevice().executeShellCommand(cmd);
     }
 
-    private void crashProcess(String processName, int numberOfCrashes) throws Exception {
-        String pid = "";
-        String lastPid = "invalid";
-        for (int i = 0; i < numberOfCrashes; ++i) {
-            // This condition makes sure before we kill the process, the process is running AND
-            // the last crash was finished.
-            while ("".equals(pid) || lastPid.equals(pid)) {
-                pid = getDevice().executeShellCommand("pidof " + processName);
-            }
-            getDevice().executeShellCommand("kill " + pid);
-            lastPid = pid;
-        }
-    }
-
-    private boolean isCheckpointSupported() throws Exception {
-        try {
-            runPhase("isCheckpointSupported");
-            return true;
-        } catch (AssertionError ignore) {
-            return false;
-        }
-    }
-
     /**
      * True if this build has mainline modules installed.
      */
@@ -706,18 +243,4 @@
             return false;
         }
     }
-
-    @FunctionalInterface
-    private interface ExceptionalRunnable {
-        void run() throws Exception;
-    }
-
-    private void runAsRoot(ExceptionalRunnable runnable) throws Exception {
-        try {
-            getDevice().enableAdbRoot();
-            runnable.run();
-        } finally {
-            getDevice().disableAdbRoot();
-        }
-    }
 }
diff --git a/tests/componentalias/Android.bp b/tests/componentalias/Android.bp
index 15a680d..4e2009d 100644
--- a/tests/componentalias/Android.bp
+++ b/tests/componentalias/Android.bp
@@ -16,26 +16,14 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-android_library {
-    name: "ComponentAliasTestsCommon",
-    srcs: [
-        "common/**/*.java",
-    ],
-    plugins: [
-        "staledataclass-annotation-processor",
-    ],
-    platform_apis: true, // We use hidden APIs in the test.
-}
-
-android_test {
-    name: "ComponentAliasTests",
+java_defaults {
+    name: "ComponentAliasTests_defaults",
     static_libs: [
         "androidx.test.rules",
         "compatibility-device-util-axt",
         "mockito-target-extended-minus-junit4",
         "truth-prebuilt",
         "ub-uiautomator",
-        "ComponentAliasTestsCommon",
     ],
     libs: ["android.test.base"],
     srcs: [
@@ -46,3 +34,53 @@
     ],
     platform_apis: true, // We use hidden APIs in the test.
 }
+
+// We build three APKs from the exact same source files, so these APKs contain the exact same tests.
+// And we run the tests on each APK, so that we can test various situations:
+// - When the alias is in the same package, target in the same package.
+// - When the alias is in the same package, target in another package.
+// - When the alias is in another package, which also contains the target.
+// - When the alias is in another package, and the target is in yet another package.
+// etc etc...
+
+android_test {
+    name: "ComponentAliasTests",
+    defaults: [
+        "ComponentAliasTests_defaults",
+    ],
+    package_name: "android.content.componentalias.tests",
+    manifest: "AndroidManifest.xml",
+    additional_manifests: [
+        "AndroidManifest_service_aliases.xml",
+        "AndroidManifest_service_targets.xml",
+    ],
+    test_config_template: "AndroidTest-template.xml",
+}
+
+android_test {
+    name: "ComponentAliasTests1",
+    defaults: [
+        "ComponentAliasTests_defaults",
+    ],
+    package_name: "android.content.componentalias.tests.sub1",
+    manifest: "AndroidManifest.xml",
+    additional_manifests: [
+        "AndroidManifest_service_aliases.xml",
+        "AndroidManifest_service_targets.xml",
+    ],
+    test_config_template: "AndroidTest-template.xml",
+}
+
+android_test {
+    name: "ComponentAliasTests2",
+    defaults: [
+        "ComponentAliasTests_defaults",
+    ],
+    package_name: "android.content.componentalias.tests.sub2",
+    manifest: "AndroidManifest.xml",
+    additional_manifests: [
+        "AndroidManifest_service_aliases.xml",
+        "AndroidManifest_service_targets.xml",
+    ],
+    test_config_template: "AndroidTest-template.xml",
+}
diff --git a/tests/componentalias/AndroidManifest_service_aliases.xml b/tests/componentalias/AndroidManifest_service_aliases.xml
new file mode 100644
index 0000000..8c1ced6c
--- /dev/null
+++ b/tests/componentalias/AndroidManifest_service_aliases.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.content.componentalias.tests" >
+    <application>
+        <!--
+            Note the alias components are essentially just placeholders, so the APKs don't have to
+            have the implementation classes.
+        -->
+        <service android:name=".s.Alias00" android:exported="true" android:enabled="true" >
+            <meta-data android:name="alias_target" android:value="android.content.componentalias.tests/android.content.componentalias.tests.s.Target00" />
+            <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
+            <intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_00" /></intent-filter>
+        </service>
+        <service android:name=".s.Alias01" android:exported="true" android:enabled="true" >
+            <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.sub1/android.content.componentalias.tests.s.Target01" />
+            <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
+            <intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_01" /></intent-filter>
+        </service>
+        <service android:name=".s.Alias02" android:exported="true" android:enabled="true" >
+            <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.sub2/android.content.componentalias.tests.s.Target02" />
+            <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
+            <intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_02" /></intent-filter>
+        </service>
+        <service android:name=".s.Alias03" android:exported="true" android:enabled="true" >
+            <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.sub1/android.content.componentalias.tests.s.Target03" />
+            <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
+            <intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_03" /></intent-filter>
+        </service>
+        <service android:name=".s.Alias04" android:exported="true" android:enabled="true" >
+            <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.sub2/android.content.componentalias.tests.s.Target04" />
+            <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
+            <intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_04" /></intent-filter>
+        </service>
+
+        <receiver android:name=".b.Alias00" android:exported="true" android:enabled="true" >
+            <meta-data android:name="alias_target" android:value="android.content.componentalias.tests/android.content.componentalias.tests.b.Target00" />
+            <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
+            <intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_00" /></intent-filter>
+            <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+        </receiver>
+        <receiver android:name=".b.Alias01" android:exported="true" android:enabled="true" >
+            <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.sub1/android.content.componentalias.tests.b.Target01" />
+            <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
+            <intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_01" /></intent-filter>
+            <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+        </receiver>
+        <receiver android:name=".b.Alias02" android:exported="true" android:enabled="true" >
+            <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.sub2/android.content.componentalias.tests.b.Target02" />
+            <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
+            <intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_02" /></intent-filter>
+            <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+        </receiver>
+        <receiver android:name=".b.Alias03" android:exported="true" android:enabled="true" >
+            <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.sub1/android.content.componentalias.tests.b.Target03" />
+            <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
+            <intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_03" /></intent-filter>
+            <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+        </receiver>
+        <receiver android:name=".b.Alias04" android:exported="true" android:enabled="true" >
+            <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.sub2/android.content.componentalias.tests.b.Target04" />
+            <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
+            <intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_04" /></intent-filter>
+            <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+        </receiver>
+    </application>
+</manifest>
diff --git a/tests/componentalias/AndroidManifest_service_targets.xml b/tests/componentalias/AndroidManifest_service_targets.xml
new file mode 100644
index 0000000..c4bcd78
--- /dev/null
+++ b/tests/componentalias/AndroidManifest_service_targets.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.content.componentalias.tests" >
+    <application>
+        <service android:name=".s.Target00" android:exported="true" android:enabled="true" >
+        </service>
+        <service android:name=".s.Target01" android:exported="true" android:enabled="true" >
+        </service>
+        <service android:name=".s.Target02" android:exported="true" android:enabled="true" >
+        </service>
+        <service android:name=".s.Target03" android:exported="true" android:enabled="true" >
+        </service>
+        <service android:name=".s.Target04" android:exported="true" android:enabled="true" >
+        </service>
+
+        <receiver android:name=".b.Target00" android:exported="true" android:enabled="true" >
+            <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+        </receiver>
+        <receiver android:name=".b.Target01" android:exported="true" android:enabled="true" >
+            <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+        </receiver>
+        <receiver android:name=".b.Target02" android:exported="true" android:enabled="true" >
+            <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+        </receiver>
+        <receiver android:name=".b.Target03" android:exported="true" android:enabled="true" >
+            <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+        </receiver>
+        <receiver android:name=".b.Target04" android:exported="true" android:enabled="true" >
+            <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+        </receiver>
+    </application>
+</manifest>
diff --git a/tests/componentalias/AndroidTest.xml b/tests/componentalias/AndroidTest-template.xml
similarity index 68%
rename from tests/componentalias/AndroidTest.xml
rename to tests/componentalias/AndroidTest-template.xml
index e2c37d2..afdfe79 100644
--- a/tests/componentalias/AndroidTest.xml
+++ b/tests/componentalias/AndroidTest-template.xml
@@ -17,18 +17,21 @@
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="ComponentAliasTests.apk" />
-        <option name="test-file-name" value="ComponentAliasAppMain.apk" />
-        <option name="test-file-name" value="ComponentAliasAppSub1.apk" />
-        <option name="test-file-name" value="ComponentAliasAppSub2.apk" />
+        <option name="test-file-name" value="ComponentAliasTests1.apk" />
+        <option name="test-file-name" value="ComponentAliasTests2.apk" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
         <!-- Exempt the helper APKs from the BG restriction, so they can start BG services. -->
-        <option name="run-command" value="cmd deviceidle whitelist +android.content.componentalias.tests.app" />
-        <option name="run-command" value="cmd deviceidle whitelist +android.content.componentalias.tests.app.sub1" />
-        <option name="run-command" value="cmd deviceidle whitelist +android.content.componentalias.tests.app.sub2" />
+        <option name="run-command" value="cmd deviceidle whitelist +android.content.componentalias.tests" />
+        <option name="run-command" value="cmd deviceidle whitelist +android.content.componentalias.tests.sub1" />
+        <option name="run-command" value="cmd deviceidle whitelist +android.content.componentalias.tests.sub2" />
+
+        <option name="teardown-command" value="cmd deviceidle whitelist -android.content.componentalias.tests" />
+        <option name="teardown-command" value="cmd deviceidle whitelist -android.content.componentalias.tests.sub1" />
+        <option name="teardown-command" value="cmd deviceidle whitelist -android.content.componentalias.tests.sub2" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.content.componentalias.tests" />
+        <option name="package" value="{PACKAGE}" />
         <option name="runtime-hint" value="2m" />
         <option name="isolated-storage" value="false" />
     </test>
diff --git a/tests/componentalias/apps/Android.bp b/tests/componentalias/apps/Android.bp
deleted file mode 100644
index b2cb0f7..0000000
--- a/tests/componentalias/apps/Android.bp
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// 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 {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-// We build three helper APKs from the same source.
-// - The main APK (ComponentAliasAppMain), which contains both the alias and the target components.
-// - The sub APKs (ComponentAliasAppSub*), which only contains the target components.
-
-java_defaults {
-    name: "component_alias_app_defaults",
-    libs: ["android.test.base"],
-    sdk_version: "test_current",
-    srcs: [
-        "src/**/*.java",
-    ],
-    static_libs: [
-        "compatibility-device-util-axt",
-        "androidx.legacy_legacy-support-v4",
-        "androidx.test.rules",
-        "ComponentAliasTestsCommon",
-    ],
-}
-
-android_test_helper_app {
-    name: "ComponentAliasAppMain",
-    defaults: [
-        "component_alias_app_defaults",
-    ],
-    package_name: "android.content.componentalias.tests.app",
-    manifest: "AndroidManifest_main.xml",
-}
-
-android_test_helper_app {
-    name: "ComponentAliasAppSub1",
-    defaults: [
-        "component_alias_app_defaults",
-    ],
-    package_name: "android.content.componentalias.tests.app.sub1",
-    manifest: "AndroidManifest_sub.xml",
-}
-
-android_test_helper_app {
-    name: "ComponentAliasAppSub2",
-    defaults: [
-        "component_alias_app_defaults",
-    ],
-    package_name: "android.content.componentalias.tests.app.sub2",
-    manifest: "AndroidManifest_sub.xml",
-}
diff --git a/tests/componentalias/apps/AndroidManifest_main.xml b/tests/componentalias/apps/AndroidManifest_main.xml
deleted file mode 100755
index 2caef3e..0000000
--- a/tests/componentalias/apps/AndroidManifest_main.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.content.componentalias.tests.app" >
-
-    <application>
-        <!--
-            Alias components.
-            Note aliases do not have the actual implementation, because they're never called
-            directly.
-        -->
-
-        <service android:name=".s.Alias01" android:exported="true" android:enabled="true" >
-            <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.app.sub1/android.content.componentalias.tests.app.s.Target01" />
-            <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
-            <intent-filter><action android:name="android.content.componentalias.tests.app.IS_ALIAS_01" /></intent-filter>
-        </service>
-        <service android:name=".s.Alias02" android:exported="true" android:enabled="true" >
-            <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.app.sub2/android.content.componentalias.tests.app.s.Target02" />
-            <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
-            <intent-filter><action android:name="android.content.componentalias.tests.app.IS_ALIAS_02" /></intent-filter>
-        </service>
-        <service android:name=".s.Alias03" android:exported="true" android:enabled="true" >
-            <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.app.sub1/android.content.componentalias.tests.app.s.Target03" />
-            <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
-            <intent-filter><action android:name="android.content.componentalias.tests.app.IS_ALIAS_03" /></intent-filter>
-        </service>
-        <service android:name=".s.Alias04" android:exported="true" android:enabled="true" >
-            <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.app.sub2/android.content.componentalias.tests.app.s.Target04" />
-            <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
-            <intent-filter><action android:name="android.content.componentalias.tests.app.IS_ALIAS_04" /></intent-filter>
-        </service>
-        <service android:name=".s.Alias05" android:exported="true" android:enabled="true" >
-            <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.app.sub1/android.content.componentalias.tests.app.s.Target05" />
-            <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
-            <intent-filter><action android:name="android.content.componentalias.tests.app.IS_ALIAS_05" /></intent-filter>
-        </service>
-
-        <!-- Target components -->
-
-        <service android:name=".s.Target01" android:exported="true" android:enabled="true" >
-        </service>
-        <service android:name=".s.Target02" android:exported="true" android:enabled="true" >
-        </service>
-        <service android:name=".s.Target03" android:exported="true" android:enabled="true" >
-        </service>
-        <service android:name=".s.Target04" android:exported="true" android:enabled="true" >
-        </service>
-        <service android:name=".s.Target05" android:exported="true" android:enabled="true" >
-        </service>
-    </application>
-</manifest>
diff --git a/tests/componentalias/apps/AndroidManifest_sub.xml b/tests/componentalias/apps/AndroidManifest_sub.xml
deleted file mode 100755
index 2ddd965..0000000
--- a/tests/componentalias/apps/AndroidManifest_sub.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.content.componentalias.tests.app" >
-
-    <application>
-        <!-- Only contain the target components -->
-
-        <service android:name=".s.Target01" android:exported="true" android:enabled="true" >
-        </service>
-        <service android:name=".s.Target02" android:exported="true" android:enabled="true" >
-        </service>
-        <service android:name=".s.Target03" android:exported="true" android:enabled="true" >
-        </service>
-        <service android:name=".s.Target04" android:exported="true" android:enabled="true" >
-        </service>
-        <service android:name=".s.Target05" android:exported="true" android:enabled="true" >
-        </service>
-    </application>
-</manifest>
diff --git a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target05.java b/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target05.java
deleted file mode 100644
index 77060cd..0000000
--- a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target05.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.content.componentalias.tests.app.s;
-
-public class Target05 extends BaseService {
-}
diff --git a/tests/componentalias/src/android/content/componentalias/tests/BaseComponentAliasTest.java b/tests/componentalias/src/android/content/componentalias/tests/BaseComponentAliasTest.java
new file mode 100644
index 0000000..a62d9eb
--- /dev/null
+++ b/tests/componentalias/src/android/content/componentalias/tests/BaseComponentAliasTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.componentalias.tests;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.provider.DeviceConfig;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.DeviceConfigStateHelper;
+import com.android.compatibility.common.util.ShellUtils;
+import com.android.compatibility.common.util.TestUtils;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+
+import java.util.function.Consumer;
+
+public class BaseComponentAliasTest {
+    protected static final Context sContext = InstrumentationRegistry.getTargetContext();
+
+    protected static final DeviceConfigStateHelper sDeviceConfig = new DeviceConfigStateHelper(
+            DeviceConfig.NAMESPACE_ACTIVITY_MANAGER);
+    @Before
+    public void enableComponentAlias() throws Exception {
+        sDeviceConfig.set("component_alias_overrides", "");
+        sDeviceConfig.set("enable_experimental_component_alias", "true");
+
+        // Device config propagation happens on a handler, so we need to wait for AM to
+        // actually set it.
+        TestUtils.waitUntil("Wait until component alias is actually enabled", () -> {
+            return ShellUtils.runShellCommand("dumpsys activity component-alias")
+                    .indexOf("Enabled: true") > 0;
+        });
+    }
+
+    @AfterClass
+    public static void restoreDeviceConfig() throws Exception {
+        sDeviceConfig.close();
+    }
+
+    protected static void log(String message) {
+        Log.i(ComponentAliasTestCommon.TAG, "[" + sContext.getPackageName() + "] " + message);
+    }
+
+    /**
+     * Defines a test target.
+     */
+    public static class Combo {
+        public final ComponentName alias;
+        public final ComponentName target;
+        public final String action;
+
+        public Combo(ComponentName alias, ComponentName target, String action) {
+            this.alias = alias;
+            this.target = target;
+            this.action = action;
+        }
+
+        @Override
+        public String toString() {
+            return "Combo{"
+                    + "alias=" + toString(alias)
+                    + ", target=" + toString(target)
+                    + ", action='" + action + '\''
+                    + '}';
+        }
+
+        private static String toString(ComponentName cn) {
+            return cn == null ? "[null]" : cn.flattenToShortString();
+        }
+
+        public void apply(Consumer<Combo> callback) {
+            log("Testing for: " + this);
+            callback.accept(this);
+        }
+    }
+}
diff --git a/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasBroadcastTest.java b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasBroadcastTest.java
new file mode 100644
index 0000000..eab0a6c
--- /dev/null
+++ b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasBroadcastTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.componentalias.tests;
+
+import static android.content.componentalias.tests.ComponentAliasTestCommon.MAIN_PACKAGE;
+import static android.content.componentalias.tests.ComponentAliasTestCommon.TAG;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ComponentName;
+import android.content.Intent;
+
+import com.android.compatibility.common.util.BroadcastMessenger.Receiver;
+
+import org.junit.Test;
+
+import java.util.function.Consumer;
+
+public class ComponentAliasBroadcastTest extends BaseComponentAliasTest {
+    private void forEachCombo(Consumer<Combo> callback) {
+        new Combo(
+                new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".b.Alias00"),
+                new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".b.Target00"),
+                MAIN_PACKAGE + ".IS_ALIAS_00").apply(callback);
+
+        // TODO: This still don't pass -- fix it. But there seems to be an issue with
+        // `am instrument`, so need to fix that first...
+//        new Combo(
+//                new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".b.Alias01"),
+//                new ComponentName(SUB1_PACKAGE, MAIN_PACKAGE + ".b.Target01"),
+//                MAIN_PACKAGE + ".IS_ALIAS_01").apply(callback);
+//        new Combo(
+//                new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".b.Alias02"),
+//                new ComponentName(SUB2_PACKAGE, MAIN_PACKAGE + ".b.Target02"),
+//                MAIN_PACKAGE + ".IS_ALIAS_02").apply(callback);
+    }
+
+    @Test
+    public void testBroadcast_explicitComponentName() {
+        forEachCombo((c) -> {
+            Intent i = new Intent().setComponent(c.alias);
+            i.setAction("ACTION_BROADCAST");
+            ComponentAliasMessage m;
+
+            try (Receiver<ComponentAliasMessage> receiver = new Receiver<>(sContext, TAG)) {
+                log("Sending: " + i);
+                sContext.sendBroadcast(i);
+
+                m = receiver.waitForNextMessage();
+
+                assertThat(m.getMethodName()).isEqualTo("onReceive");
+                assertThat(m.getSenderIdentity()).isEqualTo(c.target.flattenToShortString());
+
+                // The broadcast intent will always have the receiving component name set.
+                assertThat(m.getIntent().getComponent()).isEqualTo(c.target);
+
+                receiver.ensureNoMoreMessages();
+            }
+        });
+    }
+
+    @Test
+    public void testBroadcast_explicitPackageName() {
+        forEachCombo((c) -> {
+            Intent i = new Intent().setPackage(c.alias.getPackageName());
+            i.setAction(c.action);
+            ComponentAliasMessage m;
+
+            try (Receiver<ComponentAliasMessage> receiver = new Receiver<>(sContext, TAG)) {
+                log("Sending broadcast: " + i);
+                sContext.sendBroadcast(i);
+
+                m = receiver.waitForNextMessage();
+
+                assertThat(m.getMethodName()).isEqualTo("onReceive");
+                assertThat(m.getSenderIdentity()).isEqualTo(c.target.flattenToShortString());
+
+                // The broadcast intent will always have the receiving component name set.
+                assertThat(m.getIntent().getComponent()).isEqualTo(c.target);
+
+                receiver.ensureNoMoreMessages();
+            }
+        });
+    }
+}
diff --git a/tests/componentalias/common/android/content/componentalias/tests/common/ComponentAliasMessage.java b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasMessage.java
similarity index 94%
rename from tests/componentalias/common/android/content/componentalias/tests/common/ComponentAliasMessage.java
rename to tests/componentalias/src/android/content/componentalias/tests/ComponentAliasMessage.java
index 399c070..d41696f 100644
--- a/tests/componentalias/common/android/content/componentalias/tests/common/ComponentAliasMessage.java
+++ b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasMessage.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.componentalias.tests.common;
+package android.content.componentalias.tests;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -28,7 +28,7 @@
  * Parcelabe containing a "message" that's meant to be delivered via BroadcastMessenger.
  *
  * To add a new field, just add a private member field, and run:
- * codegen $ANDROID_BUILD_TOP/frameworks/base/tests/componentalias/common/android/content/componentalias/tests/common/ComponentAliasMessage.java
+ * codegen $ANDROID_BUILD_TOP/frameworks/base/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasMessage.java
  */
 @DataClass(
         genConstructor = false,
@@ -62,7 +62,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/componentalias/common/android/content/componentalias/tests/common/ComponentAliasMessage.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasMessage.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -201,9 +201,9 @@
     };
 
     @DataClass.Generated(
-            time = 1629137098129L,
+            time = 1630098801203L,
             codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/tests/componentalias/common/android/content/componentalias/tests/common/ComponentAliasMessage.java",
+            sourceFile = "frameworks/base/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasMessage.java",
             inputSignatures = "private @android.annotation.Nullable java.lang.String mMessage\nprivate @android.annotation.Nullable java.lang.String mMethodName\nprivate @android.annotation.Nullable java.lang.String mSenderIdentity\nprivate @android.annotation.Nullable android.content.Intent mIntent\nprivate @android.annotation.Nullable android.content.ComponentName mComponent\nclass ComponentAliasMessage extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genSetters=true, genToString=true, genAidl=false)")
     @Deprecated
     private void __metadata() {}
diff --git a/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasServiceTest.java b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasServiceTest.java
index 81fc9bf..f0ff088 100644
--- a/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasServiceTest.java
+++ b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasServiceTest.java
@@ -17,34 +17,30 @@
 package android.content.componentalias.tests;
 
 import static android.content.Context.BIND_AUTO_CREATE;
-import static android.content.componentalias.tests.common.ComponentAliasTestCommon.APP_PACKAGE;
-import static android.content.componentalias.tests.common.ComponentAliasTestCommon.SUB1_PACKAGE;
-import static android.content.componentalias.tests.common.ComponentAliasTestCommon.SUB2_PACKAGE;
-import static android.content.componentalias.tests.common.ComponentAliasTestCommon.TAG;
+import static android.content.componentalias.tests.ComponentAliasTestCommon.MAIN_PACKAGE;
+import static android.content.componentalias.tests.ComponentAliasTestCommon.SUB1_PACKAGE;
+import static android.content.componentalias.tests.ComponentAliasTestCommon.SUB2_PACKAGE;
+import static android.content.componentalias.tests.ComponentAliasTestCommon.TAG;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.hamcrest.core.IsNot.not;
+
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.content.componentalias.tests.common.ComponentAliasMessage;
 import android.os.IBinder;
-import android.provider.DeviceConfig;
-import android.util.Log;
-
-import androidx.test.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.BroadcastMessenger;
 import com.android.compatibility.common.util.BroadcastMessenger.Receiver;
-import com.android.compatibility.common.util.DeviceConfigStateHelper;
 import com.android.compatibility.common.util.ShellUtils;
 import com.android.compatibility.common.util.TestUtils;
 
-import org.junit.AfterClass;
-import org.junit.Before;
+import org.junit.Assume;
 import org.junit.Test;
 
+import java.util.function.Consumer;
+
 /**
  * Test for the experimental "Component alias" feature.
  *
@@ -54,30 +50,7 @@
  * Note all the helper APKs are battery-exempted (via AndroidTest.xml), so they can run
  * BG services.
  */
-public class ComponentAliasServiceTest {
-
-    private static final Context sContext = InstrumentationRegistry.getTargetContext();
-
-    private static final DeviceConfigStateHelper sDeviceConfig = new DeviceConfigStateHelper(
-            DeviceConfig.NAMESPACE_ACTIVITY_MANAGER);
-    @Before
-    public void enableComponentAlias() throws Exception {
-        sDeviceConfig.set("component_alias_overrides", "");
-        sDeviceConfig.set("enable_experimental_component_alias", "true");
-
-        // Device config propagation happens on a handler, so we need to wait for AM to
-        // actually set it.
-        TestUtils.waitUntil("Wait until component alias is actually enabled", () -> {
-            return ShellUtils.runShellCommand("dumpsys activity component-alias")
-                    .indexOf("Enabled: true") > 0;
-        });
-    }
-
-    @AfterClass
-    public static void restoreDeviceConfig() throws Exception {
-        sDeviceConfig.close();
-    }
-
+public class ComponentAliasServiceTest extends BaseComponentAliasTest {
     /**
      * Service connection used throughout the tests. It sends a message for each callback via
      * the messenger.
@@ -85,59 +58,59 @@
     private static final ServiceConnection sServiceConnection = new ServiceConnection() {
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
-            Log.w(TAG, "onServiceConnected: " + name);
+            log("onServiceConnected: " + name);
 
             ComponentAliasMessage m = new ComponentAliasMessage()
                     .setSenderIdentity("sServiceConnection")
                     .setMethodName("onServiceConnected")
                     .setComponent(name);
 
-            BroadcastMessenger.send(sContext, sContext.getPackageName(), m);
+            BroadcastMessenger.send(sContext, TAG, m);
         }
 
         @Override
         public void onServiceDisconnected(ComponentName name) {
-            Log.w(TAG, "onServiceDisconnected: " + name);
+            log("onServiceDisconnected: " + name);
 
             ComponentAliasMessage m = new ComponentAliasMessage()
                     .setSenderIdentity("sServiceConnection")
                     .setMethodName("onServiceDisconnected")
                     .setComponent(name);
 
-            BroadcastMessenger.send(sContext, sContext.getPackageName(), m);
+            BroadcastMessenger.send(sContext, TAG, m);
         }
 
         @Override
         public void onBindingDied(ComponentName name) {
-            Log.w(TAG, "onBindingDied: " + name);
+            log("onBindingDied: " + name);
 
             ComponentAliasMessage m = new ComponentAliasMessage()
                     .setSenderIdentity("sServiceConnection")
                     .setMethodName("onBindingDied");
 
-            BroadcastMessenger.send(sContext, sContext.getPackageName(), m);
+            BroadcastMessenger.send(sContext, TAG, m);
         }
 
         @Override
         public void onNullBinding(ComponentName name) {
-            Log.w(TAG, "onNullBinding: " + name);
+            log("onNullBinding: " + name);
 
             ComponentAliasMessage m = new ComponentAliasMessage()
                     .setSenderIdentity("sServiceConnection")
                     .setMethodName("onNullBinding");
 
-            BroadcastMessenger.send(sContext, sContext.getPackageName(), m);
+            BroadcastMessenger.send(sContext, TAG, m);
         }
     };
 
     private void testStartAndStopService_common(
             Intent originalIntent,
             ComponentName componentNameForClient,
-            ComponentName componentNameForTarget) throws Exception {
+            ComponentName componentNameForTarget) {
 
         ComponentAliasMessage m;
 
-        try (Receiver<ComponentAliasMessage> receiver = new Receiver<>(sContext)) {
+        try (Receiver<ComponentAliasMessage> receiver = new Receiver<>(sContext, TAG)) {
             // Start the service.
             ComponentName result = sContext.startService(originalIntent);
             assertThat(result).isEqualTo(componentNameForClient);
@@ -167,40 +140,51 @@
         }
     }
 
-    @Test
-    public void testStartAndStopService_explicitComponentName() throws Exception {
-        Intent i = new Intent().setComponent(
-                new ComponentName(APP_PACKAGE, APP_PACKAGE + ".s.Alias01"));
-
-        ComponentName alias = new ComponentName(APP_PACKAGE, APP_PACKAGE + ".s.Alias01");
-        ComponentName target = new ComponentName(SUB1_PACKAGE, APP_PACKAGE + ".s.Target01");
-
-        testStartAndStopService_common(i, alias, target);
+    private void forEachCombo(Consumer<Combo> callback) {
+        new Combo(
+                new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".s.Alias00"),
+                new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".s.Target00"),
+                MAIN_PACKAGE + ".IS_ALIAS_00").apply(callback);
+        new Combo(
+                new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".s.Alias01"),
+                new ComponentName(SUB1_PACKAGE, MAIN_PACKAGE + ".s.Target01"),
+                MAIN_PACKAGE + ".IS_ALIAS_01").apply(callback);
+        new Combo(
+                new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".s.Alias02"),
+                new ComponentName(SUB2_PACKAGE, MAIN_PACKAGE + ".s.Target02"),
+                MAIN_PACKAGE + ".IS_ALIAS_02").apply(callback);
     }
 
     @Test
-    public void testStartAndStopService_explicitPackageName() throws Exception {
-        Intent i = new Intent().setPackage(APP_PACKAGE);
-        i.setAction(APP_PACKAGE + ".IS_ALIAS_02");
+    public void testStartAndStopService_explicitComponentName() {
+        forEachCombo((c) -> {
+            Intent i = new Intent().setComponent(c.alias);
+            testStartAndStopService_common(i, c.alias, c.target);
+        });
+    }
 
-        ComponentName alias = new ComponentName(APP_PACKAGE, APP_PACKAGE + ".s.Alias02");
-        ComponentName target = new ComponentName(SUB2_PACKAGE, APP_PACKAGE + ".s.Target02");
+    @Test
+    public void testStartAndStopService_explicitPackageName() {
+        forEachCombo((c) -> {
+            Intent i = new Intent().setPackage(c.alias.getPackageName());
+            i.setAction(c.action);
 
-        testStartAndStopService_common(i, alias, target);
+            testStartAndStopService_common(i, c.alias, c.target);
+        });
     }
 
     @Test
     public void testStartAndStopService_override() throws Exception {
-        Intent i = new Intent().setPackage(APP_PACKAGE);
-        i.setAction(APP_PACKAGE + ".IS_ALIAS_01");
+        Intent i = new Intent().setPackage(MAIN_PACKAGE);
+        i.setAction(MAIN_PACKAGE + ".IS_ALIAS_01");
 
         // Change some of the aliases from what's defined in <meta-data>.
 
-        ComponentName aliasA = new ComponentName(APP_PACKAGE, APP_PACKAGE + ".s.Alias01");
-        ComponentName targetA = new ComponentName(APP_PACKAGE, APP_PACKAGE + ".s.Target02");
+        ComponentName aliasA = new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".s.Alias01");
+        ComponentName targetA = new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".s.Target02");
 
-        ComponentName aliasB = new ComponentName(APP_PACKAGE, APP_PACKAGE + ".s.Alias02");
-        ComponentName targetB = new ComponentName(APP_PACKAGE, APP_PACKAGE + ".s.Target01");
+        ComponentName aliasB = new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".s.Alias02");
+        ComponentName targetB = new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".s.Target01");
 
         sDeviceConfig.set("component_alias_overrides",
                 aliasA.flattenToShortString() + ":" + targetA.flattenToShortString()
@@ -220,10 +204,10 @@
     private void testBindAndUnbindService_common(
             Intent originalIntent,
             ComponentName componentNameForClient,
-            ComponentName componentNameForTarget) throws Exception {
+            ComponentName componentNameForTarget) {
         ComponentAliasMessage m;
 
-        try (Receiver<ComponentAliasMessage> receiver = new Receiver<>(sContext)) {
+        try (Receiver<ComponentAliasMessage> receiver = new Receiver<>(sContext, TAG)) {
             // Bind to the service.
             assertThat(sContext.bindService(
                     originalIntent, sServiceConnection, BIND_AUTO_CREATE)).isTrue();
@@ -262,38 +246,46 @@
     }
 
     @Test
-    public void testBindService_explicitComponentName() throws Exception {
-        Intent i = new Intent().setComponent(
-                new ComponentName(APP_PACKAGE, APP_PACKAGE + ".s.Alias01"));
+    public void testBindService_explicitComponentName() {
+        forEachCombo((c) -> {
+            Intent i = new Intent().setComponent(c.alias);
 
-        testBindAndUnbindService_common(i,
-                new ComponentName(APP_PACKAGE, APP_PACKAGE + ".s.Alias01"),
-                new ComponentName(SUB1_PACKAGE, APP_PACKAGE + ".s.Target01"));
+            testBindAndUnbindService_common(i, c.alias, c.target);
+        });
+
     }
 
     @Test
-    public void testBindService_explicitPackageName() throws Exception {
-        Intent i = new Intent().setPackage(APP_PACKAGE);
-        i.setAction(APP_PACKAGE + ".IS_ALIAS_02");
+    public void testBindService_explicitPackageName() {
+        forEachCombo((c) -> {
+            Intent i = new Intent().setPackage(c.alias.getPackageName());
+            i.setAction(c.action);
 
-        testBindAndUnbindService_common(i,
-                new ComponentName(APP_PACKAGE, APP_PACKAGE + ".s.Alias02"),
-                new ComponentName(SUB2_PACKAGE, APP_PACKAGE + ".s.Target02"));
+            testBindAndUnbindService_common(i, c.alias, c.target);
+        });
     }
 
+    /**
+     * Make sure, when the service process is killed, the client will get a callback with the
+     * right component name.
+     */
     @Test
-    public void testBindService_serviceKilled() throws Exception {
-        Intent originalIntent = new Intent().setPackage(APP_PACKAGE);
-        originalIntent.setAction(APP_PACKAGE + ".IS_ALIAS_02");
+    public void testBindService_serviceKilled() {
+
+        // We need to kill SUB2_PACKAGE, don't run it for this package.
+        Assume.assumeThat(sContext.getPackageName(), not(SUB2_PACKAGE));
+
+        Intent originalIntent = new Intent().setPackage(MAIN_PACKAGE);
+        originalIntent.setAction(MAIN_PACKAGE + ".IS_ALIAS_02");
 
         final ComponentName componentNameForClient =
-                new ComponentName(APP_PACKAGE, APP_PACKAGE + ".s.Alias02");
+                new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".s.Alias02");
         final ComponentName componentNameForTarget =
-                new ComponentName(SUB2_PACKAGE, APP_PACKAGE + ".s.Target02");
+                new ComponentName(SUB2_PACKAGE, MAIN_PACKAGE + ".s.Target02");
 
         ComponentAliasMessage m;
 
-        try (Receiver<ComponentAliasMessage> receiver = new Receiver<>(sContext)) {
+        try (Receiver<ComponentAliasMessage> receiver = new Receiver<>(sContext, TAG)) {
             // Bind to the service.
             assertThat(sContext.bindService(
                     originalIntent, sServiceConnection, BIND_AUTO_CREATE)).isTrue();
@@ -306,6 +298,7 @@
             m = receiver.waitForNextMessage();
             assertThat(m.getMethodName()).isEqualTo("onServiceConnected");
             assertThat(m.getComponent()).isEqualTo(componentNameForClient);
+            // We don't need to check all the fields because these are tested else where.
 
             // Now kill the service process.
             ShellUtils.runShellCommand("su 0 killall %s", SUB2_PACKAGE);
diff --git a/tests/componentalias/common/android/content/componentalias/tests/common/ComponentAliasTestCommon.java b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasTestCommon.java
similarity index 77%
rename from tests/componentalias/common/android/content/componentalias/tests/common/ComponentAliasTestCommon.java
rename to tests/componentalias/src/android/content/componentalias/tests/ComponentAliasTestCommon.java
index f306072..165d728 100644
--- a/tests/componentalias/common/android/content/componentalias/tests/common/ComponentAliasTestCommon.java
+++ b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasTestCommon.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.componentalias.tests.common;
+package android.content.componentalias.tests;
 
 public final class ComponentAliasTestCommon {
     private ComponentAliasTestCommon() {
@@ -21,9 +21,8 @@
 
     public static final String TAG = "ComponentAliasTest";
 
-    public static final String TEST_PACKAGE = "android.content.componentalias.tests";
+    public static final String MAIN_PACKAGE = "android.content.componentalias.tests";
 
-    public static final String APP_PACKAGE = "android.content.componentalias.tests.app";
-    public static final String SUB1_PACKAGE = "android.content.componentalias.tests.app.sub1";
-    public static final String SUB2_PACKAGE = "android.content.componentalias.tests.app.sub2";
+    public static final String SUB1_PACKAGE = "android.content.componentalias.tests.sub1";
+    public static final String SUB2_PACKAGE = "android.content.componentalias.tests.sub2";
 }
diff --git a/tests/componentalias/src/android/content/componentalias/tests/b/BaseReceiver.java b/tests/componentalias/src/android/content/componentalias/tests/b/BaseReceiver.java
new file mode 100644
index 0000000..1d05e72
--- /dev/null
+++ b/tests/componentalias/src/android/content/componentalias/tests/b/BaseReceiver.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.componentalias.tests.b;
+
+import static android.content.componentalias.tests.ComponentAliasTestCommon.TAG;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.componentalias.tests.ComponentAliasMessage;
+import android.util.Log;
+
+import com.android.compatibility.common.util.BroadcastMessenger;
+
+public class BaseReceiver extends BroadcastReceiver {
+    private String getMyIdentity(Context context) {
+        return (new ComponentName(context.getPackageName(), this.getClass().getCanonicalName()))
+                .flattenToShortString();
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        Log.i(TAG, "onReceive: on " + getMyIdentity(context) + " intent=" + intent);
+        ComponentAliasMessage m = new ComponentAliasMessage()
+                .setSenderIdentity(getMyIdentity(context))
+                .setMethodName("onReceive")
+                .setIntent(intent);
+        BroadcastMessenger.send(context, TAG, m);
+    }
+}
diff --git a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java b/tests/componentalias/src/android/content/componentalias/tests/b/Target00.java
similarity index 79%
copy from tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
copy to tests/componentalias/src/android/content/componentalias/tests/b/Target00.java
index 0e51a6b..8fb4e91 100644
--- a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
+++ b/tests/componentalias/src/android/content/componentalias/tests/b/Target00.java
@@ -13,7 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.componentalias.tests.app.s;
+package android.content.componentalias.tests.b;
 
-public class Target04 extends BaseService {
+import android.content.componentalias.tests.s.BaseService;
+
+public class Target00 extends BaseReceiver {
 }
diff --git a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java b/tests/componentalias/src/android/content/componentalias/tests/b/Target01.java
similarity index 86%
copy from tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
copy to tests/componentalias/src/android/content/componentalias/tests/b/Target01.java
index 0e51a6b..06f7a13 100644
--- a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
+++ b/tests/componentalias/src/android/content/componentalias/tests/b/Target01.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.componentalias.tests.app.s;
+package android.content.componentalias.tests.b;
 
-public class Target04 extends BaseService {
+public class Target01 extends BaseReceiver {
 }
diff --git a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java b/tests/componentalias/src/android/content/componentalias/tests/b/Target02.java
similarity index 86%
copy from tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
copy to tests/componentalias/src/android/content/componentalias/tests/b/Target02.java
index 0e51a6b..df7579d 100644
--- a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
+++ b/tests/componentalias/src/android/content/componentalias/tests/b/Target02.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.componentalias.tests.app.s;
+package android.content.componentalias.tests.b;
 
-public class Target04 extends BaseService {
+public class Target02 extends BaseReceiver {
 }
diff --git a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java b/tests/componentalias/src/android/content/componentalias/tests/b/Target03.java
similarity index 86%
copy from tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
copy to tests/componentalias/src/android/content/componentalias/tests/b/Target03.java
index 0e51a6b..5ae5521 100644
--- a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
+++ b/tests/componentalias/src/android/content/componentalias/tests/b/Target03.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.componentalias.tests.app.s;
+package android.content.componentalias.tests.b;
 
-public class Target04 extends BaseService {
+public class Target03 extends BaseReceiver {
 }
diff --git a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java b/tests/componentalias/src/android/content/componentalias/tests/b/Target04.java
similarity index 86%
copy from tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
copy to tests/componentalias/src/android/content/componentalias/tests/b/Target04.java
index 0e51a6b..f9b9886 100644
--- a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
+++ b/tests/componentalias/src/android/content/componentalias/tests/b/Target04.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.componentalias.tests.app.s;
+package android.content.componentalias.tests.b;
 
-public class Target04 extends BaseService {
+public class Target04 extends BaseReceiver {
 }
diff --git a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/BaseService.java b/tests/componentalias/src/android/content/componentalias/tests/s/BaseService.java
similarity index 81%
rename from tests/componentalias/apps/src/android/content/componentalias/tests/app/s/BaseService.java
rename to tests/componentalias/src/android/content/componentalias/tests/s/BaseService.java
index fb67829..535d9b8 100644
--- a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/BaseService.java
+++ b/tests/componentalias/src/android/content/componentalias/tests/s/BaseService.java
@@ -13,15 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.componentalias.tests.app.s;
+package android.content.componentalias.tests.s;
 
-import static android.content.componentalias.tests.common.ComponentAliasTestCommon.TAG;
-import static android.content.componentalias.tests.common.ComponentAliasTestCommon.TEST_PACKAGE;
+import static android.content.componentalias.tests.ComponentAliasTestCommon.TAG;
 
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Intent;
-import android.content.componentalias.tests.common.ComponentAliasMessage;
+import android.content.componentalias.tests.ComponentAliasMessage;
 import android.os.Binder;
 import android.os.IBinder;
 import android.util.Log;
@@ -41,7 +40,7 @@
                 .setSenderIdentity(getMyIdentity())
                 .setMethodName("onStartCommand")
                 .setIntent(intent);
-        BroadcastMessenger.send(this, TEST_PACKAGE, m);
+        BroadcastMessenger.send(this, TAG, m);
 
         return START_NOT_STICKY;
     }
@@ -53,7 +52,7 @@
         ComponentAliasMessage m = new ComponentAliasMessage()
                 .setSenderIdentity(getMyIdentity())
                 .setMethodName("onDestroy");
-        BroadcastMessenger.send(this, TEST_PACKAGE, m);
+        BroadcastMessenger.send(this, TAG, m);
     }
 
     @Override
@@ -64,7 +63,7 @@
                 .setSenderIdentity(getMyIdentity())
                 .setMethodName("onBind")
                 .setIntent(intent);
-        BroadcastMessenger.send(this, TEST_PACKAGE, m);
+        BroadcastMessenger.send(this, TAG, m);
 
         return new Binder();
     }
diff --git a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java b/tests/componentalias/src/android/content/componentalias/tests/s/Target00.java
similarity index 86%
copy from tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
copy to tests/componentalias/src/android/content/componentalias/tests/s/Target00.java
index 0e51a6b..64b91f5 100644
--- a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
+++ b/tests/componentalias/src/android/content/componentalias/tests/s/Target00.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.componentalias.tests.app.s;
+package android.content.componentalias.tests.s;
 
-public class Target04 extends BaseService {
+public class Target00 extends BaseService {
 }
diff --git a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target01.java b/tests/componentalias/src/android/content/componentalias/tests/s/Target01.java
similarity index 92%
rename from tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target01.java
rename to tests/componentalias/src/android/content/componentalias/tests/s/Target01.java
index 87e48cb..bd58999 100644
--- a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target01.java
+++ b/tests/componentalias/src/android/content/componentalias/tests/s/Target01.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.componentalias.tests.app.s;
+package android.content.componentalias.tests.s;
 
 public class Target01 extends BaseService {
 }
diff --git a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target02.java b/tests/componentalias/src/android/content/componentalias/tests/s/Target02.java
similarity index 92%
rename from tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target02.java
rename to tests/componentalias/src/android/content/componentalias/tests/s/Target02.java
index 0e8a6a8..0ddf818 100644
--- a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target02.java
+++ b/tests/componentalias/src/android/content/componentalias/tests/s/Target02.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.componentalias.tests.app.s;
+package android.content.componentalias.tests.s;
 
 public class Target02 extends BaseService {
 }
diff --git a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target03.java b/tests/componentalias/src/android/content/componentalias/tests/s/Target03.java
similarity index 92%
rename from tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target03.java
rename to tests/componentalias/src/android/content/componentalias/tests/s/Target03.java
index b7990bb..0dbc050 100644
--- a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target03.java
+++ b/tests/componentalias/src/android/content/componentalias/tests/s/Target03.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.componentalias.tests.app.s;
+package android.content.componentalias.tests.s;
 
 public class Target03 extends BaseService {
 }
diff --git a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java b/tests/componentalias/src/android/content/componentalias/tests/s/Target04.java
similarity index 92%
rename from tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
rename to tests/componentalias/src/android/content/componentalias/tests/s/Target04.java
index 0e51a6b..0994258 100644
--- a/tests/componentalias/apps/src/android/content/componentalias/tests/app/s/Target04.java
+++ b/tests/componentalias/src/android/content/componentalias/tests/s/Target04.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.componentalias.tests.app.s;
+package android.content.componentalias.tests.s;
 
 public class Target04 extends BaseService {
 }
diff --git a/tests/componentalias/common/com/android/compatibility/common/util/BroadcastMessenger.java b/tests/componentalias/src/com/android/compatibility/common/util/BroadcastMessenger.java
similarity index 67%
rename from tests/componentalias/common/com/android/compatibility/common/util/BroadcastMessenger.java
rename to tests/componentalias/src/com/android/compatibility/common/util/BroadcastMessenger.java
index 175082e..a3a2abe 100644
--- a/tests/componentalias/common/com/android/compatibility/common/util/BroadcastMessenger.java
+++ b/tests/componentalias/src/com/android/compatibility/common/util/BroadcastMessenger.java
@@ -16,6 +16,7 @@
 package com.android.compatibility.common.util;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -25,23 +26,27 @@
 import android.os.SystemClock;
 import android.util.Log;
 
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
-
 import java.util.ArrayList;
+import java.util.Objects;
 
 /**
  * Provides a one-way communication mechanism using a Parcelable as a payload, via broadcasts.
  *
+ * Use {@link #send(Context, String, Parcelable)} to send a message.
+ * USe {@link Receiver} to receive a message.
+ *
+ * Pick a unique "suffix" for your test, and use it with both the sender and receiver, in order
+ * to avoid "cross-talks" between different tests. (if they ever run at the same time.)
+ *
  * TODO: Move it to compatibility-device-util-axt.
  */
 public final class BroadcastMessenger {
     private static final String TAG = "BroadcastMessenger";
 
     private static final String ACTION_MESSAGE =
-            "com.android.compatibility.common.util.BroadcastMessenger.ACTION_MESSAGE";
+            "com.android.compatibility.common.util.BroadcastMessenger.ACTION_MESSAGE_";
     private static final String ACTION_PING =
-            "com.android.compatibility.common.util.BroadcastMessenger.ACTION_PING";
+            "com.android.compatibility.common.util.BroadcastMessenger.ACTION_PING_";
     private static final String EXTRA_MESSAGE =
             "com.android.compatibility.common.util.BroadcastMessenger.EXTRA_MESSAGE";
 
@@ -52,12 +57,14 @@
     private static final String EXTRA_SENT_TIME =
             "com.android.compatibility.common.util.BroadcastMessenger.EXTRA_SENT_TIME";
 
+    public static final int DEFAULT_TIMEOUT_MS = 10_000;
+
     private static long getCurrentTime() {
         return SystemClock.uptimeMillis();
     }
 
-    private static void sendBroadcast(@NonNull Intent i,
-            @NonNull Context context, @NonNull String receiverPackage) {
+    private static void sendBroadcast(@NonNull Intent i, @NonNull Context context,
+            @NonNull String broadcastSuffix, @Nullable String receiverPackage) {
         i.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
         i.setPackage(receiverPackage);
         i.putExtra(EXTRA_SENT_TIME, getCurrentTime());
@@ -65,21 +72,22 @@
         context.sendBroadcast(i);
     }
 
-    /** Send a message to the {@link Receiver} in a given package. */
+    /** Send a message to the {@link Receiver} expecting a given "suffix". */
     public static <T extends Parcelable> void send(@NonNull Context context,
-            @NonNull String receiverPackage, @NonNull T message) {
-        final Intent i = new Intent(ACTION_MESSAGE);
-        i.putExtra(EXTRA_MESSAGE, Preconditions.checkNotNull(message));
+            @NonNull String broadcastSuffix, @NonNull T message) {
+        final Intent i = new Intent(ACTION_MESSAGE + Objects.requireNonNull(broadcastSuffix));
+        i.putExtra(EXTRA_MESSAGE, Objects.requireNonNull(message));
 
         Log.i(TAG, "Sending: " + message);
-        sendBroadcast(i, context, receiverPackage);
+        sendBroadcast(i, context, broadcastSuffix, /*receiverPackage=*/ null);
     }
 
-    private static void sendPing(@NonNull Context context, @NonNull String receiverPackage) {
-        final Intent i = new Intent(ACTION_PING);
+    private static void sendPing(@NonNull Context context,@NonNull String broadcastSuffix,
+            @NonNull String receiverPackage) {
+        final Intent i = new Intent(ACTION_PING + Objects.requireNonNull(broadcastSuffix));
 
         Log.i(TAG, "Sending a ping");
-        sendBroadcast(i, context, receiverPackage);
+        sendBroadcast(i, context, broadcastSuffix, receiverPackage);
     }
 
     /**
@@ -88,9 +96,10 @@
      */
     public static final class Receiver<T extends Parcelable> implements AutoCloseable {
         private final Context mContext;
+        private final String mBroadcastSuffix;
         private final HandlerThread mReceiverThread = new HandlerThread(TAG);
 
-        @GuardedBy("mMessages")
+        // @GuardedBy("mMessages")
         private final ArrayList<T> mMessages = new ArrayList<>();
         private final long mCreatedTime = getCurrentTime();
         private boolean mRegistered;
@@ -99,12 +108,11 @@
             @Override
             public void onReceive(Context context, Intent intent) {
                 // Log.d(TAG, "Received intent: " + intent);
-                switch (intent.getAction()) {
-                    case ACTION_MESSAGE:
-                    case ACTION_PING:
-                        break;
-                    default:
-                        throw new RuntimeException("Unknown broadcast received: " + intent);
+                if (intent.getAction().equals(ACTION_MESSAGE + mBroadcastSuffix)
+                        || intent.getAction().equals(ACTION_PING + mBroadcastSuffix)) {
+                    // OK
+                } else {
+                    throw new RuntimeException("Unknown broadcast received: " + intent);
                 }
                 if (intent.getLongExtra(EXTRA_SENT_TIME, 0) < mCreatedTime) {
                     Log.i(TAG, "Dropping stale broadcast: " + intent);
@@ -127,16 +135,17 @@
         /**
          * Constructor.
          */
-        public Receiver(@NonNull Context context) {
+        public Receiver(@NonNull Context context, @NonNull String broadcastSuffix) {
             mContext = context;
+            mBroadcastSuffix = Objects.requireNonNull(broadcastSuffix);
 
             mReceiverThread.start();
 
-            final IntentFilter fi = new IntentFilter(ACTION_MESSAGE);
-            fi.addAction(ACTION_PING);
+            final IntentFilter fi = new IntentFilter(ACTION_MESSAGE + mBroadcastSuffix);
+            fi.addAction(ACTION_PING + mBroadcastSuffix);
 
-            context.registerReceiver(mReceiver, fi, /** permission=*/ null,
-                    mReceiverThread.getThreadHandler());
+            context.registerReceiver(mReceiver, fi, /* permission=*/ null,
+                    mReceiverThread.getThreadHandler(), Context.RECEIVER_EXPORTED);
             mRegistered = true;
         }
 
@@ -153,15 +162,15 @@
          * Receive the next message with a 60 second timeout.
          */
         @NonNull
-        public T waitForNextMessage() throws Exception {
-            return waitForNextMessage(60_000);
+        public T waitForNextMessage() {
+            return waitForNextMessage(DEFAULT_TIMEOUT_MS);
         }
 
         /**
          * Receive the next message.
          */
         @NonNull
-        public T waitForNextMessage(long timeoutMillis) throws Exception {
+        public T waitForNextMessage(long timeoutMillis) {
             synchronized (mMessages) {
                 final long timeout = System.currentTimeMillis() + timeoutMillis;
                 while (mMessages.size() == 0) {
@@ -169,7 +178,11 @@
                     if (wait <= 0) {
                         throw new RuntimeException("Timeout waiting for the next message");
                     }
-                    mMessages.wait(wait);
+                    try {
+                        mMessages.wait(wait);
+                    } catch (InterruptedException e) {
+                        throw new RuntimeException(e);
+                    }
                 }
                 return mMessages.remove(0);
             }
@@ -180,9 +193,9 @@
          *
          * Call it before {@link #close()}.
          */
-        public void ensureNoMoreMessages() throws Exception {
+        public void ensureNoMoreMessages() {
             // Send a ping to myself.
-            sendPing(mContext, mContext.getPackageName());
+            sendPing(mContext, mBroadcastSuffix, mContext.getPackageName());
 
             final T m = waitForNextMessage();
             if (m == null) {
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index 0f84f6e..c9a8947a 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -322,6 +322,7 @@
         triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID);
         verify(mSafeModeTimeoutAlarm).cancel();
         assertFalse(mGatewayConnection.isInSafeMode());
+        verifySafeModeStateAndCallbackFired(1 /* invocationCount */, false /* isInSafeMode */);
     }
 
     @Test
@@ -391,6 +392,7 @@
 
         triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID);
 
+        verifySafeModeStateAndCallbackFired(2 /* invocationCount */, false /* isInSafeMode */);
         assertFalse(mGatewayConnection.isInSafeMode());
     }
 
@@ -400,7 +402,7 @@
         mTestLooper.dispatchAll();
 
         triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID);
-        assertFalse(mGatewayConnection.isInSafeMode());
+        verifySafeModeStateAndCallbackFired(1 /* invocationCount */, false /* isInSafeMode */);
 
         // Trigger a failed validation, and the subsequent safemode timeout.
         triggerValidation(NetworkAgent.VALIDATION_STATUS_NOT_VALID);
@@ -416,7 +418,7 @@
         runnableCaptor.getValue().run();
         mTestLooper.dispatchAll();
 
-        assertTrue(mGatewayConnection.isInSafeMode());
+        verifySafeModeStateAndCallbackFired(2 /* invocationCount */, true /* isInSafeMode */);
     }
 
     private Consumer<VcnNetworkAgent> setupNetworkAndGetUnwantedCallback() {
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
index a696b3a..64d0bca 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
@@ -23,7 +23,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.CALLS_REAL_METHODS;
@@ -301,6 +300,11 @@
                 expectCanceled);
     }
 
+    protected void verifySafeModeStateAndCallbackFired(int invocationCount, boolean isInSafeMode) {
+        verify(mGatewayStatusCallback, times(invocationCount)).onSafeModeStatusChanged();
+        assertEquals(isInSafeMode, mGatewayConnection.isInSafeMode());
+    }
+
     protected void verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
             @NonNull State expectedState) {
         // Set a VcnNetworkAgent, and expect it to be unregistered and cleared
@@ -314,9 +318,8 @@
         delayedEvent.run();
         mTestLooper.dispatchAll();
 
-        verify(mGatewayStatusCallback).onSafeModeStatusChanged();
         assertEquals(expectedState, mGatewayConnection.getCurrentState());
-        assertTrue(mGatewayConnection.isInSafeMode());
+        verifySafeModeStateAndCallbackFired(1, true);
 
         verify(mockNetworkAgent).unregister();
         assertNull(mGatewayConnection.getNetworkAgent());
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 812e208..fecc7b3 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -769,7 +769,7 @@
     config.country[1] = 'S';
     config.orientation = ResTable_config::ORIENTATION_PORT;
     config.density = ResTable_config::DENSITY_MEDIUM;
-    config.sdkVersion = 10000; // Very high.
+    config.sdkVersion = SDK_CUR_DEVELOPMENT; // Very high.
     config.screenWidthDp = 320;
     config.screenHeightDp = 480;
     config.smallestScreenWidthDp = 320;
@@ -1306,16 +1306,30 @@
                                     splitName.string()).string());
                     }
 
+                    // For 'platformBuildVersionName', using both string and int type as a fallback
+                    // since it may be the code name of Android or the API level.
                     String8 platformBuildVersionName = AaptXml::getAttribute(tree, NULL,
                             "platformBuildVersionName");
+                    int32_t platformBuildVersionNameInt =
+                            AaptXml::getIntegerAttribute(tree, NULL, "platformBuildVersionName", 0,
+                                                         NULL);
                     if (platformBuildVersionName != "") {
                         printf(" platformBuildVersionName='%s'", platformBuildVersionName.string());
+                    } else if (platformBuildVersionNameInt > 0) {
+                        printf(" platformBuildVersionName='%d'", platformBuildVersionNameInt);
                     }
 
+                    // For 'platformBuildVersionCode', using both string and int type as a fallback
+                    // since it may be the code name of Android or the API level.
                     String8 platformBuildVersionCode = AaptXml::getAttribute(tree, NULL,
                             "platformBuildVersionCode");
+                    int32_t platformBuildVersionCodeInt =
+                            AaptXml::getIntegerAttribute(tree, NULL, "platformBuildVersionCode", 0,
+                                                         NULL);
                     if (platformBuildVersionCode != "") {
                         printf(" platformBuildVersionCode='%s'", platformBuildVersionCode.string());
+                    } else if (platformBuildVersionCodeInt > 0) {
+                        printf(" platformBuildVersionCode='%d'", platformBuildVersionCodeInt);
                     }
 
                     int32_t compileSdkVersion = AaptXml::getIntegerAttribute(tree,
@@ -1490,7 +1504,7 @@
                                         error.string());
                                 goto bail;
                             }
-                            if (name == "Donut") targetSdk = 4;
+                            if (name == "Donut") targetSdk = SDK_DONUT;
                             printf("sdkVersion:'%s'\n",
                                     ResTable::normalizeForOutput(name.string()).string());
                         } else if (code != -1) {
@@ -1512,7 +1526,12 @@
                                         error.string());
                                 goto bail;
                             }
-                            if (name == "Donut" && targetSdk < 4) targetSdk = 4;
+                            if (name == "Donut" && targetSdk < SDK_DONUT) {
+                                targetSdk = SDK_DONUT;
+                            } else if (name != "" && targetSdk == 0) {
+                                // Bump to current development version
+                                targetSdk = SDK_CUR_DEVELOPMENT;
+                            }
                             printf("targetSdkVersion:'%s'\n",
                                     ResTable::normalizeForOutput(name.string()).string());
                         } else if (code != -1) {
@@ -2122,7 +2141,7 @@
             }
 
             // Pre-1.6 implicitly granted permission compatibility logic
-            if (targetSdk < 4) {
+            if (targetSdk < SDK_DONUT) {
                 if (!hasWriteExternalStoragePermission) {
                     printUsesPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"));
                     printUsesImpliedPermission(String8("android.permission.WRITE_EXTERNAL_STORAGE"),
@@ -2149,7 +2168,7 @@
             }
 
             // Pre-JellyBean call log permission compatibility.
-            if (targetSdk < 16) {
+            if (targetSdk < SDK_JELLY_BEAN) {
                 if (!hasReadCallLogPermission && hasReadContactsPermission) {
                     printUsesPermission(String8("android.permission.READ_CALL_LOG"));
                     printUsesImpliedPermission(String8("android.permission.READ_CALL_LOG"),
@@ -2291,21 +2310,23 @@
             // the screen size support was introduced, so all default to
             // enabled.
             if (smallScreen > 0) {
-                smallScreen = targetSdk >= 4 ? -1 : 0;
+                smallScreen = targetSdk >= SDK_DONUT ? -1 : 0;
             }
             if (normalScreen > 0) {
                 normalScreen = -1;
             }
             if (largeScreen > 0) {
-                largeScreen = targetSdk >= 4 ? -1 : 0;
+                largeScreen = targetSdk >= SDK_DONUT ? -1 : 0;
             }
             if (xlargeScreen > 0) {
                 // Introduced in Gingerbread.
-                xlargeScreen = targetSdk >= 9 ? -1 : 0;
+                xlargeScreen = targetSdk >= SDK_GINGERBREAD ? -1 : 0;
             }
             if (anyDensity > 0) {
-                anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0
-                        || compatibleWidthLimitDp > 0) ? -1 : 0;
+                anyDensity = (targetSdk >= SDK_DONUT || requiresSmallestWidthDp > 0 ||
+                              compatibleWidthLimitDp > 0)
+                        ? -1
+                        : 0;
             }
             printf("supports-screens:");
             if (smallScreen != 0) {
diff --git a/tools/aapt/SdkConstants.h b/tools/aapt/SdkConstants.h
index 955581c..857b25e 100644
--- a/tools/aapt/SdkConstants.h
+++ b/tools/aapt/SdkConstants.h
@@ -47,6 +47,7 @@
     SDK_Q = 29,
     SDK_R = 30,
     SDK_S = 31,
+    SDK_CUR_DEVELOPMENT = 10000,
 };
 
 #endif // H_AAPT_SDK_CONSTANTS
diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h
index 7518e70..384346b 100644
--- a/tools/aapt2/SdkConstants.h
+++ b/tools/aapt2/SdkConstants.h
@@ -57,6 +57,7 @@
   SDK_Q = 29,
   SDK_R = 30,
   SDK_S = 31,
+  SDK_CUR_DEVELOPMENT = 10000,
 };
 
 ApiVersion FindAttributeSdkLevel(const ResourceId& id);
diff --git a/tools/aapt2/dump/DumpManifest.cpp b/tools/aapt2/dump/DumpManifest.cpp
index 145d7f8..40bbb36 100644
--- a/tools/aapt2/dump/DumpManifest.cpp
+++ b/tools/aapt2/dump/DumpManifest.cpp
@@ -92,7 +92,6 @@
 };
 
 const std::string& kAndroidNamespace = "http://schemas.android.com/apk/res/android";
-constexpr int kCurrentDevelopmentVersion = 10000;
 constexpr int kNeverForLocation = 0x00010000;
 
 /** Retrieves the attribute of the element with the specified attribute resource id. */
@@ -331,7 +330,7 @@
     ConfigDescription config;
     config.orientation = android::ResTable_config::ORIENTATION_PORT;
     config.density = android::ResTable_config::DENSITY_MEDIUM;
-    config.sdkVersion = kCurrentDevelopmentVersion; // Very high.
+    config.sdkVersion = SDK_CUR_DEVELOPMENT;  // Very high.
     config.screenWidthDp = 320;
     config.screenHeightDp = 480;
     config.smallestScreenWidthDp = 320;
@@ -621,7 +620,7 @@
     // Detect the target sdk of the element
     if  ((min_sdk_name && *min_sdk_name == "Donut")
         || (target_sdk_name && *target_sdk_name == "Donut")) {
-      extractor()->RaiseTargetSdk(4);
+      extractor()->RaiseTargetSdk(SDK_DONUT);
     }
     if (min_sdk) {
       extractor()->RaiseTargetSdk(*min_sdk);
@@ -629,7 +628,7 @@
     if (target_sdk) {
       extractor()->RaiseTargetSdk(*target_sdk);
     } else if (target_sdk_name) {
-      extractor()->RaiseTargetSdk(kCurrentDevelopmentVersion);
+      extractor()->RaiseTargetSdk(SDK_CUR_DEVELOPMENT);
     }
   }
 
@@ -746,21 +745,23 @@
     // the screen size support was introduced, so all default to
     // enabled.
     if (small_screen_temp  > 0) {
-      small_screen_temp  = target_sdk >= 4 ? -1 : 0;
+      small_screen_temp = target_sdk >= SDK_DONUT ? -1 : 0;
     }
     if (normal_screen_temp  > 0) {
       normal_screen_temp  = -1;
     }
     if (large_screen_temp  > 0) {
-      large_screen_temp  = target_sdk >= 4 ? -1 : 0;
+      large_screen_temp = target_sdk >= SDK_DONUT ? -1 : 0;
     }
     if (xlarge_screen_temp  > 0) {
       // Introduced in Gingerbread.
-      xlarge_screen_temp  = target_sdk >= 9 ? -1 : 0;
+      xlarge_screen_temp = target_sdk >= SDK_GINGERBREAD ? -1 : 0;
     }
     if (any_density_temp  > 0) {
-      any_density_temp  = (target_sdk >= 4 || requires_smallest_width_dp > 0
-          || compatible_width_limit_dp > 0) ? -1 : 0;
+      any_density_temp = (target_sdk >= SDK_DONUT || requires_smallest_width_dp > 0 ||
+                          compatible_width_limit_dp > 0)
+                             ? -1
+                             : 0;
     }
 
     // Print the formatted screen info
@@ -2030,7 +2031,7 @@
   auto write_external_permission = ElementCast<UsesPermission>(
       FindPermission(root.get(), "android.permission.WRITE_EXTERNAL_STORAGE"));
 
-  if (target_sdk() < 4) {
+  if (target_sdk() < SDK_DONUT) {
     if (!write_external_permission) {
       PrintPermission("android.permission.WRITE_EXTERNAL_STORAGE", "targetSdkVersion < 4", -1);
       insert_write_external = true;
@@ -2053,7 +2054,7 @@
   }
 
   // Pre-JellyBean call log permission compatibility.
-  if (target_sdk() < 16) {
+  if (target_sdk() < SDK_JELLY_BEAN) {
     if (!FindPermission(root.get(), "android.permission.READ_CALL_LOG")
         && FindPermission(root.get(), "android.permission.READ_CONTACTS")) {
       PrintPermission("android.permission.READ_CALL_LOG",
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsDetector.kt b/tools/lint/checks/src/main/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsDetector.kt
index 641f337..fe567da 100644
--- a/tools/lint/checks/src/main/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsDetector.kt
+++ b/tools/lint/checks/src/main/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsDetector.kt
@@ -45,7 +45,8 @@
                 evaluator.isMemberInClass(method, "android.provider.Settings.System")
         ) {
             val message = getIncidentMessageNonUserGetterMethods(getMethodSignature(method))
-            context.report(ISSUE_NON_USER_GETTER_CALLED, node, context.getLocation(node), message)
+            context.report(ISSUE_NON_USER_GETTER_CALLED, node, context.getNameLocation(node),
+                    message)
         }
     }
 
@@ -68,7 +69,7 @@
                     """,
                 category = Category.CORRECTNESS,
                 priority = 6,
-                severity = Severity.WARNING,
+                severity = Severity.ERROR,
                 implementation = Implementation(
                         CallingSettingsNonUserGetterMethodsDetector::class.java,
                         Scope.JAVA_FILE_SCOPE
diff --git a/tools/lint/checks/src/test/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsIssueDetectorTest.kt b/tools/lint/checks/src/test/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsIssueDetectorTest.kt
index 1034029..e72f384 100644
--- a/tools/lint/checks/src/test/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsIssueDetectorTest.kt
+++ b/tools/lint/checks/src/test/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsIssueDetectorTest.kt
@@ -71,13 +71,13 @@
                 .run()
                 .expect(
                         """
-                        src/test/pkg/TestClass1.java:5: Warning: \
+                        src/test/pkg/TestClass1.java:5: Error: \
                         android.provider.Settings.Secure#getInt() called from system process. \
                         Please call android.provider.Settings.Secure#getIntForUser() instead.  \
                         [NonUserGetterCalled]
                                 final int value = Secure.getInt(context.getContentResolver(),
-                                                  ^
-                        0 errors, 1 warnings
+                                                         ~~~~~~
+                        1 errors, 0 warnings
                         """.addLineContinuation()
                 )
     }
@@ -100,13 +100,13 @@
                 .run()
                 .expect(
                         """
-                        src/test/pkg/TestClass1.java:5: Warning: \
+                        src/test/pkg/TestClass1.java:5: Error: \
                         android.provider.Settings.System#getFloat() called from system process. \
                         Please call android.provider.Settings.System#getFloatForUser() instead.  \
                         [NonUserGetterCalled]
                                 final float value = System.getFloat(context.getContentResolver(),
-                                                    ^
-                        0 errors, 1 warnings
+                                                           ~~~~~~~~
+                        1 errors, 0 warnings
                         """.addLineContinuation()
                 )
     }
@@ -130,13 +130,13 @@
                 .run()
                 .expect(
                         """
-                        src/test/pkg/TestClass1.java:5: Warning: \
+                        src/test/pkg/TestClass1.java:5: Error: \
                         android.provider.Settings.System#getFloat() called from system process. \
                         Please call android.provider.Settings.System#getFloatForUser() instead.  \
                         [NonUserGetterCalled]
                                 float value = Settings.System.getFloat(context.getContentResolver(),
-                                              ^
-                        0 errors, 1 warnings
+                                                              ~~~~~~~~
+                        1 errors, 0 warnings
                         """.addLineContinuation()
                 )
     }
@@ -163,19 +163,19 @@
                 .run()
                 .expect(
                         """
-                        src/test/pkg/TestClass1.java:6: Warning: \
+                        src/test/pkg/TestClass1.java:6: Error: \
                         android.provider.Settings.Secure#getLong() called from system process. \
                         Please call android.provider.Settings.Secure#getLongForUser() instead.  \
                         [NonUserGetterCalled]
                                 final long value1 = Secure.getLong(context.getContentResolver(),
-                                                    ^
-                        src/test/pkg/TestClass1.java:8: Warning: \
+                                                           ~~~~~~~
+                        src/test/pkg/TestClass1.java:8: Error: \
                         android.provider.Settings.System#getString() called from system process. \
                         Please call android.provider.Settings.System#getStringForUser() instead.  \
                         [NonUserGetterCalled]
                                 final String value2 = System.getString(context.getContentResolver(),
-                                                      ^
-                        0 errors, 2 warnings
+                                                             ~~~~~~~~~
+                        2 errors, 0 warnings
                         """.addLineContinuation()
                 )
     }