Merge "UserRestriction doc fix: primary -> admin" into rvc-dev
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb
new file mode 100644
index 0000000..29bcfe0
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShimPriv_apk.asciipb
@@ -0,0 +1,12 @@
+drops {
+  android_build_drop {
+    build_id: "6508977"
+    target: "CtsShim"
+    source_file: "aosp_arm64/CtsShimPriv.apk"
+  }
+  dest_file: "packages/CtsShim/apk//arm/CtsShimPriv.apk"
+  version: ""
+  version_group: ""
+  git_project: "platform/frameworks/base"
+  git_branch: "rvc-dev"
+}
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb
new file mode 100644
index 0000000..be172e6
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__arm_CtsShim_apk.asciipb
@@ -0,0 +1,12 @@
+drops {
+  android_build_drop {
+    build_id: "6508977"
+    target: "CtsShim"
+    source_file: "aosp_arm64/CtsShim.apk"
+  }
+  dest_file: "packages/CtsShim/apk//arm/CtsShim.apk"
+  version: ""
+  version_group: ""
+  git_project: "platform/frameworks/base"
+  git_branch: "rvc-dev"
+}
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb
new file mode 100644
index 0000000..13eca13
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShimPriv_apk.asciipb
@@ -0,0 +1,12 @@
+drops {
+  android_build_drop {
+    build_id: "6508977"
+    target: "CtsShim"
+    source_file: "aosp_x86_64/CtsShimPriv.apk"
+  }
+  dest_file: "packages/CtsShim/apk//x86/CtsShimPriv.apk"
+  version: ""
+  version_group: ""
+  git_project: "platform/frameworks/base"
+  git_branch: "rvc-dev"
+}
diff --git a/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb
new file mode 100644
index 0000000..2e863fe
--- /dev/null
+++ b/.prebuilt_info/prebuilt_info_packages_CtsShim_apk__x86_CtsShim_apk.asciipb
@@ -0,0 +1,12 @@
+drops {
+  android_build_drop {
+    build_id: "6508977"
+    target: "CtsShim"
+    source_file: "aosp_x86_64/CtsShim.apk"
+  }
+  dest_file: "packages/CtsShim/apk//x86/CtsShim.apk"
+  version: ""
+  version_group: ""
+  git_project: "platform/frameworks/base"
+  git_branch: "rvc-dev"
+}
diff --git a/apex/Android.bp b/apex/Android.bp
index 51e030b..f511af5 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -63,6 +63,63 @@
     "--hide-annotation android.annotation.Hide " +
     "--hide InternalClasses " // com.android.* classes are okay in this interface
 
+// Defaults for mainline module provided java_sdk_library instances.
+java_defaults {
+    name: "framework-module-defaults",
+
+    // Additional annotations used for compiling both the implementation and the
+    // stubs libraries.
+    libs: ["framework-annotations-lib"],
+
+    // Enable api lint. This will eventually become the default for java_sdk_library
+    // but it cannot yet be turned on because some usages have not been cleaned up.
+    // TODO(b/156126315) - Remove when no longer needed.
+    api_lint: {
+        enabled: true,
+    },
+
+    // The API scope specific properties.
+    public: {
+        enabled: true,
+        sdk_version: "module_current",
+    },
+    system: {
+        enabled: true,
+        sdk_version: "module_current",
+    },
+    module_lib: {
+        enabled: true,
+        sdk_version: "module_current",
+    },
+
+    // Configure framework module specific metalava options.
+    droiddoc_options: [mainline_stubs_args],
+
+    // The stub libraries must be visible to frameworks/base so they can be combined
+    // into API specific libraries.
+    stubs_library_visibility: [
+        "//frameworks/base", // Framework
+    ],
+
+    // Set the visibility of the modules creating the stubs source.
+    stubs_source_visibility: [
+        // Ignore any visibility rules specified on the java_sdk_library when
+        // setting the visibility of the stubs source modules.
+        "//visibility:override",
+
+        // Currently, the stub source is not required for anything other than building
+        // the stubs library so is private to avoid misuse.
+        "//visibility:private",
+    ],
+
+    // Collates API usages from each module for further analysis.
+    plugins: ["java_api_finder"],
+
+    // Mainline modules should only rely on 'module_lib' APIs provided by other modules
+    // and the non updatable parts of the platform.
+    sdk_version: "module_current",
+}
+
 stubs_defaults {
     name: "framework-module-stubs-defaults-publicapi",
     args: mainline_framework_stubs_args,
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
index 0647d8a..483d2cc 100644
--- a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
+++ b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
@@ -67,9 +67,9 @@
  * <pre class="prettyprint">
  *     final long sessionId = blobStoreManager.createSession(blobHandle);
  *     try (BlobStoreManager.Session session = blobStoreManager.openSession(sessionId)) {
- *         try (ParcelFileDescriptor pfd = new ParcelFileDescriptor.AutoCloseOutputStream(
+ *         try (OutputStream out = new ParcelFileDescriptor.AutoCloseOutputStream(
  *                 session.openWrite(offsetBytes, lengthBytes))) {
- *             writeData(pfd);
+ *             writeData(out);
  *         }
  *     }
  * </pre>
@@ -100,9 +100,9 @@
  * <p> The following code snippet shows how to specify the access mode and commit the session:
  * <pre class="prettyprint">
  *     try (BlobStoreManager.Session session = blobStoreManager.openSession(sessionId)) {
- *         try (ParcelFileDescriptor pfd = new ParcelFileDescriptor.AutoCloseOutputStream(
+ *         try (OutputStream out = new ParcelFileDescriptor.AutoCloseOutputStream(
  *                 session.openWrite(offsetBytes, lengthBytes))) {
- *             writeData(pfd);
+ *             writeData(out);
  *         }
  *         session.allowSameSignatureAccess();
  *         session.allowPackageAccess(packageName, certificate);
@@ -134,9 +134,9 @@
  *
  * <p> The following code snippet shows how to access the data blob:
  * <pre class="prettyprint">
- *     try (ParcelFileDescriptor pfd = new ParcelFileDescriptor.AutoCloseInputStream(
+ *     try (InputStream in = new ParcelFileDescriptor.AutoCloseInputStream(
  *             blobStoreManager.openBlob(blobHandle)) {
- *         useData(pfd);
+ *         useData(in);
  *     }
  * </pre>
  */
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
index 35a2436..9376198 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -25,6 +25,7 @@
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
+import static android.os.UserHandle.USER_CURRENT;
 import static android.os.UserHandle.USER_NULL;
 
 import static com.android.server.blob.BlobStoreConfig.LOGV;
@@ -46,6 +47,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.blob.BlobHandle;
 import android.app.blob.BlobInfo;
 import android.app.blob.IBlobStoreManager;
@@ -1378,7 +1381,14 @@
                         + "queryBlobsForUser()");
             }
 
-            return queryBlobsForUserInternal(userId);
+            final int resolvedUserId = userId == USER_CURRENT
+                    ? ActivityManager.getCurrentUser() : userId;
+            // Don't allow any other special user ids apart from USER_CURRENT
+            final ActivityManagerInternal amInternal = LocalServices.getService(
+                    ActivityManagerInternal.class);
+            amInternal.ensureNotSpecialUser(resolvedUserId);
+
+            return queryBlobsForUserInternal(resolvedUserId);
         }
 
         @Override
@@ -1479,12 +1489,13 @@
         private static final int FLAG_DUMP_CONFIG = 1 << 2;
 
         private int mSelectedSectionFlags;
-        private boolean mDumpFull;
+        private boolean mDumpUnredacted;
         private final ArrayList<String> mDumpPackages = new ArrayList<>();
         private final ArrayList<Integer> mDumpUids = new ArrayList<>();
         private final ArrayList<Integer> mDumpUserIds = new ArrayList<>();
         private final ArrayList<Long> mDumpBlobIds = new ArrayList<>();
         private boolean mDumpHelp;
+        private boolean mDumpAll;
 
         public boolean shouldDumpSession(String packageName, int uid, long blobId) {
             if (!CollectionUtils.isEmpty(mDumpPackages)
@@ -1503,7 +1514,7 @@
         }
 
         public boolean shouldDumpAllSections() {
-            return mSelectedSectionFlags == 0;
+            return mDumpAll || (mSelectedSectionFlags == 0);
         }
 
         public void allowDumpSessions() {
@@ -1545,7 +1556,7 @@
         }
 
         public boolean shouldDumpFull() {
-            return mDumpFull;
+            return mDumpUnredacted;
         }
 
         public boolean shouldDumpUser(int userId) {
@@ -1567,10 +1578,12 @@
 
             for (int i = 0; i < args.length; ++i) {
                 final String opt = args[i];
-                if ("--full".equals(opt) || "-f".equals(opt)) {
+                if ("--all".equals(opt) || "-a".equals(opt)) {
+                    dumpArgs.mDumpAll = true;
+                } else if ("--unredacted".equals(opt) || "-u".equals(opt)) {
                     final int callingUid = Binder.getCallingUid();
                     if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID) {
-                        dumpArgs.mDumpFull = true;
+                        dumpArgs.mDumpUnredacted = true;
                     }
                 } else if ("--sessions".equals(opt)) {
                     dumpArgs.allowDumpSessions();
@@ -1580,7 +1593,7 @@
                     dumpArgs.allowDumpConfig();
                 } else if ("--package".equals(opt) || "-p".equals(opt)) {
                     dumpArgs.mDumpPackages.add(getStringArgRequired(args, ++i, "packageName"));
-                } else if ("--uid".equals(opt) || "-u".equals(opt)) {
+                } else if ("--uid".equals(opt)) {
                     dumpArgs.mDumpUids.add(getIntArgRequired(args, ++i, "uid"));
                 } else if ("--user".equals(opt)) {
                     dumpArgs.mDumpUserIds.add(getIntArgRequired(args, ++i, "userId"));
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 2aa2275..e888651 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -56,6 +56,7 @@
 import android.os.BatteryStatsInternal;
 import android.os.Binder;
 import android.os.Handler;
+import android.os.LimitExceededException;
 import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
@@ -1002,7 +1003,7 @@
                     }
                     if (isDebuggable) {
                         // Only throw the exception for debuggable apps.
-                        throw new IllegalStateException(
+                        throw new LimitExceededException(
                                 "schedule()/enqueue() called more than "
                                         + mQuotaTracker.getLimit(Category.SINGLE_CATEGORY)
                                         + " times in the past "
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
index 46d449a..372ec98 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
@@ -79,6 +79,12 @@
 
     private static final int STANDBY_BUCKET_UNKNOWN = -1;
 
+    /**
+     * The bucket beyond which apps are considered idle. Any apps in this bucket or lower are
+     * considered idle while those in higher buckets are not considered idle.
+     */
+    static final int IDLE_BUCKET_CUTOFF = STANDBY_BUCKET_RARE;
+
     @VisibleForTesting
     static final String APP_IDLE_FILENAME = "app_idle_stats.xml";
     private static final String TAG_PACKAGES = "packages";
@@ -350,7 +356,7 @@
         ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
         AppUsageHistory appUsageHistory =
                 getPackageHistory(userHistory, packageName, elapsedRealtime, true);
-        return appUsageHistory.currentBucket >= STANDBY_BUCKET_RARE;
+        return appUsageHistory.currentBucket >= IDLE_BUCKET_CUTOFF;
     }
 
     public AppUsageHistory getAppUsageHistory(String packageName, int userId,
@@ -487,7 +493,7 @@
         final int newBucket;
         final int reason;
         if (idle) {
-            newBucket = STANDBY_BUCKET_RARE;
+            newBucket = IDLE_BUCKET_CUTOFF;
             reason = REASON_MAIN_FORCED_BY_USER;
         } else {
             newBucket = STANDBY_BUCKET_ACTIVE;
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 980372d..94e5d0b 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -54,6 +54,7 @@
 import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.AppGlobals;
@@ -92,6 +93,7 @@
 import android.os.UserHandle;
 import android.provider.Settings.Global;
 import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.KeyValueListParser;
 import android.util.Slog;
@@ -227,6 +229,13 @@
     @GuardedBy("mActiveAdminApps")
     private final SparseArray<Set<String>> mActiveAdminApps = new SparseArray<>();
 
+    /**
+     * Set of system apps that are headless (don't have any declared activities, enabled or
+     * disabled). Presence in this map indicates that the app is a headless system app.
+     */
+    @GuardedBy("mAppIdleLock")
+    private final ArrayMap<String, Boolean> mHeadlessSystemApps = new ArrayMap<>();
+
     private final CountDownLatch mAdminDataAvailableLatch = new CountDownLatch(1);
 
     // Messages for the handler
@@ -667,20 +676,22 @@
                 return;
             }
         }
-        final boolean isSpecial = isAppSpecial(packageName,
+        final int minBucket = getAppMinBucket(packageName,
                 UserHandle.getAppId(uid),
                 userId);
         if (DEBUG) {
-            Slog.d(TAG, "   Checking idle state for " + packageName + " special=" +
-                    isSpecial);
+            Slog.d(TAG, "   Checking idle state for " + packageName
+                    + " minBucket=" + minBucket);
         }
-        if (isSpecial) {
+        if (minBucket <= STANDBY_BUCKET_ACTIVE) {
+            // No extra processing needed for ACTIVE or higher since apps can't drop into lower
+            // buckets.
             synchronized (mAppIdleLock) {
                 mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime,
-                        STANDBY_BUCKET_EXEMPTED, REASON_MAIN_DEFAULT);
+                        minBucket, REASON_MAIN_DEFAULT);
             }
             maybeInformListeners(packageName, userId, elapsedRealtime,
-                    STANDBY_BUCKET_EXEMPTED, REASON_MAIN_DEFAULT, false);
+                    minBucket, REASON_MAIN_DEFAULT, false);
         } else {
             synchronized (mAppIdleLock) {
                 final AppIdleHistory.AppUsageHistory app =
@@ -761,6 +772,14 @@
                         Slog.d(TAG, "Bringing up from RESTRICTED to RARE due to off switch");
                     }
                 }
+                if (newBucket > minBucket) {
+                    newBucket = minBucket;
+                    // Leave the reason alone.
+                    if (DEBUG) {
+                        Slog.d(TAG, "Bringing up from " + newBucket + " to " + minBucket
+                                + " due to min bucketing");
+                    }
+                }
                 if (DEBUG) {
                     Slog.d(TAG, "     Old bucket=" + oldBucket
                             + ", newBucket=" + newBucket);
@@ -1027,20 +1046,35 @@
         return isAppIdleFiltered(packageName, getAppId(packageName), userId, elapsedRealtime);
     }
 
-    private boolean isAppSpecial(String packageName, int appId, int userId) {
-        if (packageName == null) return false;
+    @StandbyBuckets
+    private int getAppMinBucket(String packageName, int userId) {
+        try {
+            final int uid = mPackageManager.getPackageUidAsUser(packageName, userId);
+            return getAppMinBucket(packageName, UserHandle.getAppId(uid), userId);
+        } catch (PackageManager.NameNotFoundException e) {
+            // Not a valid package for this user, nothing to do
+            return STANDBY_BUCKET_NEVER;
+        }
+    }
+
+    /**
+     * Return the lowest bucket this app should ever enter.
+     */
+    @StandbyBuckets
+    private int getAppMinBucket(String packageName, int appId, int userId) {
+        if (packageName == null) return STANDBY_BUCKET_NEVER;
         // If not enabled at all, of course nobody is ever idle.
         if (!mAppIdleEnabled) {
-            return true;
+            return STANDBY_BUCKET_EXEMPTED;
         }
         if (appId < Process.FIRST_APPLICATION_UID) {
             // System uids never go idle.
-            return true;
+            return STANDBY_BUCKET_EXEMPTED;
         }
         if (packageName.equals("android")) {
             // Nor does the framework (which should be redundant with the above, but for MR1 we will
             // retain this for safety).
-            return true;
+            return STANDBY_BUCKET_EXEMPTED;
         }
         if (mSystemServicesReady) {
             try {
@@ -1048,42 +1082,50 @@
                 // for idle mode, because app idle (aka app standby) is really not as big an issue
                 // for controlling who participates vs. doze mode.
                 if (mInjector.isNonIdleWhitelisted(packageName)) {
-                    return true;
+                    return STANDBY_BUCKET_EXEMPTED;
                 }
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
 
             if (isActiveDeviceAdmin(packageName, userId)) {
-                return true;
+                return STANDBY_BUCKET_EXEMPTED;
             }
 
             if (isActiveNetworkScorer(packageName)) {
-                return true;
+                return STANDBY_BUCKET_EXEMPTED;
             }
 
             if (mAppWidgetManager != null
                     && mInjector.isBoundWidgetPackage(mAppWidgetManager, packageName, userId)) {
-                return true;
+                return STANDBY_BUCKET_ACTIVE;
             }
 
             if (isDeviceProvisioningPackage(packageName)) {
-                return true;
+                return STANDBY_BUCKET_EXEMPTED;
             }
         }
 
         // Check this last, as it can be the most expensive check
         if (isCarrierApp(packageName)) {
-            return true;
+            return STANDBY_BUCKET_EXEMPTED;
         }
 
-        return false;
+        if (isHeadlessSystemApp(packageName)) {
+            return STANDBY_BUCKET_ACTIVE;
+        }
+
+        return STANDBY_BUCKET_NEVER;
+    }
+
+    private boolean isHeadlessSystemApp(String packageName) {
+        return mHeadlessSystemApps.containsKey(packageName);
     }
 
     @Override
     public boolean isAppIdleFiltered(String packageName, int appId, int userId,
             long elapsedRealtime) {
-        if (isAppSpecial(packageName, appId, userId)) {
+        if (getAppMinBucket(packageName, appId, userId) < AppIdleHistory.IDLE_BUCKET_CUTOFF) {
             return false;
         } else {
             synchronized (mAppIdleLock) {
@@ -1423,6 +1465,8 @@
                 }
             }
 
+            // Make sure we don't put the app in a lower bucket than it's supposed to be in.
+            newBucket = Math.min(newBucket, getAppMinBucket(packageName, userId));
             mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket,
                     reason, resetTimeout);
         }
@@ -1617,14 +1661,16 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             final String action = intent.getAction();
+            final String pkgName = intent.getData().getSchemeSpecificPart();
+            final int userId = getSendingUserId();
             if (Intent.ACTION_PACKAGE_ADDED.equals(action)
                     || Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
                 clearCarrierPrivilegedApps();
+                // ACTION_PACKAGE_ADDED is called even for system app downgrades.
+                evaluateSystemAppException(pkgName, userId);
             }
             if ((Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
                     Intent.ACTION_PACKAGE_ADDED.equals(action))) {
-                final String pkgName = intent.getData().getSchemeSpecificPart();
-                final int userId = getSendingUserId();
                 if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                     maybeUnrestrictBuggyApp(pkgName, userId);
                 } else {
@@ -1634,6 +1680,34 @@
         }
     }
 
+    private void evaluateSystemAppException(String packageName, int userId) {
+        if (!mSystemServicesReady) {
+            // The app will be evaluated in initializeDefaultsForSystemApps() when possible.
+            return;
+        }
+        try {
+            PackageInfo pi = mPackageManager.getPackageInfoAsUser(packageName,
+                    PackageManager.GET_ACTIVITIES | PackageManager.MATCH_DISABLED_COMPONENTS,
+                    userId);
+            evaluateSystemAppException(pi);
+        } catch (PackageManager.NameNotFoundException e) {
+            mHeadlessSystemApps.remove(packageName);
+        }
+    }
+
+    private void evaluateSystemAppException(@Nullable PackageInfo pkgInfo) {
+        if (pkgInfo.applicationInfo != null && pkgInfo.applicationInfo.isSystemApp()) {
+            synchronized (mAppIdleLock) {
+                if (pkgInfo.activities == null || pkgInfo.activities.length == 0) {
+                    // Headless system app.
+                    mHeadlessSystemApps.put(pkgInfo.packageName, true);
+                } else {
+                    mHeadlessSystemApps.remove(pkgInfo.packageName);
+                }
+            }
+        }
+    }
+
     @Override
     public void initializeDefaultsForSystemApps(int userId) {
         if (!mSystemServicesReady) {
@@ -1645,7 +1719,7 @@
                 + "appIdleEnabled=" + mAppIdleEnabled);
         final long elapsedRealtime = mInjector.elapsedRealtime();
         List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser(
-                PackageManager.MATCH_DISABLED_COMPONENTS,
+                PackageManager.GET_ACTIVITIES | PackageManager.MATCH_DISABLED_COMPONENTS,
                 userId);
         final int packageCount = packages.size();
         synchronized (mAppIdleLock) {
@@ -1658,6 +1732,8 @@
                     mAppIdleHistory.reportUsage(packageName, userId, STANDBY_BUCKET_ACTIVE,
                             REASON_SUB_USAGE_SYSTEM_UPDATE, 0,
                             elapsedRealtime + mSystemUpdateUsageTimeoutMillis);
+
+                    evaluateSystemAppException(pi);
                 }
             }
             // Immediately persist defaults to disk
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index c3adf60..c1011ec 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.annotation.StringDef;
 import android.media.MediaCodec.CryptoInfo;
+import android.os.Build;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
@@ -467,7 +468,24 @@
     public @interface SampleFlags {}
     /** Indicates that the sample holds a synchronization sample. */
     public static final int SAMPLE_FLAG_KEY_FRAME = MediaCodec.BUFFER_FLAG_KEY_FRAME;
-    /** Indicates that the sample has supplemental data. */
+    /**
+     * Indicates that the sample has supplemental data.
+     *
+     * <p>Samples will not have this flag set unless the {@code
+     * "android.media.mediaparser.includeSupplementalData"} parameter is set to {@code true} via
+     * {@link #setParameter}.
+     *
+     * <p>Samples with supplemental data have the following sample data format:
+     *
+     * <ul>
+     *   <li>If the {@code "android.media.mediaparser.inBandCryptoInfo"} parameter is set, all
+     *       encryption information.
+     *   <li>(4 bytes) {@code sample_data_size}: The size of the actual sample data, not including
+     *       supplemental data or encryption information.
+     *   <li>({@code sample_data_size} bytes): The media sample data.
+     *   <li>(remaining bytes) The supplemental data.
+     * </ul>
+     */
     public static final int SAMPLE_FLAG_HAS_SUPPLEMENTAL_DATA = 1 << 28;
     /** Indicates that the sample is known to contain the last media sample of the stream. */
     public static final int SAMPLE_FLAG_LAST_SAMPLE = 1 << 29;
@@ -578,7 +596,9 @@
                 PARAMETER_TS_IGNORE_AVC_STREAM,
                 PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM,
                 PARAMETER_TS_DETECT_ACCESS_UNITS,
-                PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS
+                PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS,
+                PARAMETER_IN_BAND_CRYPTO_INFO,
+                PARAMETER_INCLUDE_SUPPLEMENTAL_DATA
             })
     public @interface ParameterName {}
 
@@ -740,6 +760,16 @@
     public static final String PARAMETER_IN_BAND_CRYPTO_INFO =
             "android.media.mediaparser.inBandCryptoInfo";
 
+    /**
+     * Sets whether supplemental data should be included as part of the sample data. {@code boolean}
+     * expected. Default value is {@code false}. See {@link #SAMPLE_FLAG_HAS_SUPPLEMENTAL_DATA} for
+     * information about the sample data format.
+     *
+     * @hide
+     */
+    public static final String PARAMETER_INCLUDE_SUPPLEMENTAL_DATA =
+            "android.media.mediaparser.includeSupplementalData";
+
     // Private constants.
 
     private static final String TAG = "MediaParser";
@@ -899,6 +929,7 @@
     private final ParsableByteArrayAdapter mScratchParsableByteArrayAdapter;
     @Nullable private final Constructor<DrmInitData.SchemeInitData> mSchemeInitDataConstructor;
     private boolean mInBandCryptoInfo;
+    private boolean mIncludeSupplementalData;
     private String mParserName;
     private Extractor mExtractor;
     private ExtractorInput mExtractorInput;
@@ -949,6 +980,9 @@
         if (PARAMETER_IN_BAND_CRYPTO_INFO.equals(parameterName)) {
             mInBandCryptoInfo = (boolean) value;
         }
+        if (PARAMETER_INCLUDE_SUPPLEMENTAL_DATA.equals(parameterName)) {
+            mIncludeSupplementalData = (boolean) value;
+        }
         mParserParameters.put(parameterName, value);
         return this;
     }
@@ -1099,6 +1133,9 @@
     // Private methods.
 
     private MediaParser(OutputConsumer outputConsumer, boolean sniff, String... parserNamesPool) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
+            throw new UnsupportedOperationException("Android version must be R or greater.");
+        }
         mParserParameters = new HashMap<>();
         mOutputConsumer = outputConsumer;
         mParserNamesPool = parserNamesPool;
@@ -1330,6 +1367,7 @@
         private int mEncryptionVectorSize;
         private boolean mHasSubsampleEncryptionData;
         private CryptoInfo.Pattern mEncryptionPattern;
+        private int mSkippedSupplementalDataBytes;
 
         private TrackOutputAdapter(int trackIndex) {
             mTrackIndex = trackIndex;
@@ -1419,6 +1457,10 @@
                             throw new IllegalStateException();
                     }
                 }
+            } else if (sampleDataPart == SAMPLE_DATA_PART_SUPPLEMENTAL
+                    && !mIncludeSupplementalData) {
+                mSkippedSupplementalDataBytes += length;
+                data.skipBytes(length);
             } else {
                 outputSampleData(data, length);
             }
@@ -1427,6 +1469,8 @@
         @Override
         public void sampleMetadata(
                 long timeUs, int flags, int size, int offset, @Nullable CryptoData cryptoData) {
+            size -= mSkippedSupplementalDataBytes;
+            mSkippedSupplementalDataBytes = 0;
             mOutputConsumer.onSampleCompleted(
                     mTrackIndex,
                     timeUs,
@@ -1686,13 +1730,13 @@
         }
     }
 
-    private static int getMediaParserFlags(int flags) {
+    private int getMediaParserFlags(int flags) {
         @SampleFlags int result = 0;
         result |= (flags & C.BUFFER_FLAG_ENCRYPTED) != 0 ? SAMPLE_FLAG_ENCRYPTED : 0;
         result |= (flags & C.BUFFER_FLAG_KEY_FRAME) != 0 ? SAMPLE_FLAG_KEY_FRAME : 0;
         result |= (flags & C.BUFFER_FLAG_DECODE_ONLY) != 0 ? SAMPLE_FLAG_DECODE_ONLY : 0;
         result |=
-                (flags & C.BUFFER_FLAG_HAS_SUPPLEMENTAL_DATA) != 0
+                (flags & C.BUFFER_FLAG_HAS_SUPPLEMENTAL_DATA) != 0 && mIncludeSupplementalData
                         ? SAMPLE_FLAG_HAS_SUPPLEMENTAL_DATA
                         : 0;
         result |= (flags & C.BUFFER_FLAG_LAST_SAMPLE) != 0 ? SAMPLE_FLAG_LAST_SAMPLE : 0;
@@ -1755,6 +1799,7 @@
         expectedTypeByParameterName.put(PARAMETER_TS_DETECT_ACCESS_UNITS, Boolean.class);
         expectedTypeByParameterName.put(PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS, Boolean.class);
         expectedTypeByParameterName.put(PARAMETER_IN_BAND_CRYPTO_INFO, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_INCLUDE_SUPPLEMENTAL_DATA, Boolean.class);
         EXPECTED_TYPE_BY_PARAMETER_NAME = Collections.unmodifiableMap(expectedTypeByParameterName);
     }
 }
diff --git a/apex/permission/framework/Android.bp b/apex/permission/framework/Android.bp
index 68c27a8..c43fabd 100644
--- a/apex/permission/framework/Android.bp
+++ b/apex/permission/framework/Android.bp
@@ -21,12 +21,18 @@
     path: "java",
 }
 
-java_library {
+java_sdk_library {
     name: "framework-permission",
+    defaults: ["framework-module-defaults"],
     srcs: [
         ":framework-permission-sources",
     ],
-    sdk_version: "module_current",
+
+    // TODO(b/155480189) - Remove naming_scheme once references have been resolved.
+    // Temporary java_sdk_library component naming scheme to use to ease the transition from separate
+    // modules to java_sdk_library.
+    naming_scheme: "framework-modules",
+
     apex_available: [
         "com.android.permission",
         "test_com.android.permission",
@@ -40,91 +46,5 @@
     visibility: [
         "//frameworks/base/apex/permission:__subpackages__",
     ],
-}
-
-stubs_defaults {
-    name: "framework-permission-stubs-defaults",
-    srcs: [ ":framework-permission-sources" ],
-    libs: [ "framework-annotations-lib" ],
-    dist: { dest: "framework-permission.txt" },
-}
-
-droidstubs {
-    name: "framework-permission-stubs-srcs-publicapi",
-    defaults: [
-        "framework-module-stubs-defaults-publicapi",
-        "framework-permission-stubs-defaults",
-    ],
-    check_api: {
-        last_released: {
-            api_file: ":framework-permission.api.public.latest",
-            removed_api_file: ":framework-permission-removed.api.public.latest",
-        },
-        api_lint: {
-            new_since: ":framework-permission.api.public.latest",
-        },
-    },
-}
-
-droidstubs {
-    name: "framework-permission-stubs-srcs-systemapi",
-    defaults: [
-        "framework-module-stubs-defaults-systemapi",
-        "framework-permission-stubs-defaults",
-    ],
-    check_api: {
-        last_released: {
-            api_file: ":framework-permission.api.system.latest",
-            removed_api_file: ":framework-permission-removed.api.system.latest",
-        },
-        api_lint: {
-            new_since: ":framework-permission.api.system.latest",
-        },
-    },
-}
-
-droidstubs {
-    name: "framework-permission-api-module_libs_api",
-    defaults: [
-        "framework-module-api-defaults-module_libs_api",
-        "framework-permission-stubs-defaults",
-    ],
-    check_api: {
-        last_released: {
-            api_file: ":framework-permission.api.module-lib.latest",
-            removed_api_file: ":framework-permission-removed.api.module-lib.latest",
-        },
-        api_lint: {
-            new_since: ":framework-permission.api.module-lib.latest",
-        },
-    },
-}
-
-droidstubs {
-    name: "framework-permission-stubs-srcs-module_libs_api",
-    defaults: [
-        "framework-module-stubs-defaults-module_libs_api",
-        "framework-permission-stubs-defaults",
-    ],
-}
-
-java_library {
-    name: "framework-permission-stubs-publicapi",
-    srcs: [ ":framework-permission-stubs-srcs-publicapi" ],
-    defaults: ["framework-module-stubs-lib-defaults-publicapi"],
-    dist: { dest: "framework-permission.jar" },
-}
-
-java_library {
-    name: "framework-permission-stubs-systemapi",
-    srcs: [ ":framework-permission-stubs-srcs-systemapi" ],
-    defaults: ["framework-module-stubs-lib-defaults-systemapi"],
-    dist: { dest: "framework-permission.jar" },
-}
-
-java_library {
-    name: "framework-permission-stubs-module_libs_api",
-    srcs: [ ":framework-permission-stubs-srcs-module_libs_api" ],
-    defaults: ["framework-module-stubs-lib-defaults-module_libs_api"],
-    dist: { dest: "framework-permission.jar" },
+    stubs_library_visibility: ["//visibility:public"],
 }
diff --git a/apex/sdkextensions/Android.bp b/apex/sdkextensions/Android.bp
index dbb5bd3d..fdb078e 100644
--- a/apex/sdkextensions/Android.bp
+++ b/apex/sdkextensions/Android.bp
@@ -39,7 +39,7 @@
 
 sdk {
     name: "sdkextensions-sdk",
-    java_header_libs: [ "framework-sdkextensions-stubs-systemapi" ],
+    java_sdk_libs: [ "framework-sdkextensions" ],
 }
 
 apex_key {
diff --git a/apex/sdkextensions/framework/Android.bp b/apex/sdkextensions/framework/Android.bp
index 14e23ed..b8aad7d 100644
--- a/apex/sdkextensions/framework/Android.bp
+++ b/apex/sdkextensions/framework/Android.bp
@@ -25,14 +25,18 @@
     visibility: [ "//frameworks/base" ] // For the "global" stubs.
 }
 
-java_library {
+java_sdk_library {
     name: "framework-sdkextensions",
     srcs: [ ":framework-sdkextensions-sources" ],
-    sdk_version: "system_current",
-    libs: [ "framework-annotations-lib" ],
+    defaults: ["framework-module-defaults"],
+
+    // TODO(b/155480189) - Remove naming_scheme once references have been resolved.
+    // Temporary java_sdk_library component naming scheme to use to ease the transition from separate
+    // modules to java_sdk_library.
+    naming_scheme: "framework-modules",
+
     permitted_packages: [ "android.os.ext" ],
     installable: true,
-    plugins: ["java_api_finder"],
     visibility: [
         "//frameworks/base/apex/sdkextensions",
         "//frameworks/base/apex/sdkextensions/testing",
@@ -43,102 +47,3 @@
         "test_com.android.sdkext",
     ],
 }
-
-stubs_defaults {
-    name: "framework-sdkextensions-stubs-defaults",
-    srcs: [ ":framework-sdkextensions-sources" ],
-    libs: [ "framework-annotations-lib" ],
-    dist: { dest: "framework-sdkextensions.txt" },
-}
-
-droidstubs {
-    name: "framework-sdkextensions-stubs-srcs-publicapi",
-    defaults: [
-        "framework-module-stubs-defaults-publicapi",
-        "framework-sdkextensions-stubs-defaults",
-    ],
-    check_api: {
-        last_released: {
-            api_file: ":framework-sdkextensions.api.public.latest",
-            removed_api_file: ":framework-sdkextensions-removed.api.public.latest",
-        },
-        api_lint: {
-            new_since: ":framework-sdkextensions.api.public.latest",
-        },
-    },
-}
-
-droidstubs {
-    name: "framework-sdkextensions-stubs-srcs-systemapi",
-    defaults: [
-        "framework-module-stubs-defaults-systemapi",
-        "framework-sdkextensions-stubs-defaults",
-    ],
-    check_api: {
-        last_released: {
-            api_file: ":framework-sdkextensions.api.system.latest",
-            removed_api_file: ":framework-sdkextensions-removed.api.system.latest",
-        },
-        api_lint: {
-            new_since: ":framework-sdkextensions.api.system.latest",
-        },
-    },
-}
-
-droidstubs {
-    name: "framework-sdkextensions-api-module_libs_api",
-    defaults: [
-        "framework-module-api-defaults-module_libs_api",
-        "framework-sdkextensions-stubs-defaults",
-    ],
-    check_api: {
-        last_released: {
-            api_file: ":framework-sdkextensions.api.module-lib.latest",
-            removed_api_file: ":framework-sdkextensions-removed.api.module-lib.latest",
-        },
-        api_lint: {
-            new_since: ":framework-sdkextensions.api.module-lib.latest",
-        },
-    },
-}
-
-droidstubs {
-    name: "framework-sdkextensions-stubs-srcs-module_libs_api",
-    defaults: [
-        "framework-module-stubs-defaults-module_libs_api",
-        "framework-sdkextensions-stubs-defaults",
-    ],
-}
-
-java_library {
-    name: "framework-sdkextensions-stubs-publicapi",
-    srcs: [":framework-sdkextensions-stubs-srcs-publicapi"],
-    defaults: ["framework-module-stubs-lib-defaults-publicapi"],
-    visibility: [
-        "//frameworks/base", // Framework
-        "//frameworks/base/apex/sdkextensions", // sdkextensions SDK
-    ],
-    dist: { dest: "framework-sdkextensions.jar" },
-}
-
-java_library {
-    name: "framework-sdkextensions-stubs-systemapi",
-    srcs: [":framework-sdkextensions-stubs-srcs-systemapi"],
-    defaults: ["framework-module-stubs-lib-defaults-systemapi"],
-    visibility: [
-        "//frameworks/base", // Framework
-        "//frameworks/base/apex/sdkextensions", // sdkextensions SDK
-    ],
-    dist: { dest: "framework-sdkextensions.jar" },
-}
-
-java_library {
-    name: "framework-sdkextensions-stubs-module_libs_api",
-    srcs: [":framework-sdkextensions-stubs-srcs-module_libs_api"],
-    defaults: ["framework-module-stubs-lib-defaults-module_libs_api"],
-    visibility: [
-        "//frameworks/base", // Framework
-        "//frameworks/base/apex/sdkextensions", // sdkextensions SDK
-    ],
-    dist: { dest: "framework-sdkextensions.jar" },
-}
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index 5cf5e0b..cbc8ed6 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -662,14 +662,19 @@
             return;
         }
 
+        // Cleann up from previous statsd - cancel any alarms that had been set. Do this here
+        // instead of in binder death because statsd can come back and set different alarms, or not
+        // want to set an alarm when it had been set. This guarantees that when we get a new statsd,
+        // we cancel any alarms before it is able to set them.
+        cancelAnomalyAlarm();
+        cancelPullingAlarm();
+        cancelAlarmForSubscriberTriggering();
+
         if (DEBUG) Log.d(TAG, "Saying hi to statsd");
         mStatsManagerService.statsdReady(statsd);
         try {
             statsd.statsCompanionReady();
 
-            cancelAnomalyAlarm();
-            cancelPullingAlarm();
-
             BroadcastReceiver appUpdateReceiver = new AppUpdateReceiver();
             BroadcastReceiver userUpdateReceiver = new UserUpdateReceiver();
             BroadcastReceiver shutdownEventReceiver = new ShutdownEventReceiver();
diff --git a/api/current.txt b/api/current.txt
index 467aa32..952ccda 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -12097,6 +12097,7 @@
     field public static final String FEATURE_COMPANION_DEVICE_SETUP = "android.software.companion_device_setup";
     field public static final String FEATURE_CONNECTION_SERVICE = "android.software.connectionservice";
     field public static final String FEATURE_CONSUMER_IR = "android.hardware.consumerir";
+    field public static final String FEATURE_CONTROLS = "android.software.controls";
     field public static final String FEATURE_DEVICE_ADMIN = "android.software.device_admin";
     field public static final String FEATURE_EMBEDDED = "android.hardware.type.embedded";
     field public static final String FEATURE_ETHERNET = "android.hardware.ethernet";
@@ -58326,9 +58327,9 @@
     method public abstract void setAllowFileAccess(boolean);
     method @Deprecated public abstract void setAllowFileAccessFromFileURLs(boolean);
     method @Deprecated public abstract void setAllowUniversalAccessFromFileURLs(boolean);
-    method public abstract void setAppCacheEnabled(boolean);
+    method @Deprecated public abstract void setAppCacheEnabled(boolean);
     method @Deprecated public abstract void setAppCacheMaxSize(long);
-    method public abstract void setAppCachePath(String);
+    method @Deprecated public abstract void setAppCachePath(String);
     method public abstract void setBlockNetworkImage(boolean);
     method public abstract void setBlockNetworkLoads(boolean);
     method public abstract void setBuiltInZoomControls(boolean);
diff --git a/api/test-current.txt b/api/test-current.txt
index 46049bd..5dc7bdb 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1811,6 +1811,7 @@
   }
 
   public class ConnectivityManager {
+    method @RequiresPermission(anyOf={"android.permission.MANAGE_TEST_NETWORKS", android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
     method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle);
     field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
     field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index a1278f3..ecb95bd 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -1306,7 +1306,7 @@
     if (mSystemWd < 0) {
         close(mInotifyFd);
         mInotifyFd = -1;
-        SLOGE("Could not add watch for %s", SYSTEM_DATA_DIR_PATH);
+        SLOGE("Could not add watch for %s: %s", SYSTEM_DATA_DIR_PATH, strerror(errno));
         return NO_INIT;
     }
 
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index 9e6d0a2..dc16125 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -351,9 +351,9 @@
 
 Status IncidentService::registerSection(const int id, const String16& name16,
         const sp<IIncidentDumpCallback>& callback) {
-    const char* name = String8(name16).c_str();
+    const String8 name = String8(name16);
     const uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    ALOGI("Uid %d registers section %d '%s'", callingUid, id, name);
+    ALOGI("Uid %d registers section %d '%s'", callingUid, id, name.c_str());
     if (callback == nullptr) {
         return Status::fromExceptionCode(Status::EX_NULL_POINTER);
     }
@@ -363,11 +363,11 @@
                 ALOGW("Error registering section %d: calling uid does not match", id);
                 return Status::fromExceptionCode(Status::EX_SECURITY);
             }
-            mRegisteredSections.at(i) = new BringYourOwnSection(id, name, callingUid, callback);
+            mRegisteredSections.at(i) = new BringYourOwnSection(id, name.c_str(), callingUid, callback);
             return Status::ok();
         }
     }
-    mRegisteredSections.push_back(new BringYourOwnSection(id, name, callingUid, callback));
+    mRegisteredSections.push_back(new BringYourOwnSection(id, name.c_str(), callingUid, callback));
     return Status::ok();
 }
 
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 114cbb8..61e5eb0 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -876,7 +876,9 @@
 
 status_t BringYourOwnSection::BlockingCall(unique_fd& pipeWriteFd) const {
     android::os::ParcelFileDescriptor pfd(std::move(pipeWriteFd));
-    mCallback->onDumpSection(pfd);
+    if(mCallback != nullptr) {
+        mCallback->onDumpSection(pfd);
+    }
     return NO_ERROR;
 }
 
diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h
index 2ce45ed..bc4909d 100644
--- a/cmds/incidentd/src/Section.h
+++ b/cmds/incidentd/src/Section.h
@@ -207,7 +207,7 @@
     virtual status_t BlockingCall(unique_fd& pipeWriteFd) const;
 
 private:
-    const sp<IIncidentDumpCallback>& mCallback;
+    const sp<IIncidentDumpCallback> mCallback;
 };
 
 
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index ffd83ba..7090bd4 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -307,9 +307,6 @@
     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation);
     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition);
     FRIEND_TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents);
-    FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
-    FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
-    FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation);
 
     FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket);
     FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets);
@@ -328,6 +325,7 @@
     FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithSameDeactivation);
     FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations);
 
+    FRIEND_TEST(CountMetricE2eTest, TestInitialConditionChanges);
     FRIEND_TEST(CountMetricE2eTest, TestSlicedState);
     FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithMap);
     FRIEND_TEST(CountMetricE2eTest, TestMultipleSlicedStates);
@@ -345,6 +343,10 @@
     FRIEND_TEST(DurationMetricE2eTest, TestSlicedStatePrimaryFieldsNotSubsetDimInWhat);
     FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSubset);
 
+    FRIEND_TEST(ValueMetricE2eTest, TestInitialConditionChanges);
+    FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
+    FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
+    FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation);
     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index a65f5f7..4ffa040 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -826,7 +826,7 @@
         uids.push_back(AID_SYSTEM);
     }
     vector<shared_ptr<LogEvent>> stats;
-    if (mPullerManager->Pull(s, uids, &stats)) {
+    if (mPullerManager->Pull(s, uids, getElapsedRealtimeNs(), &stats)) {
         for (const auto& it : stats) {
             dprintf(out, "Pull from %d: %s\n", s, it->ToString().c_str());
         }
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 71dd4dd..c6e9e01 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -24,6 +24,7 @@
 import "frameworks/base/core/proto/android/app/enums.proto";
 import "frameworks/base/core/proto/android/app/job/enums.proto";
 import "frameworks/base/core/proto/android/app/settings_enums.proto";
+import "frameworks/base/core/proto/android/app/media_output_enum.proto";
 import "frameworks/base/core/proto/android/app/tvsettings_enums.proto";
 import "frameworks/base/core/proto/android/bluetooth/a2dp/enums.proto";
 import "frameworks/base/core/proto/android/bluetooth/enums.proto";
@@ -439,6 +440,10 @@
             app_permission_groups_fragment_auto_revoke_action =
             273 [(module) = "permissioncontroller"];
         EvsUsageStatsReported evs_usage_stats_reported = 274 [(module) = "evs"];
+        AudioPowerUsageDataReported audio_power_usage_data_reported = 275;
+        TvTunerStateChanged tv_tuner_state_changed = 276 [(module) = "framework"];
+        MediaOutputOpSwitchReported mediaoutput_op_switch_reported =
+            277 [(module) = "settings"];
         SdkExtensionStatus sdk_extension_status = 354;
 
         // StatsdStats tracks platform atoms with ids upto 500.
@@ -446,7 +451,7 @@
     }
 
     // Pulled events will start at field 10000.
-    // Next: 10080
+    // Next: 10084
     oneof pulled {
         WifiBytesTransfer wifi_bytes_transfer = 10000 [(module) = "framework"];
         WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001 [(module) = "framework"];
@@ -537,6 +542,10 @@
         SimSlotState sim_slot_state = 10078 [(module) = "telephony"];
         SupportedRadioAccessFamily supported_radio_access_family = 10079 [(module) = "telephony"];
         SettingSnapshot setting_snapshot = 10080 [(module) = "framework"];
+        DisplayWakeReason display_wake_reason = 10081 [(module) = "framework"];
+        DataUsageBytesTransfer data_usage_bytes_transfer = 10082 [(module) = "framework"];
+        BytesTransferByTagAndMetered bytes_transfer_by_tag_and_metered =
+                10083 [(module) = "framework"];
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP.
@@ -1255,7 +1264,8 @@
  */
 message ChargingStateChanged {
     // State of the battery, from frameworks/base/core/proto/android/os/enums.proto.
-    optional android.os.BatteryStatusEnum state = 1;
+    optional android.os.BatteryStatusEnum state = 1
+            [(state_field_option).exclusive_state = true, (state_field_option).nested = false];
 }
 
 /**
@@ -4937,6 +4947,60 @@
 }
 
 /**
+ * Used for pull network statistics via mobile|wifi networks, and sliced by interesting dimensions.
+ * Note that the data is expected to be sliced into more dimensions in future. In other words,
+ * the caller must not assume any row of data is one full report when filtering with a set of
+ * matching conditions, because future data may represent with multiple rows what is currently
+ * represented by one.
+ * To avoid being broken by future slicing, callers must take care to aggregate rows even if they
+ * query all the existing columns.
+ *
+ * Pulled from:
+ *   StatsPullAtomService (using NetworkStatsService to get NetworkStats)
+ */
+message DataUsageBytesTransfer {
+    // State of this record. Should be NetworkStats#SET_DEFAULT or NetworkStats#SET_FOREGROUND to
+    // indicate the foreground state, or NetworkStats#SET_ALL to indicate the record is for all
+    // states combined, not including debug states. See NetworkStats#SET_*.
+    optional int32 state = 1;
+
+    optional int64 rx_bytes = 2;
+
+    optional int64 rx_packets = 3;
+
+    optional int64 tx_bytes = 4;
+
+    optional int64 tx_packets = 5;
+
+    // Radio Access Technology (RAT) type of this record, should be one of
+    // TelephonyManager#NETWORK_TYPE_* constants, or NetworkTemplate#NETWORK_TYPE_ALL to indicate
+    // the record is for all rat types combined.
+    optional int32 rat_type = 6;
+
+    // Mcc/Mnc read from sim if the record is for a specific subscription, null indicates the
+    // record is combined across subscriptions.
+    optional string sim_mcc = 7;
+    optional string sim_mnc = 8;
+
+    // Allows mobile virtual network operators (MVNOs) to be identified with individual IDs.
+    // See TelephonyManager#getSimCarrierId.
+    optional int32 carrier_id = 9;
+
+    // Enumeration of opportunistic states with an additional ALL state indicates the record is
+    // combined regardless of the boolean value in its field.
+    enum DataSubscriptionState {
+        UNKNOWN = 0; // For server side backward compatibility.
+        ALL = 1;
+        OPPORTUNISTIC = 2;
+        NOT_OPPORTUNISTIC = 3;
+    }
+    // Mark whether the subscription is an opportunistic data subscription, and ALL indicates the
+    // record is combined across opportunistic data subscriptions.
+    // See {@link SubscriptionManager#setOpportunistic}.
+    optional DataSubscriptionState opportunistic_data_sub = 10;
+}
+
+/**
  * Pulls bytes transferred via bluetooth. It is pulled from Bluetooth controller.
  *
  * Pulled from:
@@ -5979,6 +6043,12 @@
     optional int32 user_locked_fields = 6;
     // Indicates if the channel was deleted by the app.
     optional bool is_deleted = 7;
+    // Indicates if the channel was marked as a conversation by the app.
+    optional bool is_conversation = 8;
+    // Indicates if the channel is a conversation that was demoted by the user.
+    optional bool is_demoted_conversation = 9;
+    // Indicates if the channel is a conversation that was marked as important by the user.
+    optional bool is_important_conversation = 10;
 }
 
 /**
@@ -9118,6 +9188,28 @@
 }
 
 /**
+ * Logs when a tune occurs through device's Frontend.
+ * This is atom ID 276.
+ *
+ * Logged from:
+ *   frameworks/base/media/java/android/media/tv/tuner/Tuner.java
+ */
+message TvTunerStateChanged {
+    enum State {
+        UNKNOWN = 0;
+        TUNING = 1; // Signal is tuned
+        LOCKED = 2;    // the signal is locked
+        NOT_LOCKED = 3; // the signal isn’t locked.
+        SIGNAL_LOST = 4; // the signal was locked, but is lost now.
+        SCANNING = 5; // the signal is scanned
+        SCAN_STOPPED = 6; // the scan is stopped.
+    }
+    // The uid of the application that sent this custom atom.
+    optional int32 uid = 1 [(is_uid) = true];
+    //  new state
+    optional State state = 2;
+}
+/**
  * Logs when an app is frozen or unfrozen.
  *
  * Logged from:
@@ -9459,9 +9551,6 @@
 
     /** The ID of the entry that the users actioned on */
     optional android.app.tvsettings.ItemId item_id = 2;
-
-    /** Additional information (e.g., navigation direction on page focused) */
-    optional string additional_info = 3;
 }
 
 /**
@@ -9587,6 +9676,9 @@
         SWITCH_USER = 1; // Indicates that this is a user switch event
         START_USER = 2; // Indicates that this is a user start event
         CREATE_USER = 3; // Indicates that this is a user create event
+        USER_RUNNING_LOCKED = 4; // Indicates that user is running in locked state
+        UNLOCKING_USER = 5; // Indicates that this is a user unlocking event
+        UNLOCKED_USER = 6; // Indicates that this is a user unlocked event
     }
     optional Event event = 3;
 
@@ -9633,6 +9725,17 @@
     optional android.stats.accessibility.ServiceStatus service_status = 2;
 }
 
+message DisplayWakeReason {
+    // Wake_up_reason code
+    // If LOWORD(wake_up_reason) = 0
+    //     reference to HIWORD(wake_up_reason) PowerManager.WAKE_REASON_XXX
+    //     else reference wake_up_reason to
+    //     frameworks/base/services/core/java/com/android/server/power/Notifier.java#DispWakeupReason
+    optional int32 wake_up_reason = 1;
+    // Count of wake up by reason
+    optional int32 wake_times = 2;
+}
+
 /**
  * Logs app usage events.
  */
@@ -9689,3 +9792,118 @@
     // The duration of the service
     optional int64 duration_millis = 10;
 }
+
+/**
+ * Logs audio power usage stats.
+ *
+ * Pushed from:
+ *  frameworks/av/services/mediametrics/AudioPowerUsage.cpp
+ */
+message AudioPowerUsageDataReported {
+    /**
+     * Device used for input/output
+     *
+     * All audio devices please refer to below file:
+     * system/media/audio/include/system/audio-base.h
+     *
+     * Define our own enum values because we don't report all audio devices.
+     * Currently, we only report built-in audio devices such as handset, speaker,
+     * built-in mics, common audio devices such as wired headset, usb headset
+     * and bluetooth devices.
+     */
+    enum AudioDevice {
+        OUTPUT_EARPIECE         = 0x1; // handset
+        OUTPUT_SPEAKER          = 0x2; // dual speaker
+        OUTPUT_WIRED_HEADSET    = 0x4; // 3.5mm headset
+        OUTPUT_USB_HEADSET      = 0x8; // usb headset
+        OUTPUT_BLUETOOTH_SCO    = 0x10; // bluetooth sco
+        OUTPUT_BLUETOOTH_A2DP   = 0x20; // a2dp
+        OUTPUT_SPEAKER_SAFE     = 0x40; // bottom speaker
+
+        INPUT_DEVICE_BIT        = 0x40000000; // non-negative positive int32.
+        INPUT_BUILTIN_MIC       = 0x40000001; // buildin mic
+        INPUT_BUILTIN_BACK_MIC  = 0x40000002; // buildin back mic
+        INPUT_WIRED_HEADSET_MIC = 0x40000004; // 3.5mm headset mic
+        INPUT_USB_HEADSET_MIC   = 0x40000008; // usb headset mic
+        INPUT_BLUETOOTH_SCO     = 0x40000010; // bluetooth sco mic
+    }
+    optional AudioDevice audio_device = 1;
+
+    // Duration of the audio in seconds
+    optional int32 duration_secs = 2;
+
+    // Average volume (0 ... 1.0)
+    optional float average_volume = 3;
+
+    enum AudioType {
+        UNKNOWN_TYPE = 0;
+        VOICE_CALL_TYPE = 1; // voice call
+        VOIP_CALL_TYPE = 2; // voip call, including uplink and downlink
+        MEDIA_TYPE = 3; // music and system sound
+        RINGTONE_NOTIFICATION_TYPE = 4; // ringtone and notification
+        ALARM_TYPE = 5; // alarm type
+        // record type
+        CAMCORDER_TYPE = 6; // camcorder
+        RECORD_TYPE = 7;  // other recording
+    }
+    optional AudioType type = 4;
+}
+
+/**
+  * Pulls bytes transferred over WiFi and mobile networks sliced by uid, is_metered, and tag.
+  *
+  * Pulled from:
+  *   StatsPullAtomService, which uses NetworkStatsService to query NetworkStats.
+  */
+message BytesTransferByTagAndMetered {
+    optional int32 uid = 1 [(is_uid) = true];
+
+    optional bool is_metered = 2;
+
+    optional int32 tag = 3;
+
+    optional int64 rx_bytes = 4;
+
+    optional int64 rx_packets = 5;
+
+    optional int64 tx_bytes = 6;
+
+    optional int64 tx_packets = 7;
+}
+
+/*
+ * Logs when the Media Output Switcher finishes a media switch operation.
+ *
+ * Logged from:
+ *  packages/apps/Settings/src/com/android/settings/media/MediaOutputSliceWorker.java
+ */
+message MediaOutputOpSwitchReported {
+    // Source medium type before switching.
+    optional android.app.settings.mediaoutput.MediumType source = 1;
+
+    // Target medium type after switching.
+    optional android.app.settings.mediaoutput.MediumType target = 2;
+
+    // The result of switching.
+    optional android.app.settings.mediaoutput.SwitchResult result = 3;
+
+    // The detail code of a switching result.
+    optional android.app.settings.mediaoutput.SubResult subresult = 4;
+
+    /*
+     * The package name of a pre-installed app, whose media session is being switched.
+     */
+    optional string media_session_package_name = 5;
+
+    // The amount of available wired devices when a switching is being performed.
+    optional int32 available_wired_device_count = 6;
+
+    // The amount of available Bluetooth devices a switching is being performed.
+    optional int32 available_bt_device_count = 7;
+
+    // The amount of available remote devices when a switching is being performed.
+    optional int32 available_remote_device_count = 8;
+
+    // The amount of applied devices within a remote dynamic group after a switching is done.
+    optional int32 applied_device_count_within_remote_group = 9;
+}
diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp
index 829a603..9df4d1f 100644
--- a/cmds/statsd/src/external/StatsPuller.cpp
+++ b/cmds/statsd/src/external/StatsPuller.cpp
@@ -38,14 +38,16 @@
       mPullTimeoutNs(pullTimeoutNs),
       mCoolDownNs(coolDownNs),
       mAdditiveFields(additiveFields),
-      mLastPullTimeNs(0) {
+      mLastPullTimeNs(0),
+      mLastEventTimeNs(0) {
 }
 
-bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) {
+bool StatsPuller::Pull(const int64_t eventTimeNs, std::vector<std::shared_ptr<LogEvent>>* data) {
     lock_guard<std::mutex> lock(mLock);
     int64_t elapsedTimeNs = getElapsedRealtimeNs();
     StatsdStats::getInstance().notePull(mTagId);
-    const bool shouldUseCache = elapsedTimeNs - mLastPullTimeNs < mCoolDownNs;
+    const bool shouldUseCache =
+            (mLastEventTimeNs == eventTimeNs) || (elapsedTimeNs - mLastPullTimeNs < mCoolDownNs);
     if (shouldUseCache) {
         if (mHasGoodData) {
             (*data) = mCachedData;
@@ -54,13 +56,13 @@
         }
         return mHasGoodData;
     }
-
     if (mLastPullTimeNs > 0) {
         StatsdStats::getInstance().updateMinPullIntervalSec(
                 mTagId, (elapsedTimeNs - mLastPullTimeNs) / NS_PER_SEC);
     }
     mCachedData.clear();
     mLastPullTimeNs = elapsedTimeNs;
+    mLastEventTimeNs = eventTimeNs;
     mHasGoodData = PullInternal(&mCachedData);
     if (!mHasGoodData) {
         return mHasGoodData;
@@ -70,7 +72,7 @@
     const bool pullTimeOut = pullDurationNs > mPullTimeoutNs;
     if (pullTimeOut) {
         // Something went wrong. Discard the data.
-        clearCacheLocked();
+        mCachedData.clear();
         mHasGoodData = false;
         StatsdStats::getInstance().notePullTimeout(mTagId);
         ALOGW("Pull for atom %d exceeds timeout %lld nano seconds.", mTagId,
@@ -104,6 +106,7 @@
     int ret = mCachedData.size();
     mCachedData.clear();
     mLastPullTimeNs = 0;
+    mLastEventTimeNs = 0;
     return ret;
 }
 
diff --git a/cmds/statsd/src/external/StatsPuller.h b/cmds/statsd/src/external/StatsPuller.h
index fee571c..470d15e 100644
--- a/cmds/statsd/src/external/StatsPuller.h
+++ b/cmds/statsd/src/external/StatsPuller.h
@@ -51,7 +51,7 @@
     //   2) pull takes longer than mPullTimeoutNs (intrinsic to puller)
     // If a metric wants to make any change to the data, like timestamps, it
     // should make a copy as this data may be shared with multiple metrics.
-    bool Pull(std::vector<std::shared_ptr<LogEvent>>* data);
+    bool Pull(const int64_t eventTimeNs, std::vector<std::shared_ptr<LogEvent>>* data);
 
     // Clear cache immediately
     int ForceClearCache();
@@ -94,6 +94,11 @@
 
     int64_t mLastPullTimeNs;
 
+    // All pulls happen due to an event (app upgrade, bucket boundary, condition change, etc).
+    // If multiple pulls need to be done at the same event time, we will always use the cache after
+    // the first pull.
+    int64_t mLastEventTimeNs;
+
     // Cache of data from last pull. If next request comes before cool down finishes,
     // cached data will be returned.
     // Cached data is cleared when
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 1a52eb9..8a9ec74 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -91,20 +91,21 @@
       mPullAtomCallbackDeathRecipient(AIBinder_DeathRecipient_new(pullAtomCallbackDied)) {
 }
 
-bool StatsPullerManager::Pull(int tagId, const ConfigKey& configKey,
+bool StatsPullerManager::Pull(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs,
                               vector<shared_ptr<LogEvent>>* data, bool useUids) {
     std::lock_guard<std::mutex> _l(mLock);
-    return PullLocked(tagId, configKey, data, useUids);
+    return PullLocked(tagId, configKey, eventTimeNs, data, useUids);
 }
 
-bool StatsPullerManager::Pull(int tagId, const vector<int32_t>& uids,
+bool StatsPullerManager::Pull(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs,
                               vector<std::shared_ptr<LogEvent>>* data, bool useUids) {
     std::lock_guard<std::mutex> _l(mLock);
-    return PullLocked(tagId, uids, data, useUids);
+    return PullLocked(tagId, uids, eventTimeNs, data, useUids);
 }
 
 bool StatsPullerManager::PullLocked(int tagId, const ConfigKey& configKey,
-                                    vector<shared_ptr<LogEvent>>* data, bool useUids) {
+                                    const int64_t eventTimeNs, vector<shared_ptr<LogEvent>>* data,
+                                    bool useUids) {
     vector<int32_t> uids;
     if (useUids) {
         auto uidProviderIt = mPullUidProviders.find(configKey);
@@ -123,18 +124,19 @@
         }
         uids = pullUidProvider->getPullAtomUids(tagId);
     }
-    return PullLocked(tagId, uids, data, useUids);
+    return PullLocked(tagId, uids, eventTimeNs, data, useUids);
 }
 
 bool StatsPullerManager::PullLocked(int tagId, const vector<int32_t>& uids,
-                                    vector<shared_ptr<LogEvent>>* data, bool useUids) {
+                                    const int64_t eventTimeNs, vector<shared_ptr<LogEvent>>* data,
+                                    bool useUids) {
     VLOG("Initiating pulling %d", tagId);
     if (useUids) {
         for (int32_t uid : uids) {
             PullerKey key = {.atomTag = tagId, .uid = uid};
             auto pullerIt = kAllPullAtomInfo.find(key);
             if (pullerIt != kAllPullAtomInfo.end()) {
-                bool ret = pullerIt->second->Pull(data);
+                bool ret = pullerIt->second->Pull(eventTimeNs, data);
                 VLOG("pulled %zu items", data->size());
                 if (!ret) {
                     StatsdStats::getInstance().notePullFailed(tagId);
@@ -149,7 +151,7 @@
         PullerKey key = {.atomTag = tagId, .uid = -1};
         auto pullerIt = kAllPullAtomInfo.find(key);
         if (pullerIt != kAllPullAtomInfo.end()) {
-            bool ret = pullerIt->second->Pull(data);
+            bool ret = pullerIt->second->Pull(eventTimeNs, data);
             VLOG("pulled %zu items", data->size());
             if (!ret) {
                 StatsdStats::getInstance().notePullFailed(tagId);
@@ -290,7 +292,8 @@
     }
     for (const auto& pullInfo : needToPull) {
         vector<shared_ptr<LogEvent>> data;
-        bool pullSuccess = PullLocked(pullInfo.first->atomTag, pullInfo.first->configKey, &data);
+        bool pullSuccess = PullLocked(pullInfo.first->atomTag, pullInfo.first->configKey,
+                                      elapsedTimeNs, &data);
         if (!pullSuccess) {
             VLOG("pull failed at %lld, will try again later", (long long)elapsedTimeNs);
         }
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index 5e18aaa..194a0f5 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -101,11 +101,11 @@
     //      registered for any of the uids for this atom.
     // If the metric wants to make any change to the data, like timestamps, they
     // should make a copy as this data may be shared with multiple metrics.
-    virtual bool Pull(int tagId, const ConfigKey& configKey,
+    virtual bool Pull(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs,
                       vector<std::shared_ptr<LogEvent>>* data, bool useUids = true);
 
     // Same as above, but directly specify the allowed uids to pull from.
-    virtual bool Pull(int tagId, const vector<int32_t>& uids,
+    virtual bool Pull(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs,
                       vector<std::shared_ptr<LogEvent>>* data, bool useUids = true);
 
     // Clear pull data cache immediately.
@@ -152,11 +152,11 @@
     // mapping from Config Key to the PullUidProvider for that config
     std::map<ConfigKey, wp<PullUidProvider>> mPullUidProviders;
 
-    bool PullLocked(int tagId, const ConfigKey& configKey, vector<std::shared_ptr<LogEvent>>* data,
-                    bool useUids = true);
+    bool PullLocked(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs,
+                    vector<std::shared_ptr<LogEvent>>* data, bool useUids = true);
 
-    bool PullLocked(int tagId, const vector<int32_t>& uids, vector<std::shared_ptr<LogEvent>>* data,
-                    bool useUids);
+    bool PullLocked(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs,
+                    vector<std::shared_ptr<LogEvent>>* data, bool useUids);
 
     // locks for data receiver and StatsCompanionService changes
     std::mutex mLock;
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 8ec0173..f56fa62 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -66,15 +66,6 @@
 #define ATTRIBUTION_CHAIN_TYPE 0x09
 #define ERROR_TYPE 0x0F
 
-LogEvent::LogEvent(const LogEvent& event) {
-    mTagId = event.mTagId;
-    mLogUid = event.mLogUid;
-    mLogPid = event.mLogPid;
-    mElapsedTimestampNs = event.mElapsedTimestampNs;
-    mLogdTimestampNs = event.mLogdTimestampNs;
-    mValues = event.mValues;
-}
-
 LogEvent::LogEvent(int32_t uid, int32_t pid)
     : mLogdTimestampNs(time(nullptr)), mLogUid(uid), mLogPid(pid) {
 }
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 53fb5d9..a5f2460 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -216,7 +216,7 @@
     /**
      * Only use this if copy is absolutely needed.
      */
-    LogEvent(const LogEvent&);
+    LogEvent(const LogEvent&) = default;
 
     void parseInt32(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations);
     void parseInt64(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations);
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 21ffff3..d865c21 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -122,11 +122,11 @@
 }
 
 void CountMetricProducer::onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
-                                         const HashableDimensionKey& primaryKey, int oldState,
-                                         int newState) {
+                                         const HashableDimensionKey& primaryKey,
+                                         const FieldValue& oldState, const FieldValue& newState) {
     VLOG("CountMetric %lld onStateChanged time %lld, State%d, key %s, %d -> %d",
          (long long)mMetricId, (long long)eventTimeNs, atomId, primaryKey.toString().c_str(),
-         oldState, newState);
+         oldState.mValue.int_value, newState.mValue.int_value);
 }
 
 void CountMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index f9a8842..26b3d3c 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -53,8 +53,8 @@
     virtual ~CountMetricProducer();
 
     void onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
-                        const HashableDimensionKey& primaryKey, int oldState,
-                        int newState) override;
+                        const HashableDimensionKey& primaryKey, const FieldValue& oldState,
+                        const FieldValue& newState) override;
 
 protected:
     void onMatchedLogEventInternalLocked(
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 0de92f3..6633659 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -161,13 +161,12 @@
 
 void DurationMetricProducer::onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
                                             const HashableDimensionKey& primaryKey,
-                                            const int32_t oldState, const int32_t newState) {
-    // Create a FieldValue object to hold the new state.
-    FieldValue value;
-    value.mValue.setInt(newState);
+                                            const FieldValue& oldState,
+                                            const FieldValue& newState) {
     // Check if this metric has a StateMap. If so, map the new state value to
     // the correct state group id.
-    mapStateValue(atomId, &value);
+    FieldValue newStateCopy = newState;
+    mapStateValue(atomId, &newStateCopy);
 
     flushIfNeededLocked(eventTimeNs);
 
@@ -185,7 +184,7 @@
         if (!containsLinkedStateValues(whatIt.first, primaryKey, mMetric2StateLinks, atomId)) {
             continue;
         }
-        whatIt.second->onStateChanged(eventTimeNs, atomId, value);
+        whatIt.second->onStateChanged(eventTimeNs, atomId, newStateCopy);
     }
 }
 
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 6f84076..53f0f28 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -55,8 +55,8 @@
                                          const sp<AlarmMonitor>& anomalyAlarmMonitor) override;
 
     void onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
-                        const HashableDimensionKey& primaryKey, const int32_t oldState,
-                        const int32_t newState) override;
+                        const HashableDimensionKey& primaryKey, const FieldValue& oldState,
+                        const FieldValue& newState) override;
 
 protected:
     void onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) override;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index cc4c565..1d4d0b3 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -321,7 +321,7 @@
         return;
     }
     vector<std::shared_ptr<LogEvent>> allData;
-    if (!mPullerManager->Pull(mPullTagId, mConfigKey, &allData)) {
+    if (!mPullerManager->Pull(mPullTagId, mConfigKey, timestampNs, &allData)) {
         ALOGE("Gauge Stats puller failed for tag: %d at %lld", mPullTagId, (long long)timestampNs);
         return;
     }
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 91c98ea2..e86fdf0 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -182,8 +182,8 @@
     };
 
     void onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
-                        const HashableDimensionKey& primaryKey, const int32_t oldState,
-                        const int32_t newState){};
+                        const HashableDimensionKey& primaryKey, const FieldValue& oldState,
+                        const FieldValue& newState){};
 
     // Output the metrics data to [protoOutput]. All metrics reports end with the same timestamp.
     // This method clears all the past buckets.
@@ -442,7 +442,7 @@
     bool mIsActive;
 
     // The slice_by_state atom ids defined in statsd_config.
-    std::vector<int32_t> mSlicedStateAtoms;
+    const std::vector<int32_t> mSlicedStateAtoms;
 
     // Maps atom ids and state values to group_ids (<atom_id, <value, group_id>>).
     const std::unordered_map<int32_t, std::unordered_map<int, int64_t>> mStateGroupMap;
@@ -459,6 +459,7 @@
     FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithMap);
     FRIEND_TEST(CountMetricE2eTest, TestMultipleSlicedStates);
     FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields);
+    FRIEND_TEST(CountMetricE2eTest, TestInitialConditionChanges);
 
     FRIEND_TEST(DurationMetricE2eTest, TestOneBucket);
     FRIEND_TEST(DurationMetricE2eTest, TestTwoBuckets);
@@ -488,6 +489,7 @@
     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
+    FRIEND_TEST(ValueMetricE2eTest, TestInitialConditionChanges);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index d7ad27b..e8c575a 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -71,6 +71,8 @@
       mLastReportTimeNs(currentTimeNs),
       mLastReportWallClockNs(getWallClockNs()),
       mPullerManager(pullerManager),
+      mWhitelistedAtomIds(config.whitelisted_atom_ids().begin(),
+                          config.whitelisted_atom_ids().end()),
       mShouldPersistHistory(config.persist_locally()) {
     // Init the ttl end timestamp.
     refreshTtl(timeBaseNs);
@@ -366,11 +368,16 @@
 
 
 bool MetricsManager::checkLogCredentials(const LogEvent& event) {
+    // TODO(b/154856835): Remove this check once we get whitelist from the config.
     if (android::util::AtomsInfo::kWhitelistedAtoms.find(event.GetTagId()) !=
       android::util::AtomsInfo::kWhitelistedAtoms.end())
     {
         return true;
     }
+
+    if (mWhitelistedAtomIds.find(event.GetTagId()) != mWhitelistedAtomIds.end()) {
+        return true;
+    }
     std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex);
     if (mAllowedLogSources.find(event.GetUid()) == mAllowedLogSources.end()) {
         VLOG("log source %d not on the whitelist", event.GetUid());
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index ef03d20..ad30a88 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -189,6 +189,8 @@
     // To guard access to mAllowedLogSources
     mutable std::mutex mAllowedLogSourcesMutex;
 
+    const std::set<int32_t> mWhitelistedAtomIds;
+
     // We can pull any atom from these uids.
     std::set<int32_t> mDefaultPullUids;
 
@@ -290,9 +292,6 @@
     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation);
     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition);
     FRIEND_TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents);
-    FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
-    FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
-    FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation);
 
     FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket);
     FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets);
@@ -320,6 +319,7 @@
             TestActivationOnBootMultipleActivationsDifferentActivationTypes);
     FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
 
+    FRIEND_TEST(CountMetricE2eTest, TestInitialConditionChanges);
     FRIEND_TEST(CountMetricE2eTest, TestSlicedState);
     FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithMap);
     FRIEND_TEST(CountMetricE2eTest, TestMultipleSlicedStates);
@@ -337,6 +337,10 @@
     FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSuperset);
     FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSubset);
 
+    FRIEND_TEST(ValueMetricE2eTest, TestInitialConditionChanges);
+    FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
+    FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
+    FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation);
     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index e5ec72e..f03ce45 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -182,15 +182,26 @@
 }
 
 void ValueMetricProducer::onStateChanged(int64_t eventTimeNs, int32_t atomId,
-                                         const HashableDimensionKey& primaryKey, int oldState,
-                                         int newState) {
+                                         const HashableDimensionKey& primaryKey,
+                                         const FieldValue& oldState, const FieldValue& newState) {
     VLOG("ValueMetric %lld onStateChanged time %lld, State %d, key %s, %d -> %d",
          (long long)mMetricId, (long long)eventTimeNs, atomId, primaryKey.toString().c_str(),
-         oldState, newState);
+         oldState.mValue.int_value, newState.mValue.int_value);
     // If condition is not true, we do not need to pull for this state change.
     if (mCondition != ConditionState::kTrue) {
         return;
     }
+
+    // If old and new states are in the same StateGroup, then we do not need to
+    // pull for this state change.
+    FieldValue oldStateCopy = oldState;
+    FieldValue newStateCopy = newState;
+    mapStateValue(atomId, &oldStateCopy);
+    mapStateValue(atomId, &newStateCopy);
+    if (oldStateCopy == newStateCopy) {
+        return;
+    }
+
     bool isEventLate = eventTimeNs < mCurrentBucketStartTimeNs;
     if (isEventLate) {
         VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
@@ -508,7 +519,7 @@
 
 void ValueMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
     vector<std::shared_ptr<LogEvent>> allData;
-    if (!mPullerManager->Pull(mPullTagId, mConfigKey, &allData)) {
+    if (!mPullerManager->Pull(mPullTagId, mConfigKey, timestampNs, &allData)) {
         ALOGE("Stats puller failed for tag: %d at %lld", mPullTagId, (long long)timestampNs);
         invalidateCurrentBucket(timestampNs, BucketDropReason::PULL_FAILED);
         return;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index c8dc8cc..751fef2 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -90,7 +90,7 @@
     };
 
     void onStateChanged(int64_t eventTimeNs, int32_t atomId, const HashableDimensionKey& primaryKey,
-                        int oldState, int newState) override;
+                        const FieldValue& oldState, const FieldValue& newState) override;
 
 protected:
     void onMatchedLogEventInternalLocked(
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 3ab44f4..210d382 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -791,10 +791,19 @@
         }
         noReportMetricIds.insert(no_report_metric);
     }
+
+    const set<int> whitelistedAtomIds(config.whitelisted_atom_ids().begin(),
+                                      config.whitelisted_atom_ids().end());
     for (const auto& it : allMetricProducers) {
         // Register metrics to StateTrackers
         for (int atomId : it->getSlicedStateAtoms()) {
-            StateManager::getInstance().registerListener(atomId, it);
+            // Register listener for non-whitelisted atoms only. Using whitelisted atom as a sliced
+            // state atom is not allowed.
+            if (whitelistedAtomIds.find(atomId) == whitelistedAtomIds.end()) {
+                StateManager::getInstance().registerListener(atomId, it);
+            } else {
+                return false;
+            }
         }
     }
     return true;
diff --git a/cmds/statsd/src/shell/ShellSubscriber.cpp b/cmds/statsd/src/shell/ShellSubscriber.cpp
index 7b68721..361b161 100644
--- a/cmds/statsd/src/shell/ShellSubscriber.cpp
+++ b/cmds/statsd/src/shell/ShellSubscriber.cpp
@@ -152,6 +152,7 @@
             }
 
             int64_t nowMillis = getElapsedRealtimeMillis();
+            int64_t nowNanos = getElapsedRealtimeNs();
             for (PullInfo& pullInfo : mSubscriptionInfo->mPulledInfo) {
                 if (pullInfo.mPrevPullElapsedRealtimeMs + pullInfo.mInterval >= nowMillis) {
                     continue;
@@ -161,7 +162,7 @@
                 getUidsForPullAtom(&uids, pullInfo);
 
                 vector<std::shared_ptr<LogEvent>> data;
-                mPullerMgr->Pull(pullInfo.mPullerMatcher.atom_id(), uids, &data);
+                mPullerMgr->Pull(pullInfo.mPullerMatcher.atom_id(), uids, nowNanos, &data);
                 VLOG("Pulled %zu atoms with id %d", data.size(), pullInfo.mPullerMatcher.atom_id());
                 writePulledAtomsLocked(data, pullInfo.mPullerMatcher);
 
diff --git a/cmds/statsd/src/state/StateListener.h b/cmds/statsd/src/state/StateListener.h
index d1af196..6388001 100644
--- a/cmds/statsd/src/state/StateListener.h
+++ b/cmds/statsd/src/state/StateListener.h
@@ -45,8 +45,8 @@
      * [newState]: Current state value after state change
      */
     virtual void onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
-                                const HashableDimensionKey& primaryKey, int oldState,
-                                int newState) = 0;
+                                const HashableDimensionKey& primaryKey, const FieldValue& oldState,
+                                const FieldValue& newState) = 0;
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/state/StateTracker.cpp b/cmds/statsd/src/state/StateTracker.cpp
index b63713b..41e525c 100644
--- a/cmds/statsd/src/state/StateTracker.cpp
+++ b/cmds/statsd/src/state/StateTracker.cpp
@@ -35,31 +35,30 @@
     HashableDimensionKey primaryKey;
     filterPrimaryKey(event.getValues(), &primaryKey);
 
-    FieldValue stateValue;
-    if (!getStateFieldValueFromLogEvent(event, &stateValue)) {
+    FieldValue newState;
+    if (!getStateFieldValueFromLogEvent(event, &newState)) {
         ALOGE("StateTracker error extracting state from log event. Missing exclusive state field.");
         clearStateForPrimaryKey(eventTimeNs, primaryKey);
         return;
     }
 
-    mField.setField(stateValue.mField.getField());
+    mField.setField(newState.mField.getField());
 
-    if (stateValue.mValue.getType() != INT) {
+    if (newState.mValue.getType() != INT) {
         ALOGE("StateTracker error extracting state from log event. Type: %d",
-              stateValue.mValue.getType());
+              newState.mValue.getType());
         clearStateForPrimaryKey(eventTimeNs, primaryKey);
         return;
     }
 
-    const int32_t resetState = event.getResetState();
-    if (resetState != -1) {
+    if (int resetState = event.getResetState(); resetState != -1) {
         VLOG("StateTracker new reset state: %d", resetState);
-        handleReset(eventTimeNs, resetState);
+        const FieldValue resetStateFieldValue(mField, Value(resetState));
+        handleReset(eventTimeNs, resetStateFieldValue);
         return;
     }
 
-    const int32_t newState = stateValue.mValue.int_value;
-    const bool nested = stateValue.mAnnotations.isNested();
+    const bool nested = newState.mAnnotations.isNested();
     StateValueInfo* stateValueInfo = &mStateMap[primaryKey];
     updateStateForPrimaryKey(eventTimeNs, primaryKey, newState, nested, stateValueInfo);
 }
@@ -85,7 +84,7 @@
     return false;
 }
 
-void StateTracker::handleReset(const int64_t eventTimeNs, const int32_t newState) {
+void StateTracker::handleReset(const int64_t eventTimeNs, const FieldValue& newState) {
     VLOG("StateTracker handle reset");
     for (auto& [primaryKey, stateValueInfo] : mStateMap) {
         updateStateForPrimaryKey(eventTimeNs, primaryKey, newState,
@@ -102,8 +101,9 @@
 
     // If there is no entry for the primaryKey in mStateMap, then the state is already
     // kStateUnknown.
+    const FieldValue state(mField, Value(kStateUnknown));
     if (it != mStateMap.end()) {
-        updateStateForPrimaryKey(eventTimeNs, primaryKey, kStateUnknown,
+        updateStateForPrimaryKey(eventTimeNs, primaryKey, state,
                                  false /* nested; treat this state change as not nested */,
                                  &it->second);
     }
@@ -111,22 +111,26 @@
 
 void StateTracker::updateStateForPrimaryKey(const int64_t eventTimeNs,
                                             const HashableDimensionKey& primaryKey,
-                                            const int32_t newState, const bool nested,
+                                            const FieldValue& newState, const bool nested,
                                             StateValueInfo* stateValueInfo) {
-    const int32_t oldState = stateValueInfo->state;
+    FieldValue oldState;
+    oldState.mField = mField;
+    oldState.mValue.setInt(stateValueInfo->state);
+    const int32_t oldStateValue = stateValueInfo->state;
+    const int32_t newStateValue = newState.mValue.int_value;
 
-    if (kStateUnknown == newState) {
+    if (kStateUnknown == newStateValue) {
         mStateMap.erase(primaryKey);
     }
 
     // Update state map for non-nested counting case.
     // Every state event triggers a state overwrite.
     if (!nested) {
-        stateValueInfo->state = newState;
+        stateValueInfo->state = newStateValue;
         stateValueInfo->count = 1;
 
         // Notify listeners if state has changed.
-        if (oldState != newState) {
+        if (oldStateValue != newStateValue) {
             notifyListeners(eventTimeNs, primaryKey, oldState, newState);
         }
         return;
@@ -142,26 +146,26 @@
     // In atoms.proto, a state atom with nested counting enabled
     // must only have 2 states. There is no enforcemnt here of this requirement.
     // The atom must be logged correctly.
-    if (kStateUnknown == newState) {
-        if (kStateUnknown != oldState) {
+    if (kStateUnknown == newStateValue) {
+        if (kStateUnknown != oldStateValue) {
             notifyListeners(eventTimeNs, primaryKey, oldState, newState);
         }
-    } else if (oldState == kStateUnknown) {
-        stateValueInfo->state = newState;
+    } else if (oldStateValue == kStateUnknown) {
+        stateValueInfo->state = newStateValue;
         stateValueInfo->count = 1;
         notifyListeners(eventTimeNs, primaryKey, oldState, newState);
-    } else if (oldState == newState) {
+    } else if (oldStateValue == newStateValue) {
         stateValueInfo->count++;
     } else if (--stateValueInfo->count == 0) {
-        stateValueInfo->state = newState;
+        stateValueInfo->state = newStateValue;
         stateValueInfo->count = 1;
         notifyListeners(eventTimeNs, primaryKey, oldState, newState);
     }
 }
 
 void StateTracker::notifyListeners(const int64_t eventTimeNs,
-                                   const HashableDimensionKey& primaryKey, const int32_t oldState,
-                                   const int32_t newState) {
+                                   const HashableDimensionKey& primaryKey,
+                                   const FieldValue& oldState, const FieldValue& newState) {
     for (auto l : mListeners) {
         auto sl = l.promote();
         if (sl != nullptr) {
diff --git a/cmds/statsd/src/state/StateTracker.h b/cmds/statsd/src/state/StateTracker.h
index c5f6315..abd579e 100644
--- a/cmds/statsd/src/state/StateTracker.h
+++ b/cmds/statsd/src/state/StateTracker.h
@@ -72,19 +72,19 @@
     std::set<wp<StateListener>> mListeners;
 
     // Reset all state values in map to the given state.
-    void handleReset(const int64_t eventTimeNs, const int32_t newState);
+    void handleReset(const int64_t eventTimeNs, const FieldValue& newState);
 
     // Clears the state value mapped to the given primary key by setting it to kStateUnknown.
     void clearStateForPrimaryKey(const int64_t eventTimeNs, const HashableDimensionKey& primaryKey);
 
     // Update the StateMap based on the received state value.
     void updateStateForPrimaryKey(const int64_t eventTimeNs, const HashableDimensionKey& primaryKey,
-                                  const int32_t newState, const bool nested,
+                                  const FieldValue& newState, const bool nested,
                                   StateValueInfo* stateValueInfo);
 
     // Notify registered state listeners of state change.
     void notifyListeners(const int64_t eventTimeNs, const HashableDimensionKey& primaryKey,
-                         const int32_t oldState, const int32_t newState);
+                         const FieldValue& oldState, const FieldValue& newState);
 };
 
 bool getStateFieldValueFromLogEvent(const LogEvent& event, FieldValue* output);
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index c7407bd..2e6043d 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -131,7 +131,7 @@
     UNKNOWN = 0;
     FALSE = 1;
   }
-  optional InitialValue initial_value = 5 [default = FALSE];
+  optional InitialValue initial_value = 5 [default = UNKNOWN];
 
   optional FieldMatcher dimensions = 6;
 }
@@ -489,6 +489,8 @@
 
   repeated PullAtomPackages pull_atom_packages = 23;
 
+  repeated int32 whitelisted_atom_ids = 24;
+
   // Field number 1000 is reserved for later use.
   reserved 1000;
 }
diff --git a/cmds/statsd/tests/AlarmMonitor_test.cpp b/cmds/statsd/tests/AlarmMonitor_test.cpp
index edbf8b5..1dc9795 100644
--- a/cmds/statsd/tests/AlarmMonitor_test.cpp
+++ b/cmds/statsd/tests/AlarmMonitor_test.cpp
@@ -49,19 +49,19 @@
     EXPECT_TRUE(set.empty());
 
     set = am.popSoonerThan(30);
-    EXPECT_EQ(4u, set.size());
+    ASSERT_EQ(4u, set.size());
     EXPECT_EQ(1u, set.count(a));
     EXPECT_EQ(1u, set.count(b));
     EXPECT_EQ(1u, set.count(c));
     EXPECT_EQ(1u, set.count(d));
 
     set = am.popSoonerThan(60);
-    EXPECT_EQ(2u, set.size());
+    ASSERT_EQ(2u, set.size());
     EXPECT_EQ(1u, set.count(e));
     EXPECT_EQ(1u, set.count(f));
 
     set = am.popSoonerThan(80);
-    EXPECT_EQ(0u, set.size());
+    ASSERT_EQ(0u, set.size());
 }
 
 #else
diff --git a/cmds/statsd/tests/FieldValue_test.cpp b/cmds/statsd/tests/FieldValue_test.cpp
index f5ba8fd..23f8ca4 100644
--- a/cmds/statsd/tests/FieldValue_test.cpp
+++ b/cmds/statsd/tests/FieldValue_test.cpp
@@ -74,7 +74,7 @@
     vector<Matcher> output;
     translateFieldMatcher(matcher1, &output);
 
-    EXPECT_EQ((size_t)1, output.size());
+    ASSERT_EQ((size_t)1, output.size());
 
     const auto& matcher12 = output[0];
     EXPECT_EQ((int32_t)10, matcher12.mMatcher.getTag());
@@ -95,7 +95,7 @@
     vector<Matcher> output;
     translateFieldMatcher(matcher1, &output);
 
-    EXPECT_EQ((size_t)1, output.size());
+    ASSERT_EQ((size_t)1, output.size());
 
     const auto& matcher12 = output[0];
     EXPECT_EQ((int32_t)10, matcher12.mMatcher.getTag());
@@ -128,7 +128,7 @@
 
     filterValues(matchers, event.getValues(), &output);
 
-    EXPECT_EQ((size_t)7, output.getValues().size());
+    ASSERT_EQ((size_t)7, output.getValues().size());
     EXPECT_EQ((int32_t)0x02010101, output.getValues()[0].mField.getField());
     EXPECT_EQ((int32_t)1111, output.getValues()[0].mValue.int_value);
     EXPECT_EQ((int32_t)0x02010102, output.getValues()[1].mField.getField());
@@ -218,12 +218,12 @@
     translateFieldMatcher(whatMatcher, &link.metricFields);
     translateFieldMatcher(conditionMatcher, &link.conditionFields);
 
-    EXPECT_EQ((size_t)1, link.metricFields.size());
+    ASSERT_EQ((size_t)1, link.metricFields.size());
     EXPECT_EQ((int32_t)0x02010001, link.metricFields[0].mMatcher.getField());
     EXPECT_EQ((int32_t)0xff7f007f, link.metricFields[0].mMask);
     EXPECT_EQ((int32_t)10, link.metricFields[0].mMatcher.getTag());
 
-    EXPECT_EQ((size_t)1, link.conditionFields.size());
+    ASSERT_EQ((size_t)1, link.conditionFields.size());
     EXPECT_EQ((int32_t)0x02028002, link.conditionFields[0].mMatcher.getField());
     EXPECT_EQ((int32_t)0xff7f807f, link.conditionFields[0].mMask);
     EXPECT_EQ((int32_t)27, link.conditionFields[0].mMatcher.getTag());
@@ -264,15 +264,15 @@
         }
 
         DimensionsValue result;
-        EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
+        ASSERT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
 
         EXPECT_EQ(10, result.field());
         EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, result.value_case());
-        EXPECT_EQ(3, result.value_tuple().dimensions_value_size());
+        ASSERT_EQ(3, result.value_tuple().dimensions_value_size());
 
         const auto& dim1 = result.value_tuple().dimensions_value(0);
         EXPECT_EQ(2, dim1.field());
-        EXPECT_EQ(2, dim1.value_tuple().dimensions_value_size());
+        ASSERT_EQ(2, dim1.value_tuple().dimensions_value_size());
 
         const auto& dim11 = dim1.value_tuple().dimensions_value(0);
         EXPECT_EQ(1, dim11.field());
@@ -285,7 +285,7 @@
 
         const auto& dim3 = result.value_tuple().dimensions_value(2);
         EXPECT_EQ(6, dim3.field());
-        EXPECT_EQ(1, dim3.value_tuple().dimensions_value_size());
+        ASSERT_EQ(1, dim3.value_tuple().dimensions_value_size());
         const auto& dim31 = dim3.value_tuple().dimensions_value(0);
         EXPECT_EQ(2, dim31.field());
     }
@@ -356,14 +356,14 @@
     }
 
     DimensionsValue result;
-    EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
+    ASSERT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
     EXPECT_EQ(10, result.field());
     EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, result.value_case());
-    EXPECT_EQ(2, result.value_tuple().dimensions_value_size());
+    ASSERT_EQ(2, result.value_tuple().dimensions_value_size());
 
     const auto& dim1 = result.value_tuple().dimensions_value(0);
     EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, dim1.value_case());
-    EXPECT_EQ(3, dim1.value_tuple().dimensions_value_size());
+    ASSERT_EQ(3, dim1.value_tuple().dimensions_value_size());
 
     const auto& dim11 = dim1.value_tuple().dimensions_value(0);
     EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim11.value_case());
@@ -418,8 +418,8 @@
     }
 
     DimensionsValueTuple result;
-    EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
-    EXPECT_EQ(4, result.dimensions_value_size());
+    ASSERT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
+    ASSERT_EQ(4, result.dimensions_value_size());
 
     const auto& dim1 = result.dimensions_value(0);
     EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim1.value_case());
@@ -460,10 +460,10 @@
     }
 
     Atom result;
-    EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
+    ASSERT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
     EXPECT_EQ(Atom::PushedCase::kBleScanResultReceived, result.pushed_case());
     const auto& atom = result.ble_scan_result_received();
-    EXPECT_EQ(2, atom.attribution_node_size());
+    ASSERT_EQ(2, atom.attribution_node_size());
     EXPECT_EQ(1111, atom.attribution_node(0).uid());
     EXPECT_EQ("location1", atom.attribution_node(0).tag());
     EXPECT_EQ(2222, atom.attribution_node(1).uid());
@@ -488,7 +488,7 @@
 
     vector<Matcher> matchers1;
     translateFieldMatcher(matcher1, &matchers1);
-    EXPECT_EQ(2, matchers1.size());
+    ASSERT_EQ(2, matchers1.size());
 
     // Initialize second set of matchers
     FieldMatcher matcher2;
@@ -501,7 +501,7 @@
 
     vector<Matcher> matchers2;
     translateFieldMatcher(matcher2, &matchers2);
-    EXPECT_EQ(1, matchers2.size());
+    ASSERT_EQ(1, matchers2.size());
 
     EXPECT_FALSE(subsetDimensions(matchers1, matchers2));
     EXPECT_TRUE(subsetDimensions(matchers2, matchers1));
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index 00f336a..5c170c0 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -98,7 +98,7 @@
     EXPECT_FALSE(logEvent.hasAttributionChain());
 
     const vector<FieldValue>& values = logEvent.getValues();
-    EXPECT_EQ(4, values.size());
+    ASSERT_EQ(4, values.size());
 
     const FieldValue& int32Item = values[0];
     Field expectedField = getField(100, {1, 1, 1}, 0, {false, false, false});
@@ -147,7 +147,7 @@
     EXPECT_FALSE(logEvent.hasAttributionChain());
 
     const vector<FieldValue>& values = logEvent.getValues();
-    EXPECT_EQ(2, values.size());
+    ASSERT_EQ(2, values.size());
 
     const FieldValue& stringItem = values[0];
     Field expectedField = getField(100, {1, 1, 1}, 0, {false, false, false});
@@ -184,7 +184,7 @@
     EXPECT_FALSE(logEvent.hasAttributionChain());
 
     const vector<FieldValue>& values = logEvent.getValues();
-    EXPECT_EQ(1, values.size());
+    ASSERT_EQ(1, values.size());
 
     const FieldValue& item = values[0];
     Field expectedField = getField(100, {1, 1, 1}, 0, {true, false, false});
@@ -213,7 +213,7 @@
     EXPECT_EQ(1001, logEvent.GetPid());
 
     const vector<FieldValue>& values = logEvent.getValues();
-    EXPECT_EQ(1, values.size());
+    ASSERT_EQ(1, values.size());
 
     const FieldValue& item = values[0];
     Field expectedField = getField(100, {1, 1, 1}, 0, {true, false, false});
@@ -249,7 +249,7 @@
     EXPECT_EQ(1001, logEvent.GetPid());
 
     const vector<FieldValue>& values = logEvent.getValues();
-    EXPECT_EQ(4, values.size());  // 2 per attribution node
+    ASSERT_EQ(4, values.size());  // 2 per attribution node
 
     std::pair<int, int> attrIndexRange;
     EXPECT_TRUE(logEvent.hasAttributionChain(&attrIndexRange));
@@ -290,7 +290,7 @@
     createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_IS_UID, true);
 
     const vector<FieldValue>& values = event.getValues();
-    EXPECT_EQ(values.size(), 1);
+    ASSERT_EQ(values.size(), 1);
     EXPECT_EQ(event.getUidFieldIndex(), 0);
 }
 
@@ -299,7 +299,7 @@
     createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_STATE_NESTED, true);
 
     const vector<FieldValue>& values = event.getValues();
-    EXPECT_EQ(values.size(), 1);
+    ASSERT_EQ(values.size(), 1);
     EXPECT_TRUE(values[0].mAnnotations.isNested());
 }
 
@@ -308,7 +308,7 @@
     createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_PRIMARY_FIELD, true);
 
     const vector<FieldValue>& values = event.getValues();
-    EXPECT_EQ(values.size(), 1);
+    ASSERT_EQ(values.size(), 1);
     EXPECT_TRUE(values[0].mAnnotations.isPrimaryField());
 }
 
@@ -317,7 +317,7 @@
     createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_EXCLUSIVE_STATE, true);
 
     const vector<FieldValue>& values = event.getValues();
-    EXPECT_EQ(values.size(), 1);
+    ASSERT_EQ(values.size(), 1);
     EXPECT_TRUE(values[0].mAnnotations.isExclusiveState());
 }
 
@@ -349,7 +349,7 @@
 
     // Check annotation
     const vector<FieldValue>& values = logEvent.getValues();
-    EXPECT_EQ(values.size(), numInts + 4);
+    ASSERT_EQ(values.size(), numInts + 4);
     EXPECT_TRUE(values[firstUidInChainIndex].mAnnotations.isPrimaryField());
 }
 
@@ -359,7 +359,7 @@
     createIntWithIntAnnotationLogEvent(&event, ANNOTATION_ID_TRIGGER_STATE_RESET, resetState);
 
     const vector<FieldValue>& values = event.getValues();
-    EXPECT_EQ(values.size(), 1);
+    ASSERT_EQ(values.size(), 1);
     EXPECT_EQ(event.getResetState(), resetState);
 }
 
diff --git a/cmds/statsd/tests/MetricsManager_test.cpp b/cmds/statsd/tests/MetricsManager_test.cpp
index a44541d..b3b095b 100644
--- a/cmds/statsd/tests/MetricsManager_test.cpp
+++ b/cmds/statsd/tests/MetricsManager_test.cpp
@@ -29,6 +29,7 @@
 #include "src/metrics/MetricProducer.h"
 #include "src/metrics/ValueMetricProducer.h"
 #include "src/metrics/metrics_manager_util.h"
+#include "src/state/StateManager.h"
 #include "statsd_test_util.h"
 
 using namespace testing;
@@ -309,10 +310,10 @@
                                  activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
                                  alertTrackerMap, metricsWithActivation,
                                  noReportMetricIds));
-    EXPECT_EQ(1u, allMetricProducers.size());
-    EXPECT_EQ(1u, allAnomalyTrackers.size());
-    EXPECT_EQ(1u, noReportMetricIds.size());
-    EXPECT_EQ(1u, alertTrackerMap.size());
+    ASSERT_EQ(1u, allMetricProducers.size());
+    ASSERT_EQ(1u, allAnomalyTrackers.size());
+    ASSERT_EQ(1u, noReportMetricIds.size());
+    ASSERT_EQ(1u, alertTrackerMap.size());
     EXPECT_NE(alertTrackerMap.find(kAlertId), alertTrackerMap.end());
     EXPECT_EQ(alertTrackerMap.find(kAlertId)->second, 0);
 }
@@ -591,6 +592,58 @@
     EXPECT_TRUE(isSubset(defaultPullUids, set<int32_t>(atom3Uids.begin(), atom3Uids.end())));
 }
 
+TEST(MetricsManagerTest, TestCheckLogCredentialsWhitelistedAtom) {
+    sp<UidMap> uidMap;
+    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+    sp<AlarmMonitor> anomalyAlarmMonitor;
+    sp<AlarmMonitor> periodicAlarmMonitor;
+
+    StatsdConfig config = buildGoodConfig();
+    config.add_whitelisted_atom_ids(3);
+    config.add_whitelisted_atom_ids(4);
+
+    MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap,
+                                  pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor);
+
+    LogEvent event(0 /* uid */, 0 /* pid */);
+    CreateNoValuesLogEvent(&event, 10 /* atom id */, 0 /* timestamp */);
+    EXPECT_FALSE(metricsManager.checkLogCredentials(event));
+
+    CreateNoValuesLogEvent(&event, 3 /* atom id */, 0 /* timestamp */);
+    EXPECT_TRUE(metricsManager.checkLogCredentials(event));
+
+    CreateNoValuesLogEvent(&event, 4 /* atom id */, 0 /* timestamp */);
+    EXPECT_TRUE(metricsManager.checkLogCredentials(event));
+}
+
+TEST(MetricsManagerTest, TestWhitelistedAtomStateTracker) {
+    sp<UidMap> uidMap;
+    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+    sp<AlarmMonitor> anomalyAlarmMonitor;
+    sp<AlarmMonitor> periodicAlarmMonitor;
+
+    StatsdConfig config = buildGoodConfig();
+    config.add_allowed_log_source("AID_SYSTEM");
+    config.add_whitelisted_atom_ids(3);
+    config.add_whitelisted_atom_ids(4);
+
+    State state;
+    state.set_id(1);
+    state.set_atom_id(3);
+
+    *config.add_state() = state;
+
+    config.mutable_count_metric(0)->add_slice_by_state(state.id());
+
+    StateManager::getInstance().clear();
+
+    MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap,
+                                  pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor);
+
+    EXPECT_EQ(0, StateManager::getInstance().getStateTrackersCount());
+    EXPECT_FALSE(metricsManager.isConfigValid());
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index e6144c5..076f327 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -187,7 +187,7 @@
     EXPECT_TRUE(output.reports_size() > 0);
     auto uidmap = output.reports(0).uid_map();
     EXPECT_TRUE(uidmap.snapshots_size() > 0);
-    EXPECT_EQ(2, uidmap.snapshots(0).package_info_size());
+    ASSERT_EQ(2, uidmap.snapshots(0).package_info_size());
 }
 
 TEST(StatsLogProcessorTest, TestEmptyConfigHasNoUidMap) {
@@ -248,7 +248,7 @@
     output.ParseFromArray(bytes.data(), bytes.size());
     EXPECT_TRUE(output.reports_size() > 0);
     auto report = output.reports(0);
-    EXPECT_EQ(1, report.annotation_size());
+    ASSERT_EQ(1, report.annotation_size());
     EXPECT_EQ(1, report.annotation(0).field_int64());
     EXPECT_EQ(2, report.annotation(0).field_int32());
 }
@@ -281,16 +281,16 @@
     processor->onDumpReport(cfgKey, 3, true, false /* Do NOT erase data. */, ADB_DUMP, FAST,
                             &bytes);
     output.ParseFromArray(bytes.data(), bytes.size());
-    EXPECT_EQ(output.reports_size(), 1);
-    EXPECT_EQ(output.reports(0).metrics_size(), 1);
-    EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
+    ASSERT_EQ(output.reports_size(), 1);
+    ASSERT_EQ(output.reports(0).metrics_size(), 1);
+    ASSERT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
 
     // Dump report WITH erasing data. There should be data since we didn't previously erase it.
     processor->onDumpReport(cfgKey, 4, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
     output.ParseFromArray(bytes.data(), bytes.size());
-    EXPECT_EQ(output.reports_size(), 1);
-    EXPECT_EQ(output.reports(0).metrics_size(), 1);
-    EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
+    ASSERT_EQ(output.reports_size(), 1);
+    ASSERT_EQ(output.reports(0).metrics_size(), 1);
+    ASSERT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
 
     // Dump report again. There should be no data since we erased it.
     processor->onDumpReport(cfgKey, 5, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
@@ -438,7 +438,7 @@
     processor.OnConfigUpdated(2, cfgKey2, config2);
     processor.OnConfigUpdated(3, cfgKey3, config3);
 
-    EXPECT_EQ(3, processor.mMetricsManagers.size());
+    ASSERT_EQ(3, processor.mMetricsManagers.size());
 
     // Expect the first config and both metrics in it to be active.
     auto it = processor.mMetricsManagers.find(cfgKey1);
@@ -535,7 +535,7 @@
 
     // A broadcast should have happened, and all 3 configs should be active in the broadcast.
     EXPECT_EQ(broadcastCount, 1);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 3);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 3);
     EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId1) !=
                 activeConfigsBroadcast.end());
     EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId2) !=
@@ -560,7 +560,7 @@
     processor2->OnConfigUpdated(timeBase2, cfgKey2, config2);
     processor2->OnConfigUpdated(timeBase2, cfgKey3, config3);
 
-    EXPECT_EQ(3, processor2->mMetricsManagers.size());
+    ASSERT_EQ(3, processor2->mMetricsManagers.size());
 
     // First config and both metrics are active.
     it = processor2->mMetricsManagers.find(cfgKey1);
@@ -619,7 +619,7 @@
     EXPECT_TRUE(it != processor2->mMetricsManagers.end());
     auto& metricsManager1003 = it->second;
     EXPECT_FALSE(metricsManager1003->isActive());
-    EXPECT_EQ(2, metricsManager1003->mAllMetricProducers.size());
+    ASSERT_EQ(2, metricsManager1003->mAllMetricProducers.size());
 
     metricIt = metricsManager1003->mAllMetricProducers.begin();
     for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
@@ -702,7 +702,7 @@
     sp<StatsLogProcessor> processor =
             CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
 
-    EXPECT_EQ(1, processor->mMetricsManagers.size());
+    ASSERT_EQ(1, processor->mMetricsManagers.size());
     auto it = processor->mMetricsManagers.find(cfgKey1);
     EXPECT_TRUE(it != processor->mMetricsManagers.end());
     auto& metricsManager1 = it->second;
@@ -752,7 +752,7 @@
     sp<StatsLogProcessor> processor2 =
             CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
 
-    EXPECT_EQ(1, processor2->mMetricsManagers.size());
+    ASSERT_EQ(1, processor2->mMetricsManagers.size());
     it = processor2->mMetricsManagers.find(cfgKey1);
     EXPECT_TRUE(it != processor2->mMetricsManagers.end());
     auto& metricsManager1001 = it->second;
@@ -835,7 +835,7 @@
     // Metric 1 is not active.
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor->mMetricsManagers.size());
+    ASSERT_EQ(1, processor->mMetricsManagers.size());
     auto it = processor->mMetricsManagers.find(cfgKey1);
     EXPECT_TRUE(it != processor->mMetricsManagers.end());
     auto& metricsManager1 = it->second;
@@ -920,7 +920,7 @@
     // Metric 1 is not active.
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor2->mMetricsManagers.size());
+    ASSERT_EQ(1, processor2->mMetricsManagers.size());
     it = processor2->mMetricsManagers.find(cfgKey1);
     EXPECT_TRUE(it != processor2->mMetricsManagers.end());
     auto& metricsManager1001 = it->second;
@@ -1021,7 +1021,7 @@
     // Metric 1 is not active.
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor3->mMetricsManagers.size());
+    ASSERT_EQ(1, processor3->mMetricsManagers.size());
     it = processor3->mMetricsManagers.find(cfgKey1);
     EXPECT_TRUE(it != processor3->mMetricsManagers.end());
     auto& metricsManagerTimeBase3 = it->second;
@@ -1123,7 +1123,7 @@
     // Metric 1 is not active.
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor4->mMetricsManagers.size());
+    ASSERT_EQ(1, processor4->mMetricsManagers.size());
     it = processor4->mMetricsManagers.find(cfgKey1);
     EXPECT_TRUE(it != processor4->mMetricsManagers.end());
     auto& metricsManagerTimeBase4 = it->second;
@@ -1237,13 +1237,13 @@
     // Metric 1 is not active.
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor1->mMetricsManagers.size());
+    ASSERT_EQ(1, processor1->mMetricsManagers.size());
     auto it = processor1->mMetricsManagers.find(cfgKey1);
     EXPECT_TRUE(it != processor1->mMetricsManagers.end());
     auto& metricsManager1 = it->second;
     EXPECT_TRUE(metricsManager1->isActive());
 
-    EXPECT_EQ(metricsManager1->mAllMetricProducers.size(), 2);
+    ASSERT_EQ(metricsManager1->mAllMetricProducers.size(), 2);
     // We assume that the index of a MetricProducer within the mAllMetricProducers
     // array follows the order in which metrics are added to the config.
     auto& metricProducer1_1 = metricsManager1->mAllMetricProducers[0];
@@ -1254,7 +1254,7 @@
     EXPECT_EQ(metricProducer1_2->getMetricId(), metricId2);
     EXPECT_TRUE(metricProducer1_2->isActive());
 
-    EXPECT_EQ(metricProducer1_1->mEventActivationMap.size(), 2);
+    ASSERT_EQ(metricProducer1_1->mEventActivationMap.size(), 2);
     // The key in mEventActivationMap is the index of the associated atom matcher. We assume
     // that matchers are indexed in the order that they are added to the config.
     const auto& activation1_1_1 = metricProducer1_1->mEventActivationMap.at(0);
@@ -1303,13 +1303,13 @@
     // Metric 1 is not active.
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor2->mMetricsManagers.size());
+    ASSERT_EQ(1, processor2->mMetricsManagers.size());
     it = processor2->mMetricsManagers.find(cfgKey1);
     EXPECT_TRUE(it != processor2->mMetricsManagers.end());
     auto& metricsManager2 = it->second;
     EXPECT_TRUE(metricsManager2->isActive());
 
-    EXPECT_EQ(metricsManager2->mAllMetricProducers.size(), 2);
+    ASSERT_EQ(metricsManager2->mAllMetricProducers.size(), 2);
     // We assume that the index of a MetricProducer within the mAllMetricProducers
     // array follows the order in which metrics are added to the config.
     auto& metricProducer2_1 = metricsManager2->mAllMetricProducers[0];
@@ -1320,7 +1320,7 @@
     EXPECT_EQ(metricProducer2_2->getMetricId(), metricId2);
     EXPECT_TRUE(metricProducer2_2->isActive());
 
-    EXPECT_EQ(metricProducer2_1->mEventActivationMap.size(), 2);
+    ASSERT_EQ(metricProducer2_1->mEventActivationMap.size(), 2);
     // The key in mEventActivationMap is the index of the associated atom matcher. We assume
     // that matchers are indexed in the order that they are added to the config.
     const auto& activation2_1_1 = metricProducer2_1->mEventActivationMap.at(0);
@@ -1387,13 +1387,13 @@
     // Metric 1 is not active.
     // Metric 2 is active.
     // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor3->mMetricsManagers.size());
+    ASSERT_EQ(1, processor3->mMetricsManagers.size());
     it = processor3->mMetricsManagers.find(cfgKey1);
     EXPECT_TRUE(it != processor3->mMetricsManagers.end());
     auto& metricsManager3 = it->second;
     EXPECT_TRUE(metricsManager3->isActive());
 
-    EXPECT_EQ(metricsManager3->mAllMetricProducers.size(), 2);
+    ASSERT_EQ(metricsManager3->mAllMetricProducers.size(), 2);
     // We assume that the index of a MetricProducer within the mAllMetricProducers
     // array follows the order in which metrics are added to the config.
     auto& metricProducer3_1 = metricsManager3->mAllMetricProducers[0];
@@ -1404,7 +1404,7 @@
     EXPECT_EQ(metricProducer3_2->getMetricId(), metricId2);
     EXPECT_TRUE(metricProducer3_2->isActive());
 
-    EXPECT_EQ(metricProducer3_1->mEventActivationMap.size(), 2);
+    ASSERT_EQ(metricProducer3_1->mEventActivationMap.size(), 2);
     // The key in mEventActivationMap is the index of the associated atom matcher. We assume
     // that matchers are indexed in the order that they are added to the config.
     const auto& activation3_1_1 = metricProducer3_1->mEventActivationMap.at(0);
@@ -1531,12 +1531,12 @@
     // Metric 3 is active.
     // {{{---------------------------------------------------------------------------
     sp<StatsLogProcessor> processor = service->mProcessor;
-    EXPECT_EQ(1, processor->mMetricsManagers.size());
+    ASSERT_EQ(1, processor->mMetricsManagers.size());
     auto it = processor->mMetricsManagers.find(cfgKey1);
     EXPECT_TRUE(it != processor->mMetricsManagers.end());
     auto& metricsManager1 = it->second;
     EXPECT_TRUE(metricsManager1->isActive());
-    EXPECT_EQ(3, metricsManager1->mAllMetricProducers.size());
+    ASSERT_EQ(3, metricsManager1->mAllMetricProducers.size());
 
     auto& metricProducer1 = metricsManager1->mAllMetricProducers[0];
     EXPECT_EQ(metricId1, metricProducer1->getMetricId());
@@ -1551,7 +1551,7 @@
     EXPECT_TRUE(metricProducer3->isActive());
 
     // Check event activations.
-    EXPECT_EQ(metricsManager1->mAllAtomMatchers.size(), 4);
+    ASSERT_EQ(metricsManager1->mAllAtomMatchers.size(), 4);
     EXPECT_EQ(metricsManager1->mAllAtomMatchers[0]->getId(),
               metric1ActivationTrigger1->atom_matcher_id());
     const auto& activation1 = metricProducer1->mEventActivationMap.at(0);
@@ -1628,12 +1628,12 @@
 
     // We should have a new metrics manager. Lets get it and ensure activation status is restored.
     // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor->mMetricsManagers.size());
+    ASSERT_EQ(1, processor->mMetricsManagers.size());
     it = processor->mMetricsManagers.find(cfgKey1);
     EXPECT_TRUE(it != processor->mMetricsManagers.end());
     auto& metricsManager2 = it->second;
     EXPECT_TRUE(metricsManager2->isActive());
-    EXPECT_EQ(3, metricsManager2->mAllMetricProducers.size());
+    ASSERT_EQ(3, metricsManager2->mAllMetricProducers.size());
 
     auto& metricProducer1001 = metricsManager2->mAllMetricProducers[0];
     EXPECT_EQ(metricId1, metricProducer1001->getMetricId());
@@ -1651,7 +1651,7 @@
     // Activation 1 is kActiveOnBoot.
     // Activation 2 and 3 are not active.
     // Activation 4 is active.
-    EXPECT_EQ(metricsManager2->mAllAtomMatchers.size(), 4);
+    ASSERT_EQ(metricsManager2->mAllAtomMatchers.size(), 4);
     EXPECT_EQ(metricsManager2->mAllAtomMatchers[0]->getId(),
               metric1ActivationTrigger1->atom_matcher_id());
     const auto& activation1001 = metricProducer1001->mEventActivationMap.at(0);
@@ -1709,7 +1709,7 @@
     processor->OnLogEvent(logEvent.get());
 
     const vector<FieldValue>* actualFieldValues = &logEvent->getValues();
-    EXPECT_EQ(3, actualFieldValues->size());
+    ASSERT_EQ(3, actualFieldValues->size());
     EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value);
     EXPECT_EQ(field1, actualFieldValues->at(1).mValue.int_value);
     EXPECT_EQ(field2, actualFieldValues->at(2).mValue.int_value);
@@ -1734,7 +1734,7 @@
     processor->OnLogEvent(logEvent.get());
 
     const vector<FieldValue>* actualFieldValues = &logEvent->getValues();
-    EXPECT_EQ(3, actualFieldValues->size());
+    ASSERT_EQ(3, actualFieldValues->size());
     EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value);
     EXPECT_EQ(field1, actualFieldValues->at(1).mValue.int_value);
     EXPECT_EQ(field2, actualFieldValues->at(2).mValue.int_value);
@@ -1759,7 +1759,7 @@
     processor->OnLogEvent(logEvent.get());
 
     const vector<FieldValue>* actualFieldValues = &logEvent->getValues();
-    EXPECT_EQ(6, actualFieldValues->size());
+    ASSERT_EQ(6, actualFieldValues->size());
     EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value);
     EXPECT_EQ("tag1", actualFieldValues->at(1).mValue.str_value);
     EXPECT_EQ(200, actualFieldValues->at(2).mValue.int_value);
@@ -1787,7 +1787,7 @@
     processor->OnLogEvent(logEvent.get());
 
     const vector<FieldValue>* actualFieldValues = &logEvent->getValues();
-    EXPECT_EQ(6, actualFieldValues->size());
+    ASSERT_EQ(6, actualFieldValues->size());
     EXPECT_EQ(hostUid, actualFieldValues->at(0).mValue.int_value);
     EXPECT_EQ("tag1", actualFieldValues->at(1).mValue.str_value);
     EXPECT_EQ(200, actualFieldValues->at(2).mValue.int_value);
diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp
index 29005a2..293e8ed 100644
--- a/cmds/statsd/tests/UidMap_test.cpp
+++ b/cmds/statsd/tests/UidMap_test.cpp
@@ -86,7 +86,7 @@
     EXPECT_FALSE(m.hasApp(1000, "not.app"));
 
     std::set<string> name_set = m.getAppNamesFromUid(1000u, true /* returnNormalized */);
-    EXPECT_EQ(name_set.size(), 2u);
+    ASSERT_EQ(name_set.size(), 2u);
     EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
 
@@ -115,7 +115,7 @@
     m.updateMap(1, uids, versions, versionStrings, apps, installers);
 
     std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
-    EXPECT_EQ(name_set.size(), 2u);
+    ASSERT_EQ(name_set.size(), 2u);
     EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
 
@@ -124,7 +124,7 @@
     EXPECT_EQ(40, m.getAppVersion(1000, kApp1));
 
     name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
-    EXPECT_EQ(name_set.size(), 2u);
+    ASSERT_EQ(name_set.size(), 2u);
     EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
 
@@ -132,7 +132,7 @@
     EXPECT_FALSE(m.hasApp(1000, kApp1));
     EXPECT_TRUE(m.hasApp(1000, kApp2));
     name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
-    EXPECT_EQ(name_set.size(), 1u);
+    ASSERT_EQ(name_set.size(), 1u);
     EXPECT_TRUE(name_set.find(kApp1) == name_set.end());
     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
 
@@ -149,14 +149,14 @@
     m.updateMap(1, {1000, 1000}, {4, 5}, {String16("v4"), String16("v5")},
                 {String16(kApp1.c_str()), String16(kApp2.c_str())}, {String16(""), String16("")});
     std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
-    EXPECT_EQ(name_set.size(), 2u);
+    ASSERT_EQ(name_set.size(), 2u);
     EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
 
     // Adds a new name for uid 1000.
     m.updateApp(2, String16("NeW_aPP1_NAmE"), 1000, 40, String16("v40"), String16(""));
     name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
-    EXPECT_EQ(name_set.size(), 3u);
+    ASSERT_EQ(name_set.size(), 3u);
     EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
     EXPECT_TRUE(name_set.find("NeW_aPP1_NAmE") == name_set.end());
@@ -165,7 +165,7 @@
     // This name is also reused by another uid 2000.
     m.updateApp(3, String16("NeW_aPP1_NAmE"), 2000, 1, String16("v1"), String16(""));
     name_set = m.getAppNamesFromUid(2000, true /* returnNormalized */);
-    EXPECT_EQ(name_set.size(), 1u);
+    ASSERT_EQ(name_set.size(), 1u);
     EXPECT_TRUE(name_set.find("NeW_aPP1_NAmE") == name_set.end());
     EXPECT_TRUE(name_set.find("new_app1_name") != name_set.end());
 }
@@ -212,7 +212,7 @@
     // Check there's still a uidmap attached this one.
     UidMapping results;
     protoOutputStreamToUidMapping(&proto, &results);
-    EXPECT_EQ(1, results.snapshots_size());
+    ASSERT_EQ(1, results.snapshots_size());
     EXPECT_EQ("v1", results.snapshots(0).package_info(0).version_string());
 }
 
@@ -240,7 +240,7 @@
     // Snapshot should still contain this item as deleted.
     UidMapping results;
     protoOutputStreamToUidMapping(&proto, &results);
-    EXPECT_EQ(1, results.snapshots(0).package_info_size());
+    ASSERT_EQ(1, results.snapshots(0).package_info_size());
     EXPECT_EQ(true, results.snapshots(0).package_info(0).deleted());
 }
 
@@ -269,7 +269,7 @@
     ProtoOutputStream proto;
     m.appendUidMap(3, config1, nullptr, true, true, &proto);
     protoOutputStreamToUidMapping(&proto, &results);
-    EXPECT_EQ(maxDeletedApps + 10, results.snapshots(0).package_info_size());
+    ASSERT_EQ(maxDeletedApps + 10, results.snapshots(0).package_info_size());
 
     // Now remove all the apps.
     m.updateMap(1, uids, versions, versionStrings, apps, installers);
@@ -281,7 +281,7 @@
     m.appendUidMap(5, config1, nullptr, true, true, &proto);
     // Snapshot drops the first nine items.
     protoOutputStreamToUidMapping(&proto, &results);
-    EXPECT_EQ(maxDeletedApps, results.snapshots(0).package_info_size());
+    ASSERT_EQ(maxDeletedApps, results.snapshots(0).package_info_size());
 }
 
 TEST(UidMapTest, TestClearingOutput) {
@@ -313,44 +313,44 @@
     m.appendUidMap(2, config1, nullptr, true, true, &proto);
     UidMapping results;
     protoOutputStreamToUidMapping(&proto, &results);
-    EXPECT_EQ(1, results.snapshots_size());
+    ASSERT_EQ(1, results.snapshots_size());
 
     // We have to keep at least one snapshot in memory at all times.
     proto.clear();
     m.appendUidMap(2, config1, nullptr, true, true, &proto);
     protoOutputStreamToUidMapping(&proto, &results);
-    EXPECT_EQ(1, results.snapshots_size());
+    ASSERT_EQ(1, results.snapshots_size());
 
     // Now add another configuration.
     m.OnConfigUpdated(config2);
     m.updateApp(5, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""));
-    EXPECT_EQ(1U, m.mChanges.size());
+    ASSERT_EQ(1U, m.mChanges.size());
     proto.clear();
     m.appendUidMap(6, config1, nullptr, true, true, &proto);
     protoOutputStreamToUidMapping(&proto, &results);
-    EXPECT_EQ(1, results.snapshots_size());
-    EXPECT_EQ(1, results.changes_size());
-    EXPECT_EQ(1U, m.mChanges.size());
+    ASSERT_EQ(1, results.snapshots_size());
+    ASSERT_EQ(1, results.changes_size());
+    ASSERT_EQ(1U, m.mChanges.size());
 
     // Add another delta update.
     m.updateApp(7, String16(kApp2.c_str()), 1001, 41, String16("v41"), String16(""));
-    EXPECT_EQ(2U, m.mChanges.size());
+    ASSERT_EQ(2U, m.mChanges.size());
 
     // We still can't remove anything.
     proto.clear();
     m.appendUidMap(8, config1, nullptr, true, true, &proto);
     protoOutputStreamToUidMapping(&proto, &results);
-    EXPECT_EQ(1, results.snapshots_size());
-    EXPECT_EQ(1, results.changes_size());
-    EXPECT_EQ(2U, m.mChanges.size());
+    ASSERT_EQ(1, results.snapshots_size());
+    ASSERT_EQ(1, results.changes_size());
+    ASSERT_EQ(2U, m.mChanges.size());
 
     proto.clear();
     m.appendUidMap(9, config2, nullptr, true, true, &proto);
     protoOutputStreamToUidMapping(&proto, &results);
-    EXPECT_EQ(1, results.snapshots_size());
-    EXPECT_EQ(2, results.changes_size());
+    ASSERT_EQ(1, results.snapshots_size());
+    ASSERT_EQ(2, results.changes_size());
     // At this point both should be cleared.
-    EXPECT_EQ(0U, m.mChanges.size());
+    ASSERT_EQ(0U, m.mChanges.size());
 }
 
 TEST(UidMapTest, TestMemoryComputed) {
@@ -408,13 +408,13 @@
 
     m.updateApp(3, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 2,
                 String16("v2"), String16(""));
-    EXPECT_EQ(1U, m.mChanges.size());
+    ASSERT_EQ(1U, m.mChanges.size());
 
     // Now force deletion by limiting the memory to hold one delta change.
     m.maxBytesOverride = 120; // Since the app string alone requires >45 characters.
     m.updateApp(5, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 4,
                 String16("v4"), String16(""));
-    EXPECT_EQ(1U, m.mChanges.size());
+    ASSERT_EQ(1U, m.mChanges.size());
 }
 
 #else
diff --git a/cmds/statsd/tests/anomaly/AlarmTracker_test.cpp b/cmds/statsd/tests/anomaly/AlarmTracker_test.cpp
index 90ffcd0..322cfaf 100644
--- a/cmds/statsd/tests/anomaly/AlarmTracker_test.cpp
+++ b/cmds/statsd/tests/anomaly/AlarmTracker_test.cpp
@@ -56,7 +56,7 @@
 
     currentTimeSec = startMillis / MS_PER_SEC + 7000;
     firedAlarmSet = subscriberAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
-    EXPECT_EQ(firedAlarmSet.size(), 1u);
+    ASSERT_EQ(firedAlarmSet.size(), 1u);
     tracker.informAlarmsFired(currentTimeSec * NS_PER_SEC, firedAlarmSet);
     EXPECT_TRUE(firedAlarmSet.empty());
     EXPECT_EQ(tracker.mAlarmSec, (int64_t)(startMillis / MS_PER_SEC + 15 + 2 * 60 * 60));
diff --git a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
index 6bde79f..0cc8af1 100644
--- a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
+++ b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
@@ -149,7 +149,7 @@
     std::shared_ptr<DimToValMap> bucket6 = MockBucket({{keyA, 2}});
 
     // Start time with no events.
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0u);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0u);
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, -1LL);
 
     // Event from bucket #0 occurs.
@@ -160,7 +160,7 @@
 
     // Adds past bucket #0
     anomalyTracker.addPastBucket(bucket0, 0);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3u);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3u);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
@@ -174,7 +174,7 @@
 
     // Adds past bucket #0 again. The sum does not change.
     anomalyTracker.addPastBucket(bucket0, 0);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3u);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3u);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
@@ -187,7 +187,7 @@
     // Adds past bucket #1.
     anomalyTracker.addPastBucket(bucket1, 1);
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 1L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
@@ -201,7 +201,7 @@
     // Adds past bucket #1 again. Nothing changes.
     anomalyTracker.addPastBucket(bucket1, 1);
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 1L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
@@ -214,7 +214,7 @@
     // Adds past bucket #2.
     anomalyTracker.addPastBucket(bucket2, 2);
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 2L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
 
@@ -227,7 +227,7 @@
     // Adds bucket #3.
     anomalyTracker.addPastBucket(bucket3, 3L);
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 3L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
 
@@ -240,7 +240,7 @@
     // Adds bucket #4.
     anomalyTracker.addPastBucket(bucket4, 4);
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 4L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 5LL);
 
@@ -253,7 +253,7 @@
     // Adds bucket #5.
     anomalyTracker.addPastBucket(bucket5, 5);
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 5L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 2LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 5LL);
 
@@ -294,7 +294,7 @@
     int64_t eventTimestamp6 = bucketSizeNs * 27 + 3;
 
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, -1LL);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
     EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 9, bucket9, {}, {keyA, keyB, keyC, keyD}));
     detectAndDeclareAnomalies(anomalyTracker, 9, bucket9, eventTimestamp1);
     checkRefractoryTimes(anomalyTracker, eventTimestamp1, refractoryPeriodSec,
@@ -303,15 +303,15 @@
     // Add past bucket #9
     anomalyTracker.addPastBucket(bucket9, 9);
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 9L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 3UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyA), 1LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 2LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
     EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 16, bucket16, {keyB}, {keyA, keyC, keyD}));
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 15L);
     detectAndDeclareAnomalies(anomalyTracker, 16, bucket16, eventTimestamp2);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 15L);
     checkRefractoryTimes(anomalyTracker, eventTimestamp2, refractoryPeriodSec,
             {{keyA, -1}, {keyB, eventTimestamp2}, {keyC, -1}, {keyD, -1}, {keyE, -1}});
@@ -319,27 +319,27 @@
     // Add past bucket #16
     anomalyTracker.addPastBucket(bucket16, 16);
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 16L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL);
     EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 18, bucket18, {keyB}, {keyA, keyC, keyD}));
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL);
     // Within refractory period.
     detectAndDeclareAnomalies(anomalyTracker, 18, bucket18, eventTimestamp3);
     checkRefractoryTimes(anomalyTracker, eventTimestamp3, refractoryPeriodSec,
             {{keyA, -1}, {keyB, eventTimestamp2}, {keyC, -1}, {keyD, -1}, {keyE, -1}});
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 4LL);
 
     // Add past bucket #18
     anomalyTracker.addPastBucket(bucket18, 18);
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 18L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
     EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 20, bucket20, {keyB}, {keyA, keyC, keyD}));
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 19L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
     detectAndDeclareAnomalies(anomalyTracker, 20, bucket20, eventTimestamp4);
@@ -349,11 +349,11 @@
     // Add bucket #18 again. Nothing changes.
     anomalyTracker.addPastBucket(bucket18, 18);
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 19L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
     EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 20, bucket20, {keyB}, {keyA, keyC, keyD}));
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 1LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
     detectAndDeclareAnomalies(anomalyTracker, 20, bucket20, eventTimestamp4 + 1);
@@ -364,12 +364,12 @@
     // Add past bucket #20
     anomalyTracker.addPastBucket(bucket20, 20);
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 20L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 2UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyB), 3LL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyC), 1LL);
     EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 25, bucket25, {}, {keyA, keyB, keyC, keyD}));
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 24L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
     detectAndDeclareAnomalies(anomalyTracker, 25, bucket25, eventTimestamp5);
     checkRefractoryTimes(anomalyTracker, eventTimestamp5, refractoryPeriodSec,
             {{keyA, -1}, {keyB, eventTimestamp4}, {keyC, -1}, {keyD, -1}, {keyE, -1}});
@@ -377,14 +377,14 @@
     // Add past bucket #25
     anomalyTracker.addPastBucket(bucket25, 25);
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 25L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 1UL);
     EXPECT_EQ(anomalyTracker.getSumOverPastBuckets(keyD), 1LL);
     EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 28, bucket28, {},
             {keyA, keyB, keyC, keyD, keyE}));
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 27L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
     detectAndDeclareAnomalies(anomalyTracker, 28, bucket28, eventTimestamp6);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
     checkRefractoryTimes(anomalyTracker, eventTimestamp6, refractoryPeriodSec,
             {{keyA, -1}, {keyB, -1}, {keyC, -1}, {keyD, -1}, {keyE, -1}});
 
@@ -393,9 +393,9 @@
     EXPECT_TRUE(detectAnomaliesPass(anomalyTracker, 28, bucket28, {keyE},
             {keyA, keyB, keyC, keyD}));
     EXPECT_EQ(anomalyTracker.mMostRecentBucketNum, 27L);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
     detectAndDeclareAnomalies(anomalyTracker, 28, bucket28, eventTimestamp6 + 7);
-    EXPECT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
+    ASSERT_EQ(anomalyTracker.mSumOverPastBuckets.size(), 0UL);
     checkRefractoryTimes(anomalyTracker, eventTimestamp6, refractoryPeriodSec,
             {{keyA, -1}, {keyB, -1}, {keyC, -1}, {keyD, -1}, {keyE, eventTimestamp6 + 7}});
 }
diff --git a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
index ba5b032..86e24fb 100644
--- a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
+++ b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
@@ -306,13 +306,13 @@
                                            changedCache);
 
         if (position == Position::FIRST || position == Position::LAST) {
-            EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+            ASSERT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
         } else {
-            EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
+            ASSERT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
         }
         EXPECT_TRUE(changedCache[0]);
         if (position == Position::FIRST || position == Position::LAST) {
-            EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), 1u);
+            ASSERT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), 1u);
             EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
         } else {
             EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(),
@@ -338,9 +338,9 @@
                                            changedCache);
         EXPECT_FALSE(changedCache[0]);
         if (position == Position::FIRST || position == Position::LAST) {
-            EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+            ASSERT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
         } else {
-            EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
+            ASSERT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
         }
         EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
         EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
@@ -359,9 +359,9 @@
         // nothing changes, because wake lock 2 is still held for this uid
         EXPECT_FALSE(changedCache[0]);
         if (position == Position::FIRST || position == Position::LAST) {
-            EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+            ASSERT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
         } else {
-            EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
+            ASSERT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
         }
         EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
         EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
@@ -375,10 +375,10 @@
         changedCache[0] = false;
         conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
                                            changedCache);
-        EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
+        ASSERT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
         EXPECT_TRUE(changedCache[0]);
         if (position == Position::FIRST || position == Position::LAST) {
-            EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), 1u);
+            ASSERT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), 1u);
             EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
         } else {
             EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(),
@@ -432,7 +432,7 @@
     conditionTracker.evaluateCondition(event1, matcherState, allPredicates, conditionCache,
                                        changedCache);
 
-    EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+    ASSERT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
     EXPECT_TRUE(changedCache[0]);
 
     // Now test query
@@ -480,7 +480,7 @@
     changedCache[0] = false;
     conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
                                        changedCache);
-    EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
+    ASSERT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
     EXPECT_TRUE(changedCache[0]);
 
     // query again
@@ -524,14 +524,14 @@
         conditionTracker.evaluateCondition(event1, matcherState, allPredicates, conditionCache,
                                            changedCache);
         if (position == Position::FIRST || position == Position::LAST) {
-            EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+            ASSERT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
         } else {
-            EXPECT_EQ(uids1.size(), conditionTracker.mSlicedConditionState.size());
+            ASSERT_EQ(uids1.size(), conditionTracker.mSlicedConditionState.size());
         }
         EXPECT_TRUE(changedCache[0]);
         {
             if (position == Position::FIRST || position == Position::LAST) {
-                EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
+                ASSERT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
                 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
             } else {
                 EXPECT_EQ(uids1.size(),
@@ -560,14 +560,14 @@
         conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
                                            changedCache);
         if (position == Position::FIRST || position == Position::LAST) {
-            EXPECT_EQ(2UL, conditionTracker.mSlicedConditionState.size());
+            ASSERT_EQ(2UL, conditionTracker.mSlicedConditionState.size());
         } else {
-            EXPECT_EQ(uids1.size() + uids2.size(), conditionTracker.mSlicedConditionState.size());
+            ASSERT_EQ(uids1.size() + uids2.size(), conditionTracker.mSlicedConditionState.size());
         }
         EXPECT_TRUE(changedCache[0]);
         {
             if (position == Position::FIRST || position == Position::LAST) {
-                EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
+                ASSERT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
                 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
             } else {
                 EXPECT_EQ(uids2.size(),
@@ -597,10 +597,10 @@
         conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
                                            changedCache);
         EXPECT_TRUE(changedCache[0]);
-        EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
+        ASSERT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
         {
             if (position == Position::FIRST || position == Position::LAST) {
-                EXPECT_EQ(2UL, conditionTracker.getChangedToFalseDimensions(allConditions)->size());
+                ASSERT_EQ(2UL, conditionTracker.getChangedToFalseDimensions(allConditions)->size());
                 EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
             } else {
                 EXPECT_EQ(uids1.size() + uids2.size(),
diff --git a/cmds/statsd/tests/e2e/Alarm_e2e_test.cpp b/cmds/statsd/tests/e2e/Alarm_e2e_test.cpp
index 9ea0b81..93b2783 100644
--- a/cmds/statsd/tests/e2e/Alarm_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Alarm_e2e_test.cpp
@@ -52,9 +52,9 @@
 
     ConfigKey cfgKey;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    EXPECT_EQ(2u, processor->mMetricsManagers.begin()->second->mAllPeriodicAlarmTrackers.size());
+    ASSERT_EQ(2u, processor->mMetricsManagers.begin()->second->mAllPeriodicAlarmTrackers.size());
 
     auto alarmTracker1 = processor->mMetricsManagers.begin()->second->mAllPeriodicAlarmTrackers[0];
     auto alarmTracker2 = processor->mMetricsManagers.begin()->second->mAllPeriodicAlarmTrackers[1];
@@ -68,7 +68,7 @@
     const int64_t alarmFiredTimestampSec0 = alarmTimestampSec1 + 5;
     auto alarmSet = processor->getPeriodicAlarmMonitor()->popSoonerThan(
             static_cast<uint32_t>(alarmFiredTimestampSec0));
-    EXPECT_EQ(1u, alarmSet.size());
+    ASSERT_EQ(1u, alarmSet.size());
     processor->onPeriodicAlarmFired(alarmFiredTimestampSec0 * NS_PER_SEC, alarmSet);
     EXPECT_EQ(alarmTimestampSec0, alarmTracker1->getAlarmTimestampSec());
     EXPECT_EQ(alarmTimestampSec1 + 30 * 60, alarmTracker2->getAlarmTimestampSec());
@@ -77,7 +77,7 @@
     const int64_t alarmFiredTimestampSec1 = alarmTimestampSec0 + 2 * 60 * 60 + 125;
     alarmSet = processor->getPeriodicAlarmMonitor()->popSoonerThan(
             static_cast<uint32_t>(alarmFiredTimestampSec1));
-    EXPECT_EQ(2u, alarmSet.size());
+    ASSERT_EQ(2u, alarmSet.size());
     processor->onPeriodicAlarmFired(alarmFiredTimestampSec1 * NS_PER_SEC, alarmSet);
     EXPECT_EQ(alarmTimestampSec0 + 60 * 60 * 3, alarmTracker1->getAlarmTimestampSec());
     EXPECT_EQ(alarmTimestampSec1 + 30 * 60 * 5, alarmTracker2->getAlarmTimestampSec());
diff --git a/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp b/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp
index c2d7043..af9436b 100644
--- a/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp
@@ -66,9 +66,9 @@
 
     ConfigKey cfgKey;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+    ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
 
     sp<AnomalyTracker> anomalyTracker =
             processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -183,9 +183,9 @@
 
     ConfigKey cfgKey;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+    ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
 
     sp<AnomalyTracker> anomalyTracker =
             processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -254,16 +254,16 @@
     int64_t configId = 1000;
     ConfigKey cfgKey(configUid, configId);
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+    ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
 
     metadata::StatsMetadataList result;
     int64_t mockWallClockNs = 1584991200 * NS_PER_SEC;
     int64_t mockElapsedTimeNs = bucketStartTimeNs + 5000 * NS_PER_SEC;
     processor->WriteMetadataToProto(mockWallClockNs, mockElapsedTimeNs, &result);
 
-    EXPECT_EQ(result.stats_metadata_size(), 0);
+    ASSERT_EQ(result.stats_metadata_size(), 0);
 }
 
 TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk) {
@@ -279,9 +279,9 @@
     int64_t configId = 1000;
     ConfigKey cfgKey(configUid, configId);
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+    ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
 
     sp<AnomalyTracker> anomalyTracker =
             processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -308,15 +308,15 @@
     processor->WriteMetadataToProto(mockWallClockNs, mockElapsedTimeNs, &result);
 
     metadata::StatsMetadata statsMetadata = result.stats_metadata(0);
-    EXPECT_EQ(result.stats_metadata_size(), 1);
+    ASSERT_EQ(result.stats_metadata_size(), 1);
     EXPECT_EQ(statsMetadata.config_key().config_id(), configId);
     EXPECT_EQ(statsMetadata.config_key().uid(), configUid);
 
     metadata::AlertMetadata alertMetadata = statsMetadata.alert_metadata(0);
-    EXPECT_EQ(statsMetadata.alert_metadata_size(), 1);
+    ASSERT_EQ(statsMetadata.alert_metadata_size(), 1);
     EXPECT_EQ(alertMetadata.alert_id(), alert_id);
     metadata::AlertDimensionKeyedData keyedData = alertMetadata.alert_dim_keyed_data(0);
-    EXPECT_EQ(alertMetadata.alert_dim_keyed_data_size(), 1);
+    ASSERT_EQ(alertMetadata.alert_dim_keyed_data_size(), 1);
     EXPECT_EQ(keyedData.last_refractory_ends_sec(),
               anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1) -
               mockElapsedTimeNs / NS_PER_SEC +
@@ -342,9 +342,9 @@
     int64_t configId = 1000;
     ConfigKey cfgKey(configUid, configId);
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+    ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
 
     sp<AnomalyTracker> anomalyTracker =
             processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
diff --git a/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp b/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
index 4f9f315..95e3010 100644
--- a/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
@@ -104,9 +104,9 @@
 
     ConfigKey cfgKey;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+    ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
 
     sp<AnomalyTracker> anomalyTracker =
             processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -162,7 +162,7 @@
     // Anomaly alarm fired.
     auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
             static_cast<uint32_t>(alarmFiredTimestampSec0));
-    EXPECT_EQ(1u, alarmSet.size());
+    ASSERT_EQ(1u, alarmSet.size());
     processor->onAnomalyAlarmFired(alarmFiredTimestampSec0 * NS_PER_SEC, alarmSet);
     EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
     EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
@@ -199,7 +199,7 @@
 
     alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
             static_cast<uint32_t>(alarmFiredTimestampSec1));
-    EXPECT_EQ(0u, alarmSet.size());
+    ASSERT_EQ(0u, alarmSet.size());
 
     // Acquire wakelock wl1 near the end of bucket #0.
     acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 2,
@@ -285,9 +285,9 @@
 
     ConfigKey cfgKey;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+    ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
 
     sp<AnomalyTracker> anomalyTracker =
             processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -406,9 +406,9 @@
 
     ConfigKey cfgKey;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+    ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
 
     sp<AnomalyTracker> anomalyTracker =
             processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -439,7 +439,7 @@
     const int64_t firedAlarmTimestampNs = bucketStartTimeNs + 2 * bucketSizeNs - NS_PER_SEC;
     auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
             static_cast<uint32_t>(firedAlarmTimestampNs / NS_PER_SEC));
-    EXPECT_EQ(1u, alarmSet.size());
+    ASSERT_EQ(1u, alarmSet.size());
     processor->onAnomalyAlarmFired(firedAlarmTimestampNs, alarmSet);
     EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
     EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
index 52229e2..4c2caa9 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -101,7 +101,7 @@
 
     ConfigKey cfgKey;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
 
     // Here it assumes that GMS core has two uids.
@@ -155,17 +155,17 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+    ASSERT_EQ(reports.reports_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics_size(), 1);
 
     StatsLogReport::CountMetricDataWrapper countMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(countMetrics.data_size(), 4);
+    ASSERT_EQ(countMetrics.data_size(), 4);
 
     auto data = countMetrics.data(0);
     ValidateAttributionUidAndTagDimension(data.dimensions_in_what(),
                                           util::WAKELOCK_STATE_CHANGED, 111, "App1");
-    EXPECT_EQ(data.bucket_info_size(), 2);
+    ASSERT_EQ(data.bucket_info_size(), 2);
     EXPECT_EQ(data.bucket_info(0).count(), 2);
     EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
     EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
@@ -178,7 +178,7 @@
     ValidateAttributionUidAndTagDimension(data.dimensions_in_what(),
                                           util::WAKELOCK_STATE_CHANGED, 222,
                                           "GMSCoreModule1");
-    EXPECT_EQ(data.bucket_info_size(), 2);
+    ASSERT_EQ(data.bucket_info_size(), 2);
     EXPECT_EQ(data.bucket_info(0).count(), 1);
     EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
     EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
@@ -190,7 +190,7 @@
     ValidateAttributionUidAndTagDimension(data.dimensions_in_what(),
                                           util::WAKELOCK_STATE_CHANGED, 222,
                                           "GMSCoreModule3");
-    EXPECT_EQ(data.bucket_info_size(), 1);
+    ASSERT_EQ(data.bucket_info_size(), 1);
     EXPECT_EQ(data.bucket_info(0).count(), 1);
     EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
               bucketStartTimeNs + 3 * bucketSizeNs);
@@ -200,7 +200,7 @@
     ValidateAttributionUidAndTagDimension(data.dimensions_in_what(),
                                           util::WAKELOCK_STATE_CHANGED, 444,
                                           "GMSCoreModule2");
-    EXPECT_EQ(data.bucket_info_size(), 1);
+    ASSERT_EQ(data.bucket_info_size(), 1);
     EXPECT_EQ(data.bucket_info(0).count(), 1);
     EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(),
               bucketStartTimeNs + 2 * bucketSizeNs);
@@ -214,7 +214,7 @@
 
     ConfigKey cfgKey;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
 
     // Here it assumes that GMS core has two uids.
@@ -268,18 +268,18 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+    ASSERT_EQ(reports.reports_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics_size(), 1);
 
     StatsLogReport::CountMetricDataWrapper countMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(countMetrics.data_size(), 6);
+    ASSERT_EQ(countMetrics.data_size(), 6);
 
     auto data = countMetrics.data(0);
     ValidateAttributionUidAndTagDimension(data.dimensions_in_what(),
                                           util::WAKELOCK_STATE_CHANGED, 222,
                                           "GMSCoreModule1");
-    EXPECT_EQ(2, data.bucket_info_size());
+    ASSERT_EQ(2, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -296,7 +296,7 @@
     ValidateUidDimension(data.dimensions_in_what(), 1, util::WAKELOCK_STATE_CHANGED, 333);
     ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 1,
                                           util::WAKELOCK_STATE_CHANGED, 333, "App3");
-    EXPECT_EQ(data.bucket_info_size(), 1);
+    ASSERT_EQ(data.bucket_info_size(), 1);
     EXPECT_EQ(data.bucket_info(0).count(), 1);
     EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
     EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
@@ -310,7 +310,7 @@
     ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 1,
                                           util::WAKELOCK_STATE_CHANGED, 222,
                                           "GMSCoreModule1");
-    EXPECT_EQ(data.bucket_info_size(), 1);
+    ASSERT_EQ(data.bucket_info_size(), 1);
     EXPECT_EQ(data.bucket_info(0).count(), 1);
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
               data.bucket_info(0).start_bucket_elapsed_nanos());
@@ -327,7 +327,7 @@
     ValidateUidDimension(data.dimensions_in_what(), 2, util::WAKELOCK_STATE_CHANGED, 333);
     ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 2,
                                           util::WAKELOCK_STATE_CHANGED, 333, "App3");
-    EXPECT_EQ(data.bucket_info_size(), 1);
+    ASSERT_EQ(data.bucket_info_size(), 1);
     EXPECT_EQ(data.bucket_info(0).count(), 1);
     EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -343,7 +343,7 @@
     ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 2,
                                           util::WAKELOCK_STATE_CHANGED, 222,
                                           "GMSCoreModule1");
-    EXPECT_EQ(data.bucket_info_size(), 1);
+    ASSERT_EQ(data.bucket_info_size(), 1);
     EXPECT_EQ(data.bucket_info(0).count(), 1);
     EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -359,7 +359,7 @@
     ValidateUidDimension(data.dimensions_in_what(), 2, util::WAKELOCK_STATE_CHANGED, 333);
     ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 2,
                                           util::WAKELOCK_STATE_CHANGED, 333, "App3");
-    EXPECT_EQ(data.bucket_info_size(), 1);
+    ASSERT_EQ(data.bucket_info_size(), 1);
     EXPECT_EQ(data.bucket_info(0).count(), 1);
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
               data.bucket_info(0).start_bucket_elapsed_nanos());
diff --git a/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp b/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp
index 16adbdd..0bce0ba 100644
--- a/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp
@@ -68,7 +68,7 @@
 
     ConfigKey cfgKey;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
 
     std::vector<int> attributionUids1 = {111};
diff --git a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
index b1461a1..04eb400 100644
--- a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
@@ -28,6 +28,92 @@
 #ifdef __ANDROID__
 
 /**
+ * Tests the initial condition and condition after the first log events for
+ * count metrics with either a combination condition or simple condition.
+ *
+ * Metrics should be initialized with condition kUnknown (given that the
+ * predicate is using the default InitialValue of UNKNOWN). The condition should
+ * be updated to either kFalse or kTrue if a condition event is logged for all
+ * children conditions.
+ */
+TEST(CountMetricE2eTest, TestInitialConditionChanges) {
+    // Initialize config.
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT");     // LogEvent defaults to UID of root.
+    config.add_default_pull_packages("AID_ROOT");  // Fake puller is registered with root.
+
+    auto syncStartMatcher = CreateSyncStartAtomMatcher();
+    *config.add_atom_matcher() = syncStartMatcher;
+    *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+    *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
+    *config.add_atom_matcher() = CreateBatteryStateNoneMatcher();
+    *config.add_atom_matcher() = CreateBatteryStateUsbMatcher();
+
+    auto screenOnPredicate = CreateScreenIsOnPredicate();
+    *config.add_predicate() = screenOnPredicate;
+
+    auto deviceUnpluggedPredicate = CreateDeviceUnpluggedPredicate();
+    *config.add_predicate() = deviceUnpluggedPredicate;
+
+    auto screenOnOnBatteryPredicate = config.add_predicate();
+    screenOnOnBatteryPredicate->set_id(StringToId("screenOnOnBatteryPredicate"));
+    screenOnOnBatteryPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
+    addPredicateToPredicateCombination(screenOnPredicate, screenOnOnBatteryPredicate);
+    addPredicateToPredicateCombination(deviceUnpluggedPredicate, screenOnOnBatteryPredicate);
+
+    // CountSyncStartWhileScreenOnOnBattery (CombinationCondition)
+    CountMetric* countMetric1 = config.add_count_metric();
+    countMetric1->set_id(StringToId("CountSyncStartWhileScreenOnOnBattery"));
+    countMetric1->set_what(syncStartMatcher.id());
+    countMetric1->set_condition(screenOnOnBatteryPredicate->id());
+    countMetric1->set_bucket(FIVE_MINUTES);
+
+    // CountSyncStartWhileOnBattery (SimpleCondition)
+    CountMetric* countMetric2 = config.add_count_metric();
+    countMetric2->set_id(StringToId("CountSyncStartWhileOnBatterySliceScreen"));
+    countMetric2->set_what(syncStartMatcher.id());
+    countMetric2->set_condition(deviceUnpluggedPredicate.id());
+    countMetric2->set_bucket(FIVE_MINUTES);
+
+    const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
+    const uint64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+    int uid = 12345;
+    int64_t cfgId = 98765;
+    ConfigKey cfgKey(uid, cfgId);
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+    EXPECT_TRUE(metricsManager->isConfigValid());
+    EXPECT_EQ(2, metricsManager->mAllMetricProducers.size());
+
+    sp<MetricProducer> metricProducer1 = metricsManager->mAllMetricProducers[0];
+    sp<MetricProducer> metricProducer2 = metricsManager->mAllMetricProducers[1];
+
+    EXPECT_EQ(ConditionState::kUnknown, metricProducer1->mCondition);
+    EXPECT_EQ(ConditionState::kUnknown, metricProducer2->mCondition);
+
+    auto screenOnEvent =
+            CreateScreenStateChangedEvent(bucketStartTimeNs + 30, android::view::DISPLAY_STATE_ON);
+    processor->OnLogEvent(screenOnEvent.get());
+    EXPECT_EQ(ConditionState::kUnknown, metricProducer1->mCondition);
+    EXPECT_EQ(ConditionState::kUnknown, metricProducer2->mCondition);
+
+    auto pluggedUsbEvent = CreateBatteryStateChangedEvent(
+            bucketStartTimeNs + 50, BatteryPluggedStateEnum::BATTERY_PLUGGED_USB);
+    processor->OnLogEvent(pluggedUsbEvent.get());
+    EXPECT_EQ(ConditionState::kFalse, metricProducer1->mCondition);
+    EXPECT_EQ(ConditionState::kFalse, metricProducer2->mCondition);
+
+    auto pluggedNoneEvent = CreateBatteryStateChangedEvent(
+            bucketStartTimeNs + 70, BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE);
+    processor->OnLogEvent(pluggedNoneEvent.get());
+    EXPECT_EQ(ConditionState::kTrue, metricProducer1->mCondition);
+    EXPECT_EQ(ConditionState::kTrue, metricProducer2->mCondition);
+}
+
+/**
 * Test a count metric that has one slice_by_state with no primary fields.
 *
 * Once the CountMetricProducer is initialized, it has one atom id in
@@ -65,14 +151,14 @@
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
 
     // Check that CountMetricProducer was initialized correctly.
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+    ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
-    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
+    ASSERT_EQ(metricProducer->mStateGroupMap.size(), 0);
 
     // Check that StateTrackers were initialized correctly.
     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
@@ -85,7 +171,7 @@
             x                x         x    x        x      x       (syncStartEvents)
           |                                       |                 (ScreenIsOnEvent)
                    |     |                                          (ScreenIsOffEvent)
-                                                        |           (ScreenUnknownEvent)
+                                                        |           (ScreenDozeEvent)
     */
     // Initialize log events - first bucket.
     std::vector<int> attributionUids1 = {123};
@@ -132,23 +218,23 @@
     ConfigMetricsReportList reports;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
                             FAST, &buffer);
-    EXPECT_GT(buffer.size(), 0);
+    ASSERT_GT(buffer.size(), 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
 
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
     StatsLogReport::CountMetricDataWrapper countMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(3, countMetrics.data_size());
+    ASSERT_EQ(3, countMetrics.data_size());
 
     // For each CountMetricData, check StateValue info is correct and buckets
     // have correct counts.
     auto data = countMetrics.data(0);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN,
@@ -157,7 +243,7 @@
     EXPECT_EQ(1, data.bucket_info(0).count());
 
     data = countMetrics.data(1);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
@@ -166,7 +252,7 @@
     EXPECT_EQ(2, data.bucket_info(1).count());
 
     data = countMetrics.data(2);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
@@ -220,14 +306,14 @@
     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
 
     // Check that CountMetricProducer was initialized correctly.
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+    ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
-    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 1);
+    ASSERT_EQ(metricProducer->mStateGroupMap.size(), 1);
 
     StateMap map = state.map();
     for (auto group : map.group()) {
@@ -243,9 +329,8 @@
     |-----------------------------|-----------------------------|--
       x   x     x       x    x   x      x         x         x       (syncStartEvents)
      -----------------------------------------------------------SCREEN_OFF events
-       |                                                            (ScreenStateUnknownEvent = 0)
              |                  |                                   (ScreenStateOffEvent = 1)
-                          |                                         (ScreenStateDozeEvent = 3)
+       |                  |                                         (ScreenStateDozeEvent = 3)
                                                 |                   (ScreenStateDozeSuspendEvent =
     4)
      -----------------------------------------------------------SCREEN_ON events
@@ -262,7 +347,7 @@
                                           attributionTags1, "sync_name"));  // 0:30
     events.push_back(CreateScreenStateChangedEvent(
             bucketStartTimeNs + 30 * NS_PER_SEC,
-            android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN));  // 0:40
+            android::view::DisplayStateEnum::DISPLAY_STATE_DOZE));  // 0:40
     events.push_back(CreateSyncStartEvent(bucketStartTimeNs + 60 * NS_PER_SEC, attributionUids1,
                                           attributionTags1, "sync_name"));  // 1:10
     events.push_back(CreateScreenStateChangedEvent(
@@ -316,44 +401,44 @@
     ConfigMetricsReportList reports;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
                             FAST, &buffer);
-    EXPECT_GT(buffer.size(), 0);
+    ASSERT_GT(buffer.size(), 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
 
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
     StatsLogReport::CountMetricDataWrapper countMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(3, countMetrics.data_size());
+    ASSERT_EQ(3, countMetrics.data_size());
 
     // For each CountMetricData, check StateValue info is correct and buckets
     // have correct counts.
     auto data = countMetrics.data(0);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
 
     data = countMetrics.data(1);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
     EXPECT_EQ(screenOnId, data.slice_by_state(0).group_id());
-    EXPECT_EQ(2, data.bucket_info_size());
+    ASSERT_EQ(2, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(1, data.bucket_info(1).count());
 
     data = countMetrics.data(2);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
     EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
-    EXPECT_EQ(2, data.bucket_info_size());
+    ASSERT_EQ(2, data.bucket_info_size());
     EXPECT_EQ(4, data.bucket_info(0).count());
     EXPECT_EQ(2, data.bucket_info(1).count());
 }
@@ -405,15 +490,15 @@
     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
 
     // Check that CountMetricProducer was initialized correctly.
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+    ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), UID_PROCESS_STATE_ATOM_ID);
-    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
-    EXPECT_EQ(metricProducer->mMetric2StateLinks.size(), 1);
+    ASSERT_EQ(metricProducer->mStateGroupMap.size(), 0);
+    ASSERT_EQ(metricProducer->mMetric2StateLinks.size(), 1);
 
     /*
     NOTE: "1" or "2" represents the uid associated with the state/app crash event
@@ -496,23 +581,23 @@
     ConfigMetricsReportList reports;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
                             FAST, &buffer);
-    EXPECT_GT(buffer.size(), 0);
+    ASSERT_GT(buffer.size(), 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
 
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
     StatsLogReport::CountMetricDataWrapper countMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(5, countMetrics.data_size());
+    ASSERT_EQ(5, countMetrics.data_size());
 
     // For each CountMetricData, check StateValue info is correct and buckets
     // have correct counts.
     auto data = countMetrics.data(0);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value());
@@ -520,7 +605,7 @@
     EXPECT_EQ(1, data.bucket_info(0).count());
 
     data = countMetrics.data(1);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(0).value());
@@ -528,7 +613,7 @@
     EXPECT_EQ(2, data.bucket_info(0).count());
 
     data = countMetrics.data(2);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::app::PROCESS_STATE_FOREGROUND_SERVICE, data.slice_by_state(0).value());
@@ -537,7 +622,7 @@
     EXPECT_EQ(2, data.bucket_info(1).count());
 
     data = countMetrics.data(3);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(0).value());
@@ -545,7 +630,7 @@
     EXPECT_EQ(2, data.bucket_info(0).count());
 
     data = countMetrics.data(4);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, data.slice_by_state(0).value());
@@ -600,16 +685,16 @@
     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
 
     // Check that CountMetricProducer was initialized correctly.
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 2);
+    ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 2);
     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(1), UID_PROCESS_STATE_ATOM_ID);
-    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 1);
-    EXPECT_EQ(metricProducer->mMetric2StateLinks.size(), 1);
+    ASSERT_EQ(metricProducer->mStateGroupMap.size(), 1);
+    ASSERT_EQ(metricProducer->mMetric2StateLinks.size(), 1);
 
     StateMap map = state1.map();
     for (auto group : map.group()) {
@@ -625,9 +710,8 @@
       |------------------------|------------------------|--
         1  1    1     1    1  2     1        1         2   (AppCrashEvents)
        ---------------------------------------------------SCREEN_OFF events
-         |                                                 (ScreenUnknownEvent = 0)
              |                              |              (ScreenOffEvent = 1)
-                        |                                  (ScreenDozeEvent = 3)
+         |              |                                  (ScreenDozeEvent = 3)
        ---------------------------------------------------SCREEN_ON events
                    |                              |        (ScreenOnEvent = 2)
                                         |                  (ScreenOnSuspendEvent = 6)
@@ -660,7 +744,7 @@
             CreateAppCrashOccurredEvent(bucketStartTimeNs + 20 * NS_PER_SEC, 1 /*uid*/));  // 0:30
     events.push_back(CreateScreenStateChangedEvent(
             bucketStartTimeNs + 30 * NS_PER_SEC,
-            android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN));  // 0:40
+            android::view::DisplayStateEnum::DISPLAY_STATE_DOZE));  // 0:40
     events.push_back(
             CreateAppCrashOccurredEvent(bucketStartTimeNs + 60 * NS_PER_SEC, 1 /*uid*/));  // 1:10
     events.push_back(CreateUidProcessStateChangedEvent(
@@ -726,23 +810,23 @@
     ConfigMetricsReportList reports;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
                             FAST, &buffer);
-    EXPECT_GT(buffer.size(), 0);
+    ASSERT_GT(buffer.size(), 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
 
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
     StatsLogReport::CountMetricDataWrapper countMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(6, countMetrics.data_size());
+    ASSERT_EQ(6, countMetrics.data_size());
 
     // For each CountMetricData, check StateValue info is correct and buckets
     // have correct counts.
     auto data = countMetrics.data(0);
-    EXPECT_EQ(2, data.slice_by_state_size());
+    ASSERT_EQ(2, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(-1, data.slice_by_state(0).value());
@@ -753,7 +837,7 @@
     EXPECT_EQ(1, data.bucket_info(0).count());
 
     data = countMetrics.data(1);
-    EXPECT_EQ(2, data.slice_by_state_size());
+    ASSERT_EQ(2, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
     EXPECT_EQ(screenOnId, data.slice_by_state(0).group_id());
@@ -764,7 +848,7 @@
     EXPECT_EQ(1, data.bucket_info(0).count());
 
     data = countMetrics.data(2);
-    EXPECT_EQ(2, data.slice_by_state_size());
+    ASSERT_EQ(2, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
     EXPECT_EQ(screenOnId, data.slice_by_state(0).group_id());
@@ -775,7 +859,7 @@
     EXPECT_EQ(1, data.bucket_info(0).count());
 
     data = countMetrics.data(3);
-    EXPECT_EQ(2, data.slice_by_state_size());
+    ASSERT_EQ(2, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
     EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
@@ -786,7 +870,7 @@
     EXPECT_EQ(2, data.bucket_info(0).count());
 
     data = countMetrics.data(4);
-    EXPECT_EQ(2, data.slice_by_state_size());
+    ASSERT_EQ(2, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
     EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
@@ -797,7 +881,7 @@
     EXPECT_EQ(1, data.bucket_info(0).count());
 
     data = countMetrics.data(5);
-    EXPECT_EQ(2, data.slice_by_state_size());
+    ASSERT_EQ(2, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
     EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
diff --git a/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
index d59ec3e..4efb038 100644
--- a/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
@@ -57,10 +57,10 @@
 
     auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
 
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
@@ -93,18 +93,18 @@
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
 
     StatsLogReport::DurationMetricDataWrapper durationMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
                                     &durationMetrics);
-    EXPECT_EQ(1, durationMetrics.data_size());
+    ASSERT_EQ(1, durationMetrics.data_size());
 
     DurationMetricData data = durationMetrics.data(0);
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(durationEndNs - durationStartNs, data.bucket_info(0).duration_nanos());
     EXPECT_EQ(configAddedTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -140,10 +140,10 @@
 
     auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
 
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
@@ -176,18 +176,18 @@
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
 
     StatsLogReport::DurationMetricDataWrapper durationMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
                                     &durationMetrics);
-    EXPECT_EQ(1, durationMetrics.data_size());
+    ASSERT_EQ(1, durationMetrics.data_size());
 
     DurationMetricData data = durationMetrics.data(0);
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
 
     auto bucketInfo = data.bucket_info(0);
     EXPECT_EQ(0, bucketInfo.bucket_num());
@@ -253,16 +253,16 @@
 
     processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);  // 0:00
 
-    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor.mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
     auto& eventActivationMap = metricProducer->mEventActivationMap;
 
     EXPECT_FALSE(metricsManager->isActive());
     EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap.size(), 1u);
+    ASSERT_EQ(eventActivationMap.size(), 1u);
     EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
@@ -289,7 +289,7 @@
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 1);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
     EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
@@ -302,8 +302,8 @@
     EXPECT_FALSE(metricsManager->isActive());
     EXPECT_FALSE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 2);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_EQ(eventActivationMap.size(), 1u);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 0);
+    ASSERT_EQ(eventActivationMap.size(), 1u);
     EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
@@ -333,7 +333,7 @@
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
     EXPECT_EQ(eventActivationMap[2]->start_ns, activation2StartNs);
@@ -347,18 +347,18 @@
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
 
     StatsLogReport::DurationMetricDataWrapper durationMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
                                     &durationMetrics);
-    EXPECT_EQ(1, durationMetrics.data_size());
+    ASSERT_EQ(1, durationMetrics.data_size());
 
     DurationMetricData data = durationMetrics.data(0);
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
 
     auto bucketInfo = data.bucket_info(0);
     EXPECT_EQ(0, bucketInfo.bucket_num());
@@ -393,10 +393,10 @@
     uint64_t bucketSizeNs =
             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
     auto& eventActivationMap = metricProducer->mEventActivationMap;
     EXPECT_TRUE(metricsManager->isActive());
@@ -428,23 +428,23 @@
     ConfigMetricsReportList reports;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
                             FAST, &buffer);
-    EXPECT_GT(buffer.size(), 0);
+    ASSERT_GT(buffer.size(), 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
 
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     StatsLogReport::DurationMetricDataWrapper durationMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
                                     &durationMetrics);
-    EXPECT_EQ(1, durationMetrics.data_size());
+    ASSERT_EQ(1, durationMetrics.data_size());
 
     DurationMetricData data = durationMetrics.data(0);
 
     // Validate bucket info.
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
 
     auto bucketInfo = data.bucket_info(0);
     EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
@@ -497,10 +497,10 @@
     uint64_t bucketSizeNs =
             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
     auto& eventActivationMap = metricProducer->mEventActivationMap;
     EXPECT_TRUE(metricsManager->isActive());
@@ -530,25 +530,25 @@
     ConfigMetricsReportList reports;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
                             FAST, &buffer);
-    EXPECT_GT(buffer.size(), 0);
+    ASSERT_GT(buffer.size(), 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
 
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     StatsLogReport::DurationMetricDataWrapper durationMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
                                     &durationMetrics);
-    EXPECT_EQ(1, durationMetrics.data_size());
+    ASSERT_EQ(1, durationMetrics.data_size());
 
     DurationMetricData data = durationMetrics.data(0);
     // Validate dimension value.
     ValidateAttributionUidDimension(data.dimensions_in_what(),
                                     util::WAKELOCK_STATE_CHANGED, appUid);
     // Validate bucket info.
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
 
     auto bucketInfo = data.bucket_info(0);
     EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
@@ -608,15 +608,15 @@
     uint64_t bucketSizeNs =
             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
     auto& eventActivationMap = metricProducer->mEventActivationMap;
     EXPECT_FALSE(metricsManager->isActive());
     EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap.size(), 1u);
+    ASSERT_EQ(eventActivationMap.size(), 1u);
     EXPECT_TRUE(eventActivationMap.find(4) != eventActivationMap.end());
     EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
@@ -691,25 +691,25 @@
     ConfigMetricsReportList reports;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true, ADB_DUMP,
                             FAST, &buffer);
-    EXPECT_GT(buffer.size(), 0);
+    ASSERT_GT(buffer.size(), 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
 
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     StatsLogReport::DurationMetricDataWrapper durationMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
                                     &durationMetrics);
-    EXPECT_EQ(1, durationMetrics.data_size());
+    ASSERT_EQ(1, durationMetrics.data_size());
 
     DurationMetricData data = durationMetrics.data(0);
     // Validate dimension value.
     ValidateAttributionUidDimension(data.dimensions_in_what(),
                                     util::WAKELOCK_STATE_CHANGED, appUid);
     // Validate bucket info.
-    EXPECT_EQ(2, data.bucket_info_size());
+    ASSERT_EQ(2, data.bucket_info_size());
 
     auto bucketInfo = data.bucket_info(0);
     EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
@@ -753,16 +753,16 @@
             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
 
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     EXPECT_TRUE(metricsManager->isActive());
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
     EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+    ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
-    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
+    ASSERT_EQ(metricProducer->mStateGroupMap.size(), 0);
 
     // Check that StateTrackers were initialized correctly.
     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
@@ -814,26 +814,26 @@
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 360 * NS_PER_SEC,
                             true /* include current partial bucket */, true, ADB_DUMP, FAST,
                             &buffer);  // 6:10
-    EXPECT_GT(buffer.size(), 0);
+    ASSERT_GT(buffer.size(), 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
 
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
     StatsLogReport::DurationMetricDataWrapper durationMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
                                     &durationMetrics);
-    EXPECT_EQ(3, durationMetrics.data_size());
+    ASSERT_EQ(3, durationMetrics.data_size());
 
     DurationMetricData data = durationMetrics.data(0);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
-    EXPECT_EQ(2, data.bucket_info_size());
+    ASSERT_EQ(2, data.bucket_info_size());
     EXPECT_EQ(50 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -842,11 +842,11 @@
     EXPECT_EQ(370 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
 
     data = durationMetrics.data(1);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
-    EXPECT_EQ(2, data.bucket_info_size());
+    ASSERT_EQ(2, data.bucket_info_size());
     EXPECT_EQ(110 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -855,11 +855,11 @@
     EXPECT_EQ(370 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
 
     data = durationMetrics.data(2);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE, data.slice_by_state(0).value());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(40 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -902,16 +902,16 @@
             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
 
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     EXPECT_TRUE(metricsManager->isActive());
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
     EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+    ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
-    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
+    ASSERT_EQ(metricProducer->mStateGroupMap.size(), 0);
 
     // Check that StateTrackers were initialized correctly.
     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
@@ -976,26 +976,26 @@
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 410 * NS_PER_SEC,
                             true /* include current partial bucket */, true, ADB_DUMP, FAST,
                             &buffer);
-    EXPECT_GT(buffer.size(), 0);
+    ASSERT_GT(buffer.size(), 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
 
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
     StatsLogReport::DurationMetricDataWrapper durationMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
                                     &durationMetrics);
-    EXPECT_EQ(3, durationMetrics.data_size());
+    ASSERT_EQ(3, durationMetrics.data_size());
 
     DurationMetricData data = durationMetrics.data(0);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
-    EXPECT_EQ(2, data.bucket_info_size());
+    ASSERT_EQ(2, data.bucket_info_size());
     EXPECT_EQ(45 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -1004,11 +1004,11 @@
     EXPECT_EQ(420 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
 
     data = durationMetrics.data(1);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
-    EXPECT_EQ(2, data.bucket_info_size());
+    ASSERT_EQ(2, data.bucket_info_size());
     EXPECT_EQ(45 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -1017,11 +1017,11 @@
     EXPECT_EQ(420 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
 
     data = durationMetrics.data(2);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE, data.slice_by_state(0).value());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(30 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -1060,16 +1060,16 @@
             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
 
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     EXPECT_TRUE(metricsManager->isActive());
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
     EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+    ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
-    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 1);
+    ASSERT_EQ(metricProducer->mStateGroupMap.size(), 1);
 
     // Check that StateTrackers were initialized correctly.
     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
@@ -1134,26 +1134,26 @@
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 490 * NS_PER_SEC,
                             true /* include current partial bucket */, true, ADB_DUMP, FAST,
                             &buffer);
-    EXPECT_GT(buffer.size(), 0);
+    ASSERT_GT(buffer.size(), 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
 
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
     StatsLogReport::DurationMetricDataWrapper durationMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
                                     &durationMetrics);
-    EXPECT_EQ(2, durationMetrics.data_size());
+    ASSERT_EQ(2, durationMetrics.data_size());
 
     DurationMetricData data = durationMetrics.data(0);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
     EXPECT_EQ(screenOnId, data.slice_by_state(0).group_id());
-    EXPECT_EQ(2, data.bucket_info_size());
+    ASSERT_EQ(2, data.bucket_info_size());
     EXPECT_EQ(130 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -1162,11 +1162,11 @@
     EXPECT_EQ(500 * NS_PER_SEC, data.bucket_info(1).end_bucket_elapsed_nanos());
 
     data = durationMetrics.data(1);
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
     EXPECT_EQ(screenOffId, data.slice_by_state(0).group_id());
-    EXPECT_EQ(2, data.bucket_info_size());
+    ASSERT_EQ(2, data.bucket_info_size());
     EXPECT_EQ(70 * NS_PER_SEC, data.bucket_info(0).duration_nanos());
     EXPECT_EQ(10 * NS_PER_SEC, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(310 * NS_PER_SEC, data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -1216,7 +1216,7 @@
 
     // This config is rejected because the dimension in what fields are not a superset of the sliced
     // state primary fields.
-    EXPECT_EQ(processor->mMetricsManagers.size(), 0);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 0);
 }
 
 TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSubset) {
@@ -1261,16 +1261,16 @@
             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
 
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     EXPECT_TRUE(metricsManager->isActive());
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
     EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+    ASSERT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
     EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), UID_PROCESS_STATE_ATOM_ID);
-    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
+    ASSERT_EQ(metricProducer->mStateGroupMap.size(), 0);
 
     // Check that StateTrackers were initialized correctly.
     EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
@@ -1328,24 +1328,24 @@
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 320 * NS_PER_SEC,
                             true /* include current partial bucket */, true, ADB_DUMP, FAST,
                             &buffer);
-    EXPECT_GT(buffer.size(), 0);
+    ASSERT_GT(buffer.size(), 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
 
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
     StatsLogReport::DurationMetricDataWrapper durationMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).duration_metrics(),
                                     &durationMetrics);
-    EXPECT_EQ(9, durationMetrics.data_size());
+    ASSERT_EQ(9, durationMetrics.data_size());
 
     DurationMetricData data = durationMetrics.data(0);
     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
                                                   "wakelock1");
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
@@ -1358,7 +1358,7 @@
     data = durationMetrics.data(1);
     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
                                                   "wakelock1");
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
@@ -1374,7 +1374,7 @@
     data = durationMetrics.data(2);
     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
                                                   "wakelock2");
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
@@ -1387,7 +1387,7 @@
     data = durationMetrics.data(3);
     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid1,
                                                   "wakelock2");
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
@@ -1400,7 +1400,7 @@
     data = durationMetrics.data(4);
     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
                                                   "wakelock1");
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(-1 /* StateTracker:: kStateUnknown */, data.slice_by_state(0).value());
@@ -1412,7 +1412,7 @@
     data = durationMetrics.data(5);
     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
                                                   "wakelock1");
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
@@ -1425,7 +1425,7 @@
     data = durationMetrics.data(6);
     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
                                                   "wakelock2");
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(-1 /* StateTracker:: kStateUnknown */, data.slice_by_state(0).value());
@@ -1437,7 +1437,7 @@
     data = durationMetrics.data(7);
     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
                                                   "wakelock2");
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
@@ -1453,7 +1453,7 @@
     data = durationMetrics.data(8);
     ValidateWakelockAttributionUidAndTagDimension(data.dimensions_in_what(), 10, appUid2,
                                                   "wakelock2");
-    EXPECT_EQ(1, data.slice_by_state_size());
+    ASSERT_EQ(1, data.slice_by_state_size());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
index c234b14..1be2612 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
@@ -76,7 +76,7 @@
     auto processor =
             CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
                                     SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     processor->mPullerManager->ForceClearPullerCache();
 
@@ -87,7 +87,7 @@
 
     // When creating the config, the gauge metric producer should register the alarm at the
     // end of the current bucket.
-    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+    ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
     EXPECT_EQ(bucketSizeNs,
               processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
     int64_t& nextPullTimeNs =
@@ -141,30 +141,30 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
-    EXPECT_GT((int)gaugeMetrics.data_size(), 1);
+    ASSERT_GT((int)gaugeMetrics.data_size(), 1);
 
     auto data = gaugeMetrics.data(0);
     EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* subsystem name field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
-    EXPECT_EQ(6, data.bucket_info_size());
+    ASSERT_EQ(6, data.bucket_info_size());
 
-    EXPECT_EQ(1, data.bucket_info(0).atom_size());
-    EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+    ASSERT_EQ(1, data.bucket_info(0).atom_size());
+    ASSERT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
     EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+    ASSERT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
     EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
 
-    EXPECT_EQ(1, data.bucket_info(1).atom_size());
+    ASSERT_EQ(1, data.bucket_info(1).atom_size());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0));
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0));
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
@@ -172,32 +172,32 @@
     EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
     EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
 
-    EXPECT_EQ(1, data.bucket_info(2).atom_size());
-    EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
+    ASSERT_EQ(1, data.bucket_info(2).atom_size());
+    ASSERT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1, data.bucket_info(2).elapsed_timestamp_nanos(0));
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
     EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
 
-    EXPECT_EQ(1, data.bucket_info(3).atom_size());
-    EXPECT_EQ(1, data.bucket_info(3).elapsed_timestamp_nanos_size());
+    ASSERT_EQ(1, data.bucket_info(3).atom_size());
+    ASSERT_EQ(1, data.bucket_info(3).elapsed_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 1, data.bucket_info(3).elapsed_timestamp_nanos(0));
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(3).atom(0).subsystem_sleep_state().subsystem_name().empty());
     EXPECT_GT(data.bucket_info(3).atom(0).subsystem_sleep_state().time_millis(), 0);
 
-    EXPECT_EQ(1, data.bucket_info(4).atom_size());
-    EXPECT_EQ(1, data.bucket_info(4).elapsed_timestamp_nanos_size());
+    ASSERT_EQ(1, data.bucket_info(4).atom_size());
+    ASSERT_EQ(1, data.bucket_info(4).elapsed_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1, data.bucket_info(4).elapsed_timestamp_nanos(0));
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(4).atom(0).subsystem_sleep_state().subsystem_name().empty());
     EXPECT_GT(data.bucket_info(4).atom(0).subsystem_sleep_state().time_millis(), 0);
 
-    EXPECT_EQ(1, data.bucket_info(5).atom_size());
-    EXPECT_EQ(1, data.bucket_info(5).elapsed_timestamp_nanos_size());
+    ASSERT_EQ(1, data.bucket_info(5).atom_size());
+    ASSERT_EQ(1, data.bucket_info(5).elapsed_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs + 2, data.bucket_info(5).elapsed_timestamp_nanos(0));
     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(5).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(5).end_bucket_elapsed_nanos());
@@ -215,7 +215,7 @@
     auto processor =
             CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
                                     SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     processor->mPullerManager->ForceClearPullerCache();
 
@@ -259,30 +259,30 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
-    EXPECT_GT((int)gaugeMetrics.data_size(), 1);
+    ASSERT_GT((int)gaugeMetrics.data_size(), 1);
 
     auto data = gaugeMetrics.data(0);
     EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* subsystem name field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
-    EXPECT_EQ(3, data.bucket_info_size());
+    ASSERT_EQ(3, data.bucket_info_size());
 
-    EXPECT_EQ(1, data.bucket_info(0).atom_size());
-    EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+    ASSERT_EQ(1, data.bucket_info(0).atom_size());
+    ASSERT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
     EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+    ASSERT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
     EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
 
-    EXPECT_EQ(1, data.bucket_info(1).atom_size());
+    ASSERT_EQ(1, data.bucket_info(1).atom_size());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 100, data.bucket_info(1).elapsed_timestamp_nanos(0));
     EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
@@ -290,8 +290,8 @@
     EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
     EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
 
-    EXPECT_EQ(2, data.bucket_info(2).atom_size());
-    EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
+    ASSERT_EQ(2, data.bucket_info(2).atom_size());
+    ASSERT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1, data.bucket_info(2).elapsed_timestamp_nanos(0));
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 10, data.bucket_info(2).elapsed_timestamp_nanos(1));
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
@@ -312,7 +312,7 @@
     auto processor =
             CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
                                     SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     processor->mPullerManager->ForceClearPullerCache();
 
@@ -323,7 +323,7 @@
 
     // When creating the config, the gauge metric producer should register the alarm at the
     // end of the current bucket.
-    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+    ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
     EXPECT_EQ(bucketSizeNs,
               processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
     int64_t& nextPullTimeNs =
@@ -359,29 +359,29 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
-    EXPECT_GT((int)gaugeMetrics.data_size(), 1);
+    ASSERT_GT((int)gaugeMetrics.data_size(), 1);
 
     auto data = gaugeMetrics.data(0);
     EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* subsystem name field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
-    EXPECT_EQ(3, data.bucket_info_size());
+    ASSERT_EQ(3, data.bucket_info_size());
 
-    EXPECT_EQ(1, data.bucket_info(0).atom_size());
-    EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+    ASSERT_EQ(1, data.bucket_info(0).atom_size());
+    ASSERT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
     EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
     EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
     EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
 
-    EXPECT_EQ(1, data.bucket_info(1).atom_size());
+    ASSERT_EQ(1, data.bucket_info(1).atom_size());
     EXPECT_EQ(configAddedTimeNs + 3 * bucketSizeNs + 11,
               data.bucket_info(1).elapsed_timestamp_nanos(0));
     EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
@@ -390,8 +390,8 @@
     EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
     EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
 
-    EXPECT_EQ(1, data.bucket_info(2).atom_size());
-    EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
+    ASSERT_EQ(1, data.bucket_info(2).atom_size());
+    ASSERT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs + 12, data.bucket_info(2).elapsed_timestamp_nanos(0));
     EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
@@ -420,7 +420,7 @@
     auto processor =
             CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
                                     SharedRefBase::make<FakeSubsystemSleepCallback>(), ATOM_TAG);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     processor->mPullerManager->ForceClearPullerCache();
 
@@ -432,7 +432,7 @@
 
     // When creating the config, the gauge metric producer should register the alarm at the
     // end of the current bucket.
-    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+    ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
     EXPECT_EQ(bucketSizeNs,
               processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
     int64_t& nextPullTimeNs =
@@ -479,45 +479,45 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
-    EXPECT_GT((int)gaugeMetrics.data_size(), 0);
+    ASSERT_GT((int)gaugeMetrics.data_size(), 0);
 
     auto data = gaugeMetrics.data(0);
     EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* subsystem name field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
-    EXPECT_EQ(3, data.bucket_info_size());
+    ASSERT_EQ(3, data.bucket_info_size());
 
     auto bucketInfo = data.bucket_info(0);
-    EXPECT_EQ(1, bucketInfo.atom_size());
-    EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
+    ASSERT_EQ(1, bucketInfo.atom_size());
+    ASSERT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
     EXPECT_EQ(activationNs, bucketInfo.elapsed_timestamp_nanos(0));
-    EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
+    ASSERT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
     EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
     EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
 
     bucketInfo = data.bucket_info(1);
-    EXPECT_EQ(1, bucketInfo.atom_size());
-    EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
+    ASSERT_EQ(1, bucketInfo.atom_size());
+    ASSERT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1, bucketInfo.elapsed_timestamp_nanos(0));
-    EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
+    ASSERT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
     EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
     EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
 
     bucketInfo = data.bucket_info(2);
-    EXPECT_EQ(1, bucketInfo.atom_size());
-    EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
+    ASSERT_EQ(1, bucketInfo.atom_size());
+    ASSERT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 2, bucketInfo.elapsed_timestamp_nanos(0));
-    EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
+    ASSERT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
     EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
               bucketInfo.start_bucket_elapsed_nanos());
     EXPECT_EQ(MillisToNano(NanoToMillis(activationNs + ttlNs + 1)),
@@ -538,7 +538,7 @@
     auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
                                              SharedRefBase::make<FakeSubsystemSleepCallback>(),
                                              ATOM_TAG);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     processor->mPullerManager->ForceClearPullerCache();
 
@@ -548,7 +548,7 @@
 
     // When creating the config, the gauge metric producer should register the alarm at the
     // end of the current bucket.
-    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+    ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
     EXPECT_EQ(bucketSizeNs,
               processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
     int64_t& nextPullTimeNs =
@@ -572,43 +572,43 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
     sortMetricDataByDimensionsValue(
             reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
-    EXPECT_GT((int)gaugeMetrics.data_size(), 0);
+    ASSERT_GT((int)gaugeMetrics.data_size(), 0);
 
     auto data = gaugeMetrics.data(0);
     EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* subsystem name field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
-    EXPECT_EQ(3, data.bucket_info_size());
+    ASSERT_EQ(3, data.bucket_info_size());
 
-    EXPECT_EQ(1, data.bucket_info(0).atom_size());
-    EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+    ASSERT_EQ(1, data.bucket_info(0).atom_size());
+    ASSERT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
     EXPECT_EQ(configAddedTimeNs, data.bucket_info(0).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+    ASSERT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
     EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
 
-    EXPECT_EQ(1, data.bucket_info(1).atom_size());
-    EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
+    ASSERT_EQ(1, data.bucket_info(1).atom_size());
+    ASSERT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(0, data.bucket_info(1).wall_clock_timestamp_nanos_size());
+    ASSERT_EQ(0, data.bucket_info(1).wall_clock_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
     EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
 
-    EXPECT_EQ(1, data.bucket_info(2).atom_size());
-    EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
+    ASSERT_EQ(1, data.bucket_info(2).atom_size());
+    ASSERT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 4, data.bucket_info(2).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(0, data.bucket_info(2).wall_clock_timestamp_nanos_size());
+    ASSERT_EQ(0, data.bucket_info(2).wall_clock_timestamp_nanos_size());
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
index 60403f2..a40a948 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
@@ -103,7 +103,7 @@
         ConfigKey cfgKey;
         auto processor =
                 CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-        EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+        ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
         EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
 
         int appUid1 = 123;
@@ -160,24 +160,24 @@
         backfillDimensionPath(&reports);
         backfillStringInReport(&reports);
         backfillStartEndTimestamp(&reports);
-        EXPECT_EQ(1, reports.reports_size());
-        EXPECT_EQ(1, reports.reports(0).metrics_size());
+        ASSERT_EQ(1, reports.reports_size());
+        ASSERT_EQ(1, reports.reports(0).metrics_size());
         StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
         sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(),
                                         &gaugeMetrics);
-        EXPECT_EQ(2, gaugeMetrics.data_size());
+        ASSERT_EQ(2, gaugeMetrics.data_size());
 
         auto data = gaugeMetrics.data(0);
         EXPECT_EQ(util::APP_START_OCCURRED, data.dimensions_in_what().field());
-        EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+        ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
         EXPECT_EQ(1 /* uid field */,
                   data.dimensions_in_what().value_tuple().dimensions_value(0).field());
         EXPECT_EQ(appUid1, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-        EXPECT_EQ(3, data.bucket_info_size());
+        ASSERT_EQ(3, data.bucket_info_size());
         if (sampling_type == GaugeMetric::FIRST_N_SAMPLES) {
-            EXPECT_EQ(2, data.bucket_info(0).atom_size());
-            EXPECT_EQ(2, data.bucket_info(0).elapsed_timestamp_nanos_size());
-            EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+            ASSERT_EQ(2, data.bucket_info(0).atom_size());
+            ASSERT_EQ(2, data.bucket_info(0).elapsed_timestamp_nanos_size());
+            ASSERT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
             EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
             EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
                       data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -194,8 +194,8 @@
             EXPECT_EQ(103L,
                       data.bucket_info(0).atom(1).app_start_occurred().activity_start_millis());
 
-            EXPECT_EQ(1, data.bucket_info(1).atom_size());
-            EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
+            ASSERT_EQ(1, data.bucket_info(1).atom_size());
+            ASSERT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
             EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
                       data.bucket_info(1).start_bucket_elapsed_nanos());
             EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
@@ -207,8 +207,8 @@
             EXPECT_EQ(104L,
                       data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
 
-            EXPECT_EQ(2, data.bucket_info(2).atom_size());
-            EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
+            ASSERT_EQ(2, data.bucket_info(2).atom_size());
+            ASSERT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
             EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
                       data.bucket_info(2).start_bucket_elapsed_nanos());
             EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
@@ -226,8 +226,8 @@
             EXPECT_EQ(106L,
                       data.bucket_info(2).atom(1).app_start_occurred().activity_start_millis());
         } else {
-            EXPECT_EQ(1, data.bucket_info(0).atom_size());
-            EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+            ASSERT_EQ(1, data.bucket_info(0).atom_size());
+            ASSERT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
             EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
             EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
                       data.bucket_info(0).end_bucket_elapsed_nanos());
@@ -238,8 +238,8 @@
             EXPECT_EQ(102L,
                       data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
 
-            EXPECT_EQ(1, data.bucket_info(1).atom_size());
-            EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
+            ASSERT_EQ(1, data.bucket_info(1).atom_size());
+            ASSERT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
             EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
                       data.bucket_info(1).start_bucket_elapsed_nanos());
             EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
@@ -251,8 +251,8 @@
             EXPECT_EQ(104L,
                       data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
 
-            EXPECT_EQ(1, data.bucket_info(2).atom_size());
-            EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
+            ASSERT_EQ(1, data.bucket_info(2).atom_size());
+            ASSERT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
             EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
                       data.bucket_info(2).start_bucket_elapsed_nanos());
             EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
@@ -268,13 +268,13 @@
         data = gaugeMetrics.data(1);
 
         EXPECT_EQ(data.dimensions_in_what().field(), util::APP_START_OCCURRED);
-        EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
+        ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
         EXPECT_EQ(1 /* uid field */,
                   data.dimensions_in_what().value_tuple().dimensions_value(0).field());
         EXPECT_EQ(appUid2, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-        EXPECT_EQ(1, data.bucket_info_size());
-        EXPECT_EQ(1, data.bucket_info(0).atom_size());
-        EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+        ASSERT_EQ(1, data.bucket_info_size());
+        ASSERT_EQ(1, data.bucket_info(0).atom_size());
+        ASSERT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
         EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
                   data.bucket_info(0).start_bucket_elapsed_nanos());
         EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
diff --git a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
index ba8d283..e320419 100644
--- a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
@@ -267,10 +267,10 @@
 
     processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
 
-    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor.mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
     auto& eventActivationMap = metricProducer->mEventActivationMap;
 
@@ -278,7 +278,7 @@
     EXPECT_FALSE(metricProducer->mIsActive);
     // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
     // triggered by screen on event (tracker index 2).
-    EXPECT_EQ(eventActivationMap.size(), 2u);
+    ASSERT_EQ(eventActivationMap.size(), 2u);
     EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
     EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
@@ -302,7 +302,7 @@
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 1);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
@@ -353,7 +353,7 @@
     EXPECT_FALSE(metricProducer->mIsActive);
     // New broadcast since the config is no longer active.
     EXPECT_EQ(broadcastCount, 2);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 0);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
     EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
@@ -368,7 +368,7 @@
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
@@ -389,42 +389,42 @@
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
 
     StatsLogReport::CountMetricDataWrapper countMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(4, countMetrics.data_size());
+    ASSERT_EQ(4, countMetrics.data_size());
 
     auto data = countMetrics.data(0);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
 
     data = countMetrics.data(1);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
 
     data = countMetrics.data(2);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     // Partial bucket as metric is deactivated.
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
@@ -433,11 +433,11 @@
 
     data = countMetrics.data(3);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
               data.bucket_info(0).start_bucket_elapsed_nanos());
@@ -478,10 +478,10 @@
 
     processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
 
-    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor.mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
     auto& eventActivationMap = metricProducer->mEventActivationMap;
     auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
@@ -490,7 +490,7 @@
     EXPECT_FALSE(metricProducer->mIsActive);
     // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
     // triggered by screen on event (tracker index 2).
-    EXPECT_EQ(eventActivationMap.size(), 2u);
+    ASSERT_EQ(eventActivationMap.size(), 2u);
     EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
     EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
@@ -499,9 +499,9 @@
     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
     EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap.size(), 1u);
+    ASSERT_EQ(eventDeactivationMap.size(), 1u);
     EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
-    EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
+    ASSERT_EQ(eventDeactivationMap[3].size(), 1u);
     EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
 
     std::unique_ptr<LogEvent> event;
@@ -518,7 +518,7 @@
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 1);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
@@ -572,7 +572,7 @@
     EXPECT_FALSE(metricProducer->mIsActive);
     // New broadcast since the config is no longer active.
     EXPECT_EQ(broadcastCount, 2);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 0);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
     EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
@@ -588,7 +588,7 @@
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
@@ -608,7 +608,7 @@
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
@@ -628,7 +628,7 @@
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
@@ -645,7 +645,7 @@
     EXPECT_FALSE(metricProducer->mIsActive);
     // New broadcast since the config is no longer active.
     EXPECT_EQ(broadcastCount, 4);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 0);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
     EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
@@ -663,7 +663,7 @@
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 5);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
@@ -679,7 +679,7 @@
     EXPECT_FALSE(metricsManager->isActive());
     EXPECT_FALSE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 6);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 0);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
     EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
@@ -696,42 +696,42 @@
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
 
     StatsLogReport::CountMetricDataWrapper countMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(5, countMetrics.data_size());
+    ASSERT_EQ(5, countMetrics.data_size());
 
     auto data = countMetrics.data(0);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
 
     data = countMetrics.data(1);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
 
     data = countMetrics.data(2);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     // Partial bucket as metric is deactivated.
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
@@ -740,11 +740,11 @@
 
     data = countMetrics.data(3);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
               data.bucket_info(0).start_bucket_elapsed_nanos());
@@ -753,11 +753,11 @@
 
     data = countMetrics.data(4);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
               data.bucket_info(0).start_bucket_elapsed_nanos());
@@ -799,10 +799,10 @@
 
     processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
 
-    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor.mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
     auto& eventActivationMap = metricProducer->mEventActivationMap;
     auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
@@ -811,7 +811,7 @@
     EXPECT_FALSE(metricProducer->mIsActive);
     // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
     // triggered by screen on event (tracker index 2).
-    EXPECT_EQ(eventActivationMap.size(), 2u);
+    ASSERT_EQ(eventActivationMap.size(), 2u);
     EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
     EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
@@ -820,11 +820,11 @@
     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
     EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap.size(), 2u);
+    ASSERT_EQ(eventDeactivationMap.size(), 2u);
     EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
     EXPECT_TRUE(eventDeactivationMap.find(4) != eventDeactivationMap.end());
-    EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
-    EXPECT_EQ(eventDeactivationMap[4].size(), 1u);
+    ASSERT_EQ(eventDeactivationMap[3].size(), 1u);
+    ASSERT_EQ(eventDeactivationMap[4].size(), 1u);
     EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
     EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
 
@@ -842,7 +842,7 @@
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 1);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
@@ -899,7 +899,7 @@
     EXPECT_FALSE(metricProducer->mIsActive);
     // New broadcast since the config is no longer active.
     EXPECT_EQ(broadcastCount, 2);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 0);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
     EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
@@ -916,7 +916,7 @@
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
@@ -937,7 +937,7 @@
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
@@ -959,7 +959,7 @@
     EXPECT_FALSE(metricProducer->mIsActive);
     // New broadcast since the config is no longer active.
     EXPECT_EQ(broadcastCount, 4);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 0);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
     EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
@@ -975,7 +975,7 @@
     EXPECT_FALSE(metricsManager->isActive());
     EXPECT_FALSE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 4);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 0);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
     EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
@@ -994,7 +994,7 @@
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 5);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
@@ -1011,7 +1011,7 @@
     EXPECT_FALSE(metricsManager->isActive());
     EXPECT_FALSE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 6);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 0);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
     EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
@@ -1029,42 +1029,42 @@
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
 
     StatsLogReport::CountMetricDataWrapper countMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(5, countMetrics.data_size());
+    ASSERT_EQ(5, countMetrics.data_size());
 
     auto data = countMetrics.data(0);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
 
     data = countMetrics.data(1);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
 
     data = countMetrics.data(2);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     // Partial bucket as metric is deactivated.
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
@@ -1073,11 +1073,11 @@
 
     data = countMetrics.data(3);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
               data.bucket_info(0).start_bucket_elapsed_nanos());
@@ -1086,11 +1086,11 @@
 
     data = countMetrics.data(4);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
               data.bucket_info(0).start_bucket_elapsed_nanos());
@@ -1132,10 +1132,10 @@
 
     processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
 
-    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor.mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 1);
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
     auto& eventActivationMap = metricProducer->mEventActivationMap;
     auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
@@ -1144,7 +1144,7 @@
     EXPECT_FALSE(metricProducer->mIsActive);
     // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
     // triggered by screen on event (tracker index 2).
-    EXPECT_EQ(eventActivationMap.size(), 2u);
+    ASSERT_EQ(eventActivationMap.size(), 2u);
     EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
     EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
@@ -1153,9 +1153,9 @@
     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
     EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap.size(), 1u);
+    ASSERT_EQ(eventDeactivationMap.size(), 1u);
     EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
-    EXPECT_EQ(eventDeactivationMap[3].size(), 2u);
+    ASSERT_EQ(eventDeactivationMap[3].size(), 2u);
     EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
     EXPECT_EQ(eventDeactivationMap[3][1], eventActivationMap[2]);
     EXPECT_EQ(broadcastCount, 0);
@@ -1172,7 +1172,7 @@
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 1);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
@@ -1205,7 +1205,7 @@
     EXPECT_FALSE(metricProducer->mIsActive);
     // New broadcast since the config is no longer active.
     EXPECT_EQ(broadcastCount, 2);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 0);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
 
@@ -1219,7 +1219,7 @@
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 15);
@@ -1236,7 +1236,7 @@
     EXPECT_FALSE(metricsManager->isActive());
     EXPECT_FALSE(metricProducer->mIsActive);
     EXPECT_EQ(broadcastCount, 4);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 0);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
 
@@ -1252,42 +1252,42 @@
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
 
     StatsLogReport::CountMetricDataWrapper countMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(3, countMetrics.data_size());
+    ASSERT_EQ(3, countMetrics.data_size());
 
     auto data = countMetrics.data(0);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(firstDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
 
     data = countMetrics.data(1);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(firstDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
 
     data = countMetrics.data(2);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(555, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     // Partial bucket as metric is deactivated.
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
@@ -1329,10 +1329,10 @@
 
     processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
 
-    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor.mMetricsManagers.size(), 1u);
     sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 2);
+    ASSERT_EQ(metricsManager->mAllMetricProducers.size(), 2);
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
     auto& eventActivationMap = metricProducer->mEventActivationMap;
     auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
@@ -1345,7 +1345,7 @@
     EXPECT_FALSE(metricProducer2->mIsActive);
     // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
     // triggered by screen on event (tracker index 2).
-    EXPECT_EQ(eventActivationMap.size(), 2u);
+    ASSERT_EQ(eventActivationMap.size(), 2u);
     EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
     EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
@@ -1354,15 +1354,15 @@
     EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
     EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap.size(), 2u);
+    ASSERT_EQ(eventDeactivationMap.size(), 2u);
     EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
     EXPECT_TRUE(eventDeactivationMap.find(4) != eventDeactivationMap.end());
-    EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
-    EXPECT_EQ(eventDeactivationMap[4].size(), 1u);
+    ASSERT_EQ(eventDeactivationMap[3].size(), 1u);
+    ASSERT_EQ(eventDeactivationMap[4].size(), 1u);
     EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
     EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
 
-    EXPECT_EQ(eventActivationMap2.size(), 2u);
+    ASSERT_EQ(eventActivationMap2.size(), 2u);
     EXPECT_TRUE(eventActivationMap2.find(0) != eventActivationMap2.end());
     EXPECT_TRUE(eventActivationMap2.find(2) != eventActivationMap2.end());
     EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
@@ -1371,11 +1371,11 @@
     EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap2[2]->start_ns, 0);
     EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap2.size(), 2u);
+    ASSERT_EQ(eventDeactivationMap2.size(), 2u);
     EXPECT_TRUE(eventDeactivationMap2.find(3) != eventDeactivationMap2.end());
     EXPECT_TRUE(eventDeactivationMap2.find(4) != eventDeactivationMap2.end());
-    EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
-    EXPECT_EQ(eventDeactivationMap[4].size(), 1u);
+    ASSERT_EQ(eventDeactivationMap[3].size(), 1u);
+    ASSERT_EQ(eventDeactivationMap[4].size(), 1u);
     EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
     EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
 
@@ -1395,7 +1395,7 @@
     processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_EQ(broadcastCount, 1);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
@@ -1487,7 +1487,7 @@
     EXPECT_FALSE(metricsManager->isActive());
     // New broadcast since the config is no longer active.
     EXPECT_EQ(broadcastCount, 2);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 0);
     EXPECT_FALSE(metricProducer->mIsActive);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
@@ -1513,7 +1513,7 @@
     processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
@@ -1545,7 +1545,7 @@
     processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
@@ -1578,7 +1578,7 @@
     EXPECT_FALSE(metricsManager->isActive());
     // New broadcast since the config is no longer active.
     EXPECT_EQ(broadcastCount, 4);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 0);
     EXPECT_FALSE(metricProducer->mIsActive);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
@@ -1605,7 +1605,7 @@
     processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
     EXPECT_FALSE(metricsManager->isActive());
     EXPECT_EQ(broadcastCount, 4);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 0);
     EXPECT_FALSE(metricProducer->mIsActive);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
@@ -1635,7 +1635,7 @@
     processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
     EXPECT_TRUE(metricsManager->isActive());
     EXPECT_EQ(broadcastCount, 5);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 1);
     EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
     EXPECT_TRUE(metricProducer->mIsActive);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
@@ -1661,7 +1661,7 @@
     processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 16);
     EXPECT_FALSE(metricsManager->isActive());
     EXPECT_EQ(broadcastCount, 6);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+    ASSERT_EQ(activeConfigsBroadcast.size(), 0);
     EXPECT_FALSE(metricProducer->mIsActive);
     EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
     EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
@@ -1689,43 +1689,43 @@
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(2, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(2, reports.reports(0).metrics_size());
 
     StatsLogReport::CountMetricDataWrapper countMetrics;
 
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(5, countMetrics.data_size());
+    ASSERT_EQ(5, countMetrics.data_size());
 
     auto data = countMetrics.data(0);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
 
     data = countMetrics.data(1);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
 
     data = countMetrics.data(2);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     // Partial bucket as metric is deactivated.
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
@@ -1734,11 +1734,11 @@
 
     data = countMetrics.data(3);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
               data.bucket_info(0).start_bucket_elapsed_nanos());
@@ -1747,11 +1747,11 @@
 
     data = countMetrics.data(4);
     EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
               data.bucket_info(0).start_bucket_elapsed_nanos());
@@ -1760,37 +1760,37 @@
 
     countMetrics.clear_data();
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(1).count_metrics(), &countMetrics);
-    EXPECT_EQ(5, countMetrics.data_size());
+    ASSERT_EQ(5, countMetrics.data_size());
 
     data = countMetrics.data(0);
     EXPECT_EQ(util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(2222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
 
     data = countMetrics.data(1);
     EXPECT_EQ(util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(3333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
 
     data = countMetrics.data(2);
     EXPECT_EQ(util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(4444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     // Partial bucket as metric is deactivated.
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
@@ -1799,11 +1799,11 @@
 
     data = countMetrics.data(3);
     EXPECT_EQ(util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(6666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
               data.bucket_info(0).start_bucket_elapsed_nanos());
@@ -1812,11 +1812,11 @@
 
     data = countMetrics.data(4);
     EXPECT_EQ(util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* uid field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_EQ(7777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(1, data.bucket_info(0).count());
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
               data.bucket_info(0).start_bucket_elapsed_nanos());
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index f0df2c6..5e77ee0 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -107,7 +107,7 @@
 
     ConfigKey cfgKey;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
 
     int appUid = 123;
@@ -204,15 +204,15 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 1);
+    ASSERT_EQ(reports.reports_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 1);
     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
     auto data = reports.reports(0).metrics(0).count_metrics().data(0);
     // Validate dimension value.
     EXPECT_EQ(data.dimensions_in_what().field(), util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
-    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
+    ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
     // Uid field.
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
@@ -226,7 +226,7 @@
 
     ConfigKey cfgKey;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
 
     int appUid = 123;
@@ -324,16 +324,16 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 2);
+    ASSERT_EQ(reports.reports_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 2);
     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
     EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(1).count(), 3);
     auto data = reports.reports(0).metrics(0).count_metrics().data(0);
     // Validate dimension value.
     EXPECT_EQ(data.dimensions_in_what().field(), util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
-    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
+    ASSERT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
     // Uid field.
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
     EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
diff --git a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
index 9117623..783f31c 100644
--- a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -127,8 +127,8 @@
 
     ConfigMetricsReport report = GetReports(service->mProcessor, start + 3);
     // Expect no metrics since the bucket has not finished yet.
-    EXPECT_EQ(1, report.metrics_size());
-    EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
+    ASSERT_EQ(1, report.metrics_size());
+    ASSERT_EQ(0, report.metrics(0).count_metrics().data_size());
 }
 
 TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
@@ -147,8 +147,8 @@
     service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
 
     ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
-    EXPECT_EQ(1, report.metrics_size());
-    EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
+    ASSERT_EQ(1, report.metrics_size());
+    ASSERT_EQ(0, report.metrics(0).count_metrics().data_size());
 }
 
 TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
@@ -267,8 +267,8 @@
             GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
     backfillStartEndTimestamp(&report);
 
-    EXPECT_EQ(1, report.metrics_size());
-    EXPECT_EQ(0, report.metrics(0).value_metrics().skipped_size());
+    ASSERT_EQ(1, report.metrics_size());
+    ASSERT_EQ(0, report.metrics(0).value_metrics().skipped_size());
 
     // The fake subsystem state sleep puller returns two atoms.
     ASSERT_EQ(2, report.metrics(0).value_metrics().data_size());
@@ -305,7 +305,7 @@
               report.metrics(0).value_metrics().skipped(0).end_bucket_elapsed_nanos());
 
     ASSERT_EQ(2, report.metrics(0).value_metrics().data_size());
-    EXPECT_EQ(1, report.metrics(0).value_metrics().data(0).bucket_info_size());
+    ASSERT_EQ(1, report.metrics(0).value_metrics().data(0).bucket_info_size());
 }
 
 TEST(PartialBucketE2eTest, TestValueMetricOnBootWithoutMinPartialBucket) {
@@ -329,7 +329,7 @@
 
     // First bucket is dropped due to the initial pull failing
     ASSERT_EQ(1, report.metrics_size());
-    EXPECT_EQ(1, report.metrics(0).value_metrics().skipped_size());
+    ASSERT_EQ(1, report.metrics(0).value_metrics().skipped_size());
     EXPECT_EQ(MillisToNano(NanoToMillis(bootCompleteTimeNs)),
               report.metrics(0).value_metrics().skipped(0).end_bucket_elapsed_nanos());
 
@@ -359,10 +359,10 @@
     ConfigMetricsReport report = GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
     backfillStartEndTimestamp(&report);
     ASSERT_EQ(1, report.metrics_size());
-    EXPECT_EQ(0, report.metrics(0).gauge_metrics().skipped_size());
+    ASSERT_EQ(0, report.metrics(0).gauge_metrics().skipped_size());
     // The fake subsystem state sleep puller returns two atoms.
     ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size());
-    EXPECT_EQ(2, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
+    ASSERT_EQ(2, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
 }
 
 TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) {
@@ -391,7 +391,7 @@
     EXPECT_EQ(MillisToNano(NanoToMillis(endSkipped)),
               report.metrics(0).gauge_metrics().skipped(0).end_bucket_elapsed_nanos());
     ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size());
-    EXPECT_EQ(1, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
+    ASSERT_EQ(1, report.metrics(0).gauge_metrics().data(0).bucket_info_size());
 }
 
 TEST(PartialBucketE2eTest, TestGaugeMetricOnBootWithoutMinPartialBucket) {
@@ -414,7 +414,7 @@
     backfillStartEndTimestamp(&report);
 
     ASSERT_EQ(1, report.metrics_size());
-    EXPECT_EQ(0, report.metrics(0).gauge_metrics().skipped_size());
+    ASSERT_EQ(0, report.metrics(0).gauge_metrics().skipped_size());
     // The fake subsystem state sleep puller returns two atoms.
     ASSERT_EQ(2, report.metrics(0).gauge_metrics().data_size());
     // No data in the first bucket, so nothing is reported
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index 0c4a7c6..4d39282 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -63,8 +63,143 @@
     return config;
 }
 
+StatsdConfig CreateStatsdConfigWithStates() {
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT");     // LogEvent defaults to UID of root.
+    config.add_default_pull_packages("AID_ROOT");  // Fake puller is registered with root.
+
+    auto pulledAtomMatcher = CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
+    *config.add_atom_matcher() = pulledAtomMatcher;
+    *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+    *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
+    *config.add_atom_matcher() = CreateBatteryStateNoneMatcher();
+    *config.add_atom_matcher() = CreateBatteryStateUsbMatcher();
+
+    auto screenOnPredicate = CreateScreenIsOnPredicate();
+    *config.add_predicate() = screenOnPredicate;
+
+    auto screenOffPredicate = CreateScreenIsOffPredicate();
+    *config.add_predicate() = screenOffPredicate;
+
+    auto deviceUnpluggedPredicate = CreateDeviceUnpluggedPredicate();
+    *config.add_predicate() = deviceUnpluggedPredicate;
+
+    auto screenOnOnBatteryPredicate = config.add_predicate();
+    screenOnOnBatteryPredicate->set_id(StringToId("screenOnOnBatteryPredicate"));
+    screenOnOnBatteryPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
+    addPredicateToPredicateCombination(screenOnPredicate, screenOnOnBatteryPredicate);
+    addPredicateToPredicateCombination(deviceUnpluggedPredicate, screenOnOnBatteryPredicate);
+
+    auto screenOffOnBatteryPredicate = config.add_predicate();
+    screenOffOnBatteryPredicate->set_id(StringToId("ScreenOffOnBattery"));
+    screenOffOnBatteryPredicate->mutable_combination()->set_operation(LogicalOperation::AND);
+    addPredicateToPredicateCombination(screenOffPredicate, screenOffOnBatteryPredicate);
+    addPredicateToPredicateCombination(deviceUnpluggedPredicate, screenOffOnBatteryPredicate);
+
+    const State screenState =
+            CreateScreenStateWithSimpleOnOffMap(/*screen on id=*/321, /*screen off id=*/123);
+    *config.add_state() = screenState;
+
+    // ValueMetricSubsystemSleepWhileScreenOnOnBattery
+    auto valueMetric1 = config.add_value_metric();
+    valueMetric1->set_id(metricId);
+    valueMetric1->set_what(pulledAtomMatcher.id());
+    valueMetric1->set_condition(screenOnOnBatteryPredicate->id());
+    *valueMetric1->mutable_value_field() =
+            CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
+    valueMetric1->set_bucket(FIVE_MINUTES);
+    valueMetric1->set_use_absolute_value_on_reset(true);
+    valueMetric1->set_skip_zero_diff_output(false);
+    valueMetric1->set_max_pull_delay_sec(INT_MAX);
+
+    // ValueMetricSubsystemSleepWhileScreenOffOnBattery
+    ValueMetric* valueMetric2 = config.add_value_metric();
+    valueMetric2->set_id(StringToId("ValueMetricSubsystemSleepWhileScreenOffOnBattery"));
+    valueMetric2->set_what(pulledAtomMatcher.id());
+    valueMetric2->set_condition(screenOffOnBatteryPredicate->id());
+    *valueMetric2->mutable_value_field() =
+            CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
+    valueMetric2->set_bucket(FIVE_MINUTES);
+    valueMetric2->set_use_absolute_value_on_reset(true);
+    valueMetric2->set_skip_zero_diff_output(false);
+    valueMetric2->set_max_pull_delay_sec(INT_MAX);
+
+    // ValueMetricSubsystemSleepWhileOnBatterySliceScreen
+    ValueMetric* valueMetric3 = config.add_value_metric();
+    valueMetric3->set_id(StringToId("ValueMetricSubsystemSleepWhileOnBatterySliceScreen"));
+    valueMetric3->set_what(pulledAtomMatcher.id());
+    valueMetric3->set_condition(deviceUnpluggedPredicate.id());
+    *valueMetric3->mutable_value_field() =
+            CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
+    valueMetric3->add_slice_by_state(screenState.id());
+    valueMetric3->set_bucket(FIVE_MINUTES);
+    valueMetric3->set_use_absolute_value_on_reset(true);
+    valueMetric3->set_skip_zero_diff_output(false);
+    valueMetric3->set_max_pull_delay_sec(INT_MAX);
+    return config;
+}
+
 }  // namespace
 
+/**
+ * Tests the initial condition and condition after the first log events for
+ * value metrics with either a combination condition or simple condition.
+ *
+ * Metrics should be initialized with condition kUnknown (given that the
+ * predicate is using the default InitialValue of UNKNOWN). The condition should
+ * be updated to either kFalse or kTrue if a condition event is logged for all
+ * children conditions.
+ */
+TEST(ValueMetricE2eTest, TestInitialConditionChanges) {
+    StatsdConfig config = CreateStatsdConfigWithStates();
+    int64_t baseTimeNs = getElapsedRealtimeNs();
+    int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
+    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
+
+    ConfigKey cfgKey;
+    int32_t tagId = util::SUBSYSTEM_SLEEP_STATE;
+    auto processor =
+            CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
+                                    SharedRefBase::make<FakeSubsystemSleepCallback>(), tagId);
+
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+    EXPECT_TRUE(metricsManager->isConfigValid());
+    EXPECT_EQ(3, metricsManager->mAllMetricProducers.size());
+
+    // Combination condition metric - screen on and device unplugged
+    sp<MetricProducer> metricProducer1 = metricsManager->mAllMetricProducers[0];
+    // Simple condition metric - device unplugged
+    sp<MetricProducer> metricProducer2 = metricsManager->mAllMetricProducers[2];
+
+    EXPECT_EQ(ConditionState::kUnknown, metricProducer1->mCondition);
+    EXPECT_EQ(ConditionState::kUnknown, metricProducer2->mCondition);
+
+    auto screenOnEvent =
+            CreateScreenStateChangedEvent(configAddedTimeNs + 30, android::view::DISPLAY_STATE_ON);
+    processor->OnLogEvent(screenOnEvent.get());
+    EXPECT_EQ(ConditionState::kUnknown, metricProducer1->mCondition);
+    EXPECT_EQ(ConditionState::kUnknown, metricProducer2->mCondition);
+
+    auto screenOffEvent =
+            CreateScreenStateChangedEvent(configAddedTimeNs + 40, android::view::DISPLAY_STATE_OFF);
+    processor->OnLogEvent(screenOffEvent.get());
+    EXPECT_EQ(ConditionState::kUnknown, metricProducer1->mCondition);
+    EXPECT_EQ(ConditionState::kUnknown, metricProducer2->mCondition);
+
+    auto pluggedUsbEvent = CreateBatteryStateChangedEvent(
+            configAddedTimeNs + 50, BatteryPluggedStateEnum::BATTERY_PLUGGED_USB);
+    processor->OnLogEvent(pluggedUsbEvent.get());
+    EXPECT_EQ(ConditionState::kFalse, metricProducer1->mCondition);
+    EXPECT_EQ(ConditionState::kFalse, metricProducer2->mCondition);
+
+    auto pluggedNoneEvent = CreateBatteryStateChangedEvent(
+            configAddedTimeNs + 70, BatteryPluggedStateEnum::BATTERY_PLUGGED_NONE);
+    processor->OnLogEvent(pluggedNoneEvent.get());
+    EXPECT_EQ(ConditionState::kFalse, metricProducer1->mCondition);
+    EXPECT_EQ(ConditionState::kTrue, metricProducer2->mCondition);
+}
+
 TEST(ValueMetricE2eTest, TestPulledEvents) {
     auto config = CreateStatsdConfig();
     int64_t baseTimeNs = getElapsedRealtimeNs();
@@ -75,7 +210,7 @@
     auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
                                              SharedRefBase::make<FakeSubsystemSleepCallback>(),
                                              util::SUBSYSTEM_SLEEP_STATE);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     processor->mPullerManager->ForceClearPullerCache();
 
@@ -86,7 +221,7 @@
 
     // When creating the config, the value metric producer should register the alarm at the
     // end of the current bucket.
-    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+    ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
     EXPECT_EQ(bucketSizeNs,
               processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
     int64_t& expectedPullTimeNs =
@@ -136,36 +271,36 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     StatsLogReport::ValueMetricDataWrapper valueMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
-    EXPECT_GT((int)valueMetrics.data_size(), 1);
+    ASSERT_GT((int)valueMetrics.data_size(), 1);
 
     auto data = valueMetrics.data(0);
     EXPECT_EQ(util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* subsystem name field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
     // We have 4 buckets, the first one was incomplete since the condition was unknown.
-    EXPECT_EQ(4, data.bucket_info_size());
+    ASSERT_EQ(4, data.bucket_info_size());
 
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(0).values_size());
+    ASSERT_EQ(1, data.bucket_info(0).values_size());
 
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(1).values_size());
+    ASSERT_EQ(1, data.bucket_info(1).values_size());
 
     EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(2).values_size());
+    ASSERT_EQ(1, data.bucket_info(2).values_size());
 
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(3).values_size());
+    ASSERT_EQ(1, data.bucket_info(3).values_size());
 }
 
 TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
@@ -179,7 +314,7 @@
     auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
                                              SharedRefBase::make<FakeSubsystemSleepCallback>(),
                                              util::SUBSYSTEM_SLEEP_STATE);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     processor->mPullerManager->ForceClearPullerCache();
 
@@ -190,7 +325,7 @@
 
     // When creating the config, the value metric producer should register the alarm at the
     // end of the current bucket.
-    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+    ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
     EXPECT_EQ(bucketSizeNs,
               processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
     int64_t& expectedPullTimeNs =
@@ -244,31 +379,31 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     StatsLogReport::ValueMetricDataWrapper valueMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
-    EXPECT_GT((int)valueMetrics.data_size(), 1);
+    ASSERT_GT((int)valueMetrics.data_size(), 1);
 
     auto data = valueMetrics.data(0);
     EXPECT_EQ(util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* subsystem name field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
-    EXPECT_EQ(3, data.bucket_info_size());
+    ASSERT_EQ(3, data.bucket_info_size());
 
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(0).values_size());
+    ASSERT_EQ(1, data.bucket_info(0).values_size());
 
     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(1).values_size());
+    ASSERT_EQ(1, data.bucket_info(1).values_size());
 
     EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(2).values_size());
+    ASSERT_EQ(1, data.bucket_info(2).values_size());
 }
 
 TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
@@ -291,7 +426,7 @@
     auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
                                              SharedRefBase::make<FakeSubsystemSleepCallback>(),
                                              util::SUBSYSTEM_SLEEP_STATE);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     processor->mPullerManager->ForceClearPullerCache();
 
@@ -303,7 +438,7 @@
 
     // When creating the config, the value metric producer should register the alarm at the
     // end of the current bucket.
-    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+    ASSERT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
     EXPECT_EQ(bucketSizeNs,
               processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
     int64_t& expectedPullTimeNs =
@@ -347,30 +482,30 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(1, reports.reports_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
     StatsLogReport::ValueMetricDataWrapper valueMetrics;
     sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
-    EXPECT_GT((int)valueMetrics.data_size(), 0);
+    ASSERT_GT((int)valueMetrics.data_size(), 0);
 
     auto data = valueMetrics.data(0);
     EXPECT_EQ(util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
     EXPECT_EQ(1 /* subsystem name field */,
               data.dimensions_in_what().value_tuple().dimensions_value(0).field());
     EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
     // We have 2 full buckets, the two surrounding the activation are dropped.
-    EXPECT_EQ(2, data.bucket_info_size());
+    ASSERT_EQ(2, data.bucket_info_size());
 
     auto bucketInfo = data.bucket_info(0);
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, bucketInfo.values_size());
+    ASSERT_EQ(1, bucketInfo.values_size());
 
     bucketInfo = data.bucket_info(1);
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, bucketInfo.values_size());
+    ASSERT_EQ(1, bucketInfo.values_size());
 }
 
 /**
@@ -416,14 +551,14 @@
     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
 
     // Check that ValueMetricProducer was initialized correctly.
-    EXPECT_EQ(1U, processor->mMetricsManagers.size());
+    ASSERT_EQ(1U, processor->mMetricsManagers.size());
     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(1, metricsManager->mAllMetricProducers.size());
+    ASSERT_EQ(1, metricsManager->mAllMetricProducers.size());
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    EXPECT_EQ(1, metricProducer->mSlicedStateAtoms.size());
+    ASSERT_EQ(1, metricProducer->mSlicedStateAtoms.size());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, metricProducer->mSlicedStateAtoms.at(0));
-    EXPECT_EQ(0, metricProducer->mStateGroupMap.size());
+    ASSERT_EQ(0, metricProducer->mStateGroupMap.size());
 }
 
 /**
@@ -476,14 +611,14 @@
     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
 
     // Check that ValueMetricProducer was initialized correctly.
-    EXPECT_EQ(1U, processor->mMetricsManagers.size());
+    ASSERT_EQ(1U, processor->mMetricsManagers.size());
     sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
     EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(1, metricsManager->mAllMetricProducers.size());
+    ASSERT_EQ(1, metricsManager->mAllMetricProducers.size());
     sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    EXPECT_EQ(1, metricProducer->mSlicedStateAtoms.size());
+    ASSERT_EQ(1, metricProducer->mSlicedStateAtoms.size());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, metricProducer->mSlicedStateAtoms.at(0));
-    EXPECT_EQ(0, metricProducer->mStateGroupMap.size());
+    ASSERT_EQ(0, metricProducer->mStateGroupMap.size());
 }
 
 /**
@@ -532,7 +667,7 @@
     EXPECT_EQ(0, StateManager::getInstance().getStateTrackersCount());
 
     // Config initialization fails.
-    EXPECT_EQ(0, processor->mMetricsManagers.size());
+    ASSERT_EQ(0, processor->mMetricsManagers.size());
 }
 
 #else
diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
index 80f3c28..52bc222 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -121,7 +121,7 @@
     uint64_t bucketSizeNs =
             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     FeedEvents(config, processor);
     vector<uint8_t> buffer;
@@ -134,17 +134,17 @@
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
 
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+    ASSERT_EQ(reports.reports_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics_size(), 1);
     // Only 1 dimension output. The tag dimension in the predicate has been aggregated.
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
 
     auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
     // Validate dimension value.
     ValidateAttributionUidDimension(data.dimensions_in_what(),
                                     util::WAKELOCK_STATE_CHANGED, 111);
     // Validate bucket info.
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
     data = reports.reports(0).metrics(0).duration_metrics().data(0);
     // The wakelock holding interval starts from the screen off event and to the end of the 1st
     // bucket.
@@ -158,7 +158,7 @@
     uint64_t bucketSizeNs =
             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     FeedEvents(config, processor);
     vector<uint8_t> buffer;
@@ -170,11 +170,11 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
+    ASSERT_EQ(reports.reports_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
     // Dump the report after the end of 2nd bucket.
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
+    ASSERT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
     auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
     // Validate dimension value.
     ValidateAttributionUidDimension(data.dimensions_in_what(),
@@ -196,7 +196,7 @@
     uint64_t bucketSizeNs =
             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     FeedEvents(config, processor);
     vector<uint8_t> buffer;
@@ -222,10 +222,10 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 6);
+    ASSERT_EQ(reports.reports_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 6);
     auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
     ValidateAttributionUidDimension(data.dimensions_in_what(),
                                     util::WAKELOCK_STATE_CHANGED, 111);
@@ -243,7 +243,7 @@
     uint64_t bucketSizeNs =
             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     FeedEvents(config, processor);
     ConfigMetricsReportList reports;
@@ -257,13 +257,13 @@
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
 
-    EXPECT_EQ(reports.reports_size(), 1);
+    ASSERT_EQ(reports.reports_size(), 1);
 
     // When using ProtoOutputStream, if nothing written to a sub msg, it won't be treated as
     // one. It was previsouly 1 because we had a fake onDumpReport which calls add_metric() by
     // itself.
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_EQ(0, reports.reports(0).metrics(0).duration_metrics().data_size());
+    ASSERT_EQ(1, reports.reports(0).metrics_size());
+    ASSERT_EQ(0, reports.reports(0).metrics(0).duration_metrics().data_size());
 }
 
 TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration2) {
@@ -273,7 +273,7 @@
     uint64_t bucketSizeNs =
             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     FeedEvents(config, processor);
     ConfigMetricsReportList reports;
@@ -285,11 +285,11 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
+    ASSERT_EQ(reports.reports_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
     // Dump the report after the end of 2nd bucket. One dimension with one bucket.
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
     auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
     // Validate dimension value.
     ValidateAttributionUidDimension(data.dimensions_in_what(),
@@ -305,7 +305,7 @@
     uint64_t bucketSizeNs =
             TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
     auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
     EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
     FeedEvents(config, processor);
     ConfigMetricsReportList reports;
@@ -331,10 +331,10 @@
     backfillDimensionPath(&reports);
     backfillStringInReport(&reports);
     backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
+    ASSERT_EQ(reports.reports_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
+    ASSERT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
     auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
     ValidateAttributionUidDimension(data.dimensions_in_what(),
                                     util::WAKELOCK_STATE_CHANGED, 111);
diff --git a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
index 4b9bac1..13cdfc2 100644
--- a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
+++ b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
@@ -131,11 +131,11 @@
     EXPECT_TRUE(puller.PullInternal(&dataHolder));
     int64_t endTimeNs = getElapsedRealtimeNs();
 
-    EXPECT_EQ(1, dataHolder.size());
+    ASSERT_EQ(1, dataHolder.size());
     EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
     EXPECT_LT(startTimeNs, dataHolder[0]->GetElapsedTimestampNs());
     EXPECT_GT(endTimeNs, dataHolder[0]->GetElapsedTimestampNs());
-    EXPECT_EQ(1, dataHolder[0]->size());
+    ASSERT_EQ(1, dataHolder[0]->size());
     EXPECT_EQ(value, dataHolder[0]->getValues()[0].mValue.int_value);
 }
 
@@ -149,13 +149,13 @@
 
     vector<shared_ptr<LogEvent>> dataHolder;
     EXPECT_FALSE(puller.PullInternal(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
+    ASSERT_EQ(0, dataHolder.size());
 }
 
 TEST_F(StatsCallbackPullerTest, PullTimeout) {
     shared_ptr<FakePullAtomCallback> cb = SharedRefBase::make<FakePullAtomCallback>();
     pullSuccess = true;
-    pullDelayNs = 500000000;  // 500ms.
+    pullDelayNs = MillisToNano(5);  // 5ms.
     pullTimeoutNs = 10000;    // 10 microseconds.
     int64_t value = 4321;
     values.push_back(value);
@@ -173,18 +173,18 @@
     // is bigger.
     EXPECT_LT(pullTimeoutNs, actualPullDurationNs);
     EXPECT_GT(pullDelayNs, actualPullDurationNs);
-    EXPECT_EQ(0, dataHolder.size());
+    ASSERT_EQ(0, dataHolder.size());
 
     // Let the pull return and make sure that the dataHolder is not modified.
     pullThread.join();
-    EXPECT_EQ(0, dataHolder.size());
+    ASSERT_EQ(0, dataHolder.size());
 }
 
 // Register a puller and ensure that the timeout logic works.
 TEST_F(StatsCallbackPullerTest, RegisterAndTimeout) {
     shared_ptr<FakePullAtomCallback> cb = SharedRefBase::make<FakePullAtomCallback>();
     pullSuccess = true;
-    pullDelayNs = 500000000;  // 500 ms.
+    pullDelayNs = MillisToNano(5);  // 5 ms.
     pullTimeoutNs = 10000;    // 10 microsseconds.
     int64_t value = 4321;
     int32_t uid = 123;
@@ -196,7 +196,7 @@
     vector<shared_ptr<LogEvent>> dataHolder;
     int64_t startTimeNs = getElapsedRealtimeNs();
     // Returns false, since StatsPuller code will evaluate the timeout.
-    EXPECT_FALSE(pullerManager->Pull(pullTagId, {uid}, &dataHolder));
+    EXPECT_FALSE(pullerManager->Pull(pullTagId, {uid}, startTimeNs, &dataHolder));
     int64_t endTimeNs = getElapsedRealtimeNs();
     int64_t actualPullDurationNs = endTimeNs - startTimeNs;
 
@@ -204,11 +204,11 @@
     // is bigger.
     EXPECT_LT(pullTimeoutNs, actualPullDurationNs);
     EXPECT_GT(pullDelayNs, actualPullDurationNs);
-    EXPECT_EQ(0, dataHolder.size());
+    ASSERT_EQ(0, dataHolder.size());
 
     // Let the pull return and make sure that the dataHolder is not modified.
     pullThread.join();
-    EXPECT_EQ(0, dataHolder.size());
+    ASSERT_EQ(0, dataHolder.size());
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/tests/external/StatsPullerManager_test.cpp b/cmds/statsd/tests/external/StatsPullerManager_test.cpp
index 6b3f4cc..c76e85e 100644
--- a/cmds/statsd/tests/external/StatsPullerManager_test.cpp
+++ b/cmds/statsd/tests/external/StatsPullerManager_test.cpp
@@ -101,14 +101,14 @@
     sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister();
 
     vector<shared_ptr<LogEvent>> data;
-    EXPECT_FALSE(pullerManager->Pull(pullTagId1, {unregisteredUid}, &data, true));
+    EXPECT_FALSE(pullerManager->Pull(pullTagId1, {unregisteredUid}, /*timestamp =*/1, &data, true));
 }
 
 TEST(StatsPullerManagerTest, TestPullChoosesCorrectUid) {
     sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister();
 
     vector<shared_ptr<LogEvent>> data;
-    EXPECT_TRUE(pullerManager->Pull(pullTagId1, {uid1}, &data, true));
+    EXPECT_TRUE(pullerManager->Pull(pullTagId1, {uid1}, /*timestamp =*/1, &data, true));
     ASSERT_EQ(data.size(), 1);
     EXPECT_EQ(data[0]->GetTagId(), pullTagId1);
     ASSERT_EQ(data[0]->getValues().size(), 1);
@@ -121,7 +121,7 @@
     pullerManager->RegisterPullUidProvider(configKey, uidProvider);
 
     vector<shared_ptr<LogEvent>> data;
-    EXPECT_FALSE(pullerManager->Pull(pullTagId1, badConfigKey, &data, true));
+    EXPECT_FALSE(pullerManager->Pull(pullTagId1, badConfigKey, /*timestamp =*/1, &data, true));
 }
 
 TEST(StatsPullerManagerTest, TestPullConfigKeyGood) {
@@ -130,7 +130,7 @@
     pullerManager->RegisterPullUidProvider(configKey, uidProvider);
 
     vector<shared_ptr<LogEvent>> data;
-    EXPECT_TRUE(pullerManager->Pull(pullTagId1, configKey, &data, true));
+    EXPECT_TRUE(pullerManager->Pull(pullTagId1, configKey, /*timestamp =*/1, &data, true));
     EXPECT_EQ(data[0]->GetTagId(), pullTagId1);
     ASSERT_EQ(data[0]->getValues().size(), 1);
     EXPECT_EQ(data[0]->getValues()[0].mValue.int_value, uid2);
@@ -142,7 +142,7 @@
     pullerManager->RegisterPullUidProvider(configKey, uidProvider);
 
     vector<shared_ptr<LogEvent>> data;
-    EXPECT_FALSE(pullerManager->Pull(pullTagId2, configKey, &data, true));
+    EXPECT_FALSE(pullerManager->Pull(pullTagId2, configKey, /*timestamp =*/1, &data, true));
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/tests/external/StatsPuller_test.cpp b/cmds/statsd/tests/external/StatsPuller_test.cpp
index 5043358..55a9036 100644
--- a/cmds/statsd/tests/external/StatsPuller_test.cpp
+++ b/cmds/statsd/tests/external/StatsPuller_test.cpp
@@ -39,7 +39,6 @@
 using testing::Contains;
 
 namespace {
-// cooldown time 1sec.
 int pullTagId = 10014;
 
 bool pullSuccess;
@@ -48,7 +47,8 @@
 
 class FakePuller : public StatsPuller {
 public:
-    FakePuller() : StatsPuller(pullTagId, /*coolDown=*/NS_PER_SEC, /*timeout=*/NS_PER_SEC / 2){};
+    FakePuller()
+        : StatsPuller(pullTagId, /*coolDownNs=*/MillisToNano(10), /*timeoutNs=*/MillisToNano(5)){};
 
 private:
     bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override {
@@ -92,25 +92,25 @@
     pullSuccess = true;
 
     vector<std::shared_ptr<LogEvent>> dataHolder;
-    EXPECT_TRUE(puller.Pull(&dataHolder));
-    EXPECT_EQ(1, dataHolder.size());
+    EXPECT_TRUE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
+    ASSERT_EQ(1, dataHolder.size());
     EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
     EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
-    EXPECT_EQ(1, dataHolder[0]->size());
+    ASSERT_EQ(1, dataHolder[0]->size());
     EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
 
-    sleep_for(std::chrono::seconds(1));
+    sleep_for(std::chrono::milliseconds(11));
 
     pullData.clear();
     pullData.push_back(createSimpleEvent(2222L, 44));
 
     pullSuccess = true;
 
-    EXPECT_TRUE(puller.Pull(&dataHolder));
-    EXPECT_EQ(1, dataHolder.size());
+    EXPECT_TRUE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
+    ASSERT_EQ(1, dataHolder.size());
     EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
     EXPECT_EQ(2222L, dataHolder[0]->GetElapsedTimestampNs());
-    EXPECT_EQ(1, dataHolder[0]->size());
+    ASSERT_EQ(1, dataHolder[0]->size());
     EXPECT_EQ(44, dataHolder[0]->getValues()[0].mValue.int_value);
 }
 
@@ -120,47 +120,49 @@
     pullSuccess = true;
 
     vector<std::shared_ptr<LogEvent>> dataHolder;
-    EXPECT_TRUE(puller.Pull(&dataHolder));
-    EXPECT_EQ(1, dataHolder.size());
+    EXPECT_TRUE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
+    ASSERT_EQ(1, dataHolder.size());
     EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
     EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
-    EXPECT_EQ(1, dataHolder[0]->size());
+    ASSERT_EQ(1, dataHolder[0]->size());
     EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
 
-    sleep_for(std::chrono::seconds(1));
+    sleep_for(std::chrono::milliseconds(11));
 
     pullData.clear();
     pullData.push_back(createSimpleEvent(2222L, 44));
 
     pullSuccess = false;
     dataHolder.clear();
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
+    EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
+    ASSERT_EQ(0, dataHolder.size());
 
+    // Fails due to hitting the cool down.
     pullSuccess = true;
     dataHolder.clear();
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
+    EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
+    ASSERT_EQ(0, dataHolder.size());
 }
 
 // Test pull takes longer than timeout, 2nd pull happens shorter than cooldown
 TEST_F(StatsPullerTest, PullTakeTooLongAndPullFast) {
     pullData.push_back(createSimpleEvent(1111L, 33));
     pullSuccess = true;
-    // timeout is 0.5
-    pullDelayNs = (long)(0.8 * NS_PER_SEC);
+    // timeout is 5ms
+    pullDelayNs = MillisToNano(6);
 
     vector<std::shared_ptr<LogEvent>> dataHolder;
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
+    EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
+    ASSERT_EQ(0, dataHolder.size());
 
     pullData.clear();
     pullData.push_back(createSimpleEvent(2222L, 44));
+    pullDelayNs = 0;
 
     pullSuccess = true;
     dataHolder.clear();
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
+    EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
+    ASSERT_EQ(0, dataHolder.size());
 }
 
 TEST_F(StatsPullerTest, PullFail) {
@@ -169,19 +171,19 @@
     pullSuccess = false;
 
     vector<std::shared_ptr<LogEvent>> dataHolder;
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
+    EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
+    ASSERT_EQ(0, dataHolder.size());
 }
 
 TEST_F(StatsPullerTest, PullTakeTooLong) {
     pullData.push_back(createSimpleEvent(1111L, 33));
 
     pullSuccess = true;
-    pullDelayNs = NS_PER_SEC;
+    pullDelayNs = MillisToNano(6);
 
     vector<std::shared_ptr<LogEvent>> dataHolder;
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
+    EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
+    ASSERT_EQ(0, dataHolder.size());
 }
 
 TEST_F(StatsPullerTest, PullTooFast) {
@@ -190,11 +192,11 @@
     pullSuccess = true;
 
     vector<std::shared_ptr<LogEvent>> dataHolder;
-    EXPECT_TRUE(puller.Pull(&dataHolder));
-    EXPECT_EQ(1, dataHolder.size());
+    EXPECT_TRUE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
+    ASSERT_EQ(1, dataHolder.size());
     EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
     EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
-    EXPECT_EQ(1, dataHolder[0]->size());
+    ASSERT_EQ(1, dataHolder[0]->size());
     EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
 
     pullData.clear();
@@ -203,11 +205,11 @@
     pullSuccess = true;
 
     dataHolder.clear();
-    EXPECT_TRUE(puller.Pull(&dataHolder));
-    EXPECT_EQ(1, dataHolder.size());
+    EXPECT_TRUE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
+    ASSERT_EQ(1, dataHolder.size());
     EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
     EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
-    EXPECT_EQ(1, dataHolder[0]->size());
+    ASSERT_EQ(1, dataHolder[0]->size());
     EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
 }
 
@@ -217,16 +219,93 @@
     pullSuccess = false;
 
     vector<std::shared_ptr<LogEvent>> dataHolder;
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
+    EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
+    ASSERT_EQ(0, dataHolder.size());
 
     pullData.clear();
     pullData.push_back(createSimpleEvent(2222L, 44));
 
     pullSuccess = true;
 
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
+    EXPECT_FALSE(puller.Pull(getElapsedRealtimeNs(), &dataHolder));
+    ASSERT_EQ(0, dataHolder.size());
+}
+
+TEST_F(StatsPullerTest, PullSameEventTime) {
+    pullData.push_back(createSimpleEvent(1111L, 33));
+
+    pullSuccess = true;
+    int64_t eventTimeNs = getElapsedRealtimeNs();
+
+    vector<std::shared_ptr<LogEvent>> dataHolder;
+    EXPECT_TRUE(puller.Pull(eventTimeNs, &dataHolder));
+    ASSERT_EQ(1, dataHolder.size());
+    EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
+    EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
+    ASSERT_EQ(1, dataHolder[0]->size());
+    EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
+
+    pullData.clear();
+    pullData.push_back(createSimpleEvent(2222L, 44));
+
+    // Sleep to ensure the cool down expires.
+    sleep_for(std::chrono::milliseconds(11));
+    pullSuccess = true;
+
+    dataHolder.clear();
+    EXPECT_TRUE(puller.Pull(eventTimeNs, &dataHolder));
+    ASSERT_EQ(1, dataHolder.size());
+    EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
+    EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
+    ASSERT_EQ(1, dataHolder[0]->size());
+    EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
+}
+
+// Test pull takes longer than timeout, 2nd pull happens at same event time
+TEST_F(StatsPullerTest, PullTakeTooLongAndPullSameEventTime) {
+    pullData.push_back(createSimpleEvent(1111L, 33));
+    pullSuccess = true;
+    int64_t eventTimeNs = getElapsedRealtimeNs();
+    // timeout is 5ms
+    pullDelayNs = MillisToNano(6);
+
+    vector<std::shared_ptr<LogEvent>> dataHolder;
+    EXPECT_FALSE(puller.Pull(eventTimeNs, &dataHolder));
+    ASSERT_EQ(0, dataHolder.size());
+
+    // Sleep to ensure the cool down expires. 6ms is taken by the delay, so only 5 is needed here.
+    sleep_for(std::chrono::milliseconds(5));
+
+    pullData.clear();
+    pullData.push_back(createSimpleEvent(2222L, 44));
+    pullDelayNs = 0;
+
+    pullSuccess = true;
+    dataHolder.clear();
+    EXPECT_FALSE(puller.Pull(eventTimeNs, &dataHolder));
+    ASSERT_EQ(0, dataHolder.size());
+}
+
+TEST_F(StatsPullerTest, PullFailsAndPullSameEventTime) {
+    pullData.push_back(createSimpleEvent(1111L, 33));
+
+    pullSuccess = false;
+    int64_t eventTimeNs = getElapsedRealtimeNs();
+
+    vector<std::shared_ptr<LogEvent>> dataHolder;
+    EXPECT_FALSE(puller.Pull(eventTimeNs, &dataHolder));
+    ASSERT_EQ(0, dataHolder.size());
+
+    // Sleep to ensure the cool down expires.
+    sleep_for(std::chrono::milliseconds(11));
+
+    pullData.clear();
+    pullData.push_back(createSimpleEvent(2222L, 44));
+
+    pullSuccess = true;
+
+    EXPECT_FALSE(puller.Pull(eventTimeNs, &dataHolder));
+    ASSERT_EQ(0, dataHolder.size());
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
index 948d587..5cc10cd 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -42,7 +42,7 @@
     StatsdStatsReport report;
     bool good = report.ParseFromArray(&output[0], output.size());
     EXPECT_TRUE(good);
-    EXPECT_EQ(1, report.config_stats_size());
+    ASSERT_EQ(1, report.config_stats_size());
     const auto& configReport = report.config_stats(0);
     EXPECT_EQ(0, configReport.uid());
     EXPECT_EQ(12345, configReport.id());
@@ -69,7 +69,7 @@
     StatsdStatsReport report;
     bool good = report.ParseFromArray(&output[0], output.size());
     EXPECT_TRUE(good);
-    EXPECT_EQ(1, report.config_stats_size());
+    ASSERT_EQ(1, report.config_stats_size());
     const auto& configReport = report.config_stats(0);
     // The invalid config should be put into icebox with a deletion time.
     EXPECT_TRUE(configReport.has_deletion_time_sec());
@@ -89,7 +89,7 @@
     StatsdStatsReport report;
     bool good = report.ParseFromArray(&output[0], output.size());
     EXPECT_TRUE(good);
-    EXPECT_EQ(1, report.config_stats_size());
+    ASSERT_EQ(1, report.config_stats_size());
     const auto& configReport = report.config_stats(0);
     EXPECT_FALSE(configReport.has_deletion_time_sec());
 
@@ -97,7 +97,7 @@
     stats.dumpStats(&output, false);
     good = report.ParseFromArray(&output[0], output.size());
     EXPECT_TRUE(good);
-    EXPECT_EQ(1, report.config_stats_size());
+    ASSERT_EQ(1, report.config_stats_size());
     const auto& configReport2 = report.config_stats(0);
     EXPECT_TRUE(configReport2.has_deletion_time_sec());
 }
@@ -145,21 +145,21 @@
     StatsdStatsReport report;
     bool good = report.ParseFromArray(&output[0], output.size());
     EXPECT_TRUE(good);
-    EXPECT_EQ(1, report.config_stats_size());
+    ASSERT_EQ(1, report.config_stats_size());
     const auto& configReport = report.config_stats(0);
-    EXPECT_EQ(2, configReport.broadcast_sent_time_sec_size());
-    EXPECT_EQ(1, configReport.data_drop_time_sec_size());
-    EXPECT_EQ(1, configReport.data_drop_bytes_size());
+    ASSERT_EQ(2, configReport.broadcast_sent_time_sec_size());
+    ASSERT_EQ(1, configReport.data_drop_time_sec_size());
+    ASSERT_EQ(1, configReport.data_drop_bytes_size());
     EXPECT_EQ(123, configReport.data_drop_bytes(0));
-    EXPECT_EQ(3, configReport.dump_report_time_sec_size());
-    EXPECT_EQ(3, configReport.dump_report_data_size_size());
-    EXPECT_EQ(2, configReport.activation_time_sec_size());
-    EXPECT_EQ(1, configReport.deactivation_time_sec_size());
-    EXPECT_EQ(1, configReport.annotation_size());
+    ASSERT_EQ(3, configReport.dump_report_time_sec_size());
+    ASSERT_EQ(3, configReport.dump_report_data_size_size());
+    ASSERT_EQ(2, configReport.activation_time_sec_size());
+    ASSERT_EQ(1, configReport.deactivation_time_sec_size());
+    ASSERT_EQ(1, configReport.annotation_size());
     EXPECT_EQ(123, configReport.annotation(0).field_int64());
     EXPECT_EQ(456, configReport.annotation(0).field_int32());
 
-    EXPECT_EQ(2, configReport.matcher_stats_size());
+    ASSERT_EQ(2, configReport.matcher_stats_size());
     // matcher1 is the first in the list
     if (configReport.matcher_stats(0).id() == StringToId("matcher1")) {
         EXPECT_EQ(2, configReport.matcher_stats(0).matched_times());
@@ -174,18 +174,18 @@
         EXPECT_EQ(StringToId("matcher1"), configReport.matcher_stats(1).id());
     }
 
-    EXPECT_EQ(2, configReport.alert_stats_size());
+    ASSERT_EQ(2, configReport.alert_stats_size());
     bool alert1first = configReport.alert_stats(0).id() == StringToId("alert1");
     EXPECT_EQ(StringToId("alert1"), configReport.alert_stats(alert1first ? 0 : 1).id());
     EXPECT_EQ(2, configReport.alert_stats(alert1first ? 0 : 1).alerted_times());
     EXPECT_EQ(StringToId("alert2"), configReport.alert_stats(alert1first ? 1 : 0).id());
     EXPECT_EQ(1, configReport.alert_stats(alert1first ? 1 : 0).alerted_times());
 
-    EXPECT_EQ(1, configReport.condition_stats_size());
+    ASSERT_EQ(1, configReport.condition_stats_size());
     EXPECT_EQ(StringToId("condition1"), configReport.condition_stats(0).id());
     EXPECT_EQ(250, configReport.condition_stats(0).max_tuple_counts());
 
-    EXPECT_EQ(1, configReport.metric_stats_size());
+    ASSERT_EQ(1, configReport.metric_stats_size());
     EXPECT_EQ(StringToId("metric1"), configReport.metric_stats(0).id());
     EXPECT_EQ(202, configReport.metric_stats(0).max_tuple_counts());
 
@@ -199,21 +199,21 @@
     stats.dumpStats(&output, false);
     good = report.ParseFromArray(&output[0], output.size());
     EXPECT_TRUE(good);
-    EXPECT_EQ(1, report.config_stats_size());
+    ASSERT_EQ(1, report.config_stats_size());
     const auto& configReport2 = report.config_stats(0);
-    EXPECT_EQ(1, configReport2.matcher_stats_size());
+    ASSERT_EQ(1, configReport2.matcher_stats_size());
     EXPECT_EQ(StringToId("matcher99"), configReport2.matcher_stats(0).id());
     EXPECT_EQ(1, configReport2.matcher_stats(0).matched_times());
 
-    EXPECT_EQ(1, configReport2.condition_stats_size());
+    ASSERT_EQ(1, configReport2.condition_stats_size());
     EXPECT_EQ(StringToId("condition99"), configReport2.condition_stats(0).id());
     EXPECT_EQ(300, configReport2.condition_stats(0).max_tuple_counts());
 
-    EXPECT_EQ(1, configReport2.metric_stats_size());
+    ASSERT_EQ(1, configReport2.metric_stats_size());
     EXPECT_EQ(StringToId("metric99tion99"), configReport2.metric_stats(0).id());
     EXPECT_EQ(270, configReport2.metric_stats(0).max_tuple_counts());
 
-    EXPECT_EQ(1, configReport2.alert_stats_size());
+    ASSERT_EQ(1, configReport2.alert_stats_size());
     EXPECT_EQ(StringToId("alert99"), configReport2.alert_stats(0).id());
     EXPECT_EQ(1, configReport2.alert_stats(0).alerted_times());
 }
@@ -234,7 +234,7 @@
     bool good = report.ParseFromArray(&output[0], output.size());
     EXPECT_TRUE(good);
 
-    EXPECT_EQ(2, report.atom_stats_size());
+    ASSERT_EQ(2, report.atom_stats_size());
     bool sensorAtomGood = false;
     bool dropboxAtomGood = false;
 
@@ -267,7 +267,7 @@
     bool good = report.ParseFromArray(&output[0], output.size());
     EXPECT_TRUE(good);
 
-    EXPECT_EQ(2, report.atom_stats_size());
+    ASSERT_EQ(2, report.atom_stats_size());
     bool newAtom1Good = false;
     bool newAtom2Good = false;
 
@@ -313,7 +313,7 @@
     bool good = report.ParseFromArray(&output[0], output.size());
     EXPECT_TRUE(good);
 
-    EXPECT_EQ(1, report.pulled_atom_stats_size());
+    ASSERT_EQ(1, report.pulled_atom_stats_size());
 
     EXPECT_EQ(util::DISK_SPACE, report.pulled_atom_stats(0).atom_id());
     EXPECT_EQ(3, report.pulled_atom_stats(0).total_pull());
@@ -348,7 +348,7 @@
     bool good = report.ParseFromArray(&output[0], output.size());
     EXPECT_TRUE(good);
 
-    EXPECT_EQ(2, report.atom_metric_stats().size());
+    ASSERT_EQ(2, report.atom_metric_stats().size());
 
     auto atomStats = report.atom_metric_stats(0);
     EXPECT_EQ(1000L, atomStats.metric_id());
@@ -407,11 +407,11 @@
     const auto& configStats = stats.mConfigStats[key];
 
     size_t maxCount = StatsdStats::kMaxTimestampCount;
-    EXPECT_EQ(maxCount, configStats->broadcast_sent_time_sec.size());
-    EXPECT_EQ(maxCount, configStats->data_drop_time_sec.size());
-    EXPECT_EQ(maxCount, configStats->dump_report_stats.size());
-    EXPECT_EQ(maxCount, configStats->activation_time_sec.size());
-    EXPECT_EQ(maxCount, configStats->deactivation_time_sec.size());
+    ASSERT_EQ(maxCount, configStats->broadcast_sent_time_sec.size());
+    ASSERT_EQ(maxCount, configStats->data_drop_time_sec.size());
+    ASSERT_EQ(maxCount, configStats->dump_report_stats.size());
+    ASSERT_EQ(maxCount, configStats->activation_time_sec.size());
+    ASSERT_EQ(maxCount, configStats->deactivation_time_sec.size());
 
     // the oldest timestamp is the second timestamp in history
     EXPECT_EQ(1, configStats->broadcast_sent_time_sec.front());
@@ -441,13 +441,13 @@
     StatsdStatsReport report;
     EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
     const int maxCount = StatsdStats::kMaxSystemServerRestarts;
-    EXPECT_EQ(maxCount, (int)report.system_restart_sec_size());
+    ASSERT_EQ(maxCount, (int)report.system_restart_sec_size());
 
     stats.noteSystemServerRestart(StatsdStats::kMaxSystemServerRestarts + 1);
     output.clear();
     stats.dumpStats(&output, false);
     EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
-    EXPECT_EQ(maxCount, (int)report.system_restart_sec_size());
+    ASSERT_EQ(maxCount, (int)report.system_restart_sec_size());
     EXPECT_EQ(StatsdStats::kMaxSystemServerRestarts + 1, report.system_restart_sec(maxCount - 1));
 }
 
@@ -468,19 +468,19 @@
     StatsdStatsReport report;
     EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
 
-    EXPECT_EQ(2, report.activation_guardrail_stats_size());
+    ASSERT_EQ(2, report.activation_guardrail_stats_size());
     bool uid1Good = false;
     bool uid2Good = false;
     for (const auto& guardrailTimes : report.activation_guardrail_stats()) {
         if (uid1 == guardrailTimes.uid()) {
             uid1Good = true;
-            EXPECT_EQ(2, guardrailTimes.guardrail_met_sec_size());
+            ASSERT_EQ(2, guardrailTimes.guardrail_met_sec_size());
             EXPECT_EQ(10, guardrailTimes.guardrail_met_sec(0));
             EXPECT_EQ(20, guardrailTimes.guardrail_met_sec(1));
         } else if (uid2 == guardrailTimes.uid()) {
             int maxCount = StatsdStats::kMaxTimestampCount;
             uid2Good = true;
-            EXPECT_EQ(maxCount, guardrailTimes.guardrail_met_sec_size());
+            ASSERT_EQ(maxCount, guardrailTimes.guardrail_met_sec_size());
             for (int i = 0; i < maxCount; i++) {
                 EXPECT_EQ(100 - maxCount + i, guardrailTimes.guardrail_met_sec(i));
             }
@@ -515,13 +515,13 @@
     EXPECT_TRUE(report.ParseFromArray(&output[0], output.size()));
 
     // Check error count = numErrors for push atom
-    EXPECT_EQ(1, report.atom_stats_size());
+    ASSERT_EQ(1, report.atom_stats_size());
     const auto& pushedAtomStats = report.atom_stats(0);
     EXPECT_EQ(pushAtomTag, pushedAtomStats.tag());
     EXPECT_EQ(numErrors, pushedAtomStats.error_count());
 
     // Check error count = numErrors for pull atom
-    EXPECT_EQ(1, report.pulled_atom_stats_size());
+    ASSERT_EQ(1, report.pulled_atom_stats_size());
     const auto& pulledAtomStats = report.pulled_atom_stats(0);
     EXPECT_EQ(pullAtomTag, pulledAtomStats.atom_id());
     EXPECT_EQ(numErrors, pulledAtomStats.atom_error_count());
diff --git a/cmds/statsd/tests/indexed_priority_queue_test.cpp b/cmds/statsd/tests/indexed_priority_queue_test.cpp
index d6cd876..3a65456 100644
--- a/cmds/statsd/tests/indexed_priority_queue_test.cpp
+++ b/cmds/statsd/tests/indexed_priority_queue_test.cpp
@@ -44,23 +44,23 @@
     sp<const AATest> aa4 = new AATest{4, emptyMetricId, emptyDimensionId};
     sp<const AATest> aa8 = new AATest{8, emptyMetricId, emptyDimensionId};
 
-    EXPECT_EQ(0u, ipq.size());
+    ASSERT_EQ(0u, ipq.size());
     EXPECT_TRUE(ipq.empty());
 
     ipq.push(aa4);
-    EXPECT_EQ(1u, ipq.size());
+    ASSERT_EQ(1u, ipq.size());
     EXPECT_FALSE(ipq.empty());
 
     ipq.push(aa8);
-    EXPECT_EQ(2u, ipq.size());
+    ASSERT_EQ(2u, ipq.size());
     EXPECT_FALSE(ipq.empty());
 
     ipq.remove(aa4);
-    EXPECT_EQ(1u, ipq.size());
+    ASSERT_EQ(1u, ipq.size());
     EXPECT_FALSE(ipq.empty());
 
     ipq.remove(aa8);
-    EXPECT_EQ(0u, ipq.size());
+    ASSERT_EQ(0u, ipq.size());
     EXPECT_TRUE(ipq.empty());
 }
 
@@ -126,17 +126,17 @@
     sp<const AATest> aa4_b = new AATest{4, emptyMetricId, emptyDimensionId};
 
     ipq.push(aa4_a);
-    EXPECT_EQ(1u, ipq.size());
+    ASSERT_EQ(1u, ipq.size());
     EXPECT_TRUE(ipq.contains(aa4_a));
     EXPECT_FALSE(ipq.contains(aa4_b));
 
     ipq.push(aa4_a);
-    EXPECT_EQ(1u, ipq.size());
+    ASSERT_EQ(1u, ipq.size());
     EXPECT_TRUE(ipq.contains(aa4_a));
     EXPECT_FALSE(ipq.contains(aa4_b));
 
     ipq.push(aa4_b);
-    EXPECT_EQ(2u, ipq.size());
+    ASSERT_EQ(2u, ipq.size());
     EXPECT_TRUE(ipq.contains(aa4_a));
     EXPECT_TRUE(ipq.contains(aa4_b));
 }
@@ -150,7 +150,7 @@
 
     ipq.push(aa4);
     ipq.remove(aa5);
-    EXPECT_EQ(1u, ipq.size());
+    ASSERT_EQ(1u, ipq.size());
     EXPECT_TRUE(ipq.contains(aa4));
     EXPECT_FALSE(ipq.contains(aa5));
 }
@@ -164,17 +164,17 @@
 
     ipq.push(aa4_a);
     ipq.push(aa4_b);
-    EXPECT_EQ(2u, ipq.size());
+    ASSERT_EQ(2u, ipq.size());
     EXPECT_TRUE(ipq.contains(aa4_a));
     EXPECT_TRUE(ipq.contains(aa4_b));
 
     ipq.remove(aa4_b);
-    EXPECT_EQ(1u, ipq.size());
+    ASSERT_EQ(1u, ipq.size());
     EXPECT_TRUE(ipq.contains(aa4_a));
     EXPECT_FALSE(ipq.contains(aa4_b));
 
     ipq.remove(aa4_a);
-    EXPECT_EQ(0u, ipq.size());
+    ASSERT_EQ(0u, ipq.size());
     EXPECT_FALSE(ipq.contains(aa4_a));
     EXPECT_FALSE(ipq.contains(aa4_b));
 }
@@ -205,22 +205,22 @@
     ipq.push(c);
     ipq.push(b);
     ipq.push(a);
-    EXPECT_EQ(3u, ipq.size());
+    ASSERT_EQ(3u, ipq.size());
 
     ipq.pop();
-    EXPECT_EQ(2u, ipq.size());
+    ASSERT_EQ(2u, ipq.size());
     EXPECT_FALSE(ipq.contains(a));
     EXPECT_TRUE(ipq.contains(b));
     EXPECT_TRUE(ipq.contains(c));
 
     ipq.pop();
-    EXPECT_EQ(1u, ipq.size());
+    ASSERT_EQ(1u, ipq.size());
     EXPECT_FALSE(ipq.contains(a));
     EXPECT_FALSE(ipq.contains(b));
     EXPECT_TRUE(ipq.contains(c));
 
     ipq.pop();
-    EXPECT_EQ(0u, ipq.size());
+    ASSERT_EQ(0u, ipq.size());
     EXPECT_FALSE(ipq.contains(a));
     EXPECT_FALSE(ipq.contains(b));
     EXPECT_FALSE(ipq.contains(c));
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index 8131725..74ecaac 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -108,15 +108,15 @@
 
     // Flushes at event #2.
     countProducer.flushIfNeededLocked(bucketStartTimeNs + 2);
-    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+    ASSERT_EQ(0UL, countProducer.mPastBuckets.size());
 
     // Flushes.
     countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
+    ASSERT_EQ(1UL, countProducer.mPastBuckets.size());
     EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
                 countProducer.mPastBuckets.end());
     const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(1UL, buckets.size());
+    ASSERT_EQ(1UL, buckets.size());
     EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
     EXPECT_EQ(2LL, buckets[0].mCount);
@@ -128,10 +128,10 @@
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
 
     countProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
+    ASSERT_EQ(1UL, countProducer.mPastBuckets.size());
     EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
                 countProducer.mPastBuckets.end());
-    EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     const auto& bucketInfo2 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1];
     EXPECT_EQ(bucket2StartTimeNs, bucketInfo2.mBucketStartNs);
     EXPECT_EQ(bucket2StartTimeNs + bucketSizeNs, bucketInfo2.mBucketEndNs);
@@ -139,11 +139,11 @@
 
     // nothing happens in bucket 3. we should not record anything for bucket 3.
     countProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
+    ASSERT_EQ(1UL, countProducer.mPastBuckets.size());
     EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
                 countProducer.mPastBuckets.end());
     const auto& buckets3 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(2UL, buckets3.size());
+    ASSERT_EQ(2UL, buckets3.size());
 }
 
 TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) {
@@ -166,7 +166,7 @@
     makeLogEvent(&event1, bucketStartTimeNs + 1, /*atomId=*/1);
     countProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
 
-    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+    ASSERT_EQ(0UL, countProducer.mPastBuckets.size());
 
     countProducer.onConditionChanged(false /*new condition*/, bucketStartTimeNs + 2);
 
@@ -174,15 +174,15 @@
     LogEvent event2(/*uid=*/0, /*pid=*/0);
     makeLogEvent(&event2, bucketStartTimeNs + 10, /*atomId=*/1);
     countProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
-    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+    ASSERT_EQ(0UL, countProducer.mPastBuckets.size());
 
     countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
+    ASSERT_EQ(1UL, countProducer.mPastBuckets.size());
     EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
                 countProducer.mPastBuckets.end());
 
     const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(1UL, buckets.size());
+    ASSERT_EQ(1UL, buckets.size());
     const auto& bucketInfo = buckets[0];
     EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
@@ -229,15 +229,15 @@
 
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
     countProducer.flushIfNeededLocked(bucketStartTimeNs + 1);
-    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+    ASSERT_EQ(0UL, countProducer.mPastBuckets.size());
 
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
     countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
+    ASSERT_EQ(1UL, countProducer.mPastBuckets.size());
     EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
                 countProducer.mPastBuckets.end());
     const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(1UL, buckets.size());
+    ASSERT_EQ(1UL, buckets.size());
     const auto& bucketInfo = buckets[0];
     EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
@@ -271,7 +271,7 @@
     LogEvent event1(/*uid=*/0, /*pid=*/0);
     makeLogEvent(&event1, bucketStartTimeNs + 1, tagId, /*uid=*/"111");
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
-    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+    ASSERT_EQ(0UL, countProducer.mPastBuckets.size());
     EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
 
     // App upgrade or boot complete forces bucket flush.
@@ -284,7 +284,7 @@
             countProducer.onStatsdInitCompleted(eventTimeNs);
             break;
     }
-    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(bucketStartTimeNs,
               countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
     EXPECT_EQ(eventTimeNs,
@@ -299,7 +299,7 @@
     LogEvent event2(/*uid=*/0, /*pid=*/0);
     makeLogEvent(&event2, bucketStartTimeNs + 59 * NS_PER_SEC + 10, tagId, /*uid=*/"222");
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(eventTimeNs, countProducer.mCurrentBucketStartTimeNs);
     EXPECT_EQ(0, countProducer.getCurrentBucketNum());
     EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
@@ -308,7 +308,7 @@
     LogEvent event3(/*uid=*/0, /*pid=*/0);
     makeLogEvent(&event3, bucketStartTimeNs + 62 * NS_PER_SEC + 10, tagId, /*uid=*/"333");
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
-    EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(lastEndTimeNs, countProducer.mCurrentBucketStartTimeNs);
     EXPECT_EQ(1, countProducer.getCurrentBucketNum());
     EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
@@ -334,7 +334,7 @@
     LogEvent event1(/*uid=*/0, /*pid=*/0);
     makeLogEvent(&event1, bucketStartTimeNs + 1, tagId, /*uid=*/"111");
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
-    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+    ASSERT_EQ(0UL, countProducer.mPastBuckets.size());
 
     // App upgrade or boot complete forces bucket flush.
     // Check that there's a past bucket and the bucket end is not adjusted since the upgrade
@@ -347,7 +347,7 @@
             countProducer.onStatsdInitCompleted(eventTimeNs);
             break;
     }
-    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(bucketStartTimeNs,
               countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
@@ -358,13 +358,13 @@
     LogEvent event2(/*uid=*/0, /*pid=*/0);
     makeLogEvent(&event2, bucketStartTimeNs + 70 * NS_PER_SEC + 10, tagId, /*uid=*/"222");
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
 
     // Third event in following bucket.
     LogEvent event3(/*uid=*/0, /*pid=*/0);
     makeLogEvent(&event3, bucketStartTimeNs + 121 * NS_PER_SEC + 10, tagId, /*uid=*/"333");
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
-    EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ((int64_t)eventTimeNs,
               countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketStartNs);
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
@@ -416,13 +416,13 @@
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
 
-    EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
+    ASSERT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
     EXPECT_EQ(2L, countProducer.mCurrentSlicedCounter->begin()->second);
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
 
     // One event in bucket #2. No alarm as bucket #0 is trashed out.
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
-    EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
+    ASSERT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
     EXPECT_EQ(1L, countProducer.mCurrentSlicedCounter->begin()->second);
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
 
@@ -430,14 +430,14 @@
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event5);
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event6);
-    EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
+    ASSERT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
     EXPECT_EQ(3L, countProducer.mCurrentSlicedCounter->begin()->second);
     // Anomaly at event 6 is within refractory period. The alarm is at event 5 timestamp not event 6
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
               std::ceil(1.0 * event5.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
 
     countProducer.onMatchedLogEvent(1 /*log matcher index*/, event7);
-    EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
+    ASSERT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
     EXPECT_EQ(4L, countProducer.mCurrentSlicedCounter->begin()->second);
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
               std::ceil(1.0 * event7.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
diff --git a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
index 8ef2519..ddda71d 100644
--- a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
@@ -104,11 +104,11 @@
     durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
     durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
     durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
-    EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
+    ASSERT_EQ(1UL, durationProducer.mPastBuckets.size());
     EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
                 durationProducer.mPastBuckets.end());
     const auto& buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(2UL, buckets.size());
+    ASSERT_EQ(2UL, buckets.size());
     EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
     EXPECT_EQ(bucketSizeNs - 1LL, buckets[0].mDuration);
@@ -150,17 +150,17 @@
     durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
     durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
     durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+    ASSERT_EQ(0UL, durationProducer.mPastBuckets.size());
 
     durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
     durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
     durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
     durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
-    EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
+    ASSERT_EQ(1UL, durationProducer.mPastBuckets.size());
     EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
                 durationProducer.mPastBuckets.end());
     const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(1UL, buckets2.size());
+    ASSERT_EQ(1UL, buckets2.size());
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
     EXPECT_EQ(1LL, buckets2[0].mDuration);
@@ -198,15 +198,15 @@
     durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
     durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
     durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+    ASSERT_EQ(0UL, durationProducer.mPastBuckets.size());
 
     durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
     durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
     durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
     durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
-    EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
+    ASSERT_EQ(1UL, durationProducer.mPastBuckets.size());
     const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(1UL, buckets2.size());
+    ASSERT_EQ(1UL, buckets2.size());
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
     EXPECT_EQ(1LL, buckets2[0].mDuration);
@@ -241,7 +241,7 @@
     LogEvent event1(/*uid=*/0, /*pid=*/0);
     makeLogEvent(&event1, startTimeNs, tagId);
     durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+    ASSERT_EQ(0UL, durationProducer.mPastBuckets.size());
     EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
 
     int64_t partialBucketSplitTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
@@ -253,7 +253,7 @@
             durationProducer.onStatsdInitCompleted(partialBucketSplitTimeNs);
             break;
     }
-    EXPECT_EQ(1UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(1UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     std::vector<DurationBucket> buckets =
             durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
     EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
@@ -268,7 +268,7 @@
     makeLogEvent(&event2, endTimeNs, tagId);
     durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
     buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(3UL, buckets.size());
+    ASSERT_EQ(3UL, buckets.size());
     EXPECT_EQ(partialBucketSplitTimeNs, buckets[1].mBucketStartNs);
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketEndNs);
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - partialBucketSplitTimeNs, buckets[1].mDuration);
@@ -303,7 +303,7 @@
     LogEvent event1(/*uid=*/0, /*pid=*/0);
     makeLogEvent(&event1, startTimeNs, tagId);
     durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+    ASSERT_EQ(0UL, durationProducer.mPastBuckets.size());
     EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
 
     int64_t partialBucketSplitTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
@@ -315,7 +315,7 @@
             durationProducer.onStatsdInitCompleted(partialBucketSplitTimeNs);
             break;
     }
-    EXPECT_EQ(2UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(2UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     std::vector<DurationBucket> buckets =
             durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
     EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
@@ -333,7 +333,7 @@
     makeLogEvent(&event2, endTimeNs, tagId);
     durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
     buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(3UL, buckets.size());
+    ASSERT_EQ(3UL, buckets.size());
     EXPECT_EQ(partialBucketSplitTimeNs, buckets[2].mBucketStartNs);
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs - partialBucketSplitTimeNs,
@@ -411,7 +411,7 @@
     LogEvent event1(/*uid=*/0, /*pid=*/0);
     makeLogEvent(&event1, startTimeNs, tagId);
     durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+    ASSERT_EQ(0UL, durationProducer.mPastBuckets.size());
     EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
 
     int64_t partialBucketSplitTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
@@ -423,7 +423,7 @@
             durationProducer.onStatsdInitCompleted(partialBucketSplitTimeNs);
             break;
     }
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(partialBucketSplitTimeNs, durationProducer.mCurrentBucketStartTimeNs);
     EXPECT_EQ(0, durationProducer.getCurrentBucketNum());
 
@@ -432,12 +432,12 @@
     LogEvent event2(/*uid=*/0, /*pid=*/0);
     makeLogEvent(&event2, endTimeNs, tagId);
     durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
 
     durationProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
     std::vector<DurationBucket> buckets =
             durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(1UL, buckets.size());
+    ASSERT_EQ(1UL, buckets.size());
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketStartNs);
     EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, buckets[0].mBucketEndNs);
     EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
@@ -464,7 +464,7 @@
     LogEvent event1(/*uid=*/0, /*pid=*/0);
     makeLogEvent(&event1, startTimeNs, tagId);
     durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+    ASSERT_EQ(0UL, durationProducer.mPastBuckets.size());
     EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
 
     int64_t partialBucketSplitTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
@@ -476,7 +476,7 @@
             durationProducer.onStatsdInitCompleted(partialBucketSplitTimeNs);
             break;
     }
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(partialBucketSplitTimeNs, durationProducer.mCurrentBucketStartTimeNs);
     EXPECT_EQ(1, durationProducer.getCurrentBucketNum());
 
@@ -485,13 +485,13 @@
     LogEvent event2(/*uid=*/0, /*pid=*/0);
     makeLogEvent(&event2, endTimeNs, tagId);
     durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(partialBucketSplitTimeNs, durationProducer.mCurrentBucketStartTimeNs);
 
     durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
     std::vector<DurationBucket> buckets =
             durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(1UL, buckets.size());
+    ASSERT_EQ(1UL, buckets.size());
     EXPECT_EQ(partialBucketSplitTimeNs, buckets[0].mBucketStartNs);
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketEndNs);
     EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
diff --git a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
index 97647a7..5bae364 100644
--- a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
@@ -79,7 +79,7 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_event_metrics());
-    EXPECT_EQ(2, report.event_metrics().data_size());
+    ASSERT_EQ(2, report.event_metrics().data_size());
     EXPECT_EQ(bucketStartTimeNs + 1, report.event_metrics().data(0).elapsed_timestamp_nanos());
     EXPECT_EQ(bucketStartTimeNs + 2, report.event_metrics().data(1).elapsed_timestamp_nanos());
 }
@@ -118,7 +118,7 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_event_metrics());
-    EXPECT_EQ(1, report.event_metrics().data_size());
+    ASSERT_EQ(1, report.event_metrics().data_size());
     EXPECT_EQ(bucketStartTimeNs + 1, report.event_metrics().data(0).elapsed_timestamp_nanos());
 }
 
@@ -168,7 +168,7 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_event_metrics());
-    EXPECT_EQ(1, report.event_metrics().data_size());
+    ASSERT_EQ(1, report.event_metrics().data_size());
     EXPECT_EQ(bucketStartTimeNs + 10, report.event_metrics().data(0).elapsed_timestamp_nanos());
 }
 
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 9d2ec88..cc5f459 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -138,11 +138,12 @@
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
                 data->clear();
-                data->push_back(makeLogEvent(tagId, bucketStartTimeNs + 10, 3, "some value", 11));
+                data->push_back(makeLogEvent(tagId, eventTimeNs + 10, 3, "some value", 11));
                 return true;
             }));
 
@@ -156,13 +157,13 @@
     allData.push_back(makeLogEvent(tagId, bucket2StartTimeNs + 1, 10, "some value", 11));
 
     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
     EXPECT_EQ(INT, it->mValue.getType());
     EXPECT_EQ(10, it->mValue.int_value);
     it++;
     EXPECT_EQ(11, it->mValue.int_value);
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+    ASSERT_EQ(1UL, gaugeProducer.mPastBuckets.size());
     EXPECT_EQ(3, gaugeProducer.mPastBuckets.begin()
                          ->second.back()
                          .mGaugeAtoms.front()
@@ -172,7 +173,7 @@
     allData.clear();
     allData.push_back(makeLogEvent(tagId, bucket3StartTimeNs + 10, 24, "some value", 25));
     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
     EXPECT_EQ(INT, it->mValue.getType());
     EXPECT_EQ(24, it->mValue.int_value);
@@ -180,8 +181,8 @@
     EXPECT_EQ(INT, it->mValue.getType());
     EXPECT_EQ(25, it->mValue.int_value);
     // One dimension.
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
+    ASSERT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+    ASSERT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
     it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
     EXPECT_EQ(INT, it->mValue.getType());
     EXPECT_EQ(10L, it->mValue.int_value);
@@ -190,10 +191,10 @@
     EXPECT_EQ(11L, it->mValue.int_value);
 
     gaugeProducer.flushIfNeededLocked(bucket4StartTimeNs);
-    EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
     // One dimension.
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-    EXPECT_EQ(3UL, gaugeProducer.mPastBuckets.begin()->second.size());
+    ASSERT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+    ASSERT_EQ(3UL, gaugeProducer.mPastBuckets.begin()->second.size());
     it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
     EXPECT_EQ(INT, it->mValue.getType());
     EXPECT_EQ(24L, it->mValue.int_value);
@@ -247,7 +248,7 @@
             break;
     }
     EXPECT_EQ(0UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(bucketStartTimeNs,
               gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
     EXPECT_EQ(partialBucketSplitTimeNs,
@@ -262,7 +263,7 @@
     CreateTwoValueLogEvent(&event2, tagId, bucketStartTimeNs + 59 * NS_PER_SEC, 1, 10);
     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
     EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(bucketStartTimeNs,
               gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
     EXPECT_EQ(partialBucketSplitTimeNs,
@@ -277,7 +278,7 @@
     CreateTwoValueLogEvent(&event3, tagId, bucketStartTimeNs + 65 * NS_PER_SEC, 1, 10);
     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
     EXPECT_EQ(1L, gaugeProducer.mCurrentBucketNum);
-    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ((int64_t)bucketStartTimeNs + bucketSizeNs, gaugeProducer.mCurrentBucketStartTimeNs);
     EXPECT_EQ(1, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
 
@@ -286,7 +287,7 @@
     CreateTwoValueLogEvent(&event4, tagId, bucketStartTimeNs + 125 * NS_PER_SEC, 1, 10);
     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
     EXPECT_EQ(2L, gaugeProducer.mCurrentBucketNum);
-    EXPECT_EQ(3UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(3UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
 }
 
@@ -311,15 +312,15 @@
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             .WillOnce(Return(false))
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(
-                                CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 2));
-                        return true;
-                    }));
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 2));
+                return true;
+            }));
 
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
@@ -329,7 +330,7 @@
     vector<shared_ptr<LogEvent>> allData;
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
                          ->second.front()
                          .mFields->begin()
@@ -343,14 +344,14 @@
             gaugeProducer.onStatsdInitCompleted(partialBucketSplitTimeNs);
             break;
     }
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(bucketStartTimeNs,
               gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
     EXPECT_EQ(partialBucketSplitTimeNs,
               gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
     EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
     EXPECT_EQ(partialBucketSplitTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(2, gaugeProducer.mCurrentSlicedBucket->begin()
                          ->second.front()
                          .mFields->begin()
@@ -359,8 +360,8 @@
     allData.clear();
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + bucketSizeNs + 1, 3));
     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
-    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin()
                          ->second.front()
                          .mFields->begin()
@@ -389,7 +390,8 @@
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(false));
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+            .WillOnce(Return(false));
 
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
                                       logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
@@ -399,17 +401,17 @@
     vector<shared_ptr<LogEvent>> allData;
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
                          ->second.front()
                          .mFields->begin()
                          ->mValue.int_value);
 
     gaugeProducer.notifyAppUpgrade(partialBucketSplitTimeNs);
-    EXPECT_EQ(0UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(0UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
     EXPECT_EQ(bucketStartTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
                          ->second.front()
                          .mFields->begin()
@@ -435,14 +437,16 @@
             new EventMatcherWizard({new SimpleLogMatchingTracker(
                     atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
 
+    int64_t conditionChangeNs = bucketStartTimeNs + 8;
+
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, conditionChangeNs, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
                 data->clear();
-                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 100));
+                data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs + 10, 100));
                 return true;
             }));
 
@@ -451,25 +455,25 @@
                                       bucketStartTimeNs, pullerManager);
     gaugeProducer.prepareFirstBucket();
 
-    gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    gaugeProducer.onConditionChanged(true, conditionChangeNs);
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(100, gaugeProducer.mCurrentSlicedBucket->begin()
                            ->second.front()
                            .mFields->begin()
                            ->mValue.int_value);
-    EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
+    ASSERT_EQ(0UL, gaugeProducer.mPastBuckets.size());
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 110));
     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
 
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(110, gaugeProducer.mCurrentSlicedBucket->begin()
                            ->second.front()
                            .mFields->begin()
                            ->mValue.int_value);
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+    ASSERT_EQ(1UL, gaugeProducer.mPastBuckets.size());
     EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()
                            ->second.back()
                            .mGaugeAtoms.front()
@@ -478,8 +482,8 @@
 
     gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10);
     gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10);
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
+    ASSERT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+    ASSERT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
     EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()
                             ->second.back()
                             .mGaugeAtoms.front()
@@ -519,14 +523,16 @@
                         return ConditionState::kTrue;
                     }));
 
+    int64_t sliceConditionChangeNs = bucketStartTimeNs + 8;
+
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, sliceConditionChangeNs, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
                 data->clear();
-                data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 10, 1000, 100));
+                data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs + 10, 1000, 100));
                 return true;
             }));
 
@@ -535,22 +541,22 @@
                                       bucketStartTimeNs, pullerManager);
     gaugeProducer.prepareFirstBucket();
 
-    gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
+    gaugeProducer.onSlicedConditionMayChange(true, sliceConditionChangeNs);
 
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     const auto& key = gaugeProducer.mCurrentSlicedBucket->begin()->first;
-    EXPECT_EQ(1UL, key.getDimensionKeyInWhat().getValues().size());
+    ASSERT_EQ(1UL, key.getDimensionKeyInWhat().getValues().size());
     EXPECT_EQ(1000, key.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
 
-    EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
+    ASSERT_EQ(0UL, gaugeProducer.mPastBuckets.size());
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
     allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1000, 110));
     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
 
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(1UL, gaugeProducer.mPastBuckets.size());
 }
 
 TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
@@ -560,7 +566,8 @@
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(false));
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+            .WillOnce(Return(false));
 
     GaugeMetric metric;
     metric.set_id(metricId);
@@ -596,7 +603,7 @@
     allData.clear();
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 13));
     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin()
                            ->second.front()
                            .mFields->begin()
@@ -609,7 +616,7 @@
     allData.clear();
     allData.push_back(event2);
     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin()
                            ->second.front()
                            .mFields->begin()
@@ -621,7 +628,7 @@
     allData.push_back(
             CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10, 26));
     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 2 * bucketSizeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(26L, gaugeProducer.mCurrentSlicedBucket->begin()
                            ->second.front()
                            .mFields->begin()
@@ -633,7 +640,7 @@
     allData.clear();
     allData.push_back(CreateNoValuesLogEvent(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10));
     gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 3 * bucketSizeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty());
 }
 
@@ -658,17 +665,19 @@
                     atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
                 data->clear();
-                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 4));
+                data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 4));
                 return true;
             }))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20);
                 data->clear();
-                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20, 5));
+                data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 5));
                 return true;
             }))
             .WillOnce(Return(true));
@@ -679,20 +688,20 @@
                                       tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
     gaugeProducer.prepareFirstBucket();
 
-    EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
 
     LogEvent triggerEvent(/*uid=*/0, /*pid=*/0);
     CreateNoValuesLogEvent(&triggerEvent, triggerId, bucketStartTimeNs + 10);
     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
     triggerEvent.setElapsedTimestampNs(bucketStartTimeNs + 20);
     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent);
-    EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+    ASSERT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
     triggerEvent.setElapsedTimestampNs(bucket2StartTimeNs + 1);
     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent);
 
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.size());
+    ASSERT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+    ASSERT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.size());
     EXPECT_EQ(4, gaugeProducer.mPastBuckets.begin()
                          ->second.back()
                          .mGaugeAtoms[0]
@@ -727,23 +736,26 @@
                     atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 3, 3, 4));
-                        return true;
-                    }))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3);
                 data->clear();
-                data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 10, 4, 5));
+                data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs, 3, 4));
                 return true;
             }))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
                 data->clear();
-                data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 20, 4, 6));
+                data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs, 4, 5));
+                return true;
+            }))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20);
+                data->clear();
+                data->push_back(CreateTwoValueLogEvent(tagId, eventTimeNs, 4, 6));
                 return true;
             }))
             .WillOnce(Return(true));
@@ -757,24 +769,24 @@
     LogEvent triggerEvent(/*uid=*/0, /*pid=*/0);
     CreateNoValuesLogEvent(&triggerEvent, triggerId, bucketStartTimeNs + 3);
     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     triggerEvent.setElapsedTimestampNs(bucketStartTimeNs + 10);
     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent);
-    EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+    ASSERT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->size());
+    ASSERT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
     triggerEvent.setElapsedTimestampNs(bucketStartTimeNs + 20);
     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent);
-    EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+    ASSERT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
     triggerEvent.setElapsedTimestampNs(bucket2StartTimeNs + 1);
     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, triggerEvent);
 
-    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.size());
+    ASSERT_EQ(2UL, gaugeProducer.mPastBuckets.size());
     auto bucketIt = gaugeProducer.mPastBuckets.begin();
-    EXPECT_EQ(1UL, bucketIt->second.back().mGaugeAtoms.size());
+    ASSERT_EQ(1UL, bucketIt->second.back().mGaugeAtoms.size());
     EXPECT_EQ(3, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value);
     EXPECT_EQ(4, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value);
     bucketIt++;
-    EXPECT_EQ(2UL, bucketIt->second.back().mGaugeAtoms.size());
+    ASSERT_EQ(2UL, bucketIt->second.back().mGaugeAtoms.size());
     EXPECT_EQ(4, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value);
     EXPECT_EQ(5, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value);
     EXPECT_EQ(6, bucketIt->second.back().mGaugeAtoms[1].mFields->begin()->mValue.int_value);
@@ -801,14 +813,14 @@
                     atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 3, _, _))
             // Bucket start.
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 10));
-                        return true;
-                    }));
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, eventTimeNs, 10));
+                return true;
+            }));
 
     int triggerId = 5;
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
@@ -828,14 +840,14 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_gauge_metrics());
-    EXPECT_EQ(0, report.gauge_metrics().data_size());
-    EXPECT_EQ(1, report.gauge_metrics().skipped_size());
+    ASSERT_EQ(0, report.gauge_metrics().data_size());
+    ASSERT_EQ(1, report.gauge_metrics().skipped_size());
 
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
               report.gauge_metrics().skipped(0).start_bucket_elapsed_millis());
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000),
               report.gauge_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.gauge_metrics().skipped(0).drop_event_size());
+    ASSERT_EQ(1, report.gauge_metrics().skipped(0).drop_event_size());
 
     auto dropEvent = report.gauge_metrics().skipped(0).drop_event(0);
     EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason());
diff --git a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
index d2f0f57..fda3daa 100644
--- a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
@@ -77,7 +77,7 @@
 
     tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
     EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
-    EXPECT_EQ(1u, buckets[eventKey].size());
+    ASSERT_EQ(1u, buckets[eventKey].size());
     EXPECT_EQ(20LL, buckets[eventKey][0].mDuration);
 }
 
@@ -110,7 +110,7 @@
 
     tracker.flushIfNeeded(bucketStartTimeNs + 3 * bucketSizeNs + 40, &buckets);
     EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
-    EXPECT_EQ(1u, buckets[eventKey].size());
+    ASSERT_EQ(1u, buckets[eventKey].size());
     EXPECT_EQ(bucketSizeNs + 40 - 1, buckets[eventKey][0].mDuration);
     EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[eventKey][0].mBucketStartNs);
     EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[eventKey][0].mBucketEndNs);
@@ -149,7 +149,7 @@
     EXPECT_TRUE(buckets.find(eventKey) == buckets.end());
 
     tracker.flushIfNeeded(bucketStartTimeNs + 4 * bucketSizeNs, &buckets);
-    EXPECT_EQ(1u, buckets[eventKey].size());
+    ASSERT_EQ(1u, buckets[eventKey].size());
     EXPECT_EQ((3 * bucketSizeNs) + 20 - 1, buckets[eventKey][0].mDuration);
     EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, buckets[eventKey][0].mBucketStartNs);
     EXPECT_EQ(bucketStartTimeNs + 4 * bucketSizeNs, buckets[eventKey][0].mBucketEndNs);
@@ -187,7 +187,7 @@
                      bucketStartTimeNs + (2 * bucketSizeNs) + 5, false);
     tracker.flushIfNeeded(bucketStartTimeNs + (3 * bucketSizeNs) + 1, &buckets);
 
-    EXPECT_EQ(1u, buckets[eventKey].size());
+    ASSERT_EQ(1u, buckets[eventKey].size());
     EXPECT_EQ(2 * bucketSizeNs + 5 - 1, buckets[eventKey][0].mDuration);
 }
 
@@ -223,15 +223,15 @@
     tracker.noteConditionChanged(key1, false, conditionStops1);
     unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
     tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
-    EXPECT_EQ(0U, buckets.size());
+    ASSERT_EQ(0U, buckets.size());
 
     tracker.noteConditionChanged(key1, true, conditionStarts2);
     tracker.noteConditionChanged(key1, false, conditionStops2);
     tracker.noteStop(key1, eventStopTimeNs, false);
     tracker.flushIfNeeded(bucketStartTimeNs + 2 * bucketSizeNs + 1, &buckets);
-    EXPECT_EQ(1U, buckets.size());
+    ASSERT_EQ(1U, buckets.size());
     vector<DurationBucket> item = buckets.begin()->second;
-    EXPECT_EQ(1UL, item.size());
+    ASSERT_EQ(1UL, item.size());
     EXPECT_EQ((int64_t)(13LL * NS_PER_SEC), item[0].mDuration);
 }
 
@@ -272,11 +272,11 @@
 
     // Remove the anomaly alarm when the duration is no longer fully met.
     tracker.noteConditionChanged(key1, false, eventStartTimeNs + 15 * NS_PER_SEC);
-    EXPECT_EQ(0U, anomalyTracker->mAlarms.size());
+    ASSERT_EQ(0U, anomalyTracker->mAlarms.size());
 
     // Since the condition was off for 10 seconds, the anomaly should trigger 10 sec later.
     tracker.noteConditionChanged(key1, true, eventStartTimeNs + 25 * NS_PER_SEC);
-    EXPECT_EQ(1U, anomalyTracker->mAlarms.size());
+    ASSERT_EQ(1U, anomalyTracker->mAlarms.size());
     alarm = anomalyTracker->mAlarms.begin()->second;
     EXPECT_EQ((long long)(63ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
 }
@@ -330,7 +330,7 @@
     tracker.noteConditionChanged(key1, false, conditionStops1);
     tracker.noteStart(key2, true, eventStartTimeNs2, conditionKey2);  // Condition is on already.
     tracker.noteConditionChanged(key1, true, conditionStarts2);
-    EXPECT_EQ(1U, anomalyTracker->mAlarms.size());
+    ASSERT_EQ(1U, anomalyTracker->mAlarms.size());
     auto alarm = anomalyTracker->mAlarms.begin()->second;
     int64_t anomalyFireTimeSec = alarm->timestampSec;
     EXPECT_EQ(conditionStarts2 + 36 * NS_PER_SEC,
@@ -341,7 +341,7 @@
     // gets correctly taken into account in future predictAnomalyTimestampNs calculations.
     std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> firedAlarms({alarm});
     anomalyTracker->informAlarmsFired(anomalyFireTimeSec * NS_PER_SEC, firedAlarms);
-    EXPECT_EQ(0u, anomalyTracker->mAlarms.size());
+    ASSERT_EQ(0u, anomalyTracker->mAlarms.size());
     int64_t refractoryPeriodEndsSec = anomalyFireTimeSec + refPeriodSec;
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), refractoryPeriodEndsSec);
 
@@ -352,7 +352,7 @@
     tracker.noteStop(key2, eventStopTimeNs, false);
     tracker.noteStart(key1, true, eventStopTimeNs + 1000000, conditionKey1);
     // Anomaly is ongoing, but we're still in the refractory period.
-    EXPECT_EQ(1U, anomalyTracker->mAlarms.size());
+    ASSERT_EQ(1U, anomalyTracker->mAlarms.size());
     alarm = anomalyTracker->mAlarms.begin()->second;
     EXPECT_EQ(refractoryPeriodEndsSec, (long long)(alarm->timestampSec));
 
@@ -410,7 +410,7 @@
     tracker.noteStart(key1, true, eventStartTimeNs1, conditionKey1);
     tracker.noteStart(key2, true, eventStartTimeNs2, conditionKey2);
     tracker.noteStop(key1, eventStopTimeNs1, false);
-    EXPECT_EQ(1U, anomalyTracker->mAlarms.size());
+    ASSERT_EQ(1U, anomalyTracker->mAlarms.size());
     auto alarm = anomalyTracker->mAlarms.begin()->second;
     EXPECT_EQ(eventStopTimeNs1 + 35 * NS_PER_SEC,
               (unsigned long long)(alarm->timestampSec * NS_PER_SEC));
diff --git a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
index 39d3919..1d6f7de 100644
--- a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
@@ -74,7 +74,7 @@
     tracker.flushIfNeeded(eventStartTimeNs + bucketSizeNs + 1, &buckets);
     EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
 
-    EXPECT_EQ(1u, buckets[eventKey].size());
+    ASSERT_EQ(1u, buckets[eventKey].size());
     EXPECT_EQ(durationTimeNs, buckets[eventKey][0].mDuration);
 }
 
@@ -103,7 +103,7 @@
 
     tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
     EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
-    EXPECT_EQ(1u, buckets[eventKey].size());
+    ASSERT_EQ(1u, buckets[eventKey].size());
     EXPECT_EQ(2003LL, buckets[eventKey][0].mDuration);
 }
 
@@ -133,7 +133,7 @@
 
     tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
     EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
-    EXPECT_EQ(1u, buckets[eventKey].size());
+    ASSERT_EQ(1u, buckets[eventKey].size());
     EXPECT_EQ(2003LL, buckets[eventKey][0].mDuration);
 }
 
@@ -161,7 +161,7 @@
     tracker.noteStart(kEventKey1, true, eventStartTimeNs + 2 * bucketSizeNs, ConditionKey());
     EXPECT_EQ((long long)(bucketStartTimeNs + 2 * bucketSizeNs), tracker.mLastStartTime);
 
-    EXPECT_EQ(2u, buckets[eventKey].size());
+    ASSERT_EQ(2u, buckets[eventKey].size());
     EXPECT_EQ(bucketSizeNs - 1, buckets[eventKey][0].mDuration);
     EXPECT_EQ(bucketSizeNs, buckets[eventKey][1].mDuration);
 
@@ -169,7 +169,7 @@
     tracker.noteStop(kEventKey1, eventStartTimeNs + 2 * bucketSizeNs + 12, false);
     tracker.flushIfNeeded(eventStartTimeNs + 2 * bucketSizeNs + 12, &buckets);
     EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
-    EXPECT_EQ(2u, buckets[eventKey].size());
+    ASSERT_EQ(2u, buckets[eventKey].size());
     EXPECT_EQ(bucketSizeNs - 1, buckets[eventKey][0].mDuration);
     EXPECT_EQ(bucketSizeNs, buckets[eventKey][1].mDuration);
 }
@@ -207,7 +207,7 @@
 
     tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
     EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
-    EXPECT_EQ(1u, buckets[eventKey].size());
+    ASSERT_EQ(1u, buckets[eventKey].size());
     EXPECT_EQ(5LL, buckets[eventKey][0].mDuration);
 }
 
@@ -248,7 +248,7 @@
 
     tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
     EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
-    EXPECT_EQ(1u, buckets[eventKey].size());
+    ASSERT_EQ(1u, buckets[eventKey].size());
     EXPECT_EQ(1005LL, buckets[eventKey][0].mDuration);
 }
 
@@ -286,7 +286,7 @@
 
     tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
     EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
-    EXPECT_EQ(1u, buckets[eventKey].size());
+    ASSERT_EQ(1u, buckets[eventKey].size());
     EXPECT_EQ(15LL, buckets[eventKey][0].mDuration);
 }
 
@@ -322,7 +322,7 @@
               tracker.predictAnomalyTimestampNs(*anomalyTracker, eventStartTimeNs));
 
     tracker.noteStop(DEFAULT_DIMENSION_KEY, eventStartTimeNs + 3, false);
-    EXPECT_EQ(0u, buckets[eventKey].size());
+    ASSERT_EQ(0u, buckets[eventKey].size());
 
     int64_t event1StartTimeNs = eventStartTimeNs + 10;
     tracker.noteStart(kEventKey1, true, event1StartTimeNs, ConditionKey());
@@ -335,7 +335,7 @@
     tracker.noteStop(kEventKey1, event1StopTimeNs, false);
 
     EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
-    EXPECT_EQ(1u, buckets[eventKey].size());
+    ASSERT_EQ(1u, buckets[eventKey].size());
     EXPECT_EQ(3LL + bucketStartTimeNs + bucketSizeNs - eventStartTimeNs - 10,
               buckets[eventKey][0].mDuration);
 
@@ -486,10 +486,10 @@
     EXPECT_TRUE(tracker.mStarted.empty());
     EXPECT_EQ(10LL, tracker.mStateKeyDurationMap[DEFAULT_DIMENSION_KEY].mDuration);  // 10ns
 
-    EXPECT_EQ(0u, tracker.mStarted.size());
+    ASSERT_EQ(0u, tracker.mStarted.size());
 
     tracker.noteStart(kEventKey1, true, eventStartTimeNs + 20, ConditionKey());
-    EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
+    ASSERT_EQ(1u, anomalyTracker->mAlarms.size());
     EXPECT_EQ((long long)(52ULL * NS_PER_SEC),  // (10s + 1s + 1ns + 20ns) - 10ns + 40s, rounded up
               (long long)(anomalyTracker->mAlarms.begin()->second->timestampSec * NS_PER_SEC));
     // The alarm is set to fire at 52s, and when it does, an anomaly would be declared. However,
@@ -530,29 +530,29 @@
                                  false, {anomalyTracker});
 
     tracker.noteStart(kEventKey1, true, 15 * NS_PER_SEC, conkey);  // start key1
-    EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
+    ASSERT_EQ(1u, anomalyTracker->mAlarms.size());
     sp<const InternalAlarm> alarm = anomalyTracker->mAlarms.begin()->second;
     EXPECT_EQ((long long)(55ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
 
     tracker.noteStop(kEventKey1, 17 * NS_PER_SEC, false); // stop key1 (2 seconds later)
-    EXPECT_EQ(0u, anomalyTracker->mAlarms.size());
+    ASSERT_EQ(0u, anomalyTracker->mAlarms.size());
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
 
     tracker.noteStart(kEventKey1, true, 22 * NS_PER_SEC, conkey);  // start key1 again
-    EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
+    ASSERT_EQ(1u, anomalyTracker->mAlarms.size());
     alarm = anomalyTracker->mAlarms.begin()->second;
     EXPECT_EQ((long long)(60ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
 
     tracker.noteStart(kEventKey2, true, 32 * NS_PER_SEC, conkey);  // start key2
-    EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
+    ASSERT_EQ(1u, anomalyTracker->mAlarms.size());
     alarm = anomalyTracker->mAlarms.begin()->second;
     EXPECT_EQ((long long)(60ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
 
     tracker.noteStop(kEventKey1, 47 * NS_PER_SEC, false); // stop key1
-    EXPECT_EQ(1u, anomalyTracker->mAlarms.size());
+    ASSERT_EQ(1u, anomalyTracker->mAlarms.size());
     alarm = anomalyTracker->mAlarms.begin()->second;
     EXPECT_EQ((long long)(60ULL * NS_PER_SEC), (long long)(alarm->timestampSec * NS_PER_SEC));
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 0U);
@@ -560,11 +560,11 @@
     // Now, at 60s, which is 38s after key1 started again, we have reached 40s of 'on' time.
     std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> firedAlarms({alarm});
     anomalyTracker->informAlarmsFired(62 * NS_PER_SEC, firedAlarms);
-    EXPECT_EQ(0u, anomalyTracker->mAlarms.size());
+    ASSERT_EQ(0u, anomalyTracker->mAlarms.size());
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 62U + refPeriodSec);
 
     tracker.noteStop(kEventKey2, 69 * NS_PER_SEC, false); // stop key2
-    EXPECT_EQ(0u, anomalyTracker->mAlarms.size());
+    ASSERT_EQ(0u, anomalyTracker->mAlarms.size());
     EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), 62U + refPeriodSec);
 }
 
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index f493cc4..474aa22 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -278,13 +278,13 @@
 TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
-                        return true;
-                    }));
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+                return true;
+            }));
 
     sp<ValueMetricProducer> valueProducer =
             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -295,7 +295,7 @@
 
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -304,7 +304,7 @@
     EXPECT_EQ(11, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(8, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
     EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
 
@@ -312,7 +312,7 @@
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 23));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
 
@@ -320,8 +320,8 @@
     EXPECT_EQ(23, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(12, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
+    ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
     EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
     EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
@@ -330,7 +330,7 @@
     allData.clear();
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
 
@@ -338,8 +338,8 @@
     EXPECT_EQ(36, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(13, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(3UL, valueProducer->mPastBuckets.begin()->second.size());
+    ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(3UL, valueProducer->mPastBuckets.begin()->second.size());
     EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
     EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
@@ -352,18 +352,20 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 2;
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // Initialize bucket.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
                 return true;
             }))
             // Partial bucket.
-            .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
-                                                        vector<std::shared_ptr<LogEvent>>* data,
-                                                        bool) {
+            .WillOnce(Invoke([partialBucketSplitTimeNs](
+                                     int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                     vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
                 data->clear();
                 data->push_back(
                         CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs + 8, 5));
@@ -416,13 +418,13 @@
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 3, 3));
-                        return true;
-                    }));
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                data->clear();
+                data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 3, 3));
+                return true;
+            }));
 
     sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
             kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
@@ -435,7 +437,7 @@
 
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -444,7 +446,7 @@
     EXPECT_EQ(11, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(8, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
     EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
 
@@ -452,20 +454,20 @@
     allData.push_back(CreateTwoValueLogEvent(tagId, bucket3StartTimeNs + 1, 4, 23));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
     // No new data seen, so data has been cleared.
-    EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
 
     EXPECT_EQ(true, curBaseInfo.hasBase);
     EXPECT_EQ(11, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(8, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
     EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
 
     allData.clear();
     allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 3, 36));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
 
@@ -473,8 +475,8 @@
     EXPECT_EQ(true, curBaseInfo.hasBase);
     EXPECT_EQ(36, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
+    ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
     EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
 }
@@ -487,7 +489,8 @@
     metric.set_use_absolute_value_on_reset(true);
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(true));
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+            .WillOnce(Return(true));
     sp<ValueMetricProducer> valueProducer =
             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
 
@@ -497,7 +500,7 @@
 
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -505,35 +508,35 @@
     EXPECT_EQ(true, curBaseInfo.hasBase);
     EXPECT_EQ(11, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
 
     allData.clear();
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 10));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(true, curBaseInfo.hasBase);
     EXPECT_EQ(10, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(10, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
     EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
 
     allData.clear();
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(true, curBaseInfo.hasBase);
     EXPECT_EQ(36, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(26, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
+    ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
     EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
     EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
@@ -546,7 +549,8 @@
 TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(false));
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+            .WillOnce(Return(false));
     sp<ValueMetricProducer> valueProducer =
             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
 
@@ -556,7 +560,7 @@
 
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -564,31 +568,31 @@
     EXPECT_EQ(true, curBaseInfo.hasBase);
     EXPECT_EQ(11, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
 
     allData.clear();
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 10));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(true, curBaseInfo.hasBase);
     EXPECT_EQ(10, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
 
     allData.clear();
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(true, curBaseInfo.hasBase);
     EXPECT_EQ(36, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(26, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
     EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
     EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
 }
@@ -601,21 +605,24 @@
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
 
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);  // First condition change.
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
                 return true;
             }))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1);  // Second condition change.
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 130));
                 return true;
             }))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucket3StartTimeNs + 1);  // Third condition change.
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 180));
                 return true;
@@ -627,7 +634,7 @@
     valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -635,7 +642,7 @@
     EXPECT_EQ(true, curBaseInfo.hasBase);
     EXPECT_EQ(100, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -645,7 +652,7 @@
                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -658,7 +665,7 @@
                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(true, curInterval.hasValue);
@@ -690,7 +697,7 @@
     LogEvent event1(/*uid=*/0, /*pid=*/0);
     CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
 
     int64_t partialBucketSplitTimeNs = bucketStartTimeNs + 150;
     switch (GetParam()) {
@@ -745,11 +752,12 @@
     int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 150;
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             .WillOnce(Return(true))
-            .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
-                                                        vector<std::shared_ptr<LogEvent>>* data,
-                                                        bool) {
+            .WillOnce(Invoke([partialBucketSplitTimeNs](
+                                     int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                     vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 120));
                 return true;
@@ -764,7 +772,7 @@
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 100));
 
     valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
 
     switch (GetParam()) {
         case APP_UPGRADE:
@@ -803,7 +811,8 @@
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(true));
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+            .WillOnce(Return(true));
     ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
                                       eventMatcherWizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
@@ -814,10 +823,10 @@
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 100));
 
     valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
 
     valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150);
-    EXPECT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    ASSERT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
 }
 
@@ -825,15 +834,18 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 1);  // Condition change to true time.
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100));
                 return true;
             }))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs,
+                          bucket2StartTimeNs - 100);  // Condition change to false time.
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs - 100, 120));
                 return true;
@@ -888,7 +900,7 @@
 
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer.mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
@@ -898,7 +910,7 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(30, curInterval.value.long_value);
 
@@ -929,7 +941,7 @@
     CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 10);
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
     // has 1 slice
-    EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
 
     valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
 
@@ -938,7 +950,7 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer.mCurrentSlicedBucket.begin()->second[0];
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -949,7 +961,7 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(50, curInterval.value.long_value);
 
@@ -960,7 +972,7 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(50, curInterval.value.long_value);
 
@@ -1049,7 +1061,8 @@
 TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(true));
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+            .WillOnce(Return(true));
     sp<ValueMetricProducer> valueProducer =
             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
 
@@ -1060,7 +1073,7 @@
 
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -1069,14 +1082,14 @@
     EXPECT_EQ(true, curBaseInfo.hasBase);
     EXPECT_EQ(11, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
 
     // pull 2 at correct time
     allData.clear();
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 23));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     // tartUpdated:false sum:12
@@ -1093,7 +1106,7 @@
     allData.clear();
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket6StartTimeNs + 1, 36));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     // startUpdated:false sum:12
@@ -1119,17 +1132,19 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // condition becomes true
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);  // First condition change.
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
                 return true;
             }))
             // condition becomes false
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1);  // Second condition change.
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
                 return true;
@@ -1140,14 +1155,14 @@
     valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(true, curBaseInfo.hasBase);
     EXPECT_EQ(100, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
 
     // pull on bucket boundary come late, condition change happens before it
     valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
@@ -1179,24 +1194,27 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // condition becomes true
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
                 return true;
             }))
             // condition becomes false
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 1);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
                 return true;
             }))
             // condition becomes true again
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 25);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 25, 130));
                 return true;
@@ -1208,7 +1226,7 @@
     valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -1216,13 +1234,13 @@
     EXPECT_EQ(true, curBaseInfo.hasBase);
     EXPECT_EQ(100, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
 
     // pull on bucket boundary come late, condition change happens before it
     valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8},
                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(false, curBaseInfo.hasBase);
@@ -1287,7 +1305,7 @@
 
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(10, curInterval.value.long_value);
@@ -1296,7 +1314,7 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(10, curInterval.value.long_value);
 
@@ -1328,7 +1346,7 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(10, curInterval.value.long_value);
@@ -1339,7 +1357,7 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(20, curInterval.value.long_value);
 
@@ -1373,7 +1391,7 @@
     CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 15);
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval;
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(10, curInterval.value.long_value);
@@ -1383,14 +1401,14 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(25, curInterval.value.long_value);
     EXPECT_EQ(2, curInterval.sampleSize);
 
     valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+    ASSERT_EQ(1UL, valueProducer.mPastBuckets.size());
+    ASSERT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
 
     EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().values[0].double_value -
                          12.5) < epsilon);
@@ -1421,7 +1439,7 @@
     CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 15);
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(10, curInterval.value.long_value);
@@ -1430,7 +1448,7 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(25, curInterval.value.long_value);
 
@@ -1463,7 +1481,7 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer.mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
@@ -1476,7 +1494,7 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(true, curInterval.hasValue);
     EXPECT_EQ(5, curInterval.value.long_value);
@@ -1486,7 +1504,7 @@
     CreateRepeatedValueLogEvent(&event3, tagId, bucket2StartTimeNs + 10, 15);
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
 
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -1497,7 +1515,7 @@
     LogEvent event4(/*uid=*/0, /*pid=*/0);
     CreateRepeatedValueLogEvent(&event4, tagId, bucket2StartTimeNs + 15, 15);
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -1538,7 +1556,7 @@
 
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer.mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
@@ -1553,7 +1571,7 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(true, curInterval.hasValue);
@@ -1568,7 +1586,7 @@
     CreateThreeValueLogEvent(&event3, tagId, bucket2StartTimeNs + 10, 1, 15, 25);
 
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
 
@@ -1585,7 +1603,7 @@
     CreateThreeValueLogEvent(&event4, tagId, bucket2StartTimeNs + 15, 1, 15, 29);
 
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(true, curBaseInfo.hasBase);
@@ -1599,10 +1617,10 @@
 
     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
 
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-    EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second[0].values.size());
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second[1].values.size());
+    ASSERT_EQ(1UL, valueProducer.mPastBuckets.size());
+    ASSERT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
+    ASSERT_EQ(2UL, valueProducer.mPastBuckets.begin()->second[0].values.size());
+    ASSERT_EQ(1UL, valueProducer.mPastBuckets.begin()->second[1].values.size());
 
     EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[0].mConditionTrueNs);
     EXPECT_EQ(5, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
@@ -1625,18 +1643,18 @@
     metric.set_use_zero_default_base(true);
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
-                        return true;
-                    }));
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                data->clear();
+                data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
+                return true;
+            }));
 
     sp<ValueMetricProducer> valueProducer =
             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
 
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     auto iter = valueProducer->mCurrentSlicedBucket.begin();
     auto& interval1 = iter->second[0];
     auto iterBase = valueProducer->mCurrentBaseInfo.begin();
@@ -1646,7 +1664,7 @@
     EXPECT_EQ(3, baseInfo1.base.long_value);
     EXPECT_EQ(false, interval1.hasValue);
     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
     vector<shared_ptr<LogEvent>> allData;
 
     allData.clear();
@@ -1654,7 +1672,7 @@
     allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 11));
 
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
     EXPECT_EQ(true, baseInfo1.hasBase);
     EXPECT_EQ(11, baseInfo1.base.long_value);
     EXPECT_EQ(false, interval1.hasValue);
@@ -1682,7 +1700,7 @@
     EXPECT_EQ(false, interval2.hasValue);
     EXPECT_EQ(4, interval2.value.long_value);
 
-    EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
     auto iterator = valueProducer->mPastBuckets.begin();
     EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
     EXPECT_EQ(8, iterator->second[0].values[0].long_value);
@@ -1701,18 +1719,18 @@
     metric.set_use_zero_default_base(true);
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
-                        return true;
-                    }));
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                data->clear();
+                data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
+                return true;
+            }));
 
     sp<ValueMetricProducer> valueProducer =
             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
 
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     const auto& it = valueProducer->mCurrentSlicedBucket.begin();
     ValueMetricProducer::Interval& interval1 = it->second[0];
     ValueMetricProducer::BaseInfo& baseInfo1 =
@@ -1722,7 +1740,7 @@
     EXPECT_EQ(3, baseInfo1.base.long_value);
     EXPECT_EQ(false, interval1.hasValue);
     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
     vector<shared_ptr<LogEvent>> allData;
 
     allData.clear();
@@ -1730,7 +1748,7 @@
     allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 11));
 
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
     EXPECT_EQ(true, baseInfo1.hasBase);
     EXPECT_EQ(11, baseInfo1.base.long_value);
     EXPECT_EQ(false, interval1.hasValue);
@@ -1751,31 +1769,31 @@
     EXPECT_EQ(4, baseInfo2.base.long_value);
     EXPECT_EQ(false, interval2.hasValue);
     EXPECT_EQ(4, interval2.value.long_value);
-    EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
 
     // next pull somehow did not happen, skip to end of bucket 3
     allData.clear();
     allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 2, 5));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
 
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     EXPECT_EQ(true, baseInfo2.hasBase);
     EXPECT_EQ(5, baseInfo2.base.long_value);
     EXPECT_EQ(false, interval2.hasValue);
     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-    EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
 
     allData.clear();
     allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 2, 13));
     allData.push_back(CreateTwoValueLogEvent(tagId, bucket5StartTimeNs + 1, 1, 5));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
 
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
     // Get new references now that entries have been deleted from the map
     const auto& it3 = valueProducer->mCurrentSlicedBucket.begin();
     const auto& it4 = std::next(valueProducer->mCurrentSlicedBucket.begin());
-    EXPECT_EQ(it3->second.size(), 1);
-    EXPECT_EQ(it4->second.size(), 1);
+    ASSERT_EQ(it3->second.size(), 1);
+    ASSERT_EQ(it4->second.size(), 1);
     ValueMetricProducer::Interval& interval3 = it3->second[0];
     ValueMetricProducer::Interval& interval4 = it4->second[0];
     ValueMetricProducer::BaseInfo& baseInfo3 =
@@ -1794,7 +1812,7 @@
     EXPECT_EQ(false, interval4.hasValue);
     EXPECT_EQ(8, interval4.value.long_value);
 
-    EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
 }
 
 /*
@@ -1806,18 +1824,18 @@
     metric.mutable_dimensions_in_what()->add_child()->set_field(1);
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
-                        return true;
-                    }));
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                data->clear();
+                data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
+                return true;
+            }));
 
     sp<ValueMetricProducer> valueProducer =
             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
 
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     auto iter = valueProducer->mCurrentSlicedBucket.begin();
     auto& interval1 = iter->second[0];
     auto iterBase = valueProducer->mCurrentBaseInfo.begin();
@@ -1826,7 +1844,7 @@
     EXPECT_EQ(true, baseInfo1.hasBase);
     EXPECT_EQ(3, baseInfo1.base.long_value);
     EXPECT_EQ(false, interval1.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -1834,7 +1852,7 @@
     allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 11));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
 
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
     EXPECT_EQ(true, baseInfo1.hasBase);
     EXPECT_EQ(11, baseInfo1.base.long_value);
     EXPECT_EQ(false, interval1.hasValue);
@@ -1870,7 +1888,7 @@
     allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 2, 5));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
     // Only one interval left. One was trimmed.
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
@@ -1909,8 +1927,8 @@
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     // Used by onConditionChanged.
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 8, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
@@ -1922,7 +1940,7 @@
 
     valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -1932,7 +1950,7 @@
 
     vector<shared_ptr<LogEvent>> allData;
     valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     EXPECT_EQ(false, curBaseInfo.hasBase);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(false, valueProducer->mHasGlobalBase);
@@ -1942,9 +1960,10 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);  // Condition change to true.
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
                 return true;
@@ -1957,19 +1976,19 @@
     valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(true, curBaseInfo.hasBase);
     EXPECT_EQ(100, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
 
     valueProducer->onConditionChanged(false, bucketStartTimeNs + 20);
 
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(false, curBaseInfo.hasBase);
     EXPECT_EQ(false, valueProducer->mHasGlobalBase);
@@ -1979,15 +1998,17 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 50));
-                        return false;
-                    }))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 50));
+                return false;
+            }))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 1);  // Condition change to false.
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
                 return true;
@@ -2001,10 +2022,10 @@
     // valueProducer->mCondition = ConditionState::kTrue;
     valueProducer->onConditionChanged(true, bucketStartTimeNs);
 
-    EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
 
     valueProducer->onConditionChanged(false, bucketStartTimeNs + 1);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -2019,8 +2040,8 @@
     metric.set_max_pull_delay_sec(0);
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 1, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 120));
@@ -2034,7 +2055,7 @@
 
     // Max delay is set to 0 so pull will exceed max delay.
     valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
-    EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
 }
 
 TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
@@ -2060,15 +2081,15 @@
     // Event should be skipped since it is from previous bucket.
     // Pull should not be called.
     valueProducer.onConditionChanged(true, bucketStartTimeNs);
-    EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+    ASSERT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
 }
 
 TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 1, _, _))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100));
@@ -2083,7 +2104,7 @@
 
     valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
     valueProducer->mHasGlobalBase = true;
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -2100,12 +2121,13 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // First onConditionChanged
             .WillOnce(Return(false))
             // Second onConditionChanged
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
                 return true;
@@ -2134,9 +2156,9 @@
 
     valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
 
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
     // Contains base from last pull which was successful.
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -2153,14 +2175,14 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
+    ASSERT_EQ(0, report.value_metrics().data_size());
+    ASSERT_EQ(1, report.value_metrics().skipped_size());
 
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+    ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
 
     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
@@ -2177,9 +2199,9 @@
     metric.set_condition(StringToId("SCREEN_ON"));
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 2, _, _))
             // First onConditionChanged
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
                 for (int i = 0; i < 2000; i++) {
                     data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i));
@@ -2193,8 +2215,8 @@
 
     valueProducer->onConditionChanged(true, bucketStartTimeNs + 2);
     EXPECT_EQ(true, valueProducer->mCurrentBucketIsInvalid);
-    EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(0UL, valueProducer->mSkippedBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(0UL, valueProducer->mSkippedBuckets.size());
 
     // Bucket 2 start.
     vector<shared_ptr<LogEvent>> allData;
@@ -2203,7 +2225,7 @@
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
 
     // First bucket added to mSkippedBuckets after flush.
-    EXPECT_EQ(1UL, valueProducer->mSkippedBuckets.size());
+    ASSERT_EQ(1UL, valueProducer->mSkippedBuckets.size());
 
     // Check dump report.
     ProtoOutputStream output;
@@ -2213,14 +2235,14 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
+    ASSERT_EQ(0, report.value_metrics().data_size());
+    ASSERT_EQ(1, report.value_metrics().skipped_size());
 
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+    ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
 
     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
     EXPECT_EQ(BucketDropReason::DIMENSION_GUARDRAIL_REACHED, dropEvent.drop_reason());
@@ -2234,17 +2256,19 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // First onConditionChanged
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 2);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120));
                 return true;
             }))
             // Second onConditionChanged
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
                 return true;
@@ -2271,9 +2295,9 @@
 
     valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
 
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
     // Contains base from last pull which was successful.
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -2290,14 +2314,14 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
+    ASSERT_EQ(0, report.value_metrics().data_size());
+    ASSERT_EQ(1, report.value_metrics().skipped_size());
 
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+    ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
 
     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
@@ -2312,17 +2336,19 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // First onConditionChanged
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 2);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120));
                 return true;
             }))
             // Second onConditionChanged
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 3);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
                 return true;
@@ -2349,9 +2375,9 @@
 
     valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
 
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mPastBuckets.size());
     // Last pull failed so base has been reset.
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -2367,14 +2393,14 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
+    ASSERT_EQ(0, report.value_metrics().data_size());
+    ASSERT_EQ(1, report.value_metrics().skipped_size());
 
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+    ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
 
     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
@@ -2384,14 +2410,14 @@
 TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
             // Start bucket.
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
-                        return true;
-                    }));
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+                return true;
+            }));
 
     sp<ValueMetricProducer> valueProducer =
             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -2401,41 +2427,43 @@
     allData.clear();
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 110));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
 
     // Bucket 3 empty.
     allData.clear();
     allData.push_back(CreateNoValuesLogEvent(tagId, bucket3StartTimeNs + 1));
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
     // Data has been trimmed.
-    EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
 }
 
 TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // First onConditionChanged
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
-                        return true;
-                    }))
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        return true;
-                    }));
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+                return true;
+            }))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
+                data->clear();
+                return true;
+            }));
 
     sp<ValueMetricProducer> valueProducer =
             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
 
     valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -2445,7 +2473,7 @@
 
     // Empty pull.
     valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(false, curBaseInfo.hasBase);
@@ -2457,26 +2485,29 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // First onConditionChanged
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
-                        return true;
-                    }))
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 2));
-                        return true;
-                    }))
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 5));
-                        return true;
-                    }));
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+                return true;
+            }))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 11);
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 2));
+                return true;
+            }))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 12);
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 5));
+                return true;
+            }));
 
     sp<ValueMetricProducer> valueProducer =
             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
@@ -2484,7 +2515,7 @@
     valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
     valueProducer->onConditionChanged(false, bucketStartTimeNs + 11);
     valueProducer->onConditionChanged(true, bucketStartTimeNs + 12);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -2496,7 +2527,7 @@
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     // Data is empty, base should be reset.
@@ -2505,7 +2536,7 @@
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
 
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(1UL, valueProducer->mPastBuckets.size());
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {1}, {bucketSizeNs - 12 + 1},
                                     {bucketStartTimeNs}, {bucket2StartTimeNs});
 }
@@ -2517,20 +2548,20 @@
     metric.set_condition(StringToId("SCREEN_ON"));
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 10, _, _))
             // First onConditionChanged
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
-                        return true;
-                    }));
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+                return true;
+            }));
 
     sp<ValueMetricProducer> valueProducer =
             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
 
     valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
 
     // End of bucket
     vector<shared_ptr<LogEvent>> allData;
@@ -2539,7 +2570,7 @@
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
 
     // Key 1 should be reset since in not present in the most pull.
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
     auto iterator = valueProducer->mCurrentSlicedBucket.begin();
     auto baseInfoIter = valueProducer->mCurrentBaseInfo.begin();
     EXPECT_EQ(true, baseInfoIter->second[0].hasBase);
@@ -2559,18 +2590,20 @@
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     int64_t partialBucketSplitTimeNs = bucketStartTimeNs + bucketSizeNs / 2;
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // Initialization.
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
-                        return true;
-                    }))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+                return true;
+            }))
             // notifyAppUpgrade.
-            .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
-                                                        vector<std::shared_ptr<LogEvent>>* data,
-                                                        bool) {
+            .WillOnce(Invoke([partialBucketSplitTimeNs](
+                                     int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                     vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 10));
                 return true;
@@ -2609,17 +2642,19 @@
 TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // Second onConditionChanged.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 5));
                 return true;
             }))
             // Third onConditionChanged.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucket3StartTimeNs + 10);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 10, 7));
                 return true;
@@ -2678,14 +2713,14 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
             // Initialization.
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
-                        return true;
-                    }));
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+                return true;
+            }));
 
     sp<ValueMetricProducer> valueProducer =
             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -2708,18 +2743,20 @@
 
     int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 2;
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // Initialization.
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
-                        return true;
-                    }))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+                return true;
+            }))
             // notifyAppUpgrade.
-            .WillOnce(Invoke([partialBucketSplitTimeNs](int tagId, const ConfigKey&,
-                                                        vector<std::shared_ptr<LogEvent>>* data,
-                                                        bool) {
+            .WillOnce(Invoke([partialBucketSplitTimeNs](
+                                     int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                     vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, partialBucketSplitTimeNs);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, partialBucketSplitTimeNs, 10));
                 return true;
@@ -2746,21 +2783,23 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // First on condition changed.
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
-                        return true;
-                    }))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+                return true;
+            }))
             // Second on condition changed.
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
-                        return true;
-                    }));
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+                return true;
+            }));
 
     sp<ValueMetricProducer> valueProducer =
             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
@@ -2769,7 +2808,7 @@
     valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
     valueProducer->onConditionChanged(false, bucketStartTimeNs + 12);
 
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
     auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(true, curInterval.hasValue);
@@ -2788,28 +2827,31 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // First condition change.
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
-                        return true;
-                    }))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10);
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+                return true;
+            }))
             // 2nd condition change.
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
-                        return true;
-                    }))
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 8);
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
+                return true;
+            }))
             // 3rd condition change.
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
-                        return true;
-                    }));
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 10);
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
+                return true;
+            }));
 
     sp<ValueMetricProducer> valueProducer =
             ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
@@ -2848,9 +2890,9 @@
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
 
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
             // Initial pull.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
                 data->clear();
                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
@@ -2869,7 +2911,7 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     // Bucket is invalid since we did not pull when dump report was called.
-    EXPECT_EQ(0, report.value_metrics().data_size());
+    ASSERT_EQ(0, report.value_metrics().data_size());
 }
 
 TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
@@ -2886,9 +2928,9 @@
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
 
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _, _))
             // Initial pull.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
                 data->clear();
                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
@@ -2912,7 +2954,7 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     // Previous bucket is part of the report.
-    EXPECT_EQ(1, report.value_metrics().data_size());
+    ASSERT_EQ(1, report.value_metrics().data_size());
     EXPECT_EQ(0, report.value_metrics().data(0).bucket_info(0).bucket_num());
 }
 
@@ -2930,16 +2972,18 @@
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
 
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // Initial pull.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
                 data->clear();
                 data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
                 return true;
             }))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
                 data->clear();
                 data->push_back(
                         CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 10, tagId, 3, 3));
@@ -2957,8 +3001,8 @@
                                NO_TIME_CONSTRAINTS, &strSet, &output);
 
     StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_EQ(1, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().data(0).bucket_info_size());
+    ASSERT_EQ(1, report.value_metrics().data_size());
+    ASSERT_EQ(1, report.value_metrics().data(0).bucket_info_size());
     EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
 }
 
@@ -2984,17 +3028,19 @@
     metric.set_use_diff(false);
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // condition becomes true
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
                 return true;
             }))
             // condition becomes false
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 20));
                 return true;
@@ -3006,7 +3052,7 @@
     valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
     valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
     // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
     ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
@@ -3032,9 +3078,9 @@
     metric.set_use_diff(false);
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 8, _, _))
             // condition becomes true
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
@@ -3083,10 +3129,11 @@
     metric.set_use_diff(false);
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // condition becomes true
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 8);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
                 return true;
@@ -3122,9 +3169,9 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 20, _, _))
             // Condition change to true.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20, 10));
@@ -3145,14 +3192,14 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
+    ASSERT_EQ(0, report.value_metrics().data_size());
+    ASSERT_EQ(1, report.value_metrics().skipped_size());
 
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40),
               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+    ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
 
     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
     EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
@@ -3167,9 +3214,9 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 50, _, _))
             // Condition change to true.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
@@ -3198,14 +3245,14 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(1, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
+    ASSERT_EQ(1, report.value_metrics().data_size());
+    ASSERT_EQ(1, report.value_metrics().skipped_size());
 
     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+    ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
 
     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
     EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
@@ -3220,17 +3267,19 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // Condition change to true.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
                 return true;
             }))
             // Dump report requested.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 100);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 100, 15));
                 return true;
@@ -3261,14 +3310,14 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(1, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
+    ASSERT_EQ(1, report.value_metrics().data_size());
+    ASSERT_EQ(1, report.value_metrics().skipped_size());
 
     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+    ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
 
     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
     EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
@@ -3283,17 +3332,19 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // Condition change to true.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
                 return true;
             }))
             // Dump report requested.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10000);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 100, 15));
                 return true;
@@ -3315,14 +3366,14 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
+    ASSERT_EQ(0, report.value_metrics().data_size());
+    ASSERT_EQ(1, report.value_metrics().skipped_size());
 
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
     EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+    ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
 
     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
     EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
@@ -3337,10 +3388,11 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // Condition change to true.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
                 return true;
@@ -3363,14 +3415,14 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
+    ASSERT_EQ(0, report.value_metrics().data_size());
+    ASSERT_EQ(1, report.value_metrics().skipped_size());
 
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
     EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+    ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
 
     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
     EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
@@ -3385,17 +3437,19 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // Condition change to true.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
                 return true;
             }))
             // Dump report requested.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucket4StartTimeNs + 10);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1000, 15));
                 return true;
@@ -3418,14 +3472,14 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
+    ASSERT_EQ(0, report.value_metrics().data_size());
+    ASSERT_EQ(1, report.value_metrics().skipped_size());
 
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
     EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+    ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
 
     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
     EXPECT_EQ(BucketDropReason::MULTIPLE_BUCKETS_SKIPPED, dropEvent.drop_reason());
@@ -3441,17 +3495,19 @@
     metric.set_min_bucket_size_nanos(10000000000);  // 10 seconds
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // Condition change to true.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
                 return true;
             }))
             // Dump report requested.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 9000000);
                 data->clear();
                 data->push_back(
                         CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 9000000, 15));
@@ -3473,14 +3529,14 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
+    ASSERT_EQ(0, report.value_metrics().data_size());
+    ASSERT_EQ(1, report.value_metrics().skipped_size());
 
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
     EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+    ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
 
     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
     EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason());
@@ -3494,9 +3550,9 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 10, _, _))
             // Condition change to true.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
@@ -3519,14 +3575,14 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
+    ASSERT_EQ(0, report.value_metrics().data_size());
+    ASSERT_EQ(1, report.value_metrics().skipped_size());
 
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
     EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(2, report.value_metrics().skipped(0).drop_event_size());
+    ASSERT_EQ(2, report.value_metrics().skipped(0).drop_event_size());
 
     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
     EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
@@ -3545,10 +3601,11 @@
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // First condition change event.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
                 for (int i = 0; i < 2000; i++) {
                     data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i));
                 }
@@ -3563,8 +3620,9 @@
             .WillOnce(Return(false))
             .WillOnce(Return(false))
             .WillOnce(Return(false))
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 220);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 220, 10));
                 return true;
@@ -3602,14 +3660,14 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
+    ASSERT_EQ(0, report.value_metrics().data_size());
+    ASSERT_EQ(1, report.value_metrics().skipped_size());
 
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
     EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(10, report.value_metrics().skipped(0).drop_event_size());
+    ASSERT_EQ(10, report.value_metrics().skipped(0).drop_event_size());
 
     auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
     EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
@@ -3662,38 +3720,43 @@
     // Set up ValueMetricProducer.
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE");
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // ValueMetricProducer initialized.
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
-                        return true;
-                    }))
-            // Screen state change to ON.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+                return true;
+            }))
+            // Screen state change to ON.
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 5);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5, 5));
                 return true;
             }))
             // Screen state change to OFF.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 10);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 9));
                 return true;
             }))
             // Screen state change to ON.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 15);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 15, 21));
                 return true;
             }))
             // Dump report requested.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 30));
                 return true;
@@ -3710,7 +3773,7 @@
     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
 
     // Bucket status after metric initialized.
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     // Base for dimension key {}
     auto it = valueProducer->mCurrentSlicedBucket.begin();
     auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
@@ -3723,7 +3786,7 @@
     auto screenEvent = CreateScreenStateChangedEvent(
             bucketStartTimeNs + 5, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
     StateManager::getInstance().onLogEvent(*screenEvent);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     // Base for dimension key {}
     it = valueProducer->mCurrentSlicedBucket.begin();
     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
@@ -3737,7 +3800,7 @@
     screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 10,
                                                 android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
     StateManager::getInstance().onLogEvent(*screenEvent);
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
     // Base for dimension key {}
     it = valueProducer->mCurrentSlicedBucket.begin();
     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
@@ -3757,7 +3820,7 @@
     screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 15,
                                                 android::view::DisplayStateEnum::DISPLAY_STATE_ON);
     StateManager::getInstance().onLogEvent(*screenEvent);
-    EXPECT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
     // Base for dimension key {}
     it = valueProducer->mCurrentSlicedBucket.begin();
     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
@@ -3787,21 +3850,21 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(3, report.value_metrics().data_size());
+    ASSERT_EQ(3, report.value_metrics().data_size());
 
     auto data = report.value_metrics().data(0);
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
 
     data = report.value_metrics().data(1);
-    EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+    ASSERT_EQ(1, report.value_metrics().data(1).bucket_info_size());
     EXPECT_EQ(13, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
 
     data = report.value_metrics().data(2);
-    EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
+    ASSERT_EQ(1, report.value_metrics().data(2).bucket_info_size());
     EXPECT_EQ(12, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
@@ -3818,38 +3881,41 @@
     // Set up ValueMetricProducer.
     ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // ValueMetricProducer initialized.
-            .WillOnce(Invoke(
-                    [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
-                        data->clear();
-                        data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
-                        return true;
-                    }))
-            // Screen state change to ON.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
+                data->clear();
+                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+                return true;
+            }))
+            // Screen state change to ON.
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
+                                vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 5);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5, 5));
                 return true;
             }))
-            // Screen state change to VR.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
-                                vector<std::shared_ptr<LogEvent>>* data, bool) {
-                data->clear();
-                data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 9));
-                return true;
-            }))
+            // Screen state change to VR has no pull because it is in the same
+            // state group as ON.
+
+            // Screen state change to ON has no pull because it is in the same
+            // state group as VR.
+
             // Screen state change to OFF.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 15);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 15, 21));
                 return true;
             }))
             // Dump report requested.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 50);
                 data->clear();
                 data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 30));
                 return true;
@@ -3878,7 +3944,7 @@
     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
 
     // Bucket status after metric initialized.
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     // Base for dimension key {}
     auto it = valueProducer->mCurrentSlicedBucket.begin();
     auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
@@ -3891,6 +3957,36 @@
     auto screenEvent = CreateScreenStateChangedEvent(
             bucketStartTimeNs + 5, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
     StateManager::getInstance().onLogEvent(*screenEvent);
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    // Base for dimension key {}
+    it = valueProducer->mCurrentSlicedBucket.begin();
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(5, itBase->second[0].base.long_value);
+    // Value for dimension, state key {{}, kStateUnknown}
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(2, it->second[0].value.long_value);
+
+    // Bucket status after screen state change ON->VR.
+    // Both ON and VR are in the same state group, so the base should not change.
+    screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 10,
+                                                android::view::DisplayStateEnum::DISPLAY_STATE_VR);
+    StateManager::getInstance().onLogEvent(*screenEvent);
+    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    // Base for dimension key {}
+    it = valueProducer->mCurrentSlicedBucket.begin();
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(5, itBase->second[0].base.long_value);
+    // Value for dimension, state key {{}, kStateUnknown}
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(2, it->second[0].value.long_value);
+
+    // Bucket status after screen state change VR->ON.
+    // Both ON and VR are in the same state group, so the base should not change.
+    screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 12,
+                                                android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+    StateManager::getInstance().onLogEvent(*screenEvent);
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     // Base for dimension key {}
     it = valueProducer->mCurrentSlicedBucket.begin();
@@ -3901,31 +3997,11 @@
     EXPECT_EQ(true, it->second[0].hasValue);
     EXPECT_EQ(2, it->second[0].value.long_value);
 
-    // Bucket status after screen state change ON->VR (also ON).
-    screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 10,
-                                                android::view::DisplayStateEnum::DISPLAY_STATE_VR);
-    StateManager::getInstance().onLogEvent(*screenEvent);
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    // Base for dimension key {}
-    it = valueProducer->mCurrentSlicedBucket.begin();
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(9, itBase->second[0].base.long_value);
-    // Value for dimension, state key {{}, ON GROUP}
-    EXPECT_EQ(screenOnGroup.group_id(),
-              it->first.getStateValuesKey().getValues()[0].mValue.long_value);
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(4, it->second[0].value.long_value);
-    // Value for dimension, state key {{}, kStateUnknown}
-    it++;
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(2, it->second[0].value.long_value);
-
     // Bucket status after screen state change VR->OFF.
     screenEvent = CreateScreenStateChangedEvent(bucketStartTimeNs + 15,
                                                 android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
     StateManager::getInstance().onLogEvent(*screenEvent);
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
     // Base for dimension key {}
     it = valueProducer->mCurrentSlicedBucket.begin();
     itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
@@ -3949,21 +4025,21 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(3, report.value_metrics().data_size());
+    ASSERT_EQ(3, report.value_metrics().data_size());
 
     auto data = report.value_metrics().data(0);
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
 
     data = report.value_metrics().data(1);
-    EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+    ASSERT_EQ(1, report.value_metrics().data(1).bucket_info_size());
     EXPECT_EQ(16, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
     EXPECT_EQ(screenOnGroup.group_id(), data.slice_by_state(0).group_id());
 
     data = report.value_metrics().data(2);
-    EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
+    ASSERT_EQ(1, report.value_metrics().data(2).bucket_info_size());
     EXPECT_EQ(9, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
     EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_group_id());
@@ -3990,18 +4066,20 @@
     *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+    EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _, _))
             // ValueMetricProducer initialized.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs);
                 data->clear();
                 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 2 /*uid*/, 7));
                 data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1 /*uid*/, 3));
                 return true;
             }))
             // Uid 1 process state change from kStateUnknown -> Foreground
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 20);
                 data->clear();
                 data->push_back(
                         CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 20, 1 /*uid*/, 6));
@@ -4012,8 +4090,9 @@
                 return true;
             }))
             // Uid 2 process state change from kStateUnknown -> Background
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucketStartTimeNs + 40);
                 data->clear();
                 data->push_back(
                         CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 40, 2 /*uid*/, 9));
@@ -4024,8 +4103,9 @@
                 return true;
             }))
             // Uid 1 process state change from Foreground -> Background
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 20);
                 data->clear();
                 data->push_back(
                         CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 20, 1 /*uid*/, 13));
@@ -4036,8 +4116,9 @@
                 return true;
             }))
             // Uid 1 process state change from Background -> Foreground
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 40);
                 data->clear();
                 data->push_back(
                         CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 40, 1 /*uid*/, 17));
@@ -4048,8 +4129,9 @@
                 return true;
             }))
             // Dump report pull.
-            .WillOnce(Invoke([](int tagId, const ConfigKey&,
+            .WillOnce(Invoke([](int tagId, const ConfigKey&, const int64_t eventTimeNs,
                                 vector<std::shared_ptr<LogEvent>>* data, bool) {
+                EXPECT_EQ(eventTimeNs, bucket2StartTimeNs + 50);
                 data->clear();
                 data->push_back(
                         CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 50, 2 /*uid*/, 20));
@@ -4069,7 +4151,7 @@
     EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
 
     // Bucket status after metric initialized.
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
     // Base for dimension key {uid 1}.
     auto it = valueProducer->mCurrentSlicedBucket.begin();
     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
@@ -4094,7 +4176,7 @@
     auto uidProcessEvent = CreateUidProcessStateChangedEvent(
             bucketStartTimeNs + 20, 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND);
     StateManager::getInstance().onLogEvent(*uidProcessEvent);
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
     // Base for dimension key {uid 1}.
     it = valueProducer->mCurrentSlicedBucket.begin();
     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
@@ -4121,7 +4203,7 @@
     uidProcessEvent = CreateUidProcessStateChangedEvent(
             bucketStartTimeNs + 40, 2 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND);
     StateManager::getInstance().onLogEvent(*uidProcessEvent);
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
     // Base for dimension key {uid 1}.
     it = valueProducer->mCurrentSlicedBucket.begin();
     EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
@@ -4151,9 +4233,9 @@
 
     // Buckets flushed after end of first bucket.
     // None of the buckets should have a value.
-    EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+    ASSERT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(4UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
     // Base for dimension key {uid 2}.
     it = valueProducer->mCurrentSlicedBucket.begin();
     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
@@ -4161,7 +4243,7 @@
     EXPECT_EQ(true, itBase->second[0].hasBase);
     EXPECT_EQ(15, itBase->second[0].base.long_value);
     // Value for key {uid 2, BACKGROUND}.
-    EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
+    ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
     EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
     EXPECT_EQ(false, it->second[0].hasValue);
 
@@ -4172,13 +4254,13 @@
     EXPECT_EQ(true, itBase->second[0].hasBase);
     EXPECT_EQ(10, itBase->second[0].base.long_value);
     // Value for key {uid 1, kStateUnknown}
-    EXPECT_EQ(0, it->first.getStateValuesKey().getValues().size());
+    ASSERT_EQ(0, it->first.getStateValuesKey().getValues().size());
     // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
     EXPECT_EQ(false, it->second[0].hasValue);
 
     // Value for key {uid 1, FOREGROUND}
     it++;
-    EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
+    ASSERT_EQ(1, it->first.getStateValuesKey().getValues().size());
     EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
     EXPECT_EQ(false, it->second[0].hasValue);
 
@@ -4191,9 +4273,9 @@
             bucket2StartTimeNs + 20, 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND);
     StateManager::getInstance().onLogEvent(*uidProcessEvent);
 
-    EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+    ASSERT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(4UL, valueProducer->mPastBuckets.size());
+    ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
     // Base for dimension key {uid 2}.
     it = valueProducer->mCurrentSlicedBucket.begin();
     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
@@ -4225,8 +4307,8 @@
             bucket2StartTimeNs + 40, 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND);
     StateManager::getInstance().onLogEvent(*uidProcessEvent);
 
-    EXPECT_EQ(5UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+    ASSERT_EQ(5UL, valueProducer->mCurrentSlicedBucket.size());
+    ASSERT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
     // Base for dimension key {uid 2}
     it = valueProducer->mCurrentSlicedBucket.begin();
     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
@@ -4261,10 +4343,10 @@
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(5, report.value_metrics().data_size());
+    ASSERT_EQ(5, report.value_metrics().data_size());
 
     auto data = report.value_metrics().data(0);
-    EXPECT_EQ(1, data.bucket_info_size());
+    ASSERT_EQ(1, data.bucket_info_size());
     EXPECT_EQ(4, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
     EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
     EXPECT_TRUE(data.slice_by_state(0).has_value());
@@ -4272,7 +4354,7 @@
               data.slice_by_state(0).value());
 
     data = report.value_metrics().data(1);
-    EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+    ASSERT_EQ(1, report.value_metrics().data(1).bucket_info_size());
     EXPECT_EQ(2, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
 
     data = report.value_metrics().data(2);
@@ -4280,12 +4362,12 @@
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
               data.slice_by_state(0).value());
-    EXPECT_EQ(2, report.value_metrics().data(2).bucket_info_size());
+    ASSERT_EQ(2, report.value_metrics().data(2).bucket_info_size());
     EXPECT_EQ(4, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
     EXPECT_EQ(7, report.value_metrics().data(2).bucket_info(1).values(0).value_long());
 
     data = report.value_metrics().data(3);
-    EXPECT_EQ(1, report.value_metrics().data(3).bucket_info_size());
+    ASSERT_EQ(1, report.value_metrics().data(3).bucket_info_size());
     EXPECT_EQ(3, report.value_metrics().data(3).bucket_info(0).values(0).value_long());
 
     data = report.value_metrics().data(4);
@@ -4293,7 +4375,7 @@
     EXPECT_TRUE(data.slice_by_state(0).has_value());
     EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
               data.slice_by_state(0).value());
-    EXPECT_EQ(2, report.value_metrics().data(4).bucket_info_size());
+    ASSERT_EQ(2, report.value_metrics().data(4).bucket_info_size());
     EXPECT_EQ(6, report.value_metrics().data(4).bucket_info(0).values(0).value_long());
     EXPECT_EQ(5, report.value_metrics().data(4).bucket_info(1).values(0).value_long());
 }
diff --git a/cmds/statsd/tests/metrics/metrics_test_helper.h b/cmds/statsd/tests/metrics/metrics_test_helper.h
index 46ef0f6..eeb38a4 100644
--- a/cmds/statsd/tests/metrics/metrics_test_helper.h
+++ b/cmds/statsd/tests/metrics/metrics_test_helper.h
@@ -38,10 +38,11 @@
                       int64_t nextPulltimeNs, int64_t intervalNs));
     MOCK_METHOD3(UnRegisterReceiver,
                  void(int tagId, const ConfigKey& key, wp<PullDataReceiver> receiver));
-    MOCK_METHOD4(Pull, bool(const int pullCode, const ConfigKey& key,
+    MOCK_METHOD5(Pull, bool(const int pullCode, const ConfigKey& key, const int64_t eventTimeNs,
                             vector<std::shared_ptr<LogEvent>>* data, bool useUids));
-    MOCK_METHOD4(Pull, bool(const int pullCode, const vector<int32_t>& uids,
-                            vector<std::shared_ptr<LogEvent>>* data, bool useUids));
+    MOCK_METHOD5(Pull,
+                 bool(const int pullCode, const vector<int32_t>& uids, const int64_t eventTimeNs,
+                      vector<std::shared_ptr<LogEvent>>* data, bool useUids));
     MOCK_METHOD2(RegisterPullUidProvider,
                  void(const ConfigKey& configKey, wp<PullUidProvider> provider));
     MOCK_METHOD2(UnregisterPullUidProvider,
diff --git a/cmds/statsd/tests/shell/ShellSubscriber_test.cpp b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
index 363fcb4..e384b6a 100644
--- a/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
+++ b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
@@ -190,8 +190,8 @@
 
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     const vector<int32_t> uids = {AID_SYSTEM};
-    EXPECT_CALL(*pullerManager, Pull(10016, uids, _, _))
-            .WillRepeatedly(Invoke([](int tagId, const vector<int32_t>&,
+    EXPECT_CALL(*pullerManager, Pull(10016, uids, _, _, _))
+            .WillRepeatedly(Invoke([](int tagId, const vector<int32_t>&, const int64_t,
                                       vector<std::shared_ptr<LogEvent>>* data, bool) {
                 data->clear();
                 data->push_back(makeCpuActiveTimeAtom(/*uid=*/kUid1, /*timeMillis=*/kCpuTime1));
diff --git a/cmds/statsd/tests/state/StateTracker_test.cpp b/cmds/statsd/tests/state/StateTracker_test.cpp
index ba2a4cf..530ac5e 100644
--- a/cmds/statsd/tests/state/StateTracker_test.cpp
+++ b/cmds/statsd/tests/state/StateTracker_test.cpp
@@ -50,8 +50,9 @@
     std::vector<Update> updates;
 
     void onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
-                        const HashableDimensionKey& primaryKey, int oldState, int newState) {
-        updates.emplace_back(primaryKey, newState);
+                        const HashableDimensionKey& primaryKey, const FieldValue& oldState,
+                        const FieldValue& newState) {
+        updates.emplace_back(primaryKey, newState.mValue.int_value);
     }
 };
 
@@ -205,7 +206,7 @@
     std::unique_ptr<LogEvent> event1 = CreateAcquireWakelockEvent(timestampNs, attributionUids1,
                                                                   attributionTags1, "wakelockName");
     mgr.onLogEvent(*event1);
-    EXPECT_EQ(1, listener->updates.size());
+    ASSERT_EQ(1, listener->updates.size());
     EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
     EXPECT_EQ(1, listener->updates[0].mState);
     listener->updates.clear();
@@ -213,17 +214,17 @@
     std::unique_ptr<LogEvent> event2 = CreateAcquireWakelockEvent(
             timestampNs + 1000, attributionUids1, attributionTags1, "wakelockName");
     mgr.onLogEvent(*event2);
-    EXPECT_EQ(0, listener->updates.size());
+    ASSERT_EQ(0, listener->updates.size());
 
     std::unique_ptr<LogEvent> event3 = CreateReleaseWakelockEvent(
             timestampNs + 2000, attributionUids1, attributionTags1, "wakelockName");
     mgr.onLogEvent(*event3);
-    EXPECT_EQ(0, listener->updates.size());
+    ASSERT_EQ(0, listener->updates.size());
 
     std::unique_ptr<LogEvent> event4 = CreateReleaseWakelockEvent(
             timestampNs + 3000, attributionUids1, attributionTags1, "wakelockName");
     mgr.onLogEvent(*event4);
-    EXPECT_EQ(1, listener->updates.size());
+    ASSERT_EQ(1, listener->updates.size());
     EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
     EXPECT_EQ(0, listener->updates[0].mState);
 }
@@ -247,7 +248,7 @@
             CreateBleScanStateChangedEvent(timestampNs, attributionUids1, attributionTags1,
                                            BleScanStateChanged::ON, false, false, false);
     mgr.onLogEvent(*event1);
-    EXPECT_EQ(1, listener->updates.size());
+    ASSERT_EQ(1, listener->updates.size());
     EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
     EXPECT_EQ(BleScanStateChanged::ON, listener->updates[0].mState);
     FieldValue stateFieldValue;
@@ -259,7 +260,7 @@
             CreateBleScanStateChangedEvent(timestampNs + 1000, attributionUids2, attributionTags1,
                                            BleScanStateChanged::ON, false, false, false);
     mgr.onLogEvent(*event2);
-    EXPECT_EQ(1, listener->updates.size());
+    ASSERT_EQ(1, listener->updates.size());
     EXPECT_EQ(2000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
     EXPECT_EQ(BleScanStateChanged::ON, listener->updates[0].mState);
     mgr.getStateValue(util::BLE_SCAN_STATE_CHANGED, listener->updates[0].mKey, &stateFieldValue);
@@ -270,7 +271,7 @@
             CreateBleScanStateChangedEvent(timestampNs + 2000, attributionUids2, attributionTags1,
                                            BleScanStateChanged::RESET, false, false, false);
     mgr.onLogEvent(*event3);
-    EXPECT_EQ(2, listener->updates.size());
+    ASSERT_EQ(2, listener->updates.size());
     for (const TestStateListener::Update& update : listener->updates) {
         EXPECT_EQ(BleScanStateChanged::OFF, update.mState);
 
@@ -294,7 +295,7 @@
     mgr.onLogEvent(*event);
 
     // check listener was updated
-    EXPECT_EQ(1, listener1->updates.size());
+    ASSERT_EQ(1, listener1->updates.size());
     EXPECT_EQ(DEFAULT_DIMENSION_KEY, listener1->updates[0].mKey);
     EXPECT_EQ(2, listener1->updates[0].mState);
 
@@ -319,7 +320,7 @@
     mgr.onLogEvent(*event);
 
     // check listener was updated
-    EXPECT_EQ(1, listener1->updates.size());
+    ASSERT_EQ(1, listener1->updates.size());
     EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
     EXPECT_EQ(1002, listener1->updates[0].mState);
 
@@ -346,8 +347,8 @@
     EXPECT_EQ(1, mgr.getListenersCount(util::WAKELOCK_STATE_CHANGED));
 
     // Check listener was updated.
-    EXPECT_EQ(1, listener1->updates.size());
-    EXPECT_EQ(3, listener1->updates[0].mKey.getValues().size());
+    ASSERT_EQ(1, listener1->updates.size());
+    ASSERT_EQ(3, listener1->updates[0].mKey.getValues().size());
     EXPECT_EQ(1001, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
     EXPECT_EQ(1, listener1->updates[0].mKey.getValues()[1].mValue.int_value);
     EXPECT_EQ("wakelockName", listener1->updates[0].mKey.getValues()[2].mValue.str_value);
@@ -388,7 +389,7 @@
     mgr.onLogEvent(*event);
 
     // check listener was updated
-    EXPECT_EQ(1, listener1->updates.size());
+    ASSERT_EQ(1, listener1->updates.size());
     EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
     EXPECT_EQ(1, listener1->updates[0].mState);
 
@@ -416,9 +417,9 @@
 
     // check listener was updated
     mgr.onLogEvent(*event1);
-    EXPECT_EQ(0, listener1->updates.size());
+    ASSERT_EQ(0, listener1->updates.size());
     mgr.onLogEvent(*event2);
-    EXPECT_EQ(0, listener1->updates.size());
+    ASSERT_EQ(0, listener1->updates.size());
 }
 
 TEST(StateTrackerTest, TestStateQuery) {
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index 2315fd7..582df0c 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -169,7 +169,6 @@
     return atom_matcher;
 }
 
-
 AtomMatcher CreateScreenTurnedOnAtomMatcher() {
     return CreateScreenStateChangedAtomMatcher("ScreenTurnedOn",
             android::view::DisplayStateEnum::DISPLAY_STATE_ON);
@@ -335,22 +334,46 @@
     return state;
 }
 
+State CreateScreenStateWithSimpleOnOffMap(int64_t screenOnId, int64_t screenOffId) {
+    State state;
+    state.set_id(StringToId("ScreenStateSimpleOnOff"));
+    state.set_atom_id(util::SCREEN_STATE_CHANGED);
+
+    auto map = CreateScreenStateSimpleOnOffMap(screenOnId, screenOffId);
+    *state.mutable_map() = map;
+
+    return state;
+}
+
 StateMap_StateGroup CreateScreenStateOnGroup(int64_t screenOnId) {
     StateMap_StateGroup group;
     group.set_group_id(screenOnId);
-    group.add_value(2);
-    group.add_value(5);
-    group.add_value(6);
+    group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+    group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_VR);
+    group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_ON_SUSPEND);
     return group;
 }
 
 StateMap_StateGroup CreateScreenStateOffGroup(int64_t screenOffId) {
     StateMap_StateGroup group;
     group.set_group_id(screenOffId);
-    group.add_value(0);
-    group.add_value(1);
-    group.add_value(3);
-    group.add_value(4);
+    group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
+    group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE);
+    group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE_SUSPEND);
+    return group;
+}
+
+StateMap_StateGroup CreateScreenStateSimpleOnGroup(int64_t screenOnId) {
+    StateMap_StateGroup group;
+    group.set_group_id(screenOnId);
+    group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+    return group;
+}
+
+StateMap_StateGroup CreateScreenStateSimpleOffGroup(int64_t screenOffId) {
+    StateMap_StateGroup group;
+    group.set_group_id(screenOffId);
+    group.add_value(android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
     return group;
 }
 
@@ -361,6 +384,13 @@
     return map;
 }
 
+StateMap CreateScreenStateSimpleOnOffMap(int64_t screenOnId, int64_t screenOffId) {
+    StateMap map;
+    *map.add_group() = CreateScreenStateSimpleOnGroup(screenOnId);
+    *map.add_group() = CreateScreenStateSimpleOffGroup(screenOffId);
+    return map;
+}
+
 void addPredicateToPredicateCombination(const Predicate& predicate,
                                         Predicate* combinationPredicate) {
     combinationPredicate->mutable_combination()->add_predicate(predicate.id());
@@ -956,11 +986,11 @@
 void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, const int atomId,
                                                    const int uid, const string& tag) {
     EXPECT_EQ(value.field(), atomId);
-    EXPECT_EQ(value.value_tuple().dimensions_value_size(), 2);
+    ASSERT_EQ(value.value_tuple().dimensions_value_size(), 2);
     // Attribution field.
     EXPECT_EQ(value.value_tuple().dimensions_value(0).field(), 1);
     // Uid field.
-    EXPECT_EQ(value.value_tuple().dimensions_value(0).value_tuple().dimensions_value_size(), 1);
+    ASSERT_EQ(value.value_tuple().dimensions_value(0).value_tuple().dimensions_value_size(), 1);
     EXPECT_EQ(value.value_tuple().dimensions_value(0).value_tuple().dimensions_value(0).field(), 1);
     EXPECT_EQ(value.value_tuple().dimensions_value(0).value_tuple().dimensions_value(0).value_int(),
               uid);
@@ -971,7 +1001,7 @@
 
 void ValidateAttributionUidDimension(const DimensionsValue& value, int atomId, int uid) {
     EXPECT_EQ(value.field(), atomId);
-    EXPECT_EQ(value.value_tuple().dimensions_value_size(), 1);
+    ASSERT_EQ(value.value_tuple().dimensions_value_size(), 1);
     // Attribution field.
     EXPECT_EQ(value.value_tuple().dimensions_value(0).field(), 1);
     // Uid only.
@@ -985,7 +1015,7 @@
 
 void ValidateUidDimension(const DimensionsValue& value, int node_idx, int atomId, int uid) {
     EXPECT_EQ(value.field(), atomId);
-    EXPECT_GT(value.value_tuple().dimensions_value_size(), node_idx);
+    ASSERT_GT(value.value_tuple().dimensions_value_size(), node_idx);
     // Attribution field.
     EXPECT_EQ(value.value_tuple().dimensions_value(node_idx).field(), 1);
     EXPECT_EQ(value.value_tuple().dimensions_value(node_idx)
@@ -997,7 +1027,7 @@
 void ValidateAttributionUidAndTagDimension(
     const DimensionsValue& value, int node_idx, int atomId, int uid, const std::string& tag) {
     EXPECT_EQ(value.field(), atomId);
-    EXPECT_GT(value.value_tuple().dimensions_value_size(), node_idx);
+    ASSERT_GT(value.value_tuple().dimensions_value_size(), node_idx);
     // Attribution field.
     EXPECT_EQ(1, value.value_tuple().dimensions_value(node_idx).field());
     // Uid only.
@@ -1016,7 +1046,7 @@
 void ValidateAttributionUidAndTagDimension(
     const DimensionsValue& value, int atomId, int uid, const std::string& tag) {
     EXPECT_EQ(value.field(), atomId);
-    EXPECT_EQ(1, value.value_tuple().dimensions_value_size());
+    ASSERT_EQ(1, value.value_tuple().dimensions_value_size());
     // Attribution field.
     EXPECT_EQ(1, value.value_tuple().dimensions_value(0).field());
     // Uid only.
@@ -1339,7 +1369,7 @@
         // stats_event.h/c uses a vector as opposed to a buffer.
         p.buffer.assign(buffer, buffer + size);
         parcels.push_back(std::move(p));
-        AStatsEvent_write(event);
+        AStatsEvent_release(event);
     }
     resultReceiver->pullFinished(atomTag, /*success=*/true, parcels);
     return Status::ok();
diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h
index dc012c5..6a5d5da 100644
--- a/cmds/statsd/tests/statsd_test_util.h
+++ b/cmds/statsd/tests/statsd_test_util.h
@@ -149,17 +149,30 @@
 // Create State proto for overlay state atom.
 State CreateOverlayState();
 
+// Create State proto for screen state atom with on/off map.
 State CreateScreenStateWithOnOffMap(int64_t screenOnId, int64_t screenOffId);
 
+// Create State proto for screen state atom with simple on/off map.
+State CreateScreenStateWithSimpleOnOffMap(int64_t screenOnId, int64_t screenOffId);
+
 // Create StateGroup proto for ScreenState ON group
 StateMap_StateGroup CreateScreenStateOnGroup(int64_t screenOnId);
 
 // Create StateGroup proto for ScreenState OFF group
 StateMap_StateGroup CreateScreenStateOffGroup(int64_t screenOffId);
 
+// Create StateGroup proto for simple ScreenState ON group
+StateMap_StateGroup CreateScreenStateSimpleOnGroup(int64_t screenOnId);
+
+// Create StateGroup proto for simple ScreenState OFF group
+StateMap_StateGroup CreateScreenStateSimpleOffGroup(int64_t screenOffId);
+
 // Create StateMap proto for ScreenState ON/OFF map
 StateMap CreateScreenStateOnOffMap(int64_t screenOnId, int64_t screenOffId);
 
+// Create StateMap proto for simple ScreenState ON/OFF map
+StateMap CreateScreenStateSimpleOnOffMap(int64_t screenOnId, int64_t screenOffId);
+
 // Add a predicate to the predicate combination.
 void addPredicateToPredicateCombination(const Predicate& predicate, Predicate* combination);
 
diff --git a/cmds/statsd/tests/storage/StorageManager_test.cpp b/cmds/statsd/tests/storage/StorageManager_test.cpp
index 27a86e42..74eafbf 100644
--- a/cmds/statsd/tests/storage/StorageManager_test.cpp
+++ b/cmds/statsd/tests/storage/StorageManager_test.cpp
@@ -49,10 +49,10 @@
     EXPECT_TRUE(result);
 
     EXPECT_EQ(trainInfo.trainVersionCode, trainInfoResult.trainVersionCode);
-    EXPECT_EQ(trainInfo.trainName.size(), trainInfoResult.trainName.size());
+    ASSERT_EQ(trainInfo.trainName.size(), trainInfoResult.trainName.size());
     EXPECT_EQ(trainInfo.trainName, trainInfoResult.trainName);
     EXPECT_EQ(trainInfo.status, trainInfoResult.status);
-    EXPECT_EQ(trainInfo.experimentIds.size(), trainInfoResult.experimentIds.size());
+    ASSERT_EQ(trainInfo.experimentIds.size(), trainInfoResult.experimentIds.size());
     EXPECT_EQ(trainInfo.experimentIds, trainInfoResult.experimentIds);
 }
 
@@ -75,10 +75,10 @@
     EXPECT_TRUE(result);
 
     EXPECT_EQ(trainInfo.trainVersionCode, trainInfoResult.trainVersionCode);
-    EXPECT_EQ(trainInfo.trainName.size(), trainInfoResult.trainName.size());
+    ASSERT_EQ(trainInfo.trainName.size(), trainInfoResult.trainName.size());
     EXPECT_EQ(trainInfo.trainName, trainInfoResult.trainName);
     EXPECT_EQ(trainInfo.status, trainInfoResult.status);
-    EXPECT_EQ(trainInfo.experimentIds.size(), trainInfoResult.experimentIds.size());
+    ASSERT_EQ(trainInfo.experimentIds.size(), trainInfoResult.experimentIds.size());
     EXPECT_EQ(trainInfo.experimentIds, trainInfoResult.experimentIds);
 }
 
diff --git a/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java b/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java
index c35f7fc..3b14be7 100644
--- a/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java
+++ b/cmds/uiautomator/cmds/uiautomator/src/com/android/commands/uiautomator/DumpCommand.java
@@ -16,6 +16,7 @@
 
 package com.android.commands.uiautomator;
 
+import android.accessibilityservice.AccessibilityServiceInfo;
 import android.app.UiAutomation;
 import android.graphics.Point;
 import android.hardware.display.DisplayManagerGlobal;
@@ -61,11 +62,14 @@
     public void run(String[] args) {
         File dumpFile = DEFAULT_DUMP_FILE;
         boolean verboseMode = true;
+        boolean allWindows = false;
 
         for (String arg : args) {
             if (arg.equals("--compressed"))
                 verboseMode = false;
-            else if (!arg.startsWith("-")) {
+            else if (arg.equals("--windows")) {
+                allWindows = true;
+            } else if (!arg.startsWith("-")) {
                 dumpFile = new File(arg);
             }
         }
@@ -85,18 +89,28 @@
         try {
             UiAutomation uiAutomation = automationWrapper.getUiAutomation();
             uiAutomation.waitForIdle(1000, 1000 * 10);
-            AccessibilityNodeInfo info = uiAutomation.getRootInActiveWindow();
-            if (info == null) {
-                System.err.println("ERROR: null root node returned by UiTestAutomationBridge.");
-                return;
-            }
+            if (allWindows) {
+                AccessibilityServiceInfo info = uiAutomation.getServiceInfo();
+                info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
+                uiAutomation.setServiceInfo(info);
+                AccessibilityNodeInfoDumper.dumpWindowsToFile(
+                        uiAutomation.getWindowsOnAllDisplays(), dumpFile,
+                        DisplayManagerGlobal.getInstance());
+            } else {
+                AccessibilityNodeInfo info = uiAutomation.getRootInActiveWindow();
+                if (info == null) {
+                    System.err.println("ERROR: null root node returned by UiTestAutomationBridge.");
+                    return;
+                }
 
-            Display display =
-                    DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
-            int rotation = display.getRotation();
-            Point size = new Point();
-            display.getSize(size);
-            AccessibilityNodeInfoDumper.dumpWindowToFile(info, dumpFile, rotation, size.x, size.y);
+                Display display =
+                        DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
+                int rotation = display.getRotation();
+                Point size = new Point();
+                display.getSize(size);
+                AccessibilityNodeInfoDumper.dumpWindowToFile(info, dumpFile, rotation, size.x,
+                        size.y);
+            }
         } catch (TimeoutException re) {
             System.err.println("ERROR: could not get idle state.");
             return;
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
index 63c51e8..ab198b3 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java
@@ -16,11 +16,17 @@
 
 package com.android.uiautomator.core;
 
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.display.DisplayManagerGlobal;
 import android.os.Environment;
 import android.os.SystemClock;
 import android.util.Log;
+import android.util.SparseArray;
 import android.util.Xml;
+import android.view.Display;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityWindowInfo;
 
 import org.xmlpull.v1.XmlSerializer;
 
@@ -28,6 +34,7 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.StringWriter;
+import java.util.List;
 
 /**
  *
@@ -98,6 +105,95 @@
         Log.w(LOGTAG, "Fetch time: " + (endTime - startTime) + "ms");
     }
 
+    /**
+     * Using {@link AccessibilityWindowInfo} this method will dump some window information and
+     * then walk the layout hierarchy of it's
+     * and generates an xml dump to the location specified by <code>dumpFile</code>
+     * @param allWindows All windows indexed by display-id.
+     * @param dumpFile The file to dump to.
+     */
+    public static void dumpWindowsToFile(SparseArray<List<AccessibilityWindowInfo>> allWindows,
+            File dumpFile, DisplayManagerGlobal displayManager) {
+        if (allWindows.size() == 0) {
+            return;
+        }
+        final long startTime = SystemClock.uptimeMillis();
+        try {
+            FileWriter writer = new FileWriter(dumpFile);
+            XmlSerializer serializer = Xml.newSerializer();
+            StringWriter stringWriter = new StringWriter();
+            serializer.setOutput(stringWriter);
+            serializer.startDocument("UTF-8", true);
+            serializer.startTag("", "displays");
+            for (int d = 0, nd = allWindows.size(); d < nd; ++d) {
+                int displayId = allWindows.keyAt(d);
+                Display display = displayManager.getRealDisplay(displayId);
+                if (display == null) {
+                    continue;
+                }
+                final List<AccessibilityWindowInfo> windows = allWindows.valueAt(d);
+                if (windows.isEmpty()) {
+                    continue;
+                }
+                serializer.startTag("", "display");
+                serializer.attribute("", "id", Integer.toString(displayId));
+                int rotation = display.getRotation();
+                Point size = new Point();
+                display.getSize(size);
+                for (int i = 0, n = windows.size(); i < n; ++i) {
+                    dumpWindowRec(windows.get(i), serializer, i, size.x, size.y, rotation);
+                }
+                serializer.endTag("", "display");
+            }
+            serializer.endTag("", "displays");
+            serializer.endDocument();
+            writer.write(stringWriter.toString());
+            writer.close();
+        } catch (IOException e) {
+            Log.e(LOGTAG, "failed to dump window to file", e);
+        }
+        final long endTime = SystemClock.uptimeMillis();
+        Log.w(LOGTAG, "Fetch time: " + (endTime - startTime) + "ms");
+    }
+
+    private static void dumpWindowRec(AccessibilityWindowInfo winfo, XmlSerializer serializer,
+            int index, int width, int height, int rotation) throws IOException {
+        serializer.startTag("", "window");
+        serializer.attribute("", "index", Integer.toString(index));
+        final CharSequence title = winfo.getTitle();
+        serializer.attribute("", "title", title != null ? title.toString() : "");
+        final Rect tmpBounds = new Rect();
+        winfo.getBoundsInScreen(tmpBounds);
+        serializer.attribute("", "bounds", tmpBounds.toShortString());
+        serializer.attribute("", "active", Boolean.toString(winfo.isActive()));
+        serializer.attribute("", "focused", Boolean.toString(winfo.isFocused()));
+        serializer.attribute("", "accessibility-focused",
+                Boolean.toString(winfo.isAccessibilityFocused()));
+        serializer.attribute("", "id", Integer.toString(winfo.getId()));
+        serializer.attribute("", "layer", Integer.toString(winfo.getLayer()));
+        serializer.attribute("", "type", AccessibilityWindowInfo.typeToString(winfo.getType()));
+        int count = winfo.getChildCount();
+        for (int i = 0; i < count; ++i) {
+            AccessibilityWindowInfo child = winfo.getChild(i);
+            if (child == null) {
+                Log.i(LOGTAG, String.format("Null window child %d/%d, parent: %s", i, count,
+                        winfo.getTitle()));
+                continue;
+            }
+            dumpWindowRec(child, serializer, i, width, height, rotation);
+            child.recycle();
+        }
+        AccessibilityNodeInfo root = winfo.getRoot();
+        if (root != null) {
+            serializer.startTag("", "hierarchy");
+            serializer.attribute("", "rotation", Integer.toString(rotation));
+            dumpNodeRec(root, serializer, 0, width, height);
+            root.recycle();
+            serializer.endTag("", "hierarchy");
+        }
+        serializer.endTag("", "window");
+    }
+
     private static void dumpNodeRec(AccessibilityNodeInfo node, XmlSerializer serializer,int index,
             int width, int height) throws IOException {
         serializer.startTag("", "node");
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index bfae632..af5fafb 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -17,6 +17,8 @@
 package android.app;
 
 import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.inMultiWindowMode;
 import static android.os.Process.myUid;
 
 import static java.lang.Character.MIN_VALUE;
@@ -947,9 +949,8 @@
     /** @hide */
     boolean mEnterAnimationComplete;
 
-    /** Track last dispatched multi-window and PiP mode to client, internal debug purpose **/
-    private Boolean mLastDispatchedIsInMultiWindowMode;
-    private Boolean mLastDispatchedIsInPictureInPictureMode;
+    private boolean mIsInMultiWindowMode;
+    private boolean mIsInPictureInPictureMode;
 
     private final WindowControllerCallback mWindowControllerCallback =
             new WindowControllerCallback() {
@@ -2748,7 +2749,7 @@
      * @return True if the activity is in multi-window mode.
      */
     public boolean isInMultiWindowMode() {
-        return mLastDispatchedIsInMultiWindowMode == Boolean.TRUE;
+        return mIsInMultiWindowMode;
     }
 
     /**
@@ -2791,7 +2792,7 @@
      * @return True if the activity is in picture-in-picture mode.
      */
     public boolean isInPictureInPictureMode() {
-        return mLastDispatchedIsInPictureInPictureMode == Boolean.TRUE;
+        return mIsInPictureInPictureMode;
     }
 
     /**
@@ -7142,14 +7143,19 @@
                 writer.print(mResumed); writer.print(" mStopped=");
                 writer.print(mStopped); writer.print(" mFinished=");
                 writer.println(mFinished);
-        writer.print(innerPrefix); writer.print("mLastDispatchedIsInMultiWindowMode=");
-                writer.print(mLastDispatchedIsInMultiWindowMode);
-                writer.print(" mLastDispatchedIsInPictureInPictureMode=");
-                writer.println(mLastDispatchedIsInPictureInPictureMode);
+        writer.print(innerPrefix); writer.print("mIsInMultiWindowMode=");
+                writer.print(mIsInMultiWindowMode);
+                writer.print(" mIsInPictureInPictureMode=");
+                writer.println(mIsInPictureInPictureMode);
         writer.print(innerPrefix); writer.print("mChangingConfigurations=");
                 writer.println(mChangingConfigurations);
         writer.print(innerPrefix); writer.print("mCurrentConfig=");
                 writer.println(mCurrentConfig);
+        if (getResources().hasOverrideDisplayAdjustments()) {
+            writer.print(innerPrefix);
+            writer.print("FixedRotationAdjustments=");
+            writer.println(getResources().getDisplayAdjustments().getFixedRotationAdjustments());
+        }
 
         mFragments.dumpLoaders(innerPrefix, fd, writer, args);
         mFragments.getFragmentManager().dump(innerPrefix, fd, writer, args);
@@ -7977,6 +7983,11 @@
     final void performCreate(Bundle icicle, PersistableBundle persistentState) {
         dispatchActivityPreCreated(icicle);
         mCanEnterPictureInPicture = true;
+        // initialize mIsInMultiWindowMode and mIsInPictureInPictureMode before onCreate
+        final int windowingMode = getResources().getConfiguration().windowConfiguration
+                .getWindowingMode();
+        mIsInMultiWindowMode = inMultiWindowMode(windowingMode);
+        mIsInPictureInPictureMode = windowingMode == WINDOWING_MODE_PINNED;
         restoreHasCurrentPermissionRequest(icicle);
         if (persistentState != null) {
             onCreate(icicle, persistentState);
@@ -8245,7 +8256,7 @@
         if (mWindow != null) {
             mWindow.onMultiWindowModeChanged();
         }
-        mLastDispatchedIsInMultiWindowMode = isInMultiWindowMode;
+        mIsInMultiWindowMode = isInMultiWindowMode;
         onMultiWindowModeChanged(isInMultiWindowMode, newConfig);
     }
 
@@ -8258,7 +8269,7 @@
         if (mWindow != null) {
             mWindow.onPictureInPictureModeChanged(isInPictureInPictureMode);
         }
-        mLastDispatchedIsInPictureInPictureMode = isInPictureInPictureMode;
+        mIsInPictureInPictureMode = isInPictureInPictureMode;
         onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
     }
 
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 9067069..97b704c 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -601,6 +601,20 @@
     @TestApi
     public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 2;
 
+    // TODO: remove this when development is done.
+    // These are debug flags used between OomAdjuster and AppOpsService to detect and report absence
+    // of the real flags.
+    /** @hide */
+    public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q = 1 << 27;
+    /** @hide */
+    public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q = 1 << 28;
+    /** @hide */
+    public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 29;
+    /** @hide */
+    public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA = 1 << 30;
+    /** @hide */
+    public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 31;
+
     /** @hide all capabilities, the ORing of all flags in {@link ProcessCapability}*/
     @TestApi
     public static final int PROCESS_CAPABILITY_ALL = PROCESS_CAPABILITY_FOREGROUND_LOCATION
@@ -623,6 +637,51 @@
     public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = PROCESS_CAPABILITY_FOREGROUND_CAMERA
             | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
 
+    /**
+     * Print capability bits in human-readable form.
+     * @hide
+     */
+    public static void printCapabilitiesSummary(PrintWriter pw, @ProcessCapability int caps) {
+        pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0 ? 'L' : '-');
+        pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0 ? 'C' : '-');
+        pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0 ? 'M' : '-');
+    }
+
+    /**
+     * Print capability bits in human-readable form.
+     * @hide
+     */
+    public static void printCapabilitiesFull(PrintWriter pw, @ProcessCapability int caps) {
+        printCapabilitiesSummary(pw, caps);
+        if ((caps & DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) {
+            pw.print(" !L");
+        }
+        if ((caps & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
+            pw.print(" !C");
+        }
+        if ((caps & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q) != 0) {
+            pw.print(" !Cq");
+        }
+        if ((caps & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
+            pw.print(" !M");
+        }
+        if ((caps & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q) != 0) {
+            pw.print(" !Mq");
+        }
+        final int remain = caps & ~(PROCESS_CAPABILITY_FOREGROUND_LOCATION
+                | PROCESS_CAPABILITY_FOREGROUND_CAMERA
+                | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
+                | DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION
+                | DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA
+                | DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q
+                | DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
+                | DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q);
+        if (remain != 0) {
+            pw.print('+');
+            pw.print(remain);
+        }
+    }
+
     // NOTE: If PROCESS_STATEs are added, then new fields must be added
     // to frameworks/base/core/proto/android/app/enums.proto and the following method must
     // be updated to correctly map between them.
@@ -2231,7 +2290,8 @@
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeLong(mId);
             ComponentName.writeToParcel(mTopActivityComponent, dest);
-            dest.writeParcelable(mSnapshot, 0);
+            dest.writeParcelable(mSnapshot != null && !mSnapshot.isDestroyed() ? mSnapshot : null,
+                    0);
             dest.writeInt(mColorSpace.getId());
             dest.writeInt(mOrientation);
             dest.writeInt(mRotation);
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index f1472dd..c491eea 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -428,4 +428,17 @@
             String[] requiredPermissions, boolean serialized,
             int userId, int[] appIdWhitelist);
 
+    /**
+     * Add or delete uid from the ActivityManagerService PendingStartActivityUids list.
+     * @param uid uid
+     * @param pending add to the list if true, delete from list if false.
+     */
+    public abstract void updatePendingTopUid(int uid, boolean pending);
+
+    /**
+     * Is the uid in ActivityManagerService PendingStartActivityUids list?
+     * @param uid
+     * @return true if exists, false otherwise.
+     */
+    public abstract boolean isPendingTopUid(int uid);
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b457059..8e43ca3 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -156,6 +156,8 @@
 import android.view.Choreographer;
 import android.view.ContextThemeWrapper;
 import android.view.Display;
+import android.view.DisplayAdjustments;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
 import android.view.ThreadedRenderer;
 import android.view.View;
 import android.view.ViewDebug;
@@ -215,6 +217,7 @@
 import java.util.TimeZone;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
 
 final class RemoteServiceException extends AndroidRuntimeException {
     public RemoteServiceException(String msg) {
@@ -405,6 +408,9 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final ResourcesManager mResourcesManager;
 
+    /** The active adjustments that override the {@link DisplayAdjustments} in resources. */
+    private ArrayList<Pair<IBinder, Consumer<DisplayAdjustments>>> mActiveRotationAdjustments;
+
     // Registry of remote cancellation transports pending a reply with reply handles.
     @GuardedBy("this")
     private @Nullable Map<SafeCancellationTransport, CancellationSignal> mRemoteCancellations;
@@ -541,6 +547,12 @@
         @UnsupportedAppUsage
         boolean mPreserveWindow;
 
+        /**
+         * If non-null, the activity is launching with a specified rotation, the adjustments should
+         * be consumed before activity creation.
+         */
+        FixedRotationAdjustments mPendingFixedRotationAdjustments;
+
         @LifecycleState
         private int mLifecycleState = PRE_ON_CREATE;
 
@@ -557,7 +569,7 @@
                 PersistableBundle persistentState, List<ResultInfo> pendingResults,
                 List<ReferrerIntent> pendingNewIntents, boolean isForward,
                 ProfilerInfo profilerInfo, ClientTransactionHandler client,
-                IBinder assistToken) {
+                IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments) {
             this.token = token;
             this.assistToken = assistToken;
             this.ident = ident;
@@ -575,6 +587,7 @@
             this.overrideConfig = overrideConfig;
             this.packageInfo = client.getPackageInfoNoCheck(activityInfo.applicationInfo,
                     compatInfo);
+            mPendingFixedRotationAdjustments = fixedRotationAdjustments;
             init();
         }
 
@@ -1525,6 +1538,12 @@
             IoUtils.closeQuietly(pfd);
         }
 
+        @Override
+        public void dumpCacheInfo(ParcelFileDescriptor pfd, String[] args) {
+            PropertyInvalidatedCache.dumpCacheInfo(pfd.getFileDescriptor(), args);
+            IoUtils.closeQuietly(pfd);
+        }
+
         private File getDatabasesDir(Context context) {
             // There's no simple way to get the databases/ path, so do it this way.
             return context.getDatabasePath("a").getParentFile();
@@ -3233,6 +3252,44 @@
         sendMessage(H.CLEAN_UP_CONTEXT, cci);
     }
 
+    @Override
+    public void handleFixedRotationAdjustments(@NonNull IBinder token,
+            @Nullable FixedRotationAdjustments fixedRotationAdjustments) {
+        final Consumer<DisplayAdjustments> override = fixedRotationAdjustments != null
+                ? displayAdjustments -> displayAdjustments.setFixedRotationAdjustments(
+                        fixedRotationAdjustments)
+                : null;
+        if (!mResourcesManager.overrideTokenDisplayAdjustments(token, override)) {
+            // No resources are associated with the token.
+            return;
+        }
+        if (mActivities.get(token) == null) {
+            // Only apply the override to application for activity token because the appearance of
+            // activity is usually more sensitive to the application resources.
+            return;
+        }
+
+        // Apply the last override to application resources for compatibility. Because the Resources
+        // of Display can be from application, e.g.
+        //    applicationContext.getSystemService(DisplayManager.class).getDisplay(displayId)
+        // and the deprecated usage:
+        //    applicationContext.getSystemService(WindowManager.class).getDefaultDisplay();
+        final Consumer<DisplayAdjustments> appOverride;
+        if (mActiveRotationAdjustments == null) {
+            mActiveRotationAdjustments = new ArrayList<>(2);
+        }
+        if (override != null) {
+            mActiveRotationAdjustments.add(Pair.create(token, override));
+            appOverride = override;
+        } else {
+            mActiveRotationAdjustments.removeIf(adjustmentsPair -> adjustmentsPair.first == token);
+            appOverride = mActiveRotationAdjustments.isEmpty()
+                    ? null
+                    : mActiveRotationAdjustments.get(mActiveRotationAdjustments.size() - 1).second;
+        }
+        mInitialApplication.getResources().overrideDisplayAdjustments(appOverride);
+    }
+
     /**  Core implementation of activity launch. */
     private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
         ActivityInfo aInfo = r.activityInfo;
@@ -3446,6 +3503,13 @@
         ContextImpl appContext = ContextImpl.createActivityContext(
                 this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
 
+        // The rotation adjustments must be applied before creating the activity, so the activity
+        // can get the adjusted display info during creation.
+        if (r.mPendingFixedRotationAdjustments != null) {
+            handleFixedRotationAdjustments(r.token, r.mPendingFixedRotationAdjustments);
+            r.mPendingFixedRotationAdjustments = null;
+        }
+
         final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
         // For debugging purposes, if the activity's package name contains the value of
         // the "debug.use-second-display" system property as a substring, then show
@@ -5844,6 +5908,12 @@
         }
     }
 
+    /**
+     * Sets the supplied {@code overrideConfig} as pending for the {@code activityToken}. Calling
+     * this method prevents any calls to
+     * {@link #handleActivityConfigurationChanged(IBinder, Configuration, int, boolean)} from
+     * processing any configurations older than {@code overrideConfig}.
+     */
     @Override
     public void updatePendingActivityConfiguration(IBinder activityToken,
             Configuration overrideConfig) {
@@ -5860,13 +5930,22 @@
         }
 
         synchronized (r) {
+            if (r.mPendingOverrideConfig != null
+                    && !r.mPendingOverrideConfig.isOtherSeqNewer(overrideConfig)) {
+                if (DEBUG_CONFIGURATION) {
+                    Slog.v(TAG, "Activity has newer configuration pending so drop this"
+                            + " transaction. overrideConfig=" + overrideConfig
+                            + " r.mPendingOverrideConfig=" + r.mPendingOverrideConfig);
+                }
+                return;
+            }
             r.mPendingOverrideConfig = overrideConfig;
         }
     }
 
     @Override
     public void handleActivityConfigurationChanged(IBinder activityToken,
-            Configuration overrideConfig, int displayId) {
+            @NonNull Configuration overrideConfig, int displayId) {
         handleActivityConfigurationChanged(activityToken, overrideConfig, displayId,
                 // This is the only place that uses alwaysReportChange=true. The entry point should
                 // be from ActivityConfigurationChangeItem or MoveToDisplayItem, so the server side
@@ -5877,15 +5956,18 @@
     }
 
     /**
-     * Handle new activity configuration and/or move to a different display.
+     * Handle new activity configuration and/or move to a different display. This method is a noop
+     * if {@link #updatePendingActivityConfiguration(IBinder, Configuration)} has been called with
+     * a newer config than {@code overrideConfig}.
+     *
      * @param activityToken Target activity token.
      * @param overrideConfig Activity override config.
      * @param displayId Id of the display where activity was moved to, -1 if there was no move and
      *                  value didn't change.
      * @param alwaysReportChange If the configuration is changed, always report to activity.
      */
-    void handleActivityConfigurationChanged(IBinder activityToken, Configuration overrideConfig,
-            int displayId, boolean alwaysReportChange) {
+    void handleActivityConfigurationChanged(IBinder activityToken,
+            @NonNull Configuration overrideConfig, int displayId, boolean alwaysReportChange) {
         ActivityClientRecord r = mActivities.get(activityToken);
         // Check input params.
         if (r == null || r.activity == null) {
@@ -5896,9 +5978,13 @@
                 && displayId != r.activity.getDisplayId();
 
         synchronized (r) {
-            if (r.mPendingOverrideConfig != null
-                    && !r.mPendingOverrideConfig.isOtherSeqNewer(overrideConfig)) {
-                overrideConfig = r.mPendingOverrideConfig;
+            if (overrideConfig.isOtherSeqNewer(r.mPendingOverrideConfig)) {
+                if (DEBUG_CONFIGURATION) {
+                    Slog.v(TAG, "Activity has newer configuration pending so drop this"
+                            + " transaction. overrideConfig=" + overrideConfig
+                            + " r.mPendingOverrideConfig=" + r.mPendingOverrideConfig);
+                }
+                return;
             }
             r.mPendingOverrideConfig = null;
         }
@@ -6144,6 +6230,12 @@
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory");
         if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
 
+        if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
+            for (PropertyInvalidatedCache pic : PropertyInvalidatedCache.getActiveCaches()) {
+                pic.clear();
+            }
+        }
+
         ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
 
         final int N = callbacks.size();
@@ -7455,7 +7547,15 @@
             try {
                 super.rename(oldPath, newPath);
             } catch (ErrnoException e) {
-                if (e.errno == OsConstants.EXDEV && oldPath.startsWith("/storage/")) {
+                // On emulated volumes, we have bind mounts for /Android/data and
+                // /Android/obb, which prevents move from working across those directories
+                // and other directories on the filesystem. To work around that, try to
+                // recover by doing a copy instead.
+                // Note that we only do this for "/storage/emulated", because public volumes
+                // don't have these bind mounts, neither do private volumes that are not
+                // the primary storage.
+                if (e.errno == OsConstants.EXDEV && oldPath.startsWith("/storage/emulated")
+                        && newPath.startsWith("/storage/emulated")) {
                     Log.v(TAG, "Recovering failed rename " + oldPath + " to " + newPath);
                     try {
                         Files.move(new File(oldPath).toPath(), new File(newPath).toPath(),
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index d321288..b058dcd 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -3688,7 +3688,7 @@
         /**
          * @hide
          */
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "{@code "
+        @UnsupportedAppUsage(/*maxTargetSdk = Build.VERSION_CODES.R,*/ publicAlternatives = "{@code "
                 + "#getOpStr()}")
         public int getOp() {
             return mOp;
@@ -3707,7 +3707,7 @@
          * @deprecated Use {@link #getLastAccessTime(int)} instead
          */
         @Deprecated
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "{@code "
+        @UnsupportedAppUsage(/*maxTargetSdk = Build.VERSION_CODES.R,*/ publicAlternatives = "{@code "
                 + "#getLastAccessTime(int)}")
         public long getTime() {
             return getLastAccessTime(OP_FLAGS_ALL);
@@ -3822,7 +3822,7 @@
          * @deprecated Use {@link #getLastRejectTime(int)} instead
          */
         @Deprecated
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "{@code "
+        @UnsupportedAppUsage(/*maxTargetSdk = Build.VERSION_CODES.R,*/ publicAlternatives = "{@code "
                 + "#getLastRejectTime(int)}")
         public long getRejectTime() {
             return getLastRejectTime(OP_FLAGS_ALL);
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 83465b0..2df756e 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -25,6 +25,7 @@
 import android.content.res.Configuration;
 import android.os.IBinder;
 import android.util.MergedConfiguration;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.ReferrerIntent;
@@ -167,6 +168,10 @@
     /** Deliver app configuration change notification. */
     public abstract void handleConfigurationChanged(Configuration config);
 
+    /** Apply addition adjustments to override display information. */
+    public abstract void handleFixedRotationAdjustments(IBinder token,
+            FixedRotationAdjustments fixedRotationAdjustments);
+
     /**
      * Get {@link android.app.ActivityThread.ActivityClientRecord} instance that corresponds to the
      * provided token.
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 3ce7689..be1681b 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -229,7 +229,16 @@
     void unregisterTaskStackListener(in ITaskStackListener listener);
     void setTaskResizeable(int taskId, int resizeableMode);
     void toggleFreeformWindowingMode(in IBinder token);
-    void resizeTask(int taskId, in Rect bounds, int resizeMode);
+
+    /**
+     * Resize the task with given bounds
+     *
+     * @param taskId The id of the task to set the bounds for.
+     * @param bounds The new bounds.
+     * @param resizeMode Resize mode defined as {@code ActivityTaskManager#RESIZE_MODE_*} constants.
+     * @return Return true on success. Otherwise false.
+     */
+    boolean resizeTask(int taskId, in Rect bounds, int resizeMode);
     void moveStackToDisplay(int stackId, int displayId);
     void removeStack(int stackId);
 
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 1f6e4ca..6e9157e 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -119,6 +119,7 @@
             boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable,
             in String[] args);
     void dumpGfxInfo(in ParcelFileDescriptor fd, in String[] args);
+    void dumpCacheInfo(in ParcelFileDescriptor fd, in String[] args);
     void dumpProvider(in ParcelFileDescriptor fd, IBinder servicetoken,
             in String[] args);
     void dumpDbInfo(in ParcelFileDescriptor fd, in String[] args);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 8dfce14..4c3e888 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -58,7 +58,9 @@
 
     void setShowBadge(String pkg, int uid, boolean showBadge);
     boolean canShowBadge(String pkg, int uid);
-    boolean hasSentMessage(String pkg, int uid);
+    boolean isInInvalidMsgState(String pkg, int uid);
+    boolean hasUserDemotedInvalidMsgApp(String pkg, int uid);
+    void setInvalidMsgAppDemoted(String pkg, int uid, boolean isDemoted);
     void setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled);
     /**
      * Updates the notification's enabled state. Additionally locks importance for all of the
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index a033b82..90206b6 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -7209,7 +7209,8 @@
          *
          * <p>Starting in {@link Build.VERSION_CODES#R, this conversation title will be ignored if a
          * valid shortcutId is added via {@link Notification.Builder#setShortcutId(String)}. In this
-         * case, {@link ShortcutInfo#getShortLabel()} will be shown as the conversation title
+         * case, {@link ShortcutInfo#getLongLabel()} (or, if missing,
+         * {@link ShortcutInfo#getShortLabel()}) will be shown as the conversation title
          * instead.
          *
          * <p>This API's behavior was changed in SDK version {@link Build.VERSION_CODES#P}. If your
diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java
index 3110e18..01cf2b94a 100644
--- a/core/java/android/app/PropertyInvalidatedCache.java
+++ b/core/java/android/app/PropertyInvalidatedCache.java
@@ -26,12 +26,20 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FastPrintWriter;
 
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Random;
+import java.util.Set;
+import java.util.WeakHashMap;
 import java.util.concurrent.atomic.AtomicLong;
 
 /**
@@ -197,6 +205,14 @@
     @GuardedBy("sCorkLock")
     private static final HashMap<String, Integer> sCorks = new HashMap<>();
 
+    /**
+     * Weakly references all cache objects in the current process, allowing us to iterate over
+     * them all for purposes like issuing debug dumps and reacting to memory pressure.
+     */
+    @GuardedBy("sCorkLock")
+    private static final WeakHashMap<PropertyInvalidatedCache, Void> sCaches =
+            new WeakHashMap<>();
+
     private final Object mLock = new Object();
 
     /**
@@ -225,6 +241,11 @@
     private boolean mDisabled = false;
 
     /**
+     * Maximum number of entries the cache will maintain.
+     */
+    private final int mMaxEntries;
+
+    /**
      * Make a new property invalidated cache.
      *
      * @param maxEntries Maximum number of entries to cache; LRU discard
@@ -232,6 +253,7 @@
      */
     public PropertyInvalidatedCache(int maxEntries, @NonNull String propertyName) {
         mPropertyName = propertyName;
+        mMaxEntries = maxEntries;
         mCache = new LinkedHashMap<Query, Result>(
             2 /* start small */,
             0.75f /* default load factor */,
@@ -241,6 +263,9 @@
                     return size() > maxEntries;
                 }
             };
+        synchronized (sCorkLock) {
+            sCaches.put(this, null);
+        }
     }
 
     /**
@@ -248,6 +273,9 @@
      */
     public final void clear() {
         synchronized (mLock) {
+            if (DEBUG) {
+                Log.d(TAG, "clearing cache for " + mPropertyName);
+            }
             mCache.clear();
         }
     }
@@ -710,4 +738,87 @@
         Log.d(TAG, "disabling all caches in the process");
         sEnabled = false;
     }
+
+    /**
+     * Returns a list of caches alive at the current time.
+     */
+    public static ArrayList<PropertyInvalidatedCache> getActiveCaches() {
+        synchronized (sCorkLock) {
+            return new ArrayList<PropertyInvalidatedCache>(sCaches.keySet());
+        }
+    }
+
+    /**
+     * Returns a list of the active corks in a process.
+     */
+    public static ArrayList<Map.Entry<String, Integer>> getActiveCorks() {
+        synchronized (sCorkLock) {
+            return new ArrayList<Map.Entry<String, Integer>>(sCorks.entrySet());
+        }
+    }
+
+    private void dumpContents(PrintWriter pw, String[] args) {
+        synchronized (mLock) {
+            pw.println(String.format("  Cache Property Name: %s", cacheName()));
+            pw.println(String.format("    Last Observed Nonce: %d", mLastSeenNonce));
+            pw.println(String.format("    Current Size: %d, Max Size: %d",
+                    mCache.entrySet().size(), mMaxEntries));
+            pw.println(String.format("    Enabled: %s", mDisabled ? "false" : "true"));
+
+            Set<Map.Entry<Query, Result>> cacheEntries = mCache.entrySet();
+            if (cacheEntries.size() == 0) {
+                pw.println("");
+                return;
+            }
+
+            pw.println("");
+            pw.println("    Contents:");
+            for (Map.Entry<Query, Result> entry : cacheEntries) {
+                String key = Objects.toString(entry.getKey());
+                String value = Objects.toString(entry.getValue());
+
+                pw.println(String.format("      Key: %s\n      Value: %s\n", key, value));
+            }
+        }
+    }
+
+    /**
+     * Dumps contents of every cache in the process to the provided FileDescriptor.
+     */
+    public static void dumpCacheInfo(FileDescriptor fd, String[] args) {
+        ArrayList<PropertyInvalidatedCache> activeCaches;
+        ArrayList<Map.Entry<String, Integer>> activeCorks;
+
+        try  (
+            FileOutputStream fout = new FileOutputStream(fd);
+            PrintWriter pw = new FastPrintWriter(fout);
+        ) {
+            if (!sEnabled) {
+                pw.println("  Caching is disabled in this process.");
+                return;
+            }
+
+            synchronized (sCorkLock) {
+                activeCaches = getActiveCaches();
+                activeCorks = getActiveCorks();
+
+                if (activeCorks.size() > 0) {
+                    pw.println("  Corking Status:");
+                    for (int i = 0; i < activeCorks.size(); i++) {
+                        Map.Entry<String, Integer> entry = activeCorks.get(i);
+                        pw.println(String.format("    Property Name: %s Count: %d",
+                                entry.getKey(), entry.getValue()));
+                    }
+                }
+            }
+
+            for (int i = 0; i < activeCaches.size(); i++) {
+                PropertyInvalidatedCache currentCache = activeCaches.get(i);
+                currentCache.dumpContents(pw, args);
+                pw.flush();
+            }
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to dump PropertyInvalidatedCache instances");
+        }
+    }
 }
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 106f8ac..1aae04d 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -59,6 +59,7 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.WeakHashMap;
+import java.util.function.Consumer;
 import java.util.function.Predicate;
 
 /** @hide */
@@ -1296,6 +1297,35 @@
         }
     }
 
+    /**
+     * Overrides the display adjustments of all resources which are associated with the given token.
+     *
+     * @param token The token that owns the resources.
+     * @param override The operation to override the existing display adjustments. If it is null,
+     *                 the override adjustments will be cleared.
+     * @return {@code true} if the override takes effect.
+     */
+    public boolean overrideTokenDisplayAdjustments(IBinder token,
+            @Nullable Consumer<DisplayAdjustments> override) {
+        boolean handled = false;
+        synchronized (this) {
+            final ActivityResources tokenResources = mActivityResourceReferences.get(token);
+            if (tokenResources == null) {
+                return false;
+            }
+            final ArrayList<WeakReference<Resources>> resourcesRefs =
+                    tokenResources.activityResources;
+            for (int i = resourcesRefs.size() - 1; i >= 0; i--) {
+                final Resources res = resourcesRefs.get(i).get();
+                if (res != null) {
+                    res.overrideDisplayAdjustments(override);
+                    handled = true;
+                }
+            }
+        }
+        return handled;
+    }
+
     private class UpdateHandler implements Resources.UpdateCallbacks {
 
         /**
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 8073982..c650643 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -6031,10 +6031,12 @@
      * this API to enforce auto time will result in
      * {@link UserManager#DISALLOW_CONFIG_DATE_TIME} being set, while calling this API to lift
      * the requirement will result in {@link UserManager#DISALLOW_CONFIG_DATE_TIME} being cleared.
+     * From Android 11, this API can also no longer be called on a managed profile.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param required Whether auto time is set required or not.
-     * @throws SecurityException if {@code admin} is not a device owner.
+     * @throws SecurityException if {@code admin} is not a device owner, not a profile owner or
+     * if this API is called on a managed profile.
      * @deprecated From {@link android.os.Build.VERSION_CODES#R}. Use {@link #setAutoTimeEnabled}
      * to turn auto time on or off and use {@link UserManager#DISALLOW_CONFIG_DATE_TIME}
      * to prevent the user from changing this setting.
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 41f04f7..8f5dbc4 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -217,4 +217,9 @@
      */
     public abstract void broadcastIntentToCrossProfileManifestReceiversAsUser(Intent intent,
             UserHandle parentHandle, boolean requiresPermission);
+
+    /**
+     * Returns the profile owner component for the given user, or {@code null} if there is not one.
+     */
+    public abstract ComponentName getProfileOwnerAsUser(int userHandle);
 }
diff --git a/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java b/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java
index 0d4e16b..8b52242 100644
--- a/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java
+++ b/core/java/android/app/servertransaction/ActivityConfigurationChangeItem.java
@@ -19,6 +19,7 @@
 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
 import static android.view.Display.INVALID_DISPLAY;
 
+import android.annotation.NonNull;
 import android.app.ClientTransactionHandler;
 import android.content.res.Configuration;
 import android.os.IBinder;
@@ -37,6 +38,8 @@
 
     @Override
     public void preExecute(android.app.ClientTransactionHandler client, IBinder token) {
+        // Notify the client of an upcoming change in the token configuration. This ensures that
+        // batches of config change items only process the newest configuration.
         client.updatePendingActivityConfiguration(token, mConfiguration);
     }
 
@@ -55,7 +58,11 @@
     private ActivityConfigurationChangeItem() {}
 
     /** Obtain an instance initialized with provided params. */
-    public static ActivityConfigurationChangeItem obtain(Configuration config) {
+    public static ActivityConfigurationChangeItem obtain(@NonNull Configuration config) {
+        if (config == null) {
+            throw new IllegalArgumentException("Config must not be null.");
+        }
+
         ActivityConfigurationChangeItem instance =
                 ObjectPool.obtain(ActivityConfigurationChangeItem.class);
         if (instance == null) {
@@ -68,7 +75,7 @@
 
     @Override
     public void recycle() {
-        mConfiguration = null;
+        mConfiguration = Configuration.EMPTY;
         ObjectPool.recycle(this);
     }
 
diff --git a/core/java/android/app/servertransaction/FixedRotationAdjustmentsItem.java b/core/java/android/app/servertransaction/FixedRotationAdjustmentsItem.java
new file mode 100644
index 0000000..6183d5f
--- /dev/null
+++ b/core/java/android/app/servertransaction/FixedRotationAdjustmentsItem.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.servertransaction;
+
+import android.app.ClientTransactionHandler;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
+
+import java.util.Objects;
+
+/**
+ * The request to update display adjustments for a rotated activity or window token.
+ * @hide
+ */
+public class FixedRotationAdjustmentsItem extends ClientTransactionItem {
+
+    /** The token who may have {@link android.content.res.Resources}. */
+    private IBinder mToken;
+
+    /**
+     * The adjustments for the display adjustments of resources. If it is null, the existing
+     * rotation adjustments will be dropped to restore natural state.
+     */
+    private FixedRotationAdjustments mFixedRotationAdjustments;
+
+    private FixedRotationAdjustmentsItem() {}
+
+    /** Obtain an instance initialized with provided params. */
+    public static FixedRotationAdjustmentsItem obtain(IBinder token,
+            FixedRotationAdjustments fixedRotationAdjustments) {
+        FixedRotationAdjustmentsItem instance =
+                ObjectPool.obtain(FixedRotationAdjustmentsItem.class);
+        if (instance == null) {
+            instance = new FixedRotationAdjustmentsItem();
+        }
+        instance.mToken = token;
+        instance.mFixedRotationAdjustments = fixedRotationAdjustments;
+
+        return instance;
+    }
+
+    @Override
+    public void execute(ClientTransactionHandler client, IBinder token,
+            PendingTransactionActions pendingActions) {
+        client.handleFixedRotationAdjustments(mToken, mFixedRotationAdjustments);
+    }
+
+    @Override
+    public void recycle() {
+        mToken = null;
+        mFixedRotationAdjustments = null;
+        ObjectPool.recycle(this);
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeStrongBinder(mToken);
+        dest.writeTypedObject(mFixedRotationAdjustments, flags);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        final FixedRotationAdjustmentsItem other = (FixedRotationAdjustmentsItem) o;
+        return Objects.equals(mToken, other.mToken)
+                && Objects.equals(mFixedRotationAdjustments, other.mFixedRotationAdjustments);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = 17;
+        result = 31 * result + Objects.hashCode(mToken);
+        result = 31 * result + Objects.hashCode(mFixedRotationAdjustments);
+        return result;
+    }
+
+    private FixedRotationAdjustmentsItem(Parcel in) {
+        mToken = in.readStrongBinder();
+        mFixedRotationAdjustments = in.readTypedObject(FixedRotationAdjustments.CREATOR);
+    }
+
+    public static final Creator<FixedRotationAdjustmentsItem> CREATOR =
+            new Creator<FixedRotationAdjustmentsItem>() {
+        public FixedRotationAdjustmentsItem createFromParcel(Parcel in) {
+            return new FixedRotationAdjustmentsItem(in);
+        }
+
+        public FixedRotationAdjustmentsItem[] newArray(int size) {
+            return new FixedRotationAdjustmentsItem[size];
+        }
+    };
+}
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 9ab6e7f..2e7b626 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -33,6 +33,7 @@
 import android.os.Parcel;
 import android.os.PersistableBundle;
 import android.os.Trace;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
 
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.content.ReferrerIntent;
@@ -64,6 +65,7 @@
     private boolean mIsForward;
     private ProfilerInfo mProfilerInfo;
     private IBinder mAssistToken;
+    private FixedRotationAdjustments mFixedRotationAdjustments;
 
     @Override
     public void preExecute(ClientTransactionHandler client, IBinder token) {
@@ -79,7 +81,7 @@
         ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                 mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                 mPendingResults, mPendingNewIntents, mIsForward,
-                mProfilerInfo, client, mAssistToken);
+                mProfilerInfo, client, mAssistToken, mFixedRotationAdjustments);
         client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     }
@@ -101,14 +103,14 @@
             String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
             PersistableBundle persistentState, List<ResultInfo> pendingResults,
             List<ReferrerIntent> pendingNewIntents, boolean isForward, ProfilerInfo profilerInfo,
-            IBinder assistToken) {
+            IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments) {
         LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class);
         if (instance == null) {
             instance = new LaunchActivityItem();
         }
         setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer,
                 voiceInteractor, procState, state, persistentState, pendingResults,
-                pendingNewIntents, isForward, profilerInfo, assistToken);
+                pendingNewIntents, isForward, profilerInfo, assistToken, fixedRotationAdjustments);
 
         return instance;
     }
@@ -116,7 +118,7 @@
     @Override
     public void recycle() {
         setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null,
-                false, null, null);
+                false, null, null, null);
         ObjectPool.recycle(this);
     }
 
@@ -142,6 +144,7 @@
         dest.writeBoolean(mIsForward);
         dest.writeTypedObject(mProfilerInfo, flags);
         dest.writeStrongBinder(mAssistToken);
+        dest.writeTypedObject(mFixedRotationAdjustments, flags);
     }
 
     /** Read from Parcel. */
@@ -156,7 +159,8 @@
                 in.createTypedArrayList(ResultInfo.CREATOR),
                 in.createTypedArrayList(ReferrerIntent.CREATOR), in.readBoolean(),
                 in.readTypedObject(ProfilerInfo.CREATOR),
-                in.readStrongBinder());
+                in.readStrongBinder(),
+                in.readTypedObject(FixedRotationAdjustments.CREATOR));
     }
 
     public static final @android.annotation.NonNull Creator<LaunchActivityItem> CREATOR =
@@ -192,7 +196,8 @@
                 && Objects.equals(mPendingNewIntents, other.mPendingNewIntents)
                 && mIsForward == other.mIsForward
                 && Objects.equals(mProfilerInfo, other.mProfilerInfo)
-                && Objects.equals(mAssistToken, other.mAssistToken);
+                && Objects.equals(mAssistToken, other.mAssistToken)
+                && Objects.equals(mFixedRotationAdjustments, other.mFixedRotationAdjustments);
     }
 
     @Override
@@ -212,6 +217,7 @@
         result = 31 * result + (mIsForward ? 1 : 0);
         result = 31 * result + Objects.hashCode(mProfilerInfo);
         result = 31 * result + Objects.hashCode(mAssistToken);
+        result = 31 * result + Objects.hashCode(mFixedRotationAdjustments);
         return result;
     }
 
@@ -247,7 +253,7 @@
                 + ",referrer=" + mReferrer + ",procState=" + mProcState + ",state=" + mState
                 + ",persistentState=" + mPersistentState + ",pendingResults=" + mPendingResults
                 + ",pendingNewIntents=" + mPendingNewIntents + ",profilerInfo=" + mProfilerInfo
-                + " assistToken=" + mAssistToken
+                + ",assistToken=" + mAssistToken + ",rotationAdj=" + mFixedRotationAdjustments
                 + "}";
     }
 
@@ -257,7 +263,8 @@
             CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
             int procState, Bundle state, PersistableBundle persistentState,
             List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
-            boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken) {
+            boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken,
+            FixedRotationAdjustments fixedRotationAdjustments) {
         instance.mIntent = intent;
         instance.mIdent = ident;
         instance.mInfo = info;
@@ -274,5 +281,6 @@
         instance.mIsForward = isForward;
         instance.mProfilerInfo = profilerInfo;
         instance.mAssistToken = assistToken;
+        instance.mFixedRotationAdjustments = fixedRotationAdjustments;
     }
 }
diff --git a/core/java/android/app/servertransaction/MoveToDisplayItem.java b/core/java/android/app/servertransaction/MoveToDisplayItem.java
index f6d3dbd..9a457a3 100644
--- a/core/java/android/app/servertransaction/MoveToDisplayItem.java
+++ b/core/java/android/app/servertransaction/MoveToDisplayItem.java
@@ -18,6 +18,7 @@
 
 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
 
+import android.annotation.NonNull;
 import android.app.ClientTransactionHandler;
 import android.content.res.Configuration;
 import android.os.IBinder;
@@ -36,6 +37,13 @@
     private Configuration mConfiguration;
 
     @Override
+    public void preExecute(ClientTransactionHandler client, IBinder token) {
+        // Notify the client of an upcoming change in the token configuration. This ensures that
+        // batches of config change items only process the newest configuration.
+        client.updatePendingActivityConfiguration(token, mConfiguration);
+    }
+
+    @Override
     public void execute(ClientTransactionHandler client, IBinder token,
             PendingTransactionActions pendingActions) {
         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityMovedToDisplay");
@@ -49,7 +57,12 @@
     private MoveToDisplayItem() {}
 
     /** Obtain an instance initialized with provided params. */
-    public static MoveToDisplayItem obtain(int targetDisplayId, Configuration configuration) {
+    public static MoveToDisplayItem obtain(int targetDisplayId,
+            @NonNull Configuration configuration) {
+        if (configuration == null) {
+            throw new IllegalArgumentException("Configuration must not be null");
+        }
+
         MoveToDisplayItem instance = ObjectPool.obtain(MoveToDisplayItem.class);
         if (instance == null) {
             instance = new MoveToDisplayItem();
@@ -63,7 +76,7 @@
     @Override
     public void recycle() {
         mTargetDisplayId = 0;
-        mConfiguration = null;
+        mConfiguration = Configuration.EMPTY;
         ObjectPool.recycle(this);
     }
 
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 75ce0dc..3fef92b 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -625,7 +625,10 @@
                     }
                 }
                 defaultView = inflater.inflate(layoutId, this, false);
-                defaultView.setOnClickListener(this::onDefaultViewClicked);
+                if (!(defaultView instanceof AdapterView)) {
+                    // AdapterView does not support onClickListener
+                    defaultView.setOnClickListener(this::onDefaultViewClicked);
+                }
             } else {
                 Log.w(TAG, "can't inflate defaultView because mInfo is missing");
             }
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 745add1..79da1f6 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -1183,7 +1183,8 @@
                     return NO_MATCH_DATA;
                 }
             }
-            if (mPort >= 0) {
+            // if we're dealing with wildcard support, we ignore ports
+            if (!wildcardSupported && mPort >= 0) {
                 if (mPort != data.getPort()) {
                     return NO_MATCH_DATA;
                 }
@@ -1580,12 +1581,13 @@
      * @param wildcardSupported if true, will allow parameters to use wildcards
      */
     private int matchData(String type, String scheme, Uri data, boolean wildcardSupported) {
-        final ArrayList<String> types = mDataTypes;
+        final boolean wildcardWithMimegroups = wildcardSupported && countMimeGroups() != 0;
+        final List<String> types = mDataTypes;
         final ArrayList<String> schemes = mDataSchemes;
 
         int match = MATCH_CATEGORY_EMPTY;
 
-        if (types == null && schemes == null) {
+        if (!wildcardWithMimegroups && types == null && schemes == null) {
             return ((type == null && data == null)
                 ? (MATCH_CATEGORY_EMPTY+MATCH_ADJUSTMENT_NORMAL) : NO_MATCH_DATA);
         }
@@ -1640,7 +1642,9 @@
             }
         }
 
-        if (types != null) {
+        if (wildcardWithMimegroups) {
+            return MATCH_CATEGORY_TYPE;
+        } else if (types != null) {
             if (findMimeType(type)) {
                 match = MATCH_CATEGORY_TYPE;
             } else {
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index 37baae3..0105896 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -51,6 +51,9 @@
     void uninstall(in VersionedPackage versionedPackage, String callerPackageName, int flags,
             in IntentSender statusReceiver, int userId);
 
+    void uninstallExistingPackage(in VersionedPackage versionedPackage, String callerPackageName,
+            in IntentSender statusReceiver, int userId);
+
     void installExistingPackage(String packageName, int installFlags, int installReason,
             in IntentSender statusReceiver, int userId, in List<String> whiteListedPermissions);
 
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 8bebaff..f257326 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -235,6 +235,16 @@
     void deletePackageVersioned(in VersionedPackage versionedPackage,
             IPackageDeleteObserver2 observer, int userId, int flags);
 
+    /**
+     * Delete a package for a specific user.
+     *
+     * @param versionedPackage The package to delete.
+     * @param observer a callback to use to notify when the package deletion in finished.
+     * @param userId the id of the user for whom to delete the package
+     */
+    void deleteExistingPackageAsUser(in VersionedPackage versionedPackage,
+            IPackageDeleteObserver2 observer, int userId);
+
     @UnsupportedAppUsage
     String getInstallerPackageName(in String packageName);
 
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 85a3986..ed75504 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -720,6 +720,27 @@
         }
     }
 
+    /**
+     * Uninstall the given package for the user for which this installer was created if the package
+     * will still exist for other users on the device.
+     *
+     * @param packageName The package to install.
+     * @param statusReceiver Where to deliver the result.
+     *
+     * {@hide}
+     */
+    @RequiresPermission(Manifest.permission.DELETE_PACKAGES)
+    public void uninstallExistingPackage(@NonNull String packageName,
+            @Nullable IntentSender statusReceiver) {
+        Objects.requireNonNull(packageName, "packageName cannot be null");
+        try {
+            mInstaller.uninstallExistingPackage(
+                    new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST),
+                    mInstallerPackageName, statusReceiver, mUserId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 
     /** {@hide} */
     @SystemApi
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index d41ace5..f354bdb 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -24,6 +24,7 @@
 import android.annotation.FloatRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.app.ActivityThread;
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -194,7 +195,7 @@
      * item does not have a label, its name is returned.
      */
     public @NonNull CharSequence loadLabel(@NonNull PackageManager pm) {
-        if (sForceSafeLabels) {
+        if (sForceSafeLabels && !Objects.equals(packageName, ActivityThread.currentPackageName())) {
             return loadSafeLabel(pm, DEFAULT_MAX_LABEL_SIZE_PX, SAFE_STRING_FLAG_TRIM
                     | SAFE_STRING_FLAG_FIRST_LINE);
         } else {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 4d718ef..2f488cd 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -51,7 +51,9 @@
 import android.content.pm.parsing.PackageInfoWithoutStateUtils;
 import android.content.pm.parsing.ParsingPackage;
 import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.parsing.result.ParseInput;
 import android.content.pm.parsing.result.ParseResult;
+import android.content.pm.parsing.result.ParseTypeImpl;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.graphics.Rect;
@@ -383,6 +385,9 @@
      * <p>
      * Note: this flag may cause less information about currently installed
      * applications to be returned.
+     * <p>
+     * Note: use of this flag requires the android.permission.QUERY_ALL_PACKAGES
+     * permission to see uninstalled packages.
      */
     public static final int MATCH_UNINSTALLED_PACKAGES = 0x00002000;
 
@@ -3049,6 +3054,16 @@
     public static final String FEATURE_IPSEC_TUNNELS = "android.software.ipsec_tunnels";
 
     /**
+     * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature}: The device supports a system interface for the user to select
+     * and bind device control services provided by applications.
+     *
+     * @see android.service.controls.ControlsProviderService
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_CONTROLS = "android.software.controls";
+
+    /**
      * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device has
      * the requisite hardware support to support reboot escrow of synthetic password for updates.
      *
@@ -6051,7 +6066,8 @@
         boolean collectCertificates = (flags & PackageManager.GET_SIGNATURES) != 0
                 || (flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0;
 
-        ParseResult<ParsingPackage> result = ParsingPackageUtils.parseDefaultOneTime(
+        ParseInput input = ParseTypeImpl.forParsingWithoutPlatformCompat().reset();
+        ParseResult<ParsingPackage> result = ParsingPackageUtils.parseDefault(input,
                 new File(archiveFilePath), 0, collectCertificates);
         if (result.isError()) {
             return null;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 312e98e..d086459 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -127,7 +127,6 @@
 import java.util.List;
 import java.util.Set;
 import java.util.UUID;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Parser for package files (APKs) on disk. This supports apps packaged either
@@ -239,11 +238,6 @@
 
     public static final boolean LOG_UNSAFE_BROADCASTS = false;
 
-    /**
-     * Total number of packages that were read from the cache.  We use it only for logging.
-     */
-    public static final AtomicInteger sCachedPackageReadCount = new AtomicInteger();
-
     // Set of broadcast actions that are safe for manifest receivers
     public static final Set<String> SAFE_BROADCASTS = new ArraySet<>();
     static {
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 85bf11c..dcc6cb2 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -1450,6 +1450,21 @@
         return mText;
     }
 
+    /**
+     * Returns the {@link #getLongLabel()} if it's populated, and if not, the
+     * {@link #getShortLabel()}.
+     * @hide
+     */
+    @Nullable
+    public CharSequence getLabel() {
+        CharSequence label = getLongLabel();
+        if (TextUtils.isEmpty(label)) {
+            label = getShortLabel();
+        }
+
+        return label;
+    }
+
     /** @hide */
     public int getLongLabelResourceId() {
         return mTextResId;
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index cb29431..5a79475 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -131,14 +131,23 @@
     public static final String TAG = ParsingUtils.TAG;
 
     /**
-     * For cases outside of PackageManagerService when an APK needs to be parsed as a one-off
-     * request, without caching the input object and without querying the internal system state
-     * for feature support.
+     * @see #parseDefault(ParseInput, File, int, boolean)
      */
     @NonNull
     public static ParseResult<ParsingPackage> parseDefaultOneTime(File file,
             @PackageParser.ParseFlags int parseFlags, boolean collectCertificates) {
         ParseInput input = ParseTypeImpl.forDefaultParsing().reset();
+        return parseDefault(input, file, parseFlags, collectCertificates);
+    }
+
+    /**
+     * For cases outside of PackageManagerService when an APK needs to be parsed as a one-off
+     * request, without caching the input object and without querying the internal system state
+     * for feature support.
+     */
+    @NonNull
+    public static ParseResult<ParsingPackage> parseDefault(ParseInput input, File file,
+            @PackageParser.ParseFlags int parseFlags, boolean collectCertificates) {
         ParseResult<ParsingPackage> result;
 
         ParsingPackageUtils parser = new ParsingPackageUtils(false, null, null, new Callback() {
diff --git a/core/java/android/content/pm/parsing/result/ParseInput.java b/core/java/android/content/pm/parsing/result/ParseInput.java
index d5898b7..0fb18ae 100644
--- a/core/java/android/content/pm/parsing/result/ParseInput.java
+++ b/core/java/android/content/pm/parsing/result/ParseInput.java
@@ -16,6 +16,7 @@
 
 package android.content.pm.parsing.result;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.ChangeId;
@@ -69,6 +70,25 @@
         @ChangeId
         @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
         public static final long RESOURCES_ARSC_COMPRESSED = 132742131;
+
+        /**
+         * TODO(chiuwinson): This is required because PackageManager#getPackageArchiveInfo
+         *   cannot read the targetSdk info from the changeId because it requires the
+         *   READ_COMPAT_CHANGE_CONFIG which cannot be obtained automatically without entering the
+         *   server process. This should be removed once an alternative is found, or if the API
+         *   is removed.
+         * @return the targetSdk that this change is gated on (> check), or -1 if disabled
+         */
+        @IntRange(from = -1, to = Integer.MAX_VALUE)
+        public static int getTargetSdkForChange(long changeId) {
+            if (changeId == MISSING_APP_TAG
+                    || changeId == EMPTY_INTENT_ACTION_CATEGORY
+                    || changeId == RESOURCES_ARSC_COMPRESSED) {
+                return Build.VERSION_CODES.Q;
+            }
+
+            return -1;
+        }
     }
 
     <ResultType> ParseResult<ResultType> success(ResultType result);
diff --git a/core/java/android/content/pm/parsing/result/ParseTypeImpl.java b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java
index 91e571b..14992fb 100644
--- a/core/java/android/content/pm/parsing/result/ParseTypeImpl.java
+++ b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java
@@ -65,6 +65,21 @@
     private Integer mTargetSdkVersion;
 
     /**
+     * Specifically for {@link PackageManager#getPackageArchiveInfo(String, int)} where
+     * {@link IPlatformCompat} cannot be used because the cross-package READ_COMPAT_CHANGE_CONFIG
+     * permission cannot be obtained.
+     */
+    public static ParseTypeImpl forParsingWithoutPlatformCompat() {
+        return new ParseTypeImpl((changeId, packageName, targetSdkVersion) -> {
+            int gateSdkVersion = DeferredError.getTargetSdkForChange(changeId);
+            if (gateSdkVersion == -1) {
+                return false;
+            }
+            return targetSdkVersion > gateSdkVersion;
+        });
+    }
+
+    /**
      * Assumes {@link Context#PLATFORM_COMPAT_SERVICE} is available to the caller. For use
      * with {@link android.content.pm.parsing.ApkLiteParseUtils} or similar where parsing is
      * done outside of {@link com.android.server.pm.PackageManagerService}.
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index c399bc7..0f1c876 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -81,6 +81,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.function.Consumer;
 
 /**
  * Class for accessing an application's resources.  This sits on top of the
@@ -140,6 +141,9 @@
     @UnsupportedAppUsage
     private DrawableInflater mDrawableInflater;
 
+    /** Used to override the returned adjustments of {@link #getDisplayAdjustments}. */
+    private DisplayAdjustments mOverrideDisplayAdjustments;
+
     /** Lock object used to protect access to {@link #mTmpValue}. */
     private final Object mTmpValueLock = new Object();
 
@@ -2055,10 +2059,41 @@
     /** @hide */
     @UnsupportedAppUsage
     public DisplayAdjustments getDisplayAdjustments() {
+        final DisplayAdjustments overrideDisplayAdjustments = mOverrideDisplayAdjustments;
+        if (overrideDisplayAdjustments != null) {
+            return overrideDisplayAdjustments;
+        }
         return mResourcesImpl.getDisplayAdjustments();
     }
 
     /**
+     * Customize the display adjustments based on the current one in {@link #mResourcesImpl}, in
+     * order to isolate the effect with other instances of {@link Resource} that may share the same
+     * instance of {@link ResourcesImpl}.
+     *
+     * @param override The operation to override the existing display adjustments. If it is null,
+     *                 the override adjustments will be cleared.
+     * @hide
+     */
+    public void overrideDisplayAdjustments(@Nullable Consumer<DisplayAdjustments> override) {
+        if (override != null) {
+            mOverrideDisplayAdjustments = new DisplayAdjustments(
+                    mResourcesImpl.getDisplayAdjustments());
+            override.accept(mOverrideDisplayAdjustments);
+        } else {
+            mOverrideDisplayAdjustments = null;
+        }
+    }
+
+    /**
+     * Return {@code true} if the override display adjustments have been set.
+     * @hide
+     */
+    public boolean hasOverrideDisplayAdjustments() {
+        return mOverrideDisplayAdjustments != null;
+    }
+
+    /**
      * Return the current configuration that is in effect for this resource 
      * object.  The returned object should be treated as read-only.
      * 
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 9b809b8..b978ae5 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -191,6 +191,58 @@
         }
     }
 
+    /** {@hide} */
+    public static long executeInsert(@NonNull SQLiteDatabase db, @NonNull String sql,
+            @Nullable Object[] bindArgs) throws SQLException {
+        try (SQLiteStatement st = db.compileStatement(sql)) {
+            bindArgs(st, bindArgs);
+            return st.executeInsert();
+        }
+    }
+
+    /** {@hide} */
+    public static int executeUpdateDelete(@NonNull SQLiteDatabase db, @NonNull String sql,
+            @Nullable Object[] bindArgs) throws SQLException {
+        try (SQLiteStatement st = db.compileStatement(sql)) {
+            bindArgs(st, bindArgs);
+            return st.executeUpdateDelete();
+        }
+    }
+
+    /** {@hide} */
+    private static void bindArgs(@NonNull SQLiteStatement st, @Nullable Object[] bindArgs) {
+        if (bindArgs == null) return;
+
+        for (int i = 0; i < bindArgs.length; i++) {
+            final Object bindArg = bindArgs[i];
+            switch (getTypeOfObject(bindArg)) {
+                case Cursor.FIELD_TYPE_NULL:
+                    st.bindNull(i + 1);
+                    break;
+                case Cursor.FIELD_TYPE_INTEGER:
+                    st.bindLong(i + 1, ((Number) bindArg).longValue());
+                    break;
+                case Cursor.FIELD_TYPE_FLOAT:
+                    st.bindDouble(i + 1, ((Number) bindArg).doubleValue());
+                    break;
+                case Cursor.FIELD_TYPE_BLOB:
+                    st.bindBlob(i + 1, (byte[]) bindArg);
+                    break;
+                case Cursor.FIELD_TYPE_STRING:
+                default:
+                    if (bindArg instanceof Boolean) {
+                        // Provide compatibility with legacy
+                        // applications which may pass Boolean values in
+                        // bind args.
+                        st.bindLong(i + 1, ((Boolean) bindArg).booleanValue() ? 1 : 0);
+                    } else {
+                        st.bindString(i + 1, bindArg.toString());
+                    }
+                    break;
+            }
+        }
+    }
+
     /**
      * Binds the given Object to the given SQLiteProgram using the proper
      * typing. For example, bind numbers as longs/doubles, and everything else
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index 36ec67e..669d046 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -626,7 +626,7 @@
                 Log.d(TAG, sql);
             }
         }
-        return db.executeSql(sql, sqlArgs);
+        return DatabaseUtils.executeInsert(db, sql, sqlArgs);
     }
 
     /**
@@ -702,7 +702,7 @@
                 Log.d(TAG, sql);
             }
         }
-        return db.executeSql(sql, sqlArgs);
+        return DatabaseUtils.executeUpdateDelete(db, sql, sqlArgs);
     }
 
     /**
@@ -762,7 +762,7 @@
                 Log.d(TAG, sql);
             }
         }
-        return db.executeSql(sql, sqlArgs);
+        return DatabaseUtils.executeUpdateDelete(db, sql, sqlArgs);
     }
 
     private void enforceStrictColumns(@Nullable String[] projection) {
diff --git a/core/java/android/debug/AdbNotifications.java b/core/java/android/debug/AdbNotifications.java
index fed5f5f..9f1a5f8 100644
--- a/core/java/android/debug/AdbNotifications.java
+++ b/core/java/android/debug/AdbNotifications.java
@@ -17,11 +17,13 @@
 package android.debug;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -42,8 +44,9 @@
      * Builds a notification to show connected state for adb over a transport type.
      * @param context the context
      * @param transportType the adb transport type.
-     * @return a newly created Notification for the transport type.
+     * @return a newly created Notification for the transport type, or null on error.
      */
+    @Nullable
     public static Notification createNotification(@NonNull Context context,
             byte transportType) {
         Resources resources = context.getResources();
@@ -66,10 +69,16 @@
 
         Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
-        intent.setPackage(context.getPackageManager().resolveActivity(intent,
-                PackageManager.MATCH_SYSTEM_ONLY).activityInfo.packageName);
-        PendingIntent pIntent = PendingIntent.getActivityAsUser(context, 0, intent,
-                PendingIntent.FLAG_IMMUTABLE, null, UserHandle.CURRENT);
+        ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(intent,
+                PackageManager.MATCH_SYSTEM_ONLY);
+        // Settings app may not be available (e.g. device policy manager removes it)
+        PendingIntent pIntent = null;
+        if (resolveInfo != null) {
+            intent.setPackage(resolveInfo.activityInfo.packageName);
+            pIntent = PendingIntent.getActivityAsUser(context, 0, intent,
+                    PendingIntent.FLAG_IMMUTABLE, null, UserHandle.CURRENT);
+        }
+
 
         return new Notification.Builder(context, SystemNotificationChannels.DEVELOPER_IMPORTANT)
                 .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 2012039..b149d77 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -43,6 +43,10 @@
  * through the {@link CameraManager CameraManager}
  * interface with {@link CameraManager#getCameraCharacteristics}.</p>
  *
+ * <p>When obtained by a client that does not hold the CAMERA permission, some metadata values are
+ * not included. The list of keys that require the permission is given by
+ * {@link #getKeysNeedingPermission}.</p>
+ *
  * <p>{@link CameraCharacteristics} objects are immutable.</p>
  *
  * @see CameraDevice
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index e81c649..6bbc37a 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -34,6 +34,7 @@
 import android.hardware.camera2.params.SessionConfiguration;
 import android.hardware.camera2.utils.CameraIdAndSessionConfiguration;
 import android.hardware.camera2.utils.ConcurrentCameraIdCombination;
+import android.hardware.display.DisplayManager;
 import android.os.Binder;
 import android.os.DeadObjectException;
 import android.os.Handler;
@@ -47,7 +48,6 @@
 import android.util.Log;
 import android.util.Size;
 import android.view.Display;
-import android.view.WindowManager;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -138,10 +138,25 @@
      * client camera application. Using these camera devices concurrently by two different
      * applications is not guaranteed to be supported, however.</p>
      *
+     * <p>For concurrent operation, in chronological order :
+     * - Applications must first close any open cameras that have sessions configured, using
+     *   {@link CameraDevice#close}.
+     * - All camera devices intended to be operated concurrently, must be opened using
+     *   {@link #openCamera}, before configuring sessions on any of the camera devices.</p>
+     *
      * <p>Each device in a combination, is guaranteed to support stream combinations which may be
      * obtained by querying {@link #getCameraCharacteristics} for the key
      * {@link android.hardware.camera2.CameraCharacteristics#SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS}.</p>
      *
+     * <p>For concurrent operation, if a camera device has a non null zoom ratio range as specified
+     * by
+     * {@link android.hardware.camera2.CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE},
+     * its complete zoom ratio range may not apply. Applications can use
+     * {@link android.hardware.camera2.CaptureRequest#CONTROL_ZOOM_RATIO} >=1 and  <=
+     * {@link android.hardware.camera2.CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM}
+     * during concurrent operation.
+     * <p>
+     *
      * <p>The set of combinations may include camera devices that may be in use by other camera API
      * clients.</p>
      *
@@ -334,19 +349,22 @@
         Size ret = new Size(0, 0);
 
         try {
-            WindowManager windowManager =
-                    (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
-            Display display = windowManager.getDefaultDisplay();
+            DisplayManager displayManager =
+                    (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
+            Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+            if (display != null) {
+                int width = display.getWidth();
+                int height = display.getHeight();
 
-            int width = display.getWidth();
-            int height = display.getHeight();
+                if (height > width) {
+                    height = width;
+                    width = display.getHeight();
+                }
 
-            if (height > width) {
-                height = width;
-                width = display.getHeight();
+                ret = new Size(width, height);
+            } else {
+                Log.e(TAG, "Invalid default display!");
             }
-
-            ret = new Size(width, height);
         } catch (Exception e) {
             Log.e(TAG, "getDisplaySize Failed. " + e.toString());
         }
@@ -362,6 +380,11 @@
      * cameras that can only be used as part of logical multi-camera. These cameras cannot be
      * opened directly via {@link #openCamera}</p>
      *
+     * <p>Also starting with API level 29, while most basic camera information is still available
+     * even without the CAMERA permission, some values are not available to apps that do not hold
+     * that permission. The keys not available are listed by
+     * {@link CameraCharacteristics#getKeysNeedingPermission}.</p>
+     *
      * @param cameraId The id of the camera device to query. This could be either a standalone
      * camera ID which can be directly opened by {@link #openCamera}, or a physical camera ID that
      * can only used as part of a logical multi-camera.
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 6905f83..d071037 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -2182,11 +2182,13 @@
      * <p>By using this control, the application gains a simpler way to control zoom, which can
      * be a combination of optical and digital zoom. For example, a multi-camera system may
      * contain more than one lens with different focal lengths, and the user can use optical
-     * zoom by switching between lenses. Using zoomRatio has benefits in the scenarios below:
-     * <em> Zooming in from a wide-angle lens to a telephoto lens: A floating-point ratio provides
-     *   better precision compared to an integer value of {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}.
-     * </em> Zooming out from a wide lens to an ultrawide lens: zoomRatio supports zoom-out whereas
-     *   {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} doesn't.</p>
+     * zoom by switching between lenses. Using zoomRatio has benefits in the scenarios below:</p>
+     * <ul>
+     * <li>Zooming in from a wide-angle lens to a telephoto lens: A floating-point ratio provides
+     *   better precision compared to an integer value of {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}.</li>
+     * <li>Zooming out from a wide lens to an ultrawide lens: zoomRatio supports zoom-out whereas
+     *   {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} doesn't.</li>
+     * </ul>
      * <p>To illustrate, here are several scenarios of different zoom ratios, crop regions,
      * and output streams, for a hypothetical camera device with an active array of size
      * <code>(2000,1500)</code>.</p>
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index be03502..b546967 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2412,11 +2412,13 @@
      * <p>By using this control, the application gains a simpler way to control zoom, which can
      * be a combination of optical and digital zoom. For example, a multi-camera system may
      * contain more than one lens with different focal lengths, and the user can use optical
-     * zoom by switching between lenses. Using zoomRatio has benefits in the scenarios below:
-     * <em> Zooming in from a wide-angle lens to a telephoto lens: A floating-point ratio provides
-     *   better precision compared to an integer value of {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}.
-     * </em> Zooming out from a wide lens to an ultrawide lens: zoomRatio supports zoom-out whereas
-     *   {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} doesn't.</p>
+     * zoom by switching between lenses. Using zoomRatio has benefits in the scenarios below:</p>
+     * <ul>
+     * <li>Zooming in from a wide-angle lens to a telephoto lens: A floating-point ratio provides
+     *   better precision compared to an integer value of {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}.</li>
+     * <li>Zooming out from a wide lens to an ultrawide lens: zoomRatio supports zoom-out whereas
+     *   {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} doesn't.</li>
+     * </ul>
      * <p>To illustrate, here are several scenarios of different zoom ratios, crop regions,
      * and output streams, for a hypothetical camera device with an active array of size
      * <code>(2000,1500)</code>.</p>
@@ -3947,14 +3949,24 @@
             new Key<Integer>("android.sensor.testPatternMode", int.class);
 
     /**
-     * <p>Duration between the start of first row exposure
-     * and the start of last row exposure.</p>
-     * <p>This is the exposure time skew between the first and last
-     * row exposure start times. The first row and the last row are
-     * the first and last rows inside of the
+     * <p>Duration between the start of exposure for the first row of the image sensor,
+     * and the start of exposure for one past the last row of the image sensor.</p>
+     * <p>This is the exposure time skew between the first and <code>(last+1)</code> row exposure start times. The
+     * first row and the last row are the first and last rows inside of the
      * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
-     * <p>For typical camera sensors that use rolling shutters, this is also equivalent
-     * to the frame readout time.</p>
+     * <p>For typical camera sensors that use rolling shutters, this is also equivalent to the frame
+     * readout time.</p>
+     * <p>If the image sensor is operating in a binned or cropped mode due to the current output
+     * target resolutions, it's possible this skew is reported to be larger than the exposure
+     * time, for example, since it is based on the full array even if a partial array is read
+     * out. Be sure to scale the number to cover the section of the sensor actually being used
+     * for the outputs you care about. So if your output covers N rows of the active array of
+     * height H, scale this value by N/H to get the total skew for that viewport.</p>
+     * <p><em>Note:</em> Prior to Android 11, this field was described as measuring duration from
+     * first to last row of the image sensor, which is not equal to the frame readout time for a
+     * rolling shutter sensor. Implementations generally reported the latter value, so to resolve
+     * the inconsistency, the description has been updated to range from (first, last+1) row
+     * exposure start, instead.</p>
      * <p><b>Units</b>: Nanoseconds</p>
      * <p><b>Range of valid values:</b><br>
      * &gt;= 0 and &lt;
diff --git a/core/java/android/hardware/display/OWNERS b/core/java/android/hardware/display/OWNERS
new file mode 100644
index 0000000..9ca3910
--- /dev/null
+++ b/core/java/android/hardware/display/OWNERS
@@ -0,0 +1,2 @@
+michaelwr@google.com
+santoscordon@google.com
diff --git a/core/java/android/hardware/input/OWNERS b/core/java/android/hardware/input/OWNERS
new file mode 100644
index 0000000..0313a40
--- /dev/null
+++ b/core/java/android/hardware/input/OWNERS
@@ -0,0 +1,2 @@
+michaelwr@google.com
+svv@google.com
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index 4bed985..f9ed2f8 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -314,6 +314,92 @@
         }
 
         @Override
+        public boolean equals(@Nullable Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (!(obj instanceof ModuleProperties)) {
+                return false;
+            }
+            ModuleProperties other = (ModuleProperties) obj;
+            if (mId != other.mId) {
+                return false;
+            }
+            if (!mImplementor.equals(other.mImplementor)) {
+                return false;
+            }
+            if (!mDescription.equals(other.mDescription)) {
+                return false;
+            }
+            if (!mUuid.equals(other.mUuid)) {
+                return false;
+            }
+            if (mVersion != other.mVersion) {
+                return false;
+            }
+            if (!mSupportedModelArch.equals(other.mSupportedModelArch)) {
+                return false;
+            }
+            if (mMaxSoundModels != other.mMaxSoundModels) {
+                return false;
+            }
+            if (mMaxKeyphrases != other.mMaxKeyphrases) {
+                return false;
+            }
+            if (mMaxUsers != other.mMaxUsers) {
+                return false;
+            }
+            if (mRecognitionModes != other.mRecognitionModes) {
+                return false;
+            }
+            if (mSupportsCaptureTransition != other.mSupportsCaptureTransition) {
+                return false;
+            }
+            if (mMaxBufferMillis != other.mMaxBufferMillis) {
+                return false;
+            }
+            if (mSupportsConcurrentCapture != other.mSupportsConcurrentCapture) {
+                return false;
+            }
+            if (mPowerConsumptionMw != other.mPowerConsumptionMw) {
+                return false;
+            }
+            if (mReturnsTriggerInEvent != other.mReturnsTriggerInEvent) {
+                return false;
+            }
+            if (mAudioCapabilities != other.mAudioCapabilities) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + mId;
+            result = prime * result + mImplementor.hashCode();
+            result = prime * result + mDescription.hashCode();
+            result = prime * result + mUuid.hashCode();
+            result = prime * result + mVersion;
+            result = prime * result + mSupportedModelArch.hashCode();
+            result = prime * result + mMaxSoundModels;
+            result = prime * result + mMaxKeyphrases;
+            result = prime * result + mMaxUsers;
+            result = prime * result + mRecognitionModes;
+            result = prime * result + (mSupportsCaptureTransition ? 1 : 0);
+            result = prime * result + mMaxBufferMillis;
+            result = prime * result + (mSupportsConcurrentCapture ? 1 : 0);
+            result = prime * result + mPowerConsumptionMw;
+            result = prime * result + (mReturnsTriggerInEvent ? 1 : 0);
+            result = prime * result + mAudioCapabilities;
+            return result;
+        }
+
+        @Override
         public String toString() {
             return "ModuleProperties [id=" + getId() + ", implementor=" + getImplementor()
                     + ", description=" + getDescription() + ", uuid=" + getUuid()
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 7332ede..36ffe50 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -48,6 +48,7 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -4693,4 +4694,28 @@
             Log.d(TAG, "StackLog:" + sb.toString());
         }
     }
+
+    /**
+     * Simulates a Data Stall for the specified Network.
+     *
+     * <p>The caller must be the owner of the specified Network.
+     *
+     * @param detectionMethod The detection method used to identify the Data Stall.
+     * @param timestampMillis The timestamp at which the stall 'occurred', in milliseconds.
+     * @param network The Network for which a Data Stall is being simluated.
+     * @param extras The PersistableBundle of extras included in the Data Stall notification.
+     * @throws SecurityException if the caller is not the owner of the given network.
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_TEST_NETWORKS,
+            android.Manifest.permission.NETWORK_STACK})
+    public void simulateDataStall(int detectionMethod, long timestampMillis,
+            @NonNull Network network, @NonNull PersistableBundle extras) {
+        try {
+            mService.simulateDataStall(detectionMethod, timestampMillis, network, extras);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 1434560..69a47f2 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -18,6 +18,7 @@
 
 import android.app.PendingIntent;
 import android.net.ConnectionInfo;
+import android.net.ConnectivityDiagnosticsManager;
 import android.net.IConnectivityDiagnosticsCallback;
 import android.net.LinkProperties;
 import android.net.Network;
@@ -33,6 +34,7 @@
 import android.os.IBinder;
 import android.os.Messenger;
 import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
 import android.os.ResultReceiver;
 
 import com.android.internal.net.LegacyVpnInfo;
@@ -227,4 +229,7 @@
     void unregisterConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback);
 
     IBinder startOrGetTestNetworkService();
+
+    void simulateDataStall(int detectionMethod, long timestampMillis, in Network network,
+                in PersistableBundle extras);
 }
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 52d6fdf..9ded22f 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -677,16 +677,27 @@
      * restrictions.
      * @hide
      */
-    public void restrictCapabilitesForTestNetwork() {
+    public void restrictCapabilitesForTestNetwork(int creatorUid) {
         final long originalCapabilities = mNetworkCapabilities;
         final NetworkSpecifier originalSpecifier = mNetworkSpecifier;
         final int originalSignalStrength = mSignalStrength;
+        final int originalOwnerUid = getOwnerUid();
+        final int[] originalAdministratorUids = getAdministratorUids();
         clearAll();
         // Reset the transports to only contain TRANSPORT_TEST.
         mTransportTypes = (1 << TRANSPORT_TEST);
         mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES;
         mNetworkSpecifier = originalSpecifier;
         mSignalStrength = originalSignalStrength;
+
+        // Only retain the owner and administrator UIDs if they match the app registering the remote
+        // caller that registered the network.
+        if (originalOwnerUid == creatorUid) {
+            setOwnerUid(creatorUid);
+        }
+        if (ArrayUtils.contains(originalAdministratorUids, creatorUid)) {
+            setAdministratorUids(new int[] {creatorUid});
+        }
     }
 
     /**
diff --git a/core/java/android/os/IIncidentDumpCallback.aidl b/core/java/android/os/IIncidentDumpCallback.aidl
index 09b5b01..d94df34 100644
--- a/core/java/android/os/IIncidentDumpCallback.aidl
+++ b/core/java/android/os/IIncidentDumpCallback.aidl
@@ -25,7 +25,8 @@
  */
 oneway interface IIncidentDumpCallback {
     /**
-     * Dumps section data to the given ParcelFileDescriptor.
+     * Dumps section data to the given ParcelFileDescriptor, which needs to be
+     * closed properly after writing the data.
      */
     void onDumpSection(in ParcelFileDescriptor fd);
 }
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index e371df0..0ec4fb8 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -1,3 +1,20 @@
+# Haptics
+per-file ExternalVibration.aidl = michaelwr@google.com
+per-file ExternalVibration.java = michaelwr@google.com
+per-file IExternalVibrationController.aidl = michaelwr@google.com
+per-file IExternalVibratorService.aidl = michaelwr@google.com
+per-file IVibratorService.aidl = michaelwr@google.com
+per-file NullVibrator.java = michaelwr@google.com
+per-file SystemVibrator.java = michaelwr@google.com
+per-file VibrationEffect.aidl = michaelwr@google.com
+per-file VibrationEffect.java = michaelwr@google.com
+per-file Vibrator.java = michaelwr@google.com
+
+# PowerManager
+per-file IPowerManager.aidl = michaelwr@google.com, santoscordon@google.com
+per-file PowerManager.java = michaelwr@google.com, santoscordon@google.com
+per-file PowerManagerInternal.java = michaelwr@google.com, santoscordon@google.com
+
 # Zygote
 per-file ZygoteProcess.java = chriswailes@google.com, ngeoffray@google.com, sehr@google.com, narayan@google.com, maco@google.com
 
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 7c0bc69..ebf4cc5 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1729,9 +1729,15 @@
      * <p>As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method can
      * now automatically identify goats using advanced goat recognition technology.</p>
      *
-     * @return Returns true if the user making this call is a goat.
+     * <p>As of {@link android.os.Build.VERSION_CODES#R}, this method always returns
+     * {@code false} in order to protect goat privacy.</p>
+     *
+     * @return Returns whether the user making this call is a goat.
      */
     public boolean isUserAGoat() {
+        if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R) {
+            return false;
+        }
         return mContext.getPackageManager()
                 .isPackageAvailable("com.coffeestainstudios.goatsimulator");
     }
@@ -2582,8 +2588,8 @@
     }
 
     /**
-     * Creates a user with the specified name and options. For non-admin users, default user
-     * restrictions are going to be applied.
+     * Creates a user with the specified name and options.
+     * Default user restrictions will be applied.
      * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      *
      * @param name the user's name
@@ -2602,8 +2608,8 @@
     }
 
     /**
-     * Creates a user with the specified name and options. For non-admin users, default user
-     * restrictions will be applied.
+     * Creates a user with the specified name and options.
+     * Default user restrictions will be applied.
      *
      * <p>Requires {@link android.Manifest.permission#MANAGE_USERS}.
      * {@link android.Manifest.permission#CREATE_USERS} suffices if flags are in
@@ -2637,8 +2643,7 @@
     }
 
     /**
-     * Pre-creates a user of the specified type. For non-admin users, default user
-     * restrictions will be applied.
+     * Pre-creates a user of the specified type. Default user restrictions will be applied.
      *
      * <p>This method can be used by OEMs to "warm" up the user creation by pre-creating some users
      * at the first boot, so they when the "real" user is created (for example,
diff --git a/core/java/android/os/incremental/IncrementalFileStorages.java b/core/java/android/os/incremental/IncrementalFileStorages.java
index 321dc9e..958c7fb 100644
--- a/core/java/android/os/incremental/IncrementalFileStorages.java
+++ b/core/java/android/os/incremental/IncrementalFileStorages.java
@@ -92,10 +92,7 @@
             }
         }
 
-        if (!result.mDefaultStorage.startLoading()) {
-            // TODO(b/146080380): add incremental-specific error code
-            throw new IOException("Failed to start loading data for Incremental installation.");
-        }
+        result.startLoading();
 
         return result;
     }
@@ -144,6 +141,15 @@
     }
 
     /**
+     * Starts or re-starts loading of data.
+     */
+    public void startLoading() throws IOException {
+        if (!mDefaultStorage.startLoading()) {
+            throw new IOException("Failed to start loading data for Incremental installation.");
+        }
+    }
+
+    /**
      * Resets the states and unbinds storage instances for an installation session.
      * TODO(b/136132412): make sure unnecessary binds are removed but useful storages are kept
      */
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index a1a11ed..66b8cab 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -162,12 +162,9 @@
     /** {@hide} */
     public static final String PROP_SETTINGS_FUSE = FeatureFlagUtils.PERSIST_PREFIX
             + FeatureFlagUtils.SETTINGS_FUSE_FLAG;
-    /**
-     * Property that determines whether {@link OP_LEGACY_STORAGE} is sticky for
-     * legacy apps.
-     * @hide
-     */
-    public static final String PROP_LEGACY_OP_STICKY = "persist.sys.legacy_storage_sticky";
+    /** {@hide} */
+    public static final String PROP_FORCED_SCOPED_STORAGE_WHITELIST =
+            "forced_scoped_storage_whitelist";
 
     /** {@hide} */
     public static final String UUID_PRIVATE_INTERNAL = null;
@@ -226,9 +223,10 @@
      * <p>
      * This intent should be launched using
      * {@link Activity#startActivityForResult(Intent, int)} so that the user
-     * knows which app is requesting to clear cache. The returned result will
-     * be {@link Activity#RESULT_OK} if the activity was launched and the user accepted to clear
-     * cache, or {@link Activity#RESULT_CANCELED} otherwise.
+     * knows which app is requesting to clear cache. The returned result will be:
+     * {@link Activity#RESULT_OK} if the activity was launched and all cache was cleared,
+     * {@link OsConstants#EIO} if an error occurred while clearing the cache or
+     * {@link Activity#RESULT_CANCELED} otherwise.
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_EXTERNAL_STORAGE)
     @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index 06caa03..dea932d 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -56,15 +56,11 @@
 import com.android.internal.infra.AndroidFuture;
 import com.android.internal.infra.RemoteStream;
 import com.android.internal.infra.ServiceConnector;
-import com.android.internal.os.TransferPipe;
 import com.android.internal.util.CollectionUtils;
 
 import libcore.util.EmptyArray;
 
 import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -72,7 +68,6 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
@@ -88,6 +83,7 @@
 public final class PermissionControllerManager {
     private static final String TAG = PermissionControllerManager.class.getSimpleName();
 
+    private static final long REQUEST_TIMEOUT_MILLIS = 60000;
     private static final long UNBIND_TIMEOUT_MILLIS = 10000;
     private static final int CHUNK_SIZE = 4 * 1024;
 
@@ -227,6 +223,11 @@
                     }
 
                     @Override
+                    protected long getRequestTimeoutMs() {
+                        return REQUEST_TIMEOUT_MILLIS;
+                    }
+
+                    @Override
                     protected long getAutoDisconnectTimeoutMs() {
                         return UNBIND_TIMEOUT_MILLIS;
                     }
@@ -487,28 +488,12 @@
      *
      * @hide
      */
-    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @Nullable String[] args) {
-        CompletableFuture<Throwable> dumpResult = new CompletableFuture<>();
-        mRemoteService.postForResult(
-                service -> TransferPipe.dumpAsync(service.asBinder(), args))
-                .whenComplete(
-                        (dump, err) -> {
-                            try (FileOutputStream out = new FileOutputStream(fd)) {
-                                out.write(dump);
-                            } catch (IOException | NullPointerException e) {
-                                Log.e(TAG, "Could for forwards permission controller dump", e);
-                            }
-
-                            dumpResult.complete(err);
-                        });
-
+    public void dump(@NonNull FileDescriptor fd, @Nullable String[] args) {
         try {
-            Throwable err = dumpResult.get(UNBIND_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
-            if (err != null) {
-                throw err;
-            }
-        } catch (Throwable e) {
-            Log.e(TAG, "Could not dump permission controller state", e);
+            mRemoteService.post(service -> service.asBinder().dump(fd, args))
+                    .get(REQUEST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        } catch (Exception e) {
+            Log.e(TAG, "Could not get dump", e);
         }
     }
 
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index c6ede32..8ad35e7 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -499,6 +499,11 @@
 
             @Override
             protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+                checkNotNull(fd, "fd");
+                checkNotNull(writer, "writer");
+
+                enforceSomePermissionsGrantedToCaller(Manifest.permission.GET_RUNTIME_PERMISSIONS);
+
                 PermissionControllerService.this.dump(fd, writer, args);
             }
         };
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 3dc8e99..bf3d46f 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -333,7 +333,7 @@
 
     /**
      * Gets the list of packages that have permissions that specified
-     * {@code allowDontAutoRevokePermissions=true} in their
+     * {@code autoRevokePermissions=disallowed} in their
      * {@code application} manifest declaration.
      *
      * @return the list of packages for current user
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ae88ba5..e0bc764 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9936,6 +9936,11 @@
         * @hide */
        public static final String PACKAGE_VERIFIER_TIMEOUT = "verifier_timeout";
 
+        /** Timeout for app integrity verification.
+         * @hide */
+        public static final String APP_INTEGRITY_VERIFICATION_TIMEOUT =
+                "app_integrity_verification_timeout";
+
        /** Default response code for package verification.
         * @hide */
        public static final String PACKAGE_VERIFIER_DEFAULT_RESPONSE = "verifier_default_response";
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index d94160c..62becc5 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -86,6 +86,16 @@
      */
     public static final @RequestFlags int FLAG_PASSWORD_INPUT_TYPE = 0x4;
 
+    /**
+     * Indicates the view was not focused.
+     *
+     * <p><b>Note:</b> Defines the flag value to 0x10, because the flag value 0x08 has been defined
+     * in {@link AutofillManager}.</p>
+     *
+     * @hide
+     */
+    public static final @RequestFlags int FLAG_VIEW_NOT_FOCUSED = 0x10;
+
     /** @hide */
     public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE;
 
@@ -165,7 +175,8 @@
     @IntDef(flag = true, prefix = "FLAG_", value = {
         FLAG_MANUAL_REQUEST,
         FLAG_COMPATIBILITY_MODE_REQUEST,
-        FLAG_PASSWORD_INPUT_TYPE
+        FLAG_PASSWORD_INPUT_TYPE,
+        FLAG_VIEW_NOT_FOCUSED
     })
     @Retention(RetentionPolicy.SOURCE)
     @DataClass.Generated.Member
@@ -187,6 +198,8 @@
                     return "FLAG_COMPATIBILITY_MODE_REQUEST";
             case FLAG_PASSWORD_INPUT_TYPE:
                     return "FLAG_PASSWORD_INPUT_TYPE";
+            case FLAG_VIEW_NOT_FOCUSED:
+                    return "FLAG_VIEW_NOT_FOCUSED";
             default: return Integer.toHexString(value);
         }
     }
@@ -248,7 +261,8 @@
                 mFlags,
                 FLAG_MANUAL_REQUEST
                         | FLAG_COMPATIBILITY_MODE_REQUEST
-                        | FLAG_PASSWORD_INPUT_TYPE);
+                        | FLAG_PASSWORD_INPUT_TYPE
+                        | FLAG_VIEW_NOT_FOCUSED);
         this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
 
         onConstructed();
@@ -384,7 +398,8 @@
                 mFlags,
                 FLAG_MANUAL_REQUEST
                         | FLAG_COMPATIBILITY_MODE_REQUEST
-                        | FLAG_PASSWORD_INPUT_TYPE);
+                        | FLAG_PASSWORD_INPUT_TYPE
+                        | FLAG_VIEW_NOT_FOCUSED);
         this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
 
         onConstructed();
@@ -405,10 +420,10 @@
     };
 
     @DataClass.Generated(
-            time = 1588119440090L,
+            time = 1589280816805L,
             codegenVersion = "1.0.15",
             sourceFile = "frameworks/base/core/java/android/service/autofill/FillRequest.java",
-            inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PASSWORD_INPUT_TYPE\npublic static final  int INVALID_REQUEST_ID\nprivate final  int mId\nprivate final @android.annotation.NonNull java.util.List<android.service.autofill.FillContext> mFillContexts\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate  void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
+            inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PASSWORD_INPUT_TYPE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_VIEW_NOT_FOCUSED\npublic static final  int INVALID_REQUEST_ID\nprivate final  int mId\nprivate final @android.annotation.NonNull java.util.List<android.service.autofill.FillContext> mFillContexts\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate  void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/util/AtomicFile.java b/core/java/android/util/AtomicFile.java
index cf7ed9b..e0d857a 100644
--- a/core/java/android/util/AtomicFile.java
+++ b/core/java/android/util/AtomicFile.java
@@ -29,31 +29,32 @@
 import java.util.function.Consumer;
 
 /**
- * Helper class for performing atomic operations on a file by creating a
- * backup file until a write has successfully completed.  If you need this
- * on older versions of the platform you can use
- * {@link android.support.v4.util.AtomicFile} in the v4 support library.
+ * Helper class for performing atomic operations on a file by writing to a new file and renaming it
+ * into the place of the original file after the write has successfully completed. If you need this
+ * on older versions of the platform you can use {@link androidx.core.util.AtomicFile} in AndroidX.
  * <p>
- * Atomic file guarantees file integrity by ensuring that a file has
- * been completely written and sync'd to disk before removing its backup.
- * As long as the backup file exists, the original file is considered
- * to be invalid (left over from a previous attempt to write the file).
- * </p><p>
- * Atomic file does not confer any file locking semantics.
- * Do not use this class when the file may be accessed or modified concurrently
- * by multiple threads or processes.  The caller is responsible for ensuring
- * appropriate mutual exclusion invariants whenever it accesses the file.
- * </p>
+ * Atomic file guarantees file integrity by ensuring that a file has been completely written and
+ * sync'd to disk before renaming it to the original file. Previously this is done by renaming the
+ * original file to a backup file beforehand, but this approach couldn't handle the case where the
+ * file is created for the first time. This class will also handle the backup file created by the
+ * old implementation properly.
+ * <p>
+ * Atomic file does not confer any file locking semantics. Do not use this class when the file may
+ * be accessed or modified concurrently by multiple threads or processes. The caller is responsible
+ * for ensuring appropriate mutual exclusion invariants whenever it accesses the file.
  */
 public class AtomicFile {
+    private static final String LOG_TAG = "AtomicFile";
+
     private final File mBaseName;
-    private final File mBackupName;
+    private final File mNewName;
+    private final File mLegacyBackupName;
     private final String mCommitTag;
     private long mStartTime;
 
     /**
      * Create a new AtomicFile for a file located at the given File path.
-     * The secondary backup file will be the same file path with ".bak" appended.
+     * The new file created when writing will be the same file path with ".new" appended.
      */
     public AtomicFile(File baseName) {
         this(baseName, null);
@@ -65,7 +66,8 @@
      */
     public AtomicFile(File baseName, String commitTag) {
         mBaseName = baseName;
-        mBackupName = new File(baseName.getPath() + ".bak");
+        mNewName = new File(baseName.getPath() + ".new");
+        mLegacyBackupName = new File(baseName.getPath() + ".bak");
         mCommitTag = commitTag;
     }
 
@@ -78,11 +80,12 @@
     }
 
     /**
-     * Delete the atomic file.  This deletes both the base and backup files.
+     * Delete the atomic file.  This deletes both the base and new files.
      */
     public void delete() {
         mBaseName.delete();
-        mBackupName.delete();
+        mNewName.delete();
+        mLegacyBackupName.delete();
     }
 
     /**
@@ -112,36 +115,25 @@
     public FileOutputStream startWrite(long startTime) throws IOException {
         mStartTime = startTime;
 
-        // Rename the current file so it may be used as a backup during the next read
-        if (mBaseName.exists()) {
-            if (!mBackupName.exists()) {
-                if (!mBaseName.renameTo(mBackupName)) {
-                    Log.w("AtomicFile", "Couldn't rename file " + mBaseName
-                            + " to backup file " + mBackupName);
-                }
-            } else {
-                mBaseName.delete();
-            }
+        if (mLegacyBackupName.exists()) {
+            rename(mLegacyBackupName, mBaseName);
         }
-        FileOutputStream str = null;
+
         try {
-            str = new FileOutputStream(mBaseName);
+            return new FileOutputStream(mNewName);
         } catch (FileNotFoundException e) {
-            File parent = mBaseName.getParentFile();
+            File parent = mNewName.getParentFile();
             if (!parent.mkdirs()) {
-                throw new IOException("Couldn't create directory " + mBaseName);
+                throw new IOException("Failed to create directory for " + mNewName);
             }
-            FileUtils.setPermissions(
-                parent.getPath(),
-                FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
-                -1, -1);
+            FileUtils.setPermissions(parent.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
+                    | FileUtils.S_IXOTH, -1, -1);
             try {
-                str = new FileOutputStream(mBaseName);
+                return new FileOutputStream(mNewName);
             } catch (FileNotFoundException e2) {
-                throw new IOException("Couldn't create " + mBaseName);
+                throw new IOException("Failed to create new file " + mNewName, e2);
             }
         }
-        return str;
     }
 
     /**
@@ -151,36 +143,43 @@
      * will return the new file stream.
      */
     public void finishWrite(FileOutputStream str) {
-        if (str != null) {
-            FileUtils.sync(str);
-            try {
-                str.close();
-                mBackupName.delete();
-            } catch (IOException e) {
-                Log.w("AtomicFile", "finishWrite: Got exception:", e);
-            }
-            if (mCommitTag != null) {
-                com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
-                        mCommitTag, SystemClock.uptimeMillis() - mStartTime);
-            }
+        if (str == null) {
+            return;
+        }
+        if (!FileUtils.sync(str)) {
+            Log.e(LOG_TAG, "Failed to sync file output stream");
+        }
+        try {
+            str.close();
+        } catch (IOException e) {
+            Log.e(LOG_TAG, "Failed to close file output stream", e);
+        }
+        rename(mNewName, mBaseName);
+        if (mCommitTag != null) {
+            com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+                    mCommitTag, SystemClock.uptimeMillis() - mStartTime);
         }
     }
 
     /**
      * Call when you have failed for some reason at writing to the stream
      * returned by {@link #startWrite()}.  This will close the current
-     * write stream, and roll back to the previous state of the file.
+     * write stream, and delete the new file.
      */
     public void failWrite(FileOutputStream str) {
-        if (str != null) {
-            FileUtils.sync(str);
-            try {
-                str.close();
-                mBaseName.delete();
-                mBackupName.renameTo(mBaseName);
-            } catch (IOException e) {
-                Log.w("AtomicFile", "failWrite: Got exception:", e);
-            }
+        if (str == null) {
+            return;
+        }
+        if (!FileUtils.sync(str)) {
+            Log.e(LOG_TAG, "Failed to sync file output stream");
+        }
+        try {
+            str.close();
+        } catch (IOException e) {
+            Log.e(LOG_TAG, "Failed to close file output stream", e);
+        }
+        if (!mNewName.delete()) {
+            Log.e(LOG_TAG, "Failed to delete new file " + mNewName);
         }
     }
 
@@ -210,32 +209,38 @@
     }
 
     /**
-     * Open the atomic file for reading.  If there previously was an
-     * incomplete write, this will roll back to the last good data before
-     * opening for read.  You should call close() on the FileInputStream when
-     * you are done reading from it.
-     *
-     * <p>Note that if another thread is currently performing
-     * a write, this will incorrectly consider it to be in the state of a bad
-     * write and roll back, causing the new data currently being written to
-     * be dropped.  You must do your own threading protection for access to
-     * AtomicFile.
+     * Open the atomic file for reading. You should call close() on the FileInputStream when you are
+     * done reading from it.
+     * <p>
+     * You must do your own threading protection for access to AtomicFile.
      */
     public FileInputStream openRead() throws FileNotFoundException {
-        if (mBackupName.exists()) {
-            mBaseName.delete();
-            mBackupName.renameTo(mBaseName);
+        if (mLegacyBackupName.exists()) {
+            rename(mLegacyBackupName, mBaseName);
+        }
+
+        // It was okay to call openRead() between startWrite() and finishWrite() for the first time
+        // (because there is no backup file), where openRead() would open the file being written,
+        // which makes no sense, but finishWrite() would still persist the write properly. For all
+        // subsequent writes, if openRead() was called in between, it would see a backup file and
+        // delete the file being written, the same behavior as our new implementation. So we only
+        // need a special case for the first write, and don't delete the new file in this case so
+        // that finishWrite() can still work.
+        if (mNewName.exists() && mBaseName.exists()) {
+            if (!mNewName.delete()) {
+                Log.e(LOG_TAG, "Failed to delete outdated new file " + mNewName);
+            }
         }
         return new FileInputStream(mBaseName);
     }
 
     /**
      * @hide
-     * Checks if the original or backup file exists.
-     * @return whether the original or backup file exists.
+     * Checks if the original or legacy backup file exists.
+     * @return whether the original or legacy backup file exists.
      */
     public boolean exists() {
-        return mBaseName.exists() || mBackupName.exists();
+        return mBaseName.exists() || mLegacyBackupName.exists();
     }
 
     /**
@@ -246,8 +251,8 @@
      *     the file does not exist or an I/O error is encountered.
      */
     public long getLastModifiedTime() {
-        if (mBackupName.exists()) {
-            return mBackupName.lastModified();
+        if (mLegacyBackupName.exists()) {
+            return mLegacyBackupName.lastModified();
         }
         return mBaseName.lastModified();
     }
@@ -298,4 +303,21 @@
             IoUtils.closeQuietly(out);
         }
     }
+
+    private static void rename(File source, File target) {
+        // We used to delete the target file before rename, but that isn't atomic, and the rename()
+        // syscall should atomically replace the target file. However in the case where the target
+        // file is a directory, a simple rename() won't work. We need to delete the file in this
+        // case because there are callers who erroneously called mBaseName.mkdirs() (instead of
+        // mBaseName.getParentFile().mkdirs()) before creating the AtomicFile, and it worked
+        // regardless, so this deletion became some kind of API.
+        if (target.isDirectory()) {
+            if (!target.delete()) {
+                Log.e(LOG_TAG, "Failed to delete file which is a directory " + target);
+            }
+        }
+        if (!source.renameTo(target)) {
+            Log.e(LOG_TAG, "Failed to rename " + source + " to " + target);
+        }
+    }
 }
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 4469fdb..8db1703 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -104,6 +104,14 @@
     private int mCachedAppHeightCompat;
 
     /**
+     * Indicates that the application is started in a different rotation than the real display, so
+     * the display information may be adjusted. That ensures the methods {@link #getRotation},
+     * {@link #getRealSize}, {@link #getRealMetrics}, and {@link #getCutout} are consistent with how
+     * the application window is laid out.
+     */
+    private boolean mMayAdjustByFixedRotation;
+
+    /**
      * The default Display id, which is the id of the primary display assuming there is one.
      */
     public static final int DEFAULT_DISPLAY = 0;
@@ -804,7 +812,9 @@
     public int getRotation() {
         synchronized (this) {
             updateDisplayInfoLocked();
-            return mDisplayInfo.rotation;
+            return mMayAdjustByFixedRotation
+                    ? getDisplayAdjustments().getRotation(mDisplayInfo.rotation)
+                    : mDisplayInfo.rotation;
         }
     }
 
@@ -828,7 +838,9 @@
     public DisplayCutout getCutout() {
         synchronized (this) {
             updateDisplayInfoLocked();
-            return mDisplayInfo.displayCutout;
+            return mMayAdjustByFixedRotation
+                    ? getDisplayAdjustments().getDisplayCutout(mDisplayInfo.displayCutout)
+                    : mDisplayInfo.displayCutout;
         }
     }
 
@@ -1140,6 +1152,9 @@
             updateDisplayInfoLocked();
             outSize.x = mDisplayInfo.logicalWidth;
             outSize.y = mDisplayInfo.logicalHeight;
+            if (mMayAdjustByFixedRotation) {
+                getDisplayAdjustments().adjustSize(outSize, mDisplayInfo.rotation);
+            }
         }
     }
 
@@ -1159,6 +1174,9 @@
             updateDisplayInfoLocked();
             mDisplayInfo.getLogicalMetrics(outMetrics,
                     CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+            if (mMayAdjustByFixedRotation) {
+                getDisplayAdjustments().adjustMetrics(outMetrics, mDisplayInfo.rotation);
+            }
         }
     }
 
@@ -1225,6 +1243,9 @@
                 }
             }
         }
+
+        mMayAdjustByFixedRotation = mResources != null
+                && mResources.hasOverrideDisplayAdjustments();
     }
 
     private void updateCachedAppSizeIfNeededLocked() {
@@ -1243,9 +1264,12 @@
     public String toString() {
         synchronized (this) {
             updateDisplayInfoLocked();
-            mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments());
+            final DisplayAdjustments adjustments = getDisplayAdjustments();
+            mDisplayInfo.getAppMetrics(mTempMetrics, adjustments);
             return "Display id " + mDisplayId + ": " + mDisplayInfo
-                    + ", " + mTempMetrics + ", isValid=" + mIsValid;
+                    + (mMayAdjustByFixedRotation
+                            ? (", " + adjustments.getFixedRotationAdjustments() + ", ") : ", ")
+                    + mTempMetrics + ", isValid=" + mIsValid;
         }
     }
 
diff --git a/core/java/android/view/DisplayAdjustments.java b/core/java/android/view/DisplayAdjustments.java
index 27c2d5c..c726bee 100644
--- a/core/java/android/view/DisplayAdjustments.java
+++ b/core/java/android/view/DisplayAdjustments.java
@@ -21,6 +21,10 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
+import android.graphics.Point;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.DisplayMetrics;
 
 import java.util.Objects;
 
@@ -30,6 +34,7 @@
 
     private volatile CompatibilityInfo mCompatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
     private final Configuration mConfiguration = new Configuration(Configuration.EMPTY);
+    private FixedRotationAdjustments mFixedRotationAdjustments;
 
     @UnsupportedAppUsage
     public DisplayAdjustments() {
@@ -44,6 +49,7 @@
     public DisplayAdjustments(@NonNull DisplayAdjustments daj) {
         setCompatibilityInfo(daj.mCompatInfo);
         mConfiguration.setTo(daj.getConfiguration());
+        mFixedRotationAdjustments = daj.mFixedRotationAdjustments;
     }
 
     @UnsupportedAppUsage
@@ -84,11 +90,78 @@
         return mConfiguration;
     }
 
+    public void setFixedRotationAdjustments(FixedRotationAdjustments fixedRotationAdjustments) {
+        mFixedRotationAdjustments = fixedRotationAdjustments;
+    }
+
+    public FixedRotationAdjustments getFixedRotationAdjustments() {
+        return mFixedRotationAdjustments;
+    }
+
+    /** Returns {@code false} if the width and height of display should swap. */
+    private boolean noFlip(@Surface.Rotation int realRotation) {
+        final FixedRotationAdjustments rotationAdjustments = mFixedRotationAdjustments;
+        if (rotationAdjustments == null) {
+            return true;
+        }
+        // Check if the delta is rotated by 90 degrees.
+        return (realRotation - rotationAdjustments.mRotation + 4) % 2 == 0;
+    }
+
+    /** Adjusts the given size if possible. */
+    public void adjustSize(@NonNull Point size, @Surface.Rotation int realRotation) {
+        if (noFlip(realRotation)) {
+            return;
+        }
+        final int w = size.x;
+        size.x = size.y;
+        size.y = w;
+    }
+
+    /** Adjusts the given metrics if possible. */
+    public void adjustMetrics(@NonNull DisplayMetrics metrics, @Surface.Rotation int realRotation) {
+        if (noFlip(realRotation)) {
+            return;
+        }
+        int w = metrics.widthPixels;
+        metrics.widthPixels = metrics.heightPixels;
+        metrics.heightPixels = w;
+
+        w = metrics.noncompatWidthPixels;
+        metrics.noncompatWidthPixels = metrics.noncompatHeightPixels;
+        metrics.noncompatHeightPixels = w;
+
+        float x = metrics.xdpi;
+        metrics.xdpi = metrics.ydpi;
+        metrics.ydpi = x;
+
+        x = metrics.noncompatXdpi;
+        metrics.noncompatXdpi = metrics.noncompatYdpi;
+        metrics.noncompatYdpi = x;
+    }
+
+    /** Returns the adjusted cutout if available. Otherwise the original cutout is returned. */
+    @Nullable
+    public DisplayCutout getDisplayCutout(@Nullable DisplayCutout realCutout) {
+        final FixedRotationAdjustments rotationAdjustments = mFixedRotationAdjustments;
+        return rotationAdjustments != null && rotationAdjustments.mRotatedDisplayCutout != null
+                ? rotationAdjustments.mRotatedDisplayCutout
+                : realCutout;
+    }
+
+    /** Returns the adjusted rotation if available. Otherwise the original rotation is returned. */
+    @Surface.Rotation
+    public int getRotation(@Surface.Rotation int realRotation) {
+        final FixedRotationAdjustments rotationAdjustments = mFixedRotationAdjustments;
+        return rotationAdjustments != null ? rotationAdjustments.mRotation : realRotation;
+    }
+
     @Override
     public int hashCode() {
         int hash = 17;
         hash = hash * 31 + Objects.hashCode(mCompatInfo);
         hash = hash * 31 + Objects.hashCode(mConfiguration);
+        hash = hash * 31 + Objects.hashCode(mFixedRotationAdjustments);
         return hash;
     }
 
@@ -98,7 +171,82 @@
             return false;
         }
         DisplayAdjustments daj = (DisplayAdjustments)o;
-        return Objects.equals(daj.mCompatInfo, mCompatInfo) &&
-                Objects.equals(daj.mConfiguration, mConfiguration);
+        return Objects.equals(daj.mCompatInfo, mCompatInfo)
+                && Objects.equals(daj.mConfiguration, mConfiguration)
+                && Objects.equals(daj.mFixedRotationAdjustments, mFixedRotationAdjustments);
+    }
+
+    /**
+     * An application can be launched in different rotation than the real display. This class
+     * provides the information to adjust the values returned by {@link #Display}.
+     * @hide
+     */
+    public static class FixedRotationAdjustments implements Parcelable {
+        /** The application-based rotation. */
+        @Surface.Rotation
+        final int mRotation;
+
+        /** Non-null if the device has cutout. */
+        @Nullable
+        final DisplayCutout mRotatedDisplayCutout;
+
+        public FixedRotationAdjustments(@Surface.Rotation int rotation, DisplayCutout cutout) {
+            mRotation = rotation;
+            mRotatedDisplayCutout = cutout;
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 17;
+            hash = hash * 31 + mRotation;
+            hash = hash * 31 + Objects.hashCode(mRotatedDisplayCutout);
+            return hash;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof FixedRotationAdjustments)) {
+                return false;
+            }
+            final FixedRotationAdjustments other = (FixedRotationAdjustments) o;
+            return mRotation == other.mRotation
+                    && Objects.equals(mRotatedDisplayCutout, other.mRotatedDisplayCutout);
+        }
+
+        @Override
+        public String toString() {
+            return "FixedRotationAdjustments{rotation=" + Surface.rotationToString(mRotation)
+                    + " cutout=" + mRotatedDisplayCutout + "}";
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(mRotation);
+            dest.writeTypedObject(
+                    new DisplayCutout.ParcelableWrapper(mRotatedDisplayCutout), flags);
+        }
+
+        private FixedRotationAdjustments(Parcel in) {
+            mRotation = in.readInt();
+            final DisplayCutout.ParcelableWrapper cutoutWrapper =
+                    in.readTypedObject(DisplayCutout.ParcelableWrapper.CREATOR);
+            mRotatedDisplayCutout = cutoutWrapper != null ? cutoutWrapper.get() : null;
+        }
+
+        public static final Creator<FixedRotationAdjustments> CREATOR =
+                new Creator<FixedRotationAdjustments>() {
+            public FixedRotationAdjustments createFromParcel(Parcel in) {
+                return new FixedRotationAdjustments(in);
+            }
+
+            public FixedRotationAdjustments[] newArray(int size) {
+                return new FixedRotationAdjustments[size];
+            }
+        };
     }
 }
diff --git a/core/java/android/view/IDisplayWindowListener.aidl b/core/java/android/view/IDisplayWindowListener.aidl
index 973a208..610e0f8 100644
--- a/core/java/android/view/IDisplayWindowListener.aidl
+++ b/core/java/android/view/IDisplayWindowListener.aidl
@@ -46,4 +46,13 @@
      */
     void onDisplayRemoved(int displayId);
 
+    /**
+     * Called when fixed rotation is started on a display.
+     */
+    void onFixedRotationStarted(int displayId, int newRotation);
+
+    /**
+     * Called when the previous fixed rotation on a display is finished.
+     */
+    void onFixedRotationFinished(int displayId);
 }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 926d8fc..0410c90 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -336,7 +336,7 @@
     * an input channel where the client can receive input.
     */
     void grantInputChannel(int displayId, in SurfaceControl surface, in IWindow window,
-            in IBinder hostInputToken, int flags, out InputChannel outInputChannel);
+            in IBinder hostInputToken, int flags, int type, out InputChannel outInputChannel);
 
     /**
      * Update the flags on an input channel associated with a particular surface.
diff --git a/core/java/android/view/ImeFocusController.java b/core/java/android/view/ImeFocusController.java
index dbbe4b6..a480072 100644
--- a/core/java/android/view/ImeFocusController.java
+++ b/core/java/android/view/ImeFocusController.java
@@ -208,26 +208,6 @@
     }
 
     /**
-     * Called by {@link ViewRootImpl} to feedback the state of the screen for this view.
-     * @param newScreenState The new state of the screen. Can be either
-     *                       {@link View#SCREEN_STATE_ON} or {@link View#SCREEN_STATE_OFF}
-     */
-    @UiThread
-    void onScreenStateChanged(int newScreenState) {
-        if (!getImmDelegate().isCurrentRootView(mViewRootImpl)) {
-            return;
-        }
-        // Close input connection and IME when the screen is turn off for security concern.
-        if (newScreenState == View.SCREEN_STATE_OFF && mServedView != null) {
-            if (DEBUG) {
-                Log.d(TAG, "onScreenStateChanged, disconnect input when screen turned off");
-            }
-            mNextServedView = null;
-            mViewRootImpl.dispatchCheckFocus();
-        }
-    }
-
-    /**
      * @param windowAttribute {@link WindowManager.LayoutParams} to be checked.
      * @return Whether the window is in local focus mode or not.
      */
diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java
index 9dfdd06..3215b7c 100644
--- a/core/java/android/view/InsetsAnimationThreadControlRunner.java
+++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java
@@ -21,6 +21,7 @@
 import android.annotation.UiThread;
 import android.graphics.Rect;
 import android.os.Handler;
+import android.os.Trace;
 import android.util.SparseArray;
 import android.view.InsetsController.AnimationType;
 import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
@@ -60,6 +61,9 @@
 
         @Override
         public void notifyFinished(InsetsAnimationControlRunner runner, boolean shown) {
+            Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW,
+                    "InsetsAsyncAnimation: " + WindowInsets.Type.toString(runner.getTypes()),
+                    runner.getTypes());
             releaseControls(mControl.getControls());
             mMainThreadHandler.post(() ->
                     mOuterCallbacks.notifyFinished(InsetsAnimationThreadControlRunner.this, shown));
@@ -93,7 +97,11 @@
         mOuterCallbacks = controller;
         mControl = new InsetsAnimationControlImpl(controls, frame, state, listener,
                 types, mCallbacks, durationMs, interpolator, animationType);
-        InsetsAnimationThread.getHandler().post(() -> listener.onReady(mControl, types));
+        InsetsAnimationThread.getHandler().post(() -> {
+            Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW,
+                    "InsetsAsyncAnimation: " + WindowInsets.Type.toString(types), types);
+            listener.onReady(mControl, types);
+        });
     }
 
     private void releaseControls(SparseArray<InsetsSourceControl> controls) {
@@ -102,15 +110,6 @@
         }
     }
 
-    private SparseArray<InsetsSourceControl> copyControls(
-            SparseArray<InsetsSourceControl> controls) {
-        SparseArray<InsetsSourceControl> copy = new SparseArray<>(controls.size());
-        for (int i = 0; i < controls.size(); i++) {
-            copy.append(controls.keyAt(i), new InsetsSourceControl(controls.valueAt(i)));
-        }
-        return copy;
-    }
-
     @Override
     @UiThread
     public int getTypes() {
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 2d17b6d..758062f 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -35,6 +35,7 @@
 import android.graphics.Rect;
 import android.os.CancellationSignal;
 import android.os.Handler;
+import android.os.Trace;
 import android.util.ArraySet;
 import android.util.Pair;
 import android.util.SparseArray;
@@ -1143,6 +1144,8 @@
             if (controller.isCancelled()) {
                 return;
             }
+            Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW,
+                    "InsetsAnimation: " + WindowInsets.Type.toString(types), types);
             for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
                 RunningAnimation runningAnimation = mRunningAnimations.get(i);
                 if (runningAnimation.runner == controller) {
@@ -1159,6 +1162,9 @@
 
     @VisibleForTesting
     public void dispatchAnimationEnd(WindowInsetsAnimation animation) {
+        Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW,
+                "InsetsAnimation: " + WindowInsets.Type.toString(animation.getTypeMask()),
+                animation.getTypeMask());
         mHost.dispatchWindowInsetsAnimationEnd(animation);
     }
 
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index 2dcfd89..df3ac87 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -18,6 +18,7 @@
 
 import static android.view.InsetsController.ANIMATION_TYPE_NONE;
 import static android.view.InsetsController.AnimationType;
+import static android.view.InsetsState.getDefaultVisibility;
 import static android.view.InsetsState.toPublicType;
 
 import android.annotation.IntDef;
@@ -82,7 +83,7 @@
         mState = state;
         mTransactionSupplier = transactionSupplier;
         mController = controller;
-        mRequestedVisible = InsetsState.getDefaultVisibility(type);
+        mRequestedVisible = getDefaultVisibility(type);
     }
 
     /**
@@ -200,8 +201,8 @@
     }
 
     boolean applyLocalVisibilityOverride() {
-        InsetsSource source = mState.peekSource(mType);
-        final boolean isVisible = source != null && source.isVisible();
+        final InsetsSource source = mState.peekSource(mType);
+        final boolean isVisible = source != null ? source.isVisible() : getDefaultVisibility(mType);
         final boolean hasControl = mSourceControl != null;
 
         // We still need to let the legacy app know the visibility change even if we don't have the
diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS
new file mode 100644
index 0000000..7b60f2e
--- /dev/null
+++ b/core/java/android/view/OWNERS
@@ -0,0 +1,15 @@
+# Display
+per-file Display.java = michaelwr@google.com, santoscordon@google.com
+per-file DisplayInfo.java = michaelwr@google.com, santoscordon@google.com
+
+# Haptics
+per-file HapticFeedbackConstants.java = michaelwr@google.com, santoscordon@google.com
+
+# Input
+per-file IInputMonitorHost.aidl = michaelwr@google.com, svv@google.com
+per-file Input*.java = michaelwr@google.com, svv@google.com
+per-file Input*.aidl = michaelwr@google.com, svv@google.com
+per-file KeyEvent.java = michaelwr@google.com, svv@google.com
+per-file MotionEvent.java = michaelwr@google.com, svv@google.com
+per-file PointerIcon.java = michaelwr@google.com, svv@google.com
+per-file SimulatedDpad.java = michaelwr@google.com, svv@google.com
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index c0c29eb..9109f50 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -220,6 +220,8 @@
 
     private static native long nativeAcquireFrameRateFlexibilityToken();
     private static native void nativeReleaseFrameRateFlexibilityToken(long token);
+    private static native void nativeSetFixedTransformHint(long transactionObj, long nativeObject,
+            int transformHint);
 
     private final CloseGuard mCloseGuard = CloseGuard.get();
     private String mName;
@@ -2307,6 +2309,39 @@
         }
 
         /**
+         * Provide the graphic producer a transform hint if the layer and its children are
+         * in an orientation different from the display's orientation. The caller is responsible
+         * for clearing this transform hint if the layer is no longer in a fixed orientation.
+         *
+         * The transform hint is used to prevent allocating a buffer of different size when a
+         * layer is rotated. The producer can choose to consume the hint and allocate the buffer
+         * with the same size.
+         *
+         * @return This Transaction.
+         * @hide
+         */
+        @NonNull
+        public Transaction setFixedTransformHint(@NonNull SurfaceControl sc,
+                       @Surface.Rotation int transformHint) {
+            checkPreconditions(sc);
+            nativeSetFixedTransformHint(mNativeObject, sc.mNativeObject, transformHint);
+            return this;
+        }
+
+        /**
+         * Clearing any transform hint if set on this layer.
+         *
+         * @return This Transaction.
+         * @hide
+         */
+        @NonNull
+        public Transaction unsetFixedTransformHint(@NonNull SurfaceControl sc) {
+            checkPreconditions(sc);
+            nativeSetFixedTransformHint(mNativeObject, sc.mNativeObject, -1/* INVALID_ROTATION */);
+            return this;
+        }
+
+        /**
          * Set the Z-order for a given SurfaceControl, relative to it's siblings.
          * If two siblings share the same Z order the ordering is undefined. Surfaces
          * with a negative Z will be placed below the parent surface.
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index 7086dc0..3850781 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -275,12 +275,4 @@
         // ViewRoot will release mSurfaceControl for us.
         mViewRoot.die(false /* immediate */);
     }
-
-    /**
-     * Tell this viewroot to clean itself up.
-     * @hide
-     */
-    public void die() {
-        mViewRoot.die(false /* immediate */);
-    }
 }
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index db6fe0f..bd811fc 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -134,6 +134,23 @@
     // we need to preserve the old one until the new one has drawn.
     SurfaceControl mDeferredDestroySurfaceControl;
     SurfaceControl mBackgroundControl;
+
+    /**
+     * We use this lock in SOME cases when reading or writing SurfaceControl,
+     * but use the following model so that the RenderThread can run locklessly
+     * in the position up-date case.
+     *
+     * 1. UI Thread can read from mSurfaceControl (use in Transactions) without
+     * holding the lock.
+     * 2. UI Thread will hold the lock when writing to mSurfaceControl (calling release
+     * or remove).
+     * 3. Render thread will also hold the lock when writing to mSurfaceControl (e.g.
+     * calling release from positionLost).
+     * 3. RenderNode.PositionUpdateListener::positionChanged will only be called
+     * when the UI thread is paused (blocked on the Render thread).
+     * 4. positionChanged thus will not be required to hold the lock as the
+     * UI thread is blocked, and the other writer is the RT itself.
+     */
     final Object mSurfaceControlLock = new Object();
     final Rect mTmpRect = new Rect();
 
@@ -1297,15 +1314,19 @@
                 (viewRoot != null ? viewRoot.getBLASTSyncTransaction() : mRtTransaction) :
                 mRtTransaction;
 
-            if (frameNumber > 0 && viewRoot !=  null && !useBLAST) {
-                if (viewRoot.mSurface.isValid()) {
-                    mRtTransaction.deferTransactionUntil(mSurfaceControl,
-                            viewRoot.getRenderSurfaceControl(), frameNumber);
-                }
-            }
-            t.hide(mSurfaceControl);
-
+            /**
+             * positionLost can be called while UI thread is un-paused so we
+             * need to hold the lock here.
+             */
             synchronized (mSurfaceControlLock) {
+                if (frameNumber > 0 && viewRoot !=  null && !useBLAST) {
+                    if (viewRoot.mSurface.isValid()) {
+                        mRtTransaction.deferTransactionUntil(mSurfaceControl,
+                                viewRoot.getRenderSurfaceControl(), frameNumber);
+                    }
+                }
+                t.hide(mSurfaceControl);
+
                 if (mRtReleaseSurfaces) {
                     mRtReleaseSurfaces = false;
                     mRtTransaction.remove(mSurfaceControl);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 5b9cd77..511e755 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1496,7 +1496,6 @@
                         final int newScreenState = toViewScreenState(newDisplayState);
                         if (oldScreenState != newScreenState) {
                             mView.dispatchScreenStateChanged(newScreenState);
-                            mImeFocusController.onScreenStateChanged(newScreenState);
                         }
                         if (oldDisplayState == Display.STATE_OFF) {
                             // Draw was suppressed so we need to for it to happen here.
@@ -1977,6 +1976,11 @@
             mCompatibleVisibilityInfo.globalVisibility =
                     (mCompatibleVisibilityInfo.globalVisibility & ~View.SYSTEM_UI_FLAG_LOW_PROFILE)
                             | (mAttachInfo.mSystemUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE);
+            if (mDispatchedSystemUiVisibility != mCompatibleVisibilityInfo.globalVisibility) {
+                mHandler.removeMessages(MSG_DISPATCH_SYSTEM_UI_VISIBILITY);
+                mHandler.sendMessage(mHandler.obtainMessage(
+                        MSG_DISPATCH_SYSTEM_UI_VISIBILITY, mCompatibleVisibilityInfo));
+            }
             if (mAttachInfo.mKeepScreenOn != oldScreenOn
                     || mAttachInfo.mSystemUiVisibility != params.subtreeSystemUiVisibility
                     || mAttachInfo.mHasSystemUiListeners != params.hasSystemUiListeners) {
@@ -2028,9 +2032,11 @@
             }
         } else {
             info.globalVisibility |= systemUiFlag;
+            info.localChanges &= ~systemUiFlag;
         }
         if (mDispatchedSystemUiVisibility != info.globalVisibility) {
-            scheduleTraversals();
+            mHandler.removeMessages(MSG_DISPATCH_SYSTEM_UI_VISIBILITY);
+            mHandler.sendMessage(mHandler.obtainMessage(MSG_DISPATCH_SYSTEM_UI_VISIBILITY, info));
         }
     }
 
@@ -2478,9 +2484,6 @@
             mAttachInfo.mForceReportNewAttributes = false;
             params = lp;
         }
-        if (sNewInsetsMode == NEW_INSETS_MODE_FULL) {
-            handleDispatchSystemUiVisibilityChanged(mCompatibleVisibilityInfo);
-        }
 
         if (mFirst || mAttachInfo.mViewVisibilityChanged) {
             mAttachInfo.mViewVisibilityChanged = false;
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index aad1c60..4d6b72f 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -1328,30 +1328,36 @@
             }
         }
 
-        static String toString(@InsetsType int type) {
-            switch (type) {
-                case STATUS_BARS:
-                    return "statusBars";
-                case NAVIGATION_BARS:
-                    return "navigationBars";
-                case CAPTION_BAR:
-                    return "captionBar";
-                case IME:
-                    return "ime";
-                case SYSTEM_GESTURES:
-                    return "systemGestures";
-                case MANDATORY_SYSTEM_GESTURES:
-                    return "mandatorySystemGestures";
-                case TAPPABLE_ELEMENT:
-                    return "tappableElement";
-                case DISPLAY_CUTOUT:
-                    return "displayCutout";
-                case WINDOW_DECOR:
-                    return "windowDecor";
-                default:
-                    throw new IllegalArgumentException("type needs to be >= FIRST and <= LAST,"
-                            + " type=" + type);
+        static String toString(@InsetsType int types) {
+            StringBuilder result = new StringBuilder();
+            if ((types & STATUS_BARS) != 0) {
+                result.append("statusBars |");
             }
+            if ((types & NAVIGATION_BARS) != 0) {
+                result.append("navigationBars |");
+            }
+            if ((types & IME) != 0) {
+                result.append("ime |");
+            }
+            if ((types & SYSTEM_GESTURES) != 0) {
+                result.append("systemGestures |");
+            }
+            if ((types & MANDATORY_SYSTEM_GESTURES) != 0) {
+                result.append("mandatorySystemGestures |");
+            }
+            if ((types & TAPPABLE_ELEMENT) != 0) {
+                result.append("tappableElement |");
+            }
+            if ((types & DISPLAY_CUTOUT) != 0) {
+                result.append("displayCutout |");
+            }
+            if ((types & WINDOW_DECOR) != 0) {
+                result.append("windowDecor |");
+            }
+            if (result.length() > 0) {
+                result.delete(result.length() - 2, result.length());
+            }
+            return result.toString();
         }
 
         private Type() {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 8cb05da..7607127 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1162,7 +1162,7 @@
 
         /**
          * Window type: shows directly above the keyguard. The layer is
-         * reserved for screenshot region selection. These windows must not take input focus.
+         * reserved for screenshot animation, region selection and UI.
          * In multiuser systems shows only on the owning user's window.
          * @hide
          */
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index cd954c4..d20ffb3 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -143,7 +143,7 @@
                 WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0)) {
             try {
                 mRealWm.grantInputChannel(displayId, sc, window, mHostInputToken, attrs.flags,
-                        outInputChannel);
+                        attrs.type, outInputChannel);
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to grant input to surface: ", e);
             }
@@ -432,7 +432,7 @@
 
     @Override
     public void grantInputChannel(int displayId, SurfaceControl surface, IWindow window,
-            IBinder hostInputToken, int flags, InputChannel outInputChannel) {
+            IBinder hostInputToken, int flags, int type, InputChannel outInputChannel) {
     }
 
     @Override
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index ca5c417..813234f 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -752,7 +752,10 @@
         }
     }
 
-    private static String typeToString(int type) {
+    /**
+     * @hide
+     */
+    public static String typeToString(int type) {
         switch (type) {
             case TYPE_APPLICATION: {
                 return "TYPE_APPLICATION";
@@ -770,7 +773,7 @@
                 return "TYPE_SPLIT_SCREEN_DIVIDER";
             }
             default:
-                return "<UNKNOWN>";
+                return "<UNKNOWN:" + type + ">";
         }
     }
 
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 76fe6b5f..553e3c8 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -18,6 +18,7 @@
 
 import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
 import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE;
+import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED;
 import static android.view.autofill.Helper.sDebug;
 import static android.view.autofill.Helper.sVerbose;
 import static android.view.autofill.Helper.toList;
@@ -879,7 +880,11 @@
      * @param view view requesting the new autofill context.
      */
     public void requestAutofill(@NonNull View view) {
-        notifyViewEntered(view, FLAG_MANUAL_REQUEST);
+        int flags = FLAG_MANUAL_REQUEST;
+        if (!view.isFocused()) {
+            flags |= FLAG_VIEW_NOT_FOCUSED;
+        }
+        notifyViewEntered(view, flags);
     }
 
     /**
@@ -926,7 +931,11 @@
      * @param absBounds absolute boundaries of the virtual view in the screen.
      */
     public void requestAutofill(@NonNull View view, int virtualId, @NonNull Rect absBounds) {
-        notifyViewEntered(view, virtualId, absBounds, FLAG_MANUAL_REQUEST);
+        int flags = FLAG_MANUAL_REQUEST;
+        if (!view.isFocused()) {
+            flags |= FLAG_VIEW_NOT_FOCUSED;
+        }
+        notifyViewEntered(view, virtualId, absBounds, flags);
     }
 
     /**
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 4519aef..d021fc9 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -346,7 +346,7 @@
 
 
     /** @hide */
-    public static final int DEFAULT_MAX_BUFFER_SIZE = 100;
+    public static final int DEFAULT_MAX_BUFFER_SIZE = 500; // Enough for typical busy screen.
     /** @hide */
     public static final int DEFAULT_IDLE_FLUSHING_FREQUENCY_MS = 5_000;
     /** @hide */
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 39c7210..301ce9f 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -166,6 +166,8 @@
     public static final int FLUSH_REASON_IDLE_TIMEOUT = 5;
     /** @hide */
     public static final int FLUSH_REASON_TEXT_CHANGE_TIMEOUT = 6;
+    /** @hide */
+    public static final int FLUSH_REASON_SESSION_CONNECTED = 7;
 
     /** @hide */
     @IntDef(prefix = { "FLUSH_REASON_" }, value = {
@@ -174,7 +176,8 @@
             FLUSH_REASON_SESSION_STARTED,
             FLUSH_REASON_SESSION_FINISHED,
             FLUSH_REASON_IDLE_TIMEOUT,
-            FLUSH_REASON_TEXT_CHANGE_TIMEOUT
+            FLUSH_REASON_TEXT_CHANGE_TIMEOUT,
+            FLUSH_REASON_SESSION_CONNECTED
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface FlushReason{}
@@ -609,6 +612,8 @@
                 return "IDLE";
             case FLUSH_REASON_TEXT_CHANGE_TIMEOUT:
                 return "TEXT_CHANGE";
+            case FLUSH_REASON_SESSION_CONNECTED:
+                return "CONNECTED";
             default:
                 return "UNKOWN-" + reason;
         }
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index 893d38d..6eb71f7 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -273,6 +273,8 @@
         } else {
             mState = resultCode;
             mDisabled.set(false);
+            // Flush any pending data immediately as buffering forced until now.
+            flushIfNeeded(FLUSH_REASON_SESSION_CONNECTED);
         }
         if (sVerbose) {
             Log.v(TAG, "handleSessionStarted() result: id=" + mId + " resultCode=" + resultCode
diff --git a/core/java/android/view/inputmethod/InlineSuggestion.java b/core/java/android/view/inputmethod/InlineSuggestion.java
index 4c72474..e4ac588 100644
--- a/core/java/android/view/inputmethod/InlineSuggestion.java
+++ b/core/java/android/view/inputmethod/InlineSuggestion.java
@@ -326,11 +326,13 @@
 
         @MainThread
         private void handleOnSurfacePackageReleased() {
-            mSurfacePackage = null;
-            try {
-                mInlineContentProvider.onSurfacePackageReleased();
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Error calling onSurfacePackageReleased(): " + e);
+            if (mSurfacePackage != null) {
+                try {
+                    mInlineContentProvider.onSurfacePackageReleased();
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Error calling onSurfacePackageReleased(): " + e);
+                }
+                mSurfacePackage = null;
             }
         }
 
@@ -573,7 +575,7 @@
     };
 
     @DataClass.Generated(
-            time = 1588308946517L,
+            time = 1589396017700L,
             codegenVersion = "1.0.15",
             sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java",
             inputSignatures = "private static final  java.lang.String TAG\nprivate final @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo mInfo\nprivate final @android.annotation.Nullable com.android.internal.view.inline.IInlineContentProvider mContentProvider\nprivate @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineContentCallbackImplParceling.class) @android.annotation.Nullable android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl mInlineContentCallback\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestion newInlineSuggestion(android.view.inputmethod.InlineSuggestionInfo)\npublic  void inflate(android.content.Context,android.util.Size,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nprivate static  boolean isValid(int,int,int)\nprivate synchronized  android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl getInlineContentCallback(android.content.Context,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index f8522ed..0807f41 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -189,14 +189,29 @@
     public void onCloseWindow(WebView window) {}
 
     /**
-     * Tell the client to display a javascript alert dialog.  If the client
-     * returns {@code true}, WebView will assume that the client will handle the
-     * dialog.  If the client returns {@code false}, it will continue execution.
+     * Notify the host application that the web page wants to display a
+     * JavaScript {@code alert()} dialog.
+     * <p>The default behavior if this method returns {@code false} or is not
+     * overridden is to show a dialog containing the alert message and suspend
+     * JavaScript execution until the dialog is dismissed.
+     * <p>To show a custom dialog, the app should return {@code true} from this
+     * method, in which case the default dialog will not be shown and JavaScript
+     * execution will be suspended. The app should call
+     * {@code JsResult.confirm()} when the custom dialog is dismissed such that
+     * JavaScript execution can be resumed.
+     * <p>To suppress the dialog and allow JavaScript execution to
+     * continue, call {@code JsResult.confirm()} immediately and then return
+     * {@code true}.
+     * <p>Note that if the {@link WebChromeClient} is {@code null}, the default
+     * dialog will be suppressed and Javascript execution will continue
+     * immediately.
+     *
      * @param view The WebView that initiated the callback.
      * @param url The url of the page requesting the dialog.
      * @param message Message to be displayed in the window.
-     * @param result A JsResult to confirm that the user hit enter.
-     * @return boolean Whether the client will handle the alert dialog.
+     * @param result A JsResult to confirm that the user closed the window.
+     * @return boolean {@code true} if the request is handled or ignored.
+     * {@code false} if WebView needs to show the default dialog.
      */
     public boolean onJsAlert(WebView view, String url, String message,
             JsResult result) {
@@ -204,17 +219,34 @@
     }
 
     /**
-     * Tell the client to display a confirm dialog to the user. If the client
-     * returns {@code true}, WebView will assume that the client will handle the
-     * confirm dialog and call the appropriate JsResult method. If the
-     * client returns false, a default value of {@code false} will be returned to
-     * javascript. The default behavior is to return {@code false}.
+     * Notify the host application that the web page wants to display a
+     * JavaScript {@code confirm()} dialog.
+     * <p>The default behavior if this method returns {@code false} or is not
+     * overridden is to show a dialog containing the message and suspend
+     * JavaScript execution until the dialog is dismissed. The default dialog
+     * will return {@code true} to the JavaScript {@code confirm()} code when
+     * the user presses the 'confirm' button, and will return {@code false} to
+     * the JavaScript code when the user presses the 'cancel' button or
+     * dismisses the dialog.
+     * <p>To show a custom dialog, the app should return {@code true} from this
+     * method, in which case the default dialog will not be shown and JavaScript
+     * execution will be suspended. The app should call
+     * {@code JsResult.confirm()} or {@code JsResult.cancel()} when the custom
+     * dialog is dismissed.
+     * <p>To suppress the dialog and allow JavaScript execution to continue,
+     * call {@code JsResult.confirm()} or {@code JsResult.cancel()} immediately
+     * and then return {@code true}.
+     * <p>Note that if the {@link WebChromeClient} is {@code null}, the default
+     * dialog will be suppressed and the default value of {@code false} will be
+     * returned to the JavaScript code immediately.
+     *
      * @param view The WebView that initiated the callback.
      * @param url The url of the page requesting the dialog.
      * @param message Message to be displayed in the window.
      * @param result A JsResult used to send the user's response to
      *               javascript.
-     * @return boolean Whether the client will handle the confirm dialog.
+     * @return boolean {@code true} if the request is handled or ignored.
+     * {@code false} if WebView needs to show the default dialog.
      */
     public boolean onJsConfirm(WebView view, String url, String message,
             JsResult result) {
@@ -222,18 +254,33 @@
     }
 
     /**
-     * Tell the client to display a prompt dialog to the user. If the client
-     * returns {@code true}, WebView will assume that the client will handle the
-     * prompt dialog and call the appropriate JsPromptResult method. If the
-     * client returns false, a default value of {@code false} will be returned to to
-     * javascript. The default behavior is to return {@code false}.
+     * Notify the host application that the web page wants to display a
+     * JavaScript {@code prompt()} dialog.
+     * <p>The default behavior if this method returns {@code false} or is not
+     * overridden is to show a dialog containing the message and suspend
+     * JavaScript execution until the dialog is dismissed. Once the dialog is
+     * dismissed, JavaScript {@code prompt()} will return the string that the
+     * user typed in, or null if the user presses the 'cancel' button.
+     * <p>To show a custom dialog, the app should return {@code true} from this
+     * method, in which case the default dialog will not be shown and JavaScript
+     * execution will be suspended. The app should call
+     * {@code JsPromptResult.confirm(result)} when the custom dialog is
+     * dismissed.
+     * <p>To suppress the dialog and allow JavaScript execution to continue,
+     * call {@code JsPromptResult.confirm(result)} immediately and then
+     * return {@code true}.
+     * <p>Note that if the {@link WebChromeClient} is {@code null}, the default
+     * dialog will be suppressed and {@code null} will be returned to the
+     * JavaScript code immediately.
+     *
      * @param view The WebView that initiated the callback.
      * @param url The url of the page requesting the dialog.
      * @param message Message to be displayed in the window.
      * @param defaultValue The default value displayed in the prompt dialog.
      * @param result A JsPromptResult used to send the user's reponse to
      *               javascript.
-     * @return boolean Whether the client will handle the prompt dialog.
+     * @return boolean {@code true} if the request is handled or ignored.
+     * {@code false} if WebView needs to show the default dialog.
      */
     public boolean onJsPrompt(WebView view, String url, String message,
             String defaultValue, JsPromptResult result) {
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 35dd576..91b9390 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -1118,6 +1118,10 @@
      * {@link #setAppCachePath}.
      *
      * @param flag {@code true} if the WebView should enable Application Caches
+     * @deprecated The Application Cache API is deprecated and this method will
+     *             become a no-op on all Android versions once support is
+     *             removed in Chromium. Consider using Service Workers instead.
+     *             See https://web.dev/appcache-removal/ for more information.
      */
     public abstract void setAppCacheEnabled(boolean flag);
 
@@ -1130,6 +1134,10 @@
      * @param appCachePath a String path to the directory containing
      *                     Application Caches files.
      * @see #setAppCacheEnabled
+     * @deprecated The Application Cache API is deprecated and this method will
+     *             become a no-op on all Android versions once support is
+     *             removed in Chromium. Consider using Service Workers instead.
+     *             See https://web.dev/appcache-removal/ for more information.
      */
     public abstract void setAppCachePath(String appCachePath);
 
@@ -1142,7 +1150,7 @@
      * It is recommended to leave the maximum size set to the default value.
      *
      * @param appCacheMaxSize the maximum size in bytes
-     * @deprecated In future quota will be managed automatically.
+     * @deprecated Quota is managed automatically; this method is a no-op.
      */
     @Deprecated
     public abstract void setAppCacheMaxSize(long appCacheMaxSize);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 29914aa..226f5797 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8315,23 +8315,6 @@
         return false;
     }
 
-    /**
-     * Returns true if pressing TAB in this field advances focus instead
-     * of inserting the character.  Insert tabs only in multi-line editors.
-     */
-    private boolean shouldAdvanceFocusOnTab() {
-        if (getKeyListener() != null && !mSingleLine && mEditor != null
-                && (mEditor.mInputType & EditorInfo.TYPE_MASK_CLASS)
-                        == EditorInfo.TYPE_CLASS_TEXT) {
-            int multilineFlags = EditorInfo.TYPE_TEXT_FLAG_IME_MULTI_LINE
-                    | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
-            if ((mEditor.mInputType & multilineFlags) != 0) {
-                return false;
-            }
-        }
-        return true;
-    }
-
     private boolean isDirectionalNavigationKey(int keyCode) {
         switch(keyCode) {
             case KeyEvent.KEYCODE_DPAD_UP:
@@ -8400,9 +8383,8 @@
 
             case KeyEvent.KEYCODE_TAB:
                 if (event.hasNoModifiers() || event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
-                    if (shouldAdvanceFocusOnTab()) {
-                        return KEY_EVENT_NOT_HANDLED;
-                    }
+                    // Tab is used to move focus.
+                    return KEY_EVENT_NOT_HANDLED;
                 }
                 break;
 
diff --git a/core/java/com/android/internal/BrightnessSynchronizer.java b/core/java/com/android/internal/BrightnessSynchronizer.java
index aa23251..42724be 100644
--- a/core/java/com/android/internal/BrightnessSynchronizer.java
+++ b/core/java/com/android/internal/BrightnessSynchronizer.java
@@ -84,17 +84,17 @@
      * Converts between the int brightness system and the float brightness system.
      */
     public static float brightnessIntToFloat(Context context, int brightnessInt) {
-        PowerManager pm = context.getSystemService(PowerManager.class);
-        float pmMinBrightness = pm.getBrightnessConstraint(
+        final PowerManager pm = context.getSystemService(PowerManager.class);
+        final float pmMinBrightness = pm.getBrightnessConstraint(
                 PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
-        float pmMaxBrightness = pm.getBrightnessConstraint(
+        final float pmMaxBrightness = pm.getBrightnessConstraint(
                 PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
-        int minBrightnessInt = brightnessFloatToInt(pmMinBrightness, PowerManager.BRIGHTNESS_MIN,
-                PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_OFF + 1,
-                PowerManager.BRIGHTNESS_ON);
-        int maxBrightnessInt = brightnessFloatToInt(pmMaxBrightness, PowerManager.BRIGHTNESS_MIN,
-                PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_OFF + 1,
-                PowerManager.BRIGHTNESS_ON);
+        final int minBrightnessInt = Math.round(brightnessFloatToIntRange(pmMinBrightness,
+                PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX,
+                PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON));
+        final int maxBrightnessInt = Math.round(brightnessFloatToIntRange(pmMaxBrightness,
+                PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX,
+                PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON));
 
         return brightnessIntToFloat(brightnessInt, minBrightnessInt, maxBrightnessInt,
                 pmMinBrightness, pmMaxBrightness);
@@ -119,34 +119,43 @@
      * Converts between the float brightness system and the int brightness system.
      */
     public static int brightnessFloatToInt(Context context, float brightnessFloat) {
-        PowerManager pm = context.getSystemService(PowerManager.class);
-        float pmMinBrightness = pm.getBrightnessConstraint(
-                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
-        float pmMaxBrightness = pm.getBrightnessConstraint(
-                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
-        int minBrightnessInt = brightnessFloatToInt(pmMinBrightness, PowerManager.BRIGHTNESS_MIN,
-                PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_OFF + 1,
-                PowerManager.BRIGHTNESS_ON);
-        int maxBrightnessInt = brightnessFloatToInt(pmMaxBrightness, PowerManager.BRIGHTNESS_MIN,
-                PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_OFF + 1,
-                PowerManager.BRIGHTNESS_ON);
-
-        return brightnessFloatToInt(brightnessFloat, pmMinBrightness, pmMaxBrightness,
-                minBrightnessInt, maxBrightnessInt);
+        return Math.round(brightnessFloatToIntRange(context, brightnessFloat));
     }
 
     /**
-     * Converts between the float brightness system and the int brightness system.
+     * Converts between the float brightness system and the int brightness system, but returns
+     * the converted value as a float within the int-system's range. This method helps with
+     * conversions from one system to the other without losing the floating-point precision.
      */
-    public static int brightnessFloatToInt(float brightnessFloat, float minFloat, float maxFloat,
-            int minInt, int maxInt) {
+    public static float brightnessFloatToIntRange(Context context, float brightnessFloat) {
+        final PowerManager pm = context.getSystemService(PowerManager.class);
+        final float minFloat = pm.getBrightnessConstraint(
+                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
+        final float maxFloat = pm.getBrightnessConstraint(
+                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
+        final float minInt = brightnessFloatToIntRange(minFloat,
+                PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX,
+                PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON);
+        final float maxInt = brightnessFloatToIntRange(maxFloat,
+                PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX,
+                PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON);
+        return brightnessFloatToIntRange(brightnessFloat, minFloat, maxFloat, minInt, maxInt);
+    }
+
+    /**
+     * Translates specified value from the float brightness system to the int brightness system,
+     * given the min/max of each range.  Accounts for special values such as OFF and invalid values.
+     * Value returned as a float privimite (to preserve precision), but is a value within the
+     * int-system range.
+     */
+    private static float brightnessFloatToIntRange(float brightnessFloat, float minFloat,
+            float maxFloat, float minInt, float maxInt) {
         if (floatEquals(brightnessFloat, PowerManager.BRIGHTNESS_OFF_FLOAT)) {
             return PowerManager.BRIGHTNESS_OFF;
         } else if (Float.isNaN(brightnessFloat)) {
             return PowerManager.BRIGHTNESS_INVALID;
         } else {
-            return Math.round(MathUtils.constrainedMap((float) minInt, (float) maxInt, minFloat,
-                    maxFloat, brightnessFloat));
+            return MathUtils.constrainedMap(minInt, maxInt, minFloat, maxFloat, brightnessFloat);
         }
     }
 
diff --git a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
index 891d535..a3c29a8 100644
--- a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
+++ b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
@@ -19,6 +19,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
 
+import static com.android.internal.accessibility.dialog.AccessibilityTargetHelper.getTargets;
 import static com.android.internal.util.ArrayUtils.convertToLongArray;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
@@ -52,6 +53,7 @@
 import android.widget.Toast;
 
 import com.android.internal.R;
+import com.android.internal.accessibility.dialog.AccessibilityTarget;
 import com.android.internal.util.function.pooled.PooledLambda;
 
 import java.lang.annotation.Retention;
@@ -267,16 +269,21 @@
     }
 
     private AlertDialog createShortcutWarningDialog(int userId) {
-        final String warningMessage = mContext.getString(
-                R.string.accessibility_shortcut_toogle_warning);
+        List<AccessibilityTarget> targets = getTargets(mContext, ACCESSIBILITY_SHORTCUT_KEY);
+        if (targets.size() == 0) {
+            return null;
+        }
+
+        // Avoid non-a11y users accidentally turning shortcut on without reading this carefully.
+        // Put "don't turn on" as the primary action.
         final AlertDialog alertDialog = mFrameworkObjectProvider.getAlertDialogBuilder(
                 // Use SystemUI context so we pick up any theme set in a vendor overlay
                 mFrameworkObjectProvider.getSystemUiContext())
-                .setTitle(R.string.accessibility_shortcut_warning_dialog_title)
-                .setMessage(warningMessage)
+                .setTitle(getShortcutWarningTitle(targets))
+                .setMessage(getShortcutWarningMessage(targets))
                 .setCancelable(false)
-                .setPositiveButton(R.string.leave_accessibility_shortcut_on, null)
-                .setNegativeButton(R.string.disable_accessibility_shortcut,
+                .setNegativeButton(R.string.accessibility_shortcut_on, null)
+                .setPositiveButton(R.string.accessibility_shortcut_off,
                         (DialogInterface d, int which) -> {
                             Settings.Secure.putStringForUser(mContext.getContentResolver(),
                                     Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, "",
@@ -297,6 +304,32 @@
         return alertDialog;
     }
 
+    private String getShortcutWarningTitle(List<AccessibilityTarget> targets) {
+        if (targets.size() == 1) {
+            return mContext.getString(
+                    R.string.accessibility_shortcut_single_service_warning_title,
+                    targets.get(0).getLabel());
+        }
+        return mContext.getString(
+                R.string.accessibility_shortcut_multiple_service_warning_title);
+    }
+
+    private String getShortcutWarningMessage(List<AccessibilityTarget> targets) {
+        if (targets.size() == 1) {
+            return mContext.getString(
+                    R.string.accessibility_shortcut_single_service_warning,
+                    targets.get(0).getLabel());
+        }
+
+        final StringBuilder sb = new StringBuilder();
+        for (AccessibilityTarget target : targets) {
+            sb.append(mContext.getString(R.string.accessibility_shortcut_multiple_service_list,
+                    target.getLabel()));
+        }
+        return mContext.getString(R.string.accessibility_shortcut_multiple_service_warning,
+                sb.toString());
+    }
+
     private AccessibilityServiceInfo getInfoForTargetService() {
         final ComponentName targetComponentName = getShortcutTargetComponentName();
         if (targetComponentName == null) {
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java
index 37871d0..d756593 100644
--- a/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java
@@ -38,7 +38,7 @@
  * Abstract base class for creating various target related to accessibility service,
  * accessibility activity, and white listing feature.
  */
-abstract class AccessibilityTarget implements TargetOperations, OnTargetSelectedListener,
+public abstract class AccessibilityTarget implements TargetOperations, OnTargetSelectedListener,
         OnTargetCheckedChangeListener {
     private Context mContext;
     @ShortcutType
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java
index f63cbe0..60a102a 100644
--- a/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java
@@ -53,19 +53,61 @@
 /**
  * Collection of utilities for accessibility target.
  */
-final class AccessibilityTargetHelper {
+public final class AccessibilityTargetHelper {
     private AccessibilityTargetHelper() {}
 
-    static List<AccessibilityTarget> getTargets(Context context,
+    /**
+     * Returns list of {@link AccessibilityTarget} of assigned accessibility shortcuts from
+     * {@link AccessibilityManager#getAccessibilityShortcutTargets} including accessibility
+     * feature's package name, component id, etc.
+     *
+     * @param context The context of the application.
+     * @param shortcutType The shortcut type.
+     * @return The list of {@link AccessibilityTarget}.
+     * @hide
+     */
+    public static List<AccessibilityTarget> getTargets(Context context,
             @ShortcutType int shortcutType) {
-        final List<AccessibilityTarget> targets = getInstalledTargets(context, shortcutType);
-        final AccessibilityManager ams = context.getSystemService(AccessibilityManager.class);
-        final List<String> requiredTargets = ams.getAccessibilityShortcutTargets(shortcutType);
-        targets.removeIf(target -> !requiredTargets.contains(target.getId()));
+        // List all accessibility target
+        final List<AccessibilityTarget> installedTargets = getInstalledTargets(context,
+                shortcutType);
 
-        return targets;
+        // List accessibility shortcut target
+        final AccessibilityManager am = (AccessibilityManager) context.getSystemService(
+                Context.ACCESSIBILITY_SERVICE);
+        final List<String> assignedTargets = am.getAccessibilityShortcutTargets(shortcutType);
+
+        // Get the list of accessibility shortcut target in all accessibility target
+        final List<AccessibilityTarget> results = new ArrayList<>();
+        for (String assignedTarget : assignedTargets) {
+            for (AccessibilityTarget installedTarget : installedTargets) {
+                if (!MAGNIFICATION_CONTROLLER_NAME.contentEquals(assignedTarget)) {
+                    final ComponentName assignedTargetComponentName =
+                            ComponentName.unflattenFromString(assignedTarget);
+                    final ComponentName targetComponentName = ComponentName.unflattenFromString(
+                            installedTarget.getId());
+                    if (assignedTargetComponentName.equals(targetComponentName)) {
+                        results.add(installedTarget);
+                        continue;
+                    }
+                }
+                if (assignedTarget.contentEquals(installedTarget.getId())) {
+                    results.add(installedTarget);
+                }
+            }
+        }
+        return results;
     }
 
+    /**
+     * Returns list of {@link AccessibilityTarget} of the installed accessibility service,
+     * accessibility activity, and white listing feature including accessibility feature's package
+     * name, component id, etc.
+     *
+     * @param context The context of the application.
+     * @param shortcutType The shortcut type.
+     * @return The list of {@link AccessibilityTarget}.
+     */
     static List<AccessibilityTarget> getInstalledTargets(Context context,
             @ShortcutType int shortcutType) {
         final List<AccessibilityTarget> targets = new ArrayList<>();
@@ -110,9 +152,10 @@
 
     private static List<AccessibilityTarget> getAccessibilityServiceTargets(Context context,
             @ShortcutType int shortcutType) {
-        final AccessibilityManager ams = context.getSystemService(AccessibilityManager.class);
+        final AccessibilityManager am = (AccessibilityManager) context.getSystemService(
+                Context.ACCESSIBILITY_SERVICE);
         final List<AccessibilityServiceInfo> installedServices =
-                ams.getInstalledAccessibilityServiceList();
+                am.getInstalledAccessibilityServiceList();
         if (installedServices == null) {
             return Collections.emptyList();
         }
@@ -136,9 +179,10 @@
 
     private static List<AccessibilityTarget> getAccessibilityActivityTargets(Context context,
             @ShortcutType int shortcutType) {
-        final AccessibilityManager ams = context.getSystemService(AccessibilityManager.class);
+        final AccessibilityManager am = (AccessibilityManager) context.getSystemService(
+                Context.ACCESSIBILITY_SERVICE);
         final List<AccessibilityShortcutInfo> installedServices =
-                ams.getInstalledAccessibilityShortcutListAsUser(context,
+                am.getInstalledAccessibilityShortcutListAsUser(context,
                         ActivityManager.getCurrentUser());
         if (installedServices == null) {
             return Collections.emptyList();
diff --git a/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java b/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
index e50b010..9ee0b0e 100644
--- a/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
+++ b/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
@@ -142,7 +142,8 @@
      */
     public static boolean isAccessibilityServiceEnabled(Context context,
             @NonNull String componentId) {
-        final AccessibilityManager am = context.getSystemService(AccessibilityManager.class);
+        final AccessibilityManager am = (AccessibilityManager) context.getSystemService(
+                Context.ACCESSIBILITY_SERVICE);
         final List<AccessibilityServiceInfo> enabledServices =
                 am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
 
diff --git a/core/java/com/android/internal/accessibility/util/ShortcutUtils.java b/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
index 100422f..31ccb6c3 100644
--- a/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
+++ b/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
@@ -137,7 +137,8 @@
      */
     public static boolean isShortcutContained(Context context, @ShortcutType int shortcutType,
             @NonNull String componentId) {
-        final AccessibilityManager am = context.getSystemService(AccessibilityManager.class);
+        final AccessibilityManager am = (AccessibilityManager) context.getSystemService(
+                Context.ACCESSIBILITY_SERVICE);
         final List<String> requiredTargets = am.getAccessibilityShortcutTargets(shortcutType);
         return requiredTargets.contains(componentId);
     }
diff --git a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
index a47ad73..c8f5be4 100644
--- a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
@@ -62,6 +62,7 @@
     private final Context mContext;
     private int mCurrentPage;
     private OnProfileSelectedListener mOnProfileSelectedListener;
+    private OnSwitchOnWorkSelectedListener mOnSwitchOnWorkSelectedListener;
     private Set<Integer> mLoadedPages;
     private final UserHandle mPersonalProfileUserHandle;
     private final UserHandle mWorkProfileUserHandle;
@@ -124,6 +125,10 @@
         mOnProfileSelectedListener = listener;
     }
 
+    void setOnSwitchOnWorkSelectedListener(OnSwitchOnWorkSelectedListener listener) {
+        mOnSwitchOnWorkSelectedListener = listener;
+    }
+
     Context getContext() {
         return mContext;
     }
@@ -397,6 +402,9 @@
                     ProfileDescriptor descriptor = getItem(
                             userHandleToPageIndex(listAdapter.getUserHandle()));
                     showSpinner(descriptor.getEmptyStateView());
+                    if (mOnSwitchOnWorkSelectedListener != null) {
+                        mOnSwitchOnWorkSelectedListener.onSwitchOnWorkSelected();
+                    }
                     mInjector.requestQuietModeEnabled(false, mWorkProfileUserHandle);
                 });
         return true;
@@ -576,6 +584,16 @@
     }
 
     /**
+     * Listener for when the user switches on the work profile from the work tab.
+     */
+    interface OnSwitchOnWorkSelectedListener {
+        /**
+         * Callback for when the user switches on the work profile from the work tab.
+         */
+        void onSwitchOnWorkSelected();
+    }
+
+    /**
      * Describes an injector to be used for cross profile functionality. Overridable for testing.
      */
     @VisibleForTesting
diff --git a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
index 37a5a63..0d16cc4 100644
--- a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
+++ b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
@@ -128,9 +128,8 @@
                         mResolverRankerService.compute(targets);
                     } else {
                         Log.i(TAG, "AppPredictionService response received");
-                        Message msg =
-                            Message.obtain(mHandler, RANKER_SERVICE_RESULT, sortedAppTargets);
-                        msg.sendToTarget();
+                        // Skip sending to Handler which takes extra time to dispatch messages.
+                        handleResult(sortedAppTargets);
                     }
                 }
         );
@@ -141,23 +140,35 @@
         // Null value is okay if we have defaulted to the ResolverRankerService.
         if (msg.what == RANKER_SERVICE_RESULT && msg.obj != null) {
             final List<AppTarget> sortedAppTargets = (List<AppTarget>) msg.obj;
-            if (checkAppTargetRankValid(sortedAppTargets)) {
-                sortedAppTargets.forEach(target -> mTargetScores.put(
-                        new ComponentName(target.getPackageName(), target.getClassName()),
-                        target.getRank()));
-            }
-            for (int i = 0; i < sortedAppTargets.size(); i++) {
-                ComponentName componentName = new ComponentName(
-                        sortedAppTargets.get(i).getPackageName(),
-                        sortedAppTargets.get(i).getClassName());
-                mTargetRanks.put(componentName, i);
-                Log.i(TAG, "handleResultMessage, sortedAppTargets #" + i + ": " + componentName);
-            }
+            handleSortedAppTargets(sortedAppTargets);
         } else if (msg.obj == null && mResolverRankerService == null) {
             Log.e(TAG, "Unexpected null result");
         }
     }
 
+    private void handleResult(List<AppTarget> sortedAppTargets) {
+        if (mHandler.hasMessages(RANKER_RESULT_TIMEOUT)) {
+            handleSortedAppTargets(sortedAppTargets);
+            mHandler.removeMessages(RANKER_RESULT_TIMEOUT);
+            afterCompute();
+        }
+    }
+
+    private void handleSortedAppTargets(List<AppTarget> sortedAppTargets) {
+        if (checkAppTargetRankValid(sortedAppTargets)) {
+            sortedAppTargets.forEach(target -> mTargetScores.put(
+                    new ComponentName(target.getPackageName(), target.getClassName()),
+                    target.getRank()));
+        }
+        for (int i = 0; i < sortedAppTargets.size(); i++) {
+            ComponentName componentName = new ComponentName(
+                    sortedAppTargets.get(i).getPackageName(),
+                    sortedAppTargets.get(i).getClassName());
+            mTargetRanks.put(componentName, i);
+            Log.i(TAG, "handleSortedAppTargets, sortedAppTargets #" + i + ": " + componentName);
+        }
+    }
+
     private boolean checkAppTargetRankValid(List<AppTarget> sortedAppTargets) {
         for (AppTarget target : sortedAppTargets) {
             if (target.getRank() != 0) {
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 3fc3f3e..389e33ae 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -99,7 +99,6 @@
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.View.OnClickListener;
-import android.view.View.OnLongClickListener;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.animation.AccelerateInterpolator;
@@ -778,6 +777,11 @@
         mDirectShareShortcutInfoCache = new HashMap<>();
     }
 
+    @Override
+    protected int appliedThemeResId() {
+        return R.style.Theme_DeviceDefault_Chooser;
+    }
+
     private AppPredictor setupAppPredictorForUser(UserHandle userHandle,
             AppPredictor.Callback appPredictorCallback) {
         AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled(userHandle);
@@ -1617,32 +1621,22 @@
         return getIntent().getBooleanExtra(Intent.EXTRA_AUTO_LAUNCH_SINGLE_CHOICE, true);
     }
 
-    void showTargetDetails(TargetInfo ti) {
-        if (ti == null) {
-            return;
-        }
-        ComponentName name = ti.getResolveInfo().activityInfo.getComponentName();
-        boolean pinned = mPinnedSharedPrefs.getBoolean(name.flattenToString(), false);
+    private void showTargetDetails(DisplayResolveInfo ti) {
+        if (ti == null) return;
 
-        ResolverTargetActionsDialogFragment f;
+        List<DisplayResolveInfo> targetList;
 
         // For multiple targets, include info on all targets
         if (ti instanceof MultiDisplayResolveInfo) {
             MultiDisplayResolveInfo mti = (MultiDisplayResolveInfo) ti;
-            List<CharSequence> labels = new ArrayList<>();
-
-            for (TargetInfo innerInfo : mti.getTargets()) {
-                labels.add(innerInfo.getResolveInfo().loadLabel(getPackageManager()));
-            }
-            f = new ResolverTargetActionsDialogFragment(mti.getDisplayLabel(), name,
-                    mti.getTargets(), labels,
-                    mChooserMultiProfilePagerAdapter.getCurrentUserHandle());
+            targetList = mti.getTargets();
         } else {
-            f = new ResolverTargetActionsDialogFragment(
-                    ti.getResolveInfo().loadLabel(getPackageManager()), name, pinned,
-                    mChooserMultiProfilePagerAdapter.getCurrentUserHandle());
+            targetList = Collections.singletonList(ti);
         }
 
+        ResolverTargetActionsDialogFragment f = new ResolverTargetActionsDialogFragment(
+                targetList, mChooserMultiProfilePagerAdapter.getCurrentUserHandle());
+
         f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG);
     }
 
@@ -2151,7 +2145,10 @@
 
             Bundle extras = new Bundle();
             extras.putString(Intent.EXTRA_SHORTCUT_ID, shortcutInfo.getId());
-            ChooserTarget chooserTarget = new ChooserTarget(shortcutInfo.getShortLabel(),
+
+            ChooserTarget chooserTarget = new ChooserTarget(
+                    shortcutInfo.getLongLabel() != null ? shortcutInfo.getLongLabel()
+                            : shortcutInfo.getShortLabel(),
                     null, // Icon will be loaded later if this target is selected to be shown.
                     score, matchingShortcuts.get(i).getTargetComponent().clone(), extras);
 
@@ -2974,12 +2971,17 @@
             if (isClickable) {
                 itemView.setOnClickListener(v -> startSelected(mListPosition,
                         false/* always */, true/* filterd */));
-                itemView.setOnLongClickListener(v -> {
-                    showTargetDetails(
-                            mChooserMultiProfilePagerAdapter.getActiveListAdapter()
-                                    .targetInfoForPosition(mListPosition, /* filtered */ true));
-                    return true;
-                });
+
+                TargetInfo ti = mChooserMultiProfilePagerAdapter.getActiveListAdapter()
+                        .targetInfoForPosition(mListPosition, /* filtered */ true);
+
+                // This should always be the case for ItemViewHolder, check for sanity
+                if (ti instanceof DisplayResolveInfo) {
+                    itemView.setOnLongClickListener(v -> {
+                        showTargetDetails((DisplayResolveInfo) ti);
+                        return true;
+                    });
+                }
             }
         }
     }
@@ -3304,15 +3306,21 @@
                         startSelected(holder.getItemIndex(column), false, true);
                     }
                 });
-                v.setOnLongClickListener(new OnLongClickListener() {
-                    @Override
-                    public boolean onLongClick(View v) {
-                        showTargetDetails(
-                                mChooserListAdapter.targetInfoForPosition(
-                                        holder.getItemIndex(column), true));
-                        return true;
+
+                // Direct Share targets should not show any menu
+                if (!isDirectShare) {
+                    final TargetInfo ti = mChooserListAdapter.targetInfoForPosition(
+                            holder.getItemIndex(column), true);
+
+                    // This should always be the case for non-DS targets, check for sanity
+                    if (ti instanceof DisplayResolveInfo) {
+                        v.setOnLongClickListener(v1 -> {
+                            showTargetDetails((DisplayResolveInfo) ti);
+                            return true;
+                        });
                     }
-                });
+                }
+
                 holder.addView(i, v);
 
                 // Force Direct Share to be 2 lines and auto-wrap to second line via hoz scroll =
@@ -3501,13 +3509,11 @@
         }
 
         /**
-         * Only expand direct share area if there is a minimum number of shortcuts,
-         * which will help reduce the amount of visible shuffling due to older-style
-         * direct share targets.
+         * Only expand direct share area if there is a minimum number of targets.
          */
         private boolean canExpandDirectShare() {
             int orientation = getResources().getConfiguration().orientation;
-            return mChooserListAdapter.getNumShortcutResults() > getMaxTargetsPerRow()
+            return mChooserListAdapter.getNumServiceTargetsForExpand() > getMaxTargetsPerRow()
                     && orientation == Configuration.ORIENTATION_PORTRAIT
                     && !isInMultiWindowMode();
         }
@@ -3716,8 +3722,12 @@
 
                 // only expand if we have more than maxTargetsPerRow, and delay that decision
                 // until they start to scroll
-                if (mChooserMultiProfilePagerAdapter.getActiveListAdapter()
-                        .getSelectableServiceTargetCount() <= maxTargetsPerRow) {
+                ChooserListAdapter adapter =
+                        mChooserMultiProfilePagerAdapter.getActiveListAdapter();
+                int validTargets =
+                        mAppendDirectShareEnabled ? adapter.getNumServiceTargetsForExpand()
+                                : adapter.getSelectableServiceTargetCount();
+                if (validTargets <= maxTargetsPerRow) {
                     mHideDirectShareExpansion = true;
                     return;
                 }
diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java
index f426bc0..f1b7161 100644
--- a/core/java/com/android/internal/app/ChooserListAdapter.java
+++ b/core/java/com/android/internal/app/ChooserListAdapter.java
@@ -30,6 +30,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ShortcutInfo;
+import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -78,6 +79,7 @@
 
     private static final int MAX_SUGGESTED_APP_TARGETS = 4;
     private static final int MAX_CHOOSER_TARGETS_PER_APP = 2;
+    private static final int MAX_SERVICE_TARGET_APP = 8;
 
     static final int MAX_SERVICE_TARGETS = 8;
 
@@ -97,13 +99,14 @@
     private ChooserTargetInfo
             mPlaceHolderTargetInfo = new ChooserActivity.PlaceHolderTargetInfo();
     private int mValidServiceTargetsNum = 0;
+    private int mAvailableServiceTargetsNum = 0;
     private final Map<ComponentName, Pair<List<ChooserTargetInfo>, Integer>>
             mParkingDirectShareTargets = new HashMap<>();
     private final Map<ComponentName, Map<String, Integer>> mChooserTargetScores = new HashMap<>();
     private Set<ComponentName> mPendingChooserTargetService = new HashSet<>();
     private Set<ComponentName> mShortcutComponents = new HashSet<>();
     private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
-    private final List<TargetInfo> mCallerTargets = new ArrayList<>();
+    private final List<DisplayResolveInfo> mCallerTargets = new ArrayList<>();
 
     private final ChooserActivity.BaseChooserTargetComparator mBaseTargetComparator =
             new ChooserActivity.BaseChooserTargetComparator();
@@ -235,8 +238,9 @@
     }
 
     @Override
-    protected void onBindView(View view, TargetInfo info) {
-        super.onBindView(view, info);
+    protected void onBindView(View view, TargetInfo info, int position) {
+        super.onBindView(view, info, position);
+        if (info == null) return;
 
         // If target is loading, show a special placeholder shape in the label, make unclickable
         final ViewHolder holder = (ViewHolder) view.getTag();
@@ -253,28 +257,49 @@
             holder.text.setBackground(null);
             holder.itemView.setBackground(holder.defaultItemViewBackground);
         }
+
+        if (info instanceof MultiDisplayResolveInfo) {
+            // If the target is grouped show an indicator
+            Drawable bkg = mContext.getDrawable(R.drawable.chooser_group_background);
+            holder.text.setPaddingRelative(0, 0, bkg.getIntrinsicWidth() /* end */, 0);
+            holder.text.setBackground(bkg);
+        } else if (info.isPinned() && getPositionTargetType(position) == TARGET_STANDARD) {
+            // If the target is pinned and in the suggested row show a pinned indicator
+            Drawable bkg = mContext.getDrawable(R.drawable.chooser_pinned_background);
+            holder.text.setPaddingRelative(bkg.getIntrinsicWidth() /* start */, 0, 0, 0);
+            holder.text.setBackground(bkg);
+        } else {
+            holder.text.setBackground(null);
+            holder.text.setPaddingRelative(0, 0, 0, 0);
+        }
     }
 
     void updateAlphabeticalList() {
         mSortedList.clear();
+        List<DisplayResolveInfo> tempList = new ArrayList<>();
+        tempList.addAll(mDisplayList);
+        tempList.addAll(mCallerTargets);
         if (mEnableStackedApps) {
             // Consolidate multiple targets from same app.
             Map<String, DisplayResolveInfo> consolidated = new HashMap<>();
-            for (DisplayResolveInfo info : mDisplayList) {
+            for (DisplayResolveInfo info : tempList) {
                 String packageName = info.getResolvedComponentName().getPackageName();
-                if (consolidated.get(packageName) != null) {
-                    // create consolidated target
-                    MultiDisplayResolveInfo multiDisplayResolveInfo =
-                            new MultiDisplayResolveInfo(packageName, info);
-                    multiDisplayResolveInfo.addTarget(consolidated.get(packageName));
-                    consolidated.put(packageName, multiDisplayResolveInfo);
-                } else {
+                DisplayResolveInfo multiDri = consolidated.get(packageName);
+                if (multiDri == null) {
                     consolidated.put(packageName, info);
+                } else if (multiDri instanceof MultiDisplayResolveInfo) {
+                    ((MultiDisplayResolveInfo) multiDri).addTarget(info);
+                } else {
+                    // create consolidated target from the single DisplayResolveInfo
+                    MultiDisplayResolveInfo multiDisplayResolveInfo =
+                            new MultiDisplayResolveInfo(packageName, multiDri);
+                    multiDisplayResolveInfo.addTarget(info);
+                    consolidated.put(packageName, multiDisplayResolveInfo);
                 }
             }
             mSortedList.addAll(consolidated.values());
         } else {
-            mSortedList.addAll(mDisplayList);
+            mSortedList.addAll(tempList);
         }
         Collections.sort(mSortedList, new ChooserActivity.AzInfoComparator(mContext));
     }
@@ -326,7 +351,10 @@
         return standardCount > mChooserListCommunicator.getMaxRankedTargets() ? standardCount : 0;
     }
 
-    int getRankedTargetCount() {
+    /**
+     * Fetch ranked app target count
+     */
+    public int getRankedTargetCount() {
         int spacesAvailable =
                 mChooserListCommunicator.getMaxRankedTargets() - getCallerTargetCount();
         return Math.min(spacesAvailable, super.getCount());
@@ -411,6 +439,19 @@
         return null;
     }
 
+    // Check whether {@code dri} should be added into mDisplayList.
+    @Override
+    protected boolean shouldAddResolveInfo(DisplayResolveInfo dri) {
+        // Checks if this info is already listed in callerTargets.
+        for (TargetInfo existingInfo : mCallerTargets) {
+            if (mResolverListCommunicator
+                    .resolveInfoMatch(dri.getResolveInfo(), existingInfo.getResolveInfo())) {
+                return false;
+            }
+        }
+        return super.shouldAddResolveInfo(dri);
+    }
+
     /**
      * Fetch surfaced direct share target info
      */
@@ -570,7 +611,13 @@
             Pair<List<ChooserTargetInfo>, Integer> parkingTargetInfoPair =
                     mParkingDirectShareTargets.getOrDefault(origComponentName,
                             new Pair<>(new ArrayList<>(), 0));
-            parkingTargetInfoPair.first.addAll(parkingTargetInfos);
+            for (ChooserTargetInfo target : parkingTargetInfos) {
+                if (!checkDuplicateTarget(target, parkingTargetInfoPair.first)
+                        && !checkDuplicateTarget(target, mServiceTargets)) {
+                    parkingTargetInfoPair.first.add(target);
+                    mAvailableServiceTargetsNum++;
+                }
+            }
             mParkingDirectShareTargets.put(origComponentName, parkingTargetInfoPair);
             rankTargetsWithinComponent(origComponentName);
             if (isShortcutResult) {
@@ -615,7 +662,7 @@
             List<ChooserTargetInfo> parkingTargets = parkingTargetsItem.first;
             int insertedNum = parkingTargetsItem.second;
             while (insertedNum < quota && !parkingTargets.isEmpty()) {
-                if (!checkDuplicateTarget(parkingTargets.get(0))) {
+                if (!checkDuplicateTarget(parkingTargets.get(0), mServiceTargets)) {
                     mServiceTargets.add(mValidServiceTargetsNum, parkingTargets.get(0));
                     mValidServiceTargetsNum++;
                     insertedNum++;
@@ -630,9 +677,6 @@
                         + " totalScore=" + totalScore
                         + " quota=" + quota);
             }
-            if (mShortcutComponents.contains(component)) {
-                mNumShortcutResults += insertedNum - parkingTargetsItem.second;
-            }
             mParkingDirectShareTargets.put(component, new Pair<>(parkingTargets, insertedNum));
         }
         if (!shouldWaitPendingService) {
@@ -648,19 +692,15 @@
             return;
         }
         Log.i(TAG, " fillAllServiceTargets");
-        int maxRankedTargets = mChooserListCommunicator.getMaxRankedTargets();
-        List<ComponentName> topComponentNames = getTopComponentNames(maxRankedTargets);
+        List<ComponentName> topComponentNames = getTopComponentNames(MAX_SERVICE_TARGET_APP);
         // Append all remaining targets of top recommended components into direct share row.
         for (ComponentName component : topComponentNames) {
             if (!mParkingDirectShareTargets.containsKey(component)) {
                 continue;
             }
             mParkingDirectShareTargets.get(component).first.stream()
-                    .filter(target -> !checkDuplicateTarget(target))
+                    .filter(target -> !checkDuplicateTarget(target, mServiceTargets))
                     .forEach(target -> {
-                        if (mShortcutComponents.contains(component)) {
-                            mNumShortcutResults++;
-                        }
                         mServiceTargets.add(mValidServiceTargetsNum, target);
                         mValidServiceTargetsNum++;
                     });
@@ -673,28 +713,34 @@
                 .map(pair -> pair.first)
                 .forEach(targets -> {
                     for (ChooserTargetInfo target : targets) {
-                        if (!checkDuplicateTarget(target)) {
+                        if (!checkDuplicateTarget(target, mServiceTargets)) {
                             mServiceTargets.add(mValidServiceTargetsNum, target);
                             mValidServiceTargetsNum++;
-                            mNumShortcutResults++;
                         }
                     }
                 });
         mParkingDirectShareTargets.clear();
     }
 
-    private boolean checkDuplicateTarget(ChooserTargetInfo chooserTargetInfo) {
+    private boolean checkDuplicateTarget(ChooserTargetInfo target,
+            List<ChooserTargetInfo> destination) {
         // Check for duplicates and abort if found
-        for (ChooserTargetInfo otherTargetInfo : mServiceTargets) {
-            if (chooserTargetInfo.isSimilar(otherTargetInfo)) {
+        for (ChooserTargetInfo otherTargetInfo : destination) {
+            if (target.isSimilar(otherTargetInfo)) {
                 return true;
             }
         }
         return false;
     }
 
-    int getNumShortcutResults() {
-        return mNumShortcutResults;
+    /**
+     * The return number have to exceed a minimum limit to make direct share area expandable. When
+     * append direct share targets is enabled, return count of all available targets parking in the
+     * memory; otherwise, it is shortcuts count which will help reduce the amount of visible
+     * shuffling due to older-style direct share targets.
+     */
+    int getNumServiceTargetsForExpand() {
+        return mAppendDirectShareEnabled ? mAvailableServiceTargetsNum : mNumShortcutResults;
     }
 
     /**
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 9c2df13..182c7f2 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -324,7 +324,7 @@
     protected void onCreate(Bundle savedInstanceState, Intent intent,
             CharSequence title, int defaultTitleRes, Intent[] initialIntents,
             List<ResolveInfo> rList, boolean supportsAlwaysUseOption) {
-        setTheme(R.style.Theme_DeviceDefault_Resolver);
+        setTheme(appliedThemeResId());
         super.onCreate(savedInstanceState);
 
         // Determine whether we should show that intent is forwarded
@@ -358,6 +358,7 @@
                 : isHttpSchemeAndViewAction(getTargetIntent());
 
         mSupportsAlwaysUseOption = supportsAlwaysUseOption;
+        mWorkProfileUserHandle = fetchWorkProfileUserProfile();
 
         // The last argument of createResolverListAdapter is whether to do special handling
         // of the last used choice to highlight it in the list.  We need to always
@@ -366,7 +367,6 @@
         // to handle. We also turn it off when the work tab is shown to simplify the UX.
         boolean filterLastUsed = mSupportsAlwaysUseOption && !isVoiceInteraction()
                 && !shouldShowTabs();
-        mWorkProfileUserHandle = fetchWorkProfileUserProfile();
         mMultiProfilePagerAdapter = createMultiProfilePagerAdapter(initialIntents, rList, filterLastUsed);
         if (configureContentView()) {
             return;
@@ -507,6 +507,10 @@
                 /* shouldShowNoCrossProfileIntentsEmptyState= */ getUser().equals(intentUser));
     }
 
+    protected int appliedThemeResId() {
+        return R.style.Theme_DeviceDefault_Resolver;
+    }
+
     /**
      * Returns the user id of the user that the starting intent originated from.
      * <p>This is not necessarily equal to {@link #getUserId()} or {@link UserHandle#myUserId()},
@@ -1612,6 +1616,7 @@
     }
 
     private void setupProfileTabs() {
+        maybeHideDivider();
         TabHost tabHost = findViewById(R.id.profile_tabhost);
         tabHost.setup();
         ViewPager viewPager = findViewById(R.id.profile_pager);
@@ -1657,9 +1662,27 @@
                     resetButtonBar();
                     resetCheckedItem();
                 });
+        mMultiProfilePagerAdapter.setOnSwitchOnWorkSelectedListener(
+                () -> {
+                    final View workTab = tabHost.getTabWidget().getChildAt(1);
+                    workTab.setFocusable(true);
+                    workTab.setFocusableInTouchMode(true);
+                    workTab.requestFocus();
+                });
         findViewById(R.id.resolver_tab_divider).setVisibility(View.VISIBLE);
     }
 
+    private void maybeHideDivider() {
+        if (!isIntentPicker()) {
+            return;
+        }
+        final View divider = findViewById(R.id.divider);
+        if (divider == null) {
+            return;
+        }
+        divider.setVisibility(View.GONE);
+    }
+
     /**
      * Callback called when user changes the profile tab.
      * <p>This method is intended to be overridden by subclasses.
diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java
index 24bf98b..d942e85 100644
--- a/core/java/com/android/internal/app/ResolverListAdapter.java
+++ b/core/java/com/android/internal/app/ResolverListAdapter.java
@@ -85,7 +85,7 @@
 
     private int mLastChosenPosition = -1;
     private boolean mFilterLastUsed;
-    private final ResolverListCommunicator mResolverListCommunicator;
+    final ResolverListCommunicator mResolverListCommunicator;
     private Runnable mPostListReadyRunnable;
     private final boolean mIsAudioCaptureDevice;
     private boolean mIsTabLoaded;
@@ -443,17 +443,24 @@
         // TODO(arangelov): Is that UserHandle.USER_CURRENT check okay?
         if (dri != null && dri.getResolveInfo() != null
                 && dri.getResolveInfo().targetUserId == UserHandle.USER_CURRENT) {
-            // Checks if this info is already listed in display.
-            for (DisplayResolveInfo existingInfo : mDisplayList) {
-                if (mResolverListCommunicator
-                        .resolveInfoMatch(dri.getResolveInfo(), existingInfo.getResolveInfo())) {
-                    return;
-                }
+            if (shouldAddResolveInfo(dri)) {
+                mDisplayList.add(dri);
             }
-            mDisplayList.add(dri);
         }
     }
 
+    // Check whether {@code dri} should be added into mDisplayList.
+    protected boolean shouldAddResolveInfo(DisplayResolveInfo dri) {
+        // Checks if this info is already listed in display.
+        for (DisplayResolveInfo existingInfo : mDisplayList) {
+            if (mResolverListCommunicator
+                    .resolveInfoMatch(dri.getResolveInfo(), existingInfo.getResolveInfo())) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     @Nullable
     public ResolveInfo resolveInfoForPosition(int position, boolean filtered) {
         TargetInfo target = targetInfoForPosition(position, filtered);
@@ -517,7 +524,7 @@
         if (view == null) {
             view = createView(parent);
         }
-        onBindView(view, getItem(position));
+        onBindView(view, getItem(position), position);
         return view;
     }
 
@@ -534,10 +541,10 @@
     }
 
     public final void bindView(int position, View view) {
-        onBindView(view, getItem(position));
+        onBindView(view, getItem(position), position);
     }
 
-    protected void onBindView(View view, TargetInfo info) {
+    protected void onBindView(View view, TargetInfo info, int position) {
         final ViewHolder holder = (ViewHolder) view.getTag();
         if (info == null) {
             holder.icon.setImageDrawable(
diff --git a/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java b/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java
index 35d9bcd..cdc600c 100644
--- a/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java
+++ b/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java
@@ -17,21 +17,25 @@
 
 package com.android.internal.app;
 
+import static android.content.Context.ACTIVITY_SERVICE;
+
+import static com.android.internal.app.ResolverListAdapter.ResolveInfoPresentationGetter;
+
+import android.app.ActivityManager;
 import android.app.AlertDialog.Builder;
 import android.app.Dialog;
 import android.app.DialogFragment;
 import android.content.ComponentName;
 import android.content.DialogInterface;
-import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
 import android.content.res.Configuration;
-import android.net.Uri;
 import android.os.Bundle;
 import android.os.UserHandle;
-import android.provider.Settings;
 
 import com.android.internal.R;
 import com.android.internal.app.chooser.DisplayResolveInfo;
+import com.android.internal.app.chooser.TargetInfo;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -41,94 +45,53 @@
  */
 public class ResolverTargetActionsDialogFragment extends DialogFragment
         implements DialogInterface.OnClickListener {
-    private static final String NAME_KEY = "componentName";
-    private static final String TITLE_KEY = "title";
-    private static final String PINNED_KEY = "pinned";
-    private static final String USER_ID_KEY = "userId";
-
-    // Sync with R.array.resolver_target_actions_* resources
-    private static final int TOGGLE_PIN_INDEX = 0;
-    private static final int APP_INFO_INDEX = 1;
 
     private List<DisplayResolveInfo> mTargetInfos = new ArrayList<>();
-    private List<CharSequence> mLabels = new ArrayList<>();
-    private boolean[] mPinned;
+    private UserHandle mUserHandle;
 
     public ResolverTargetActionsDialogFragment() {
     }
 
-    public ResolverTargetActionsDialogFragment(CharSequence title, ComponentName name,
-            boolean pinned, UserHandle userHandle) {
-        Bundle args = new Bundle();
-        args.putCharSequence(TITLE_KEY, title);
-        args.putParcelable(NAME_KEY, name);
-        args.putBoolean(PINNED_KEY, pinned);
-        args.putParcelable(USER_ID_KEY, userHandle);
-        setArguments(args);
-    }
-
-    public ResolverTargetActionsDialogFragment(CharSequence title, ComponentName name,
-            List<DisplayResolveInfo> targets, List<CharSequence> labels, UserHandle userHandle) {
-        Bundle args = new Bundle();
-        args.putCharSequence(TITLE_KEY, title);
-        args.putParcelable(NAME_KEY, name);
-        args.putParcelable(USER_ID_KEY, userHandle);
+    public ResolverTargetActionsDialogFragment(List<DisplayResolveInfo> targets,
+            UserHandle userHandle) {
+        mUserHandle = userHandle;
         mTargetInfos = targets;
-        mLabels = labels;
-        setArguments(args);
     }
 
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
         final Bundle args = getArguments();
-        final int itemRes = args.getBoolean(PINNED_KEY, false)
-                ? R.array.resolver_target_actions_unpin
-                : R.array.resolver_target_actions_pin;
-        String[] defaultActions = getResources().getStringArray(itemRes);
-        CharSequence[] items;
+        final PackageManager pm = getContext().getPackageManager();
 
-        if (mTargetInfos == null || mTargetInfos.size() < 2) {
-            items = defaultActions;
-        } else {
-            // Pin item for each sub-item
-            items = new CharSequence[mTargetInfos.size() + 1];
-            for (int i = 0; i < mTargetInfos.size(); i++) {
-                items[i] = mTargetInfos.get(i).isPinned()
-                         ? getResources().getString(R.string.unpin_specific_target, mLabels.get(i))
-                         : getResources().getString(R.string.pin_specific_target, mLabels.get(i));
-            }
-            // "App info"
-            items[mTargetInfos.size()] = defaultActions[1];
+        // Pin item for each sub-item
+        CharSequence[] items = new CharSequence[mTargetInfos.size()];
+        for (int i = 0; i < mTargetInfos.size(); i++) {
+            final TargetInfo ti = mTargetInfos.get(i);
+            final CharSequence label = ti.getResolveInfo().loadLabel(pm);
+            items[i] = ti.isPinned()
+                     ? getResources().getString(R.string.unpin_specific_target, label)
+                     : getResources().getString(R.string.pin_specific_target, label);
         }
 
+        // Use the matching application icon and label for the title, any TargetInfo will do
+        final ActivityManager am = (ActivityManager) getContext()
+                .getSystemService(ACTIVITY_SERVICE);
+        final int iconDpi = am.getLauncherLargeIconDensity();
+        final ResolveInfoPresentationGetter pg = new ResolveInfoPresentationGetter(getContext(),
+                iconDpi, mTargetInfos.get(0).getResolveInfo());
 
         return new Builder(getContext())
+                .setTitle(pg.getLabel())
+                .setIcon(pg.getIcon(mUserHandle))
                 .setCancelable(true)
                 .setItems(items, this)
-                .setTitle(args.getCharSequence(TITLE_KEY))
                 .create();
     }
 
     @Override
     public void onClick(DialogInterface dialog, int which) {
-        final Bundle args = getArguments();
-        ComponentName name = args.getParcelable(NAME_KEY);
-        if (which == 0 || (mTargetInfos.size() > 0 && which < mTargetInfos.size())) {
-            if (mTargetInfos == null || mTargetInfos.size() == 0) {
-                pinComponent(name);
-            } else {
-                pinComponent(mTargetInfos.get(which).getResolvedComponentName());
-            }
-            // Force the chooser to requery and resort things
-            ((ChooserActivity) getActivity()).handlePackagesChanged();
-        } else {
-            // Last item in dialog is App Info
-            Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
-                    .setData(Uri.fromParts("package", name.getPackageName(), null))
-                    .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
-            UserHandle userHandle = args.getParcelable(USER_ID_KEY);
-            getActivity().startActivityAsUser(in, userHandle);
-        }
+        pinComponent(mTargetInfos.get(which).getResolvedComponentName());
+        ((ChooserActivity) getActivity()).handlePackagesChanged();
         dismiss();
     }
 
diff --git a/core/java/com/android/internal/app/SimpleIconFactory.java b/core/java/com/android/internal/app/SimpleIconFactory.java
index d618cdf..ffe2dbe 100644
--- a/core/java/com/android/internal/app/SimpleIconFactory.java
+++ b/core/java/com/android/internal/app/SimpleIconFactory.java
@@ -20,6 +20,7 @@
 import static android.graphics.Paint.DITHER_FLAG;
 import static android.graphics.Paint.FILTER_BITMAP_FLAG;
 
+import android.annotation.AttrRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -46,6 +47,7 @@
 import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.util.Pools.SynchronizedPool;
+import android.util.TypedValue;
 
 import com.android.internal.R;
 
@@ -92,10 +94,8 @@
             final ActivityManager am = (ActivityManager) ctx.getSystemService(ACTIVITY_SERVICE);
             final int iconDpi = (am == null) ? 0 : am.getLauncherLargeIconDensity();
 
-            final Resources r = ctx.getResources();
-            final int iconSize = r.getDimensionPixelSize(R.dimen.resolver_icon_size);
-            final int badgeSize = r.getDimensionPixelSize(R.dimen.resolver_badge_size);
-
+            final int iconSize = getIconSizeFromContext(ctx);
+            final int badgeSize = getBadgeSizeFromContext(ctx);
             instance = new SimpleIconFactory(ctx, iconDpi, iconSize, badgeSize);
             instance.setWrapperBackgroundColor(Color.WHITE);
         }
@@ -103,6 +103,27 @@
         return instance;
     }
 
+    private static int getAttrDimFromContext(Context ctx, @AttrRes int attrId, String errorMsg) {
+        final Resources res = ctx.getResources();
+        TypedValue outVal = new TypedValue();
+        if (!ctx.getTheme().resolveAttribute(attrId, outVal, true)) {
+            throw new IllegalStateException(errorMsg);
+        }
+        return res.getDimensionPixelSize(outVal.resourceId);
+    }
+
+    private static int getIconSizeFromContext(Context ctx) {
+        return getAttrDimFromContext(ctx,
+                com.android.internal.R.attr.iconfactoryIconSize,
+                "Expected theme to define iconfactoryIconSize.");
+    }
+
+    private static int getBadgeSizeFromContext(Context ctx) {
+        return getAttrDimFromContext(ctx,
+                com.android.internal.R.attr.iconfactoryBadgeSize,
+                "Expected theme to define iconfactoryBadgeSize.");
+    }
+
     /**
      * Recycles the SimpleIconFactory so others may use it.
      *
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 6f33096..d238d0e 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -61,22 +61,6 @@
     public static final String SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS =
             "screenshot_notification_smart_actions_timeout_ms";
 
-    // Flags related to controls
-
-    /**
-     * (boolean) Whether to have split behavior when opening QS
-     */
-    public static final String QS_SPLIT_ENABLED = "qs_split_enabled";
-
-    /**
-     * (int) Open settings panels for WiFi and BT tiles
-     * 0 - default behavior, link to settings
-     * 1 - open panel on long press, click remains the same
-     * 2 - open panel on click, long press remains the same
-     * 3 - use details on long press
-     */
-    public static final String QS_USE_SETTINGS_PANELS = "qs_use_settings_panels";
-
     // Flags related to Smart Suggestions - these are read in SmartReplyConstants.
 
     /** (boolean) Whether to enable smart suggestions in notifications. */
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index 2f048c9..a50a522 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -68,6 +68,7 @@
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Predicate;
 import java.util.regex.Pattern;
 
 /**
@@ -381,17 +382,51 @@
         return result;
     }
 
+    /**
+     * This method is similar to
+     * {@link DocumentsProvider#queryChildDocuments(String, String[], String)}. This method returns
+     * all children documents including hidden directories/files.
+     *
+     * <p>
+     * In a scoped storage world, access to "Android/data" style directories are hidden for privacy
+     * reasons. This method may show privacy sensitive data, so its usage should only be in
+     * restricted modes.
+     *
+     * @param parentDocumentId the directory to return children for.
+     * @param projection list of {@link Document} columns to put into the
+     *            cursor. If {@code null} all supported columns should be
+     *            included.
+     * @param sortOrder how to order the rows, formatted as an SQL
+     *            {@code ORDER BY} clause (excluding the ORDER BY itself).
+     *            Passing {@code null} will use the default sort order, which
+     *            may be unordered. This ordering is a hint that can be used to
+     *            prioritize how data is fetched from the network, but UI may
+     *            always enforce a specific ordering
+     * @throws FileNotFoundException when parent document doesn't exist or query fails
+     */
+    protected Cursor queryChildDocumentsShowAll(
+            String parentDocumentId, String[] projection, String sortOrder)
+            throws FileNotFoundException {
+        return queryChildDocuments(parentDocumentId, projection, sortOrder, File -> true);
+    }
+
     @Override
     public Cursor queryChildDocuments(
             String parentDocumentId, String[] projection, String sortOrder)
             throws FileNotFoundException {
+        // Access to some directories is hidden for privacy reasons.
+        return queryChildDocuments(parentDocumentId, projection, sortOrder, this::shouldShow);
+    }
 
+    private Cursor queryChildDocuments(
+            String parentDocumentId, String[] projection, String sortOrder,
+            @NonNull Predicate<File> filter) throws FileNotFoundException {
         final File parent = getFileForDocId(parentDocumentId);
         final MatrixCursor result = new DirectoryCursor(
                 resolveProjection(projection), parentDocumentId, parent);
         if (parent.isDirectory()) {
             for (File file : FileUtils.listFilesOrEmpty(parent)) {
-                if (!shouldHide(file)) {
+                if (filter.test(file)) {
                     includeFile(result, null, file);
                 }
             }
@@ -617,6 +652,10 @@
         return (PATTERN_HIDDEN_PATH.matcher(file.getAbsolutePath()).matches());
     }
 
+    private boolean shouldShow(@NonNull File file) {
+        return !shouldHide(file);
+    }
+
     protected boolean shouldBlockFromTree(@NonNull String docId) {
         return false;
     }
diff --git a/core/java/com/android/internal/util/ScreenshotHelper.java b/core/java/com/android/internal/util/ScreenshotHelper.java
index 49c9302..ad6c7e8 100644
--- a/core/java/com/android/internal/util/ScreenshotHelper.java
+++ b/core/java/com/android/internal/util/ScreenshotHelper.java
@@ -132,6 +132,7 @@
                     }
                 };
     }
+
     private static final String TAG = "ScreenshotHelper";
 
     // Time until we give up on the screenshot & show an error instead.
@@ -146,8 +147,6 @@
         mContext = context;
     }
 
-
-
     /**
      * Request a screenshot be taken.
      *
@@ -284,8 +283,8 @@
                             break;
                         case SCREENSHOT_MSG_PROCESS_COMPLETE:
                             synchronized (mScreenshotLock) {
-                                if (mScreenshotConnection == myConn) {
-                                    mContext.unbindService(mScreenshotConnection);
+                                if (myConn != null && mScreenshotConnection == myConn) {
+                                    mContext.unbindService(myConn);
                                     mScreenshotConnection = null;
                                     mScreenshotService = null;
                                 }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index d9b2902..03a7b3d 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1369,7 +1369,7 @@
 
     public void registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
         try {
-            getLockSettings().registerStrongAuthTracker(strongAuthTracker.mStub);
+            getLockSettings().registerStrongAuthTracker(strongAuthTracker.getStub());
         } catch (RemoteException e) {
             throw new RuntimeException("Could not register StrongAuthTracker");
         }
@@ -1377,7 +1377,7 @@
 
     public void unregisterStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
         try {
-            getLockSettings().unregisterStrongAuthTracker(strongAuthTracker.mStub);
+            getLockSettings().unregisterStrongAuthTracker(strongAuthTracker.getStub());
         } catch (RemoteException e) {
             Log.e(TAG, "Could not unregister StrongAuthTracker", e);
         }
@@ -1740,7 +1740,7 @@
             }
         }
 
-        protected final IStrongAuthTracker.Stub mStub = new IStrongAuthTracker.Stub() {
+        private final IStrongAuthTracker.Stub mStub = new IStrongAuthTracker.Stub() {
             @Override
             public void onStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
                     int userId) {
@@ -1755,6 +1755,10 @@
             }
         };
 
+        public IStrongAuthTracker.Stub getStub() {
+            return mStub;
+        }
+
         private class H extends Handler {
             static final int MSG_ON_STRONG_AUTH_REQUIRED_CHANGED = 1;
             static final int MSG_ON_IS_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED = 2;
diff --git a/core/java/com/android/internal/widget/OWNERS b/core/java/com/android/internal/widget/OWNERS
new file mode 100644
index 0000000..cca39ea
--- /dev/null
+++ b/core/java/com/android/internal/widget/OWNERS
@@ -0,0 +1 @@
+per-file PointerLocationView.java = michaelwr@google.com, svv@google.com
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index a420ba6..7b708ef 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -652,6 +652,7 @@
     char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX];
     char extraOptsBuf[PROPERTY_VALUE_MAX];
     char voldDecryptBuf[PROPERTY_VALUE_MAX];
+    char perfettoHprofOptBuf[sizeof("-XX:PerfettoHprof=") + PROPERTY_VALUE_MAX];
     enum {
       kEMDefault,
       kEMIntPortable,
@@ -766,6 +767,16 @@
     addOption("-verbose:gc");
     //addOption("-verbose:class");
 
+    // On Android, we always want to allow loading the PerfettoHprof plugin.
+    // Even with this option set, we will still only actually load the plugin
+    // if we are on a userdebug build or the app is debuggable or profileable.
+    // This is enforced in art/runtime/runtime.cc.
+    //
+    // We want to be able to disable this, because this does not work on host,
+    // and we do not want to enable it in tests.
+    parseRuntimeOption("dalvik.vm.perfetto_hprof", perfettoHprofOptBuf, "-XX:PerfettoHprof=",
+                       "true");
+
     if (primary_zygote) {
         addOption("-Xprimaryzygote");
     }
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 7ff15f2..d7d8621 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -5,5 +5,16 @@
 # Connectivity
 per-file android_net_* = codewiz@google.com, jchalard@google.com, lorenzo@google.com, reminv@google.com, satk@google.com
 
+# Display
+per-file android_hardware_display_* = michaelwr@google.com, santoscordon@google.com
+
+# Input
+per-file android_hardware_input* = michaelwr@google.com, svv@google.com
+per-file android_view_Input* = michaelwr@google.com, svv@google.com
+per-file android_view_KeyCharacterMap.* = michaelwr@google.com, svv@google.com
+per-file android_view_*KeyEvent.* = michaelwr@google.com, svv@google.com
+per-file android_view_*MotionEvent.* = michaelwr@google.com, svv@google.com
+per-file android_view_PointerIcon.* = michaelwr@google.com, svv@google.com
+
 # Zygote
 per-file com_android_internal_os_Zygote.*,fd_utils.* = chriswailes@google.com, ngeoffray@google.com, sehr@google.com, narayan@google.com, maco@google.com
diff --git a/core/jni/android_os_storage_StorageManager.cpp b/core/jni/android_os_storage_StorageManager.cpp
index fd3e66b..3116cc8 100644
--- a/core/jni/android_os_storage_StorageManager.cpp
+++ b/core/jni/android_os_storage_StorageManager.cpp
@@ -17,33 +17,23 @@
 #define LOG_TAG "StorageManager"
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 #include <android-base/unique_fd.h>
 #include <fcntl.h>
 #include <linux/fs.h>
 
 #include <nativehelper/JNIHelp.h>
 #include "core_jni_helpers.h"
+#include "filesystem_utils.h"
 
 namespace android {
 
-static const char* kProcFilesystems = "/proc/filesystems";
-
-// Checks whether the passed in filesystem is listed in /proc/filesystems
-static bool IsFilesystemSupported(const std::string& fsType) {
-    std::string supported;
-    if (!android::base::ReadFileToString(kProcFilesystems, &supported)) {
-        PLOG(ERROR) << "Failed to read supported filesystems";
-        return false;
-    }
-    return supported.find(fsType + "\n") != std::string::npos;
-}
-
 jboolean android_os_storage_StorageManager_setQuotaProjectId(JNIEnv* env, jobject self,
                                                              jstring path, jlong projectId) {
     struct fsxattr fsx;
     ScopedUtfChars utf_chars_path(env, path);
 
-    static bool sdcardFsSupported = IsFilesystemSupported("sdcardfs");
+    static bool sdcardFsSupported = IsSdcardfsUsed();
     if (sdcardFsSupported) {
         // sdcardfs doesn't support project ID quota tracking and takes care of quota
         // in a different way.
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 36b4b6a..e553a78 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -645,6 +645,14 @@
     token->decStrong((void*)nativeAcquireFrameRateFlexibilityToken);
 }
 
+static void nativeSetFixedTransformHint(JNIEnv* env, jclass clazz, jlong transactionObj,
+                                        jlong nativeObject, jint transformHint) {
+    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+    transaction->setFixedTransformHint(ctrl, transformHint);
+}
+
 static jlongArray nativeGetPhysicalDisplayIds(JNIEnv* env, jclass clazz) {
     const auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds();
     jlongArray array = env->NewLongArray(displayIds.size());
@@ -1644,6 +1652,7 @@
             (void*)nativeSetGlobalShadowSettings },
     {"nativeGetHandle", "(J)J",
             (void*)nativeGetHandle },
+    {"nativeSetFixedTransformHint", "(JJI)V", (void*)nativeSetFixedTransformHint},
 };
 
 int register_android_view_SurfaceControl(JNIEnv* env)
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index c5bc083..fc2005a 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -88,12 +88,13 @@
 #include <utils/String8.h>
 #include <utils/Trace.h>
 
-#include "core_jni_helpers.h"
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedLocalRef.h>
 #include <nativehelper/ScopedPrimitiveArray.h>
 #include <nativehelper/ScopedUtfChars.h>
+#include "core_jni_helpers.h"
 #include "fd_utils.h"
+#include "filesystem_utils.h"
 
 #include "nativebridge/native_bridge.h"
 
@@ -614,15 +615,6 @@
   }
 }
 
-static bool IsFilesystemSupported(const std::string& fsType) {
-    std::string supported;
-    if (!ReadFileToString("/proc/filesystems", &supported)) {
-        ALOGE("Failed to read supported filesystems");
-        return false;
-    }
-    return supported.find(fsType + "\n") != std::string::npos;
-}
-
 static void PreApplicationInit() {
   // The child process sets this to indicate it's not the zygote.
   android_mallopt(M_SET_ZYGOTE_CHILD, nullptr, 0);
@@ -1554,15 +1546,14 @@
 
 static void BindMountStorageToLowerFs(const userid_t user_id, const uid_t uid,
     const char* dir_name, const char* package, fail_fn_t fail_fn) {
-
-  bool hasSdcardFs = IsFilesystemSupported("sdcardfs");
-  std::string source;
-  if (hasSdcardFs) {
-    source = StringPrintf("/mnt/runtime/default/emulated/%d/%s/%s", user_id, dir_name, package);
-  } else {
-    source = StringPrintf("/mnt/pass_through/%d/emulated/%d/%s/%s",
-        user_id, user_id, dir_name, package);
-  }
+    bool hasSdcardFs = IsSdcardfsUsed();
+    std::string source;
+    if (hasSdcardFs) {
+        source = StringPrintf("/mnt/runtime/default/emulated/%d/%s/%s", user_id, dir_name, package);
+    } else {
+        source = StringPrintf("/mnt/pass_through/%d/emulated/%d/%s/%s", user_id, user_id, dir_name,
+                              package);
+    }
   std::string target = StringPrintf("/storage/emulated/%d/%s/%s", user_id, dir_name, package);
 
   // As the parent is mounted as tmpfs, we need to create the target dir here.
diff --git a/core/jni/filesystem_utils.h b/core/jni/filesystem_utils.h
new file mode 100644
index 0000000..c4728a0
--- /dev/null
+++ b/core/jni/filesystem_utils.h
@@ -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.
+ */
+
+#ifndef FRAMEWORKS_BASE_CORE_JNI_MISC_UTILS_H_
+#define FRAMEWORKS_BASE_CORE_JNI_MISC_UTILS_H_
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <fcntl.h>
+#include <linux/fs.h>
+
+namespace {
+static constexpr const char* kExternalStorageSdcardfs = "external_storage.sdcardfs.enabled";
+
+static bool IsFilesystemSupported(const std::string& fsType) {
+    std::string supported;
+    if (!android::base::ReadFileToString("/proc/filesystems", &supported)) {
+        ALOGE("Failed to read supported filesystems");
+        return false;
+    }
+    return supported.find(fsType + "\n") != std::string::npos;
+}
+
+static inline bool IsSdcardfsUsed() {
+    return IsFilesystemSupported("sdcardfs") &&
+            android::base::GetBoolProperty(kExternalStorageSdcardfs, true);
+}
+} // namespace
+#endif // FRAMEWORKS_BASE_CORE_JNI_MISC_UTILS_H_
diff --git a/core/proto/android/app/media_output_enum.proto b/core/proto/android/app/media_output_enum.proto
new file mode 100644
index 0000000..0d42fb7
--- /dev/null
+++ b/core/proto/android/app/media_output_enum.proto
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+package android.app.settings.mediaoutput;
+option java_multiple_files = true;
+
+/**
+ * The medium type specified in an output switching operation.
+ */
+enum MediumType {
+    UNKNOWN_TYPE = 0;
+    BUILTIN_SPEAKER = 1;
+    WIRED_3POINT5_MM_AUDIO = 100;
+    WIRED_3POINT5_MM_HEADSET = 101;
+    WIRED_3POINT5_MM_HEADPHONES = 102;
+    USB_C_AUDIO = 200;
+    USB_C_DEVICE = 201;
+    USB_C_HEADSET = 202;
+    USB_C_ACCESSORY = 203;
+    USB_C_DOCK = 204;
+    USB_C_HDMI = 205;
+    BLUETOOTH = 300;
+    BLUETOOTH_HEARING_AID = 301;
+    BLUETOOTH_A2DP = 302;
+    REMOTE_SINGLE = 400;
+    REMOTE_TV = 401;
+    REMOTE_SPEAKER = 402;
+    REMOTE_GROUP = 500;
+    REMOTE_DYNAMIC_GROUP = 501;
+};
+
+/**
+ * The result of an output switching operation.
+ */
+enum SwitchResult {
+    ERROR = 0;
+    OK = 1;
+};
+
+/**
+ * The sub result of an output switching operation.
+ */
+enum SubResult {
+    UNKNOWN_ERROR = 0;
+    NO_ERROR = 1;
+    REJECTED = 2;
+    NETWORK_ERROR = 3;
+    ROUTE_NOT_AVAILABLE = 4;
+    INVALID_COMMAND = 5;
+}
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index bfa5d70..997829e 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2678,15 +2678,4 @@
     // CATEGORY: SETTINGS
     // OS: R
     DEVICE_CONTROLS_SETTINGS = 1844;
-
-    // ACTION: Settings > Wi-Fi > Tap on Openroaming Wi-Fi
-    // CATEGORY: SETTINGS
-    // OS: R
-    OPENROAMING_TAP  = 1845;
-
-    // When device already using any Wi-Fi service, to track if user still want to use Openroaming
-    // ACTION: Settings > Wi-Fi > Tap on Openroaming Wi-Fi
-    // CATEGORY: SETTINGS
-    // OS: R
-    OPENROAMING_TAP_ON_WIFI_CONNECTION  = 1846;
 }
diff --git a/core/proto/android/app/tvsettings_enums.proto b/core/proto/android/app/tvsettings_enums.proto
index 30d365c..31c5dd6 100644
--- a/core/proto/android/app/tvsettings_enums.proto
+++ b/core/proto/android/app/tvsettings_enums.proto
@@ -44,6 +44,24 @@
     /** Denotes that a toggle is clicked by a user. */
     TOGGLE_INTERACTED = 3;
 
+    /**
+     * Denotes that a TvSettings page is being focused in the forward direction
+     * into the settings tree.
+     */
+    PAGE_FOCUSED_FORWARD = 4;
+
+    /**
+     * Denotes that a TvSettings page is being focused in the backward direction
+     * up the settings tree.
+     */
+    PAGE_FOCUSED_BACKWARD = 5;
+
+    /** Denotes that a toggle is turned on by a user. */
+    TOGGLED_ON = 6;
+
+    /** Denotes that a toggle is turned off by a user. */
+    TOGGLED_OFF = 7;
+
 }
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt b/core/proto/android/view/imefocuscontroller.proto
similarity index 66%
copy from packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt
copy to core/proto/android/view/imefocuscontroller.proto
index d0f7607..ff9dee6 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt
+++ b/core/proto/android/view/imefocuscontroller.proto
@@ -13,12 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.systemui.bubbles.storage
 
-import android.annotation.UserIdInt
+syntax = "proto2";
 
-data class BubbleXmlEntity(
-    @UserIdInt val userId: Int,
-    val packageName: String,
-    val shortcutId: String
-)
+package android.view;
+
+option java_multiple_files = true;
+
+/**
+ * Represents a {@link android.view.ImeFocusController} object.
+ */
+message ImeFocusControllerProto {
+    optional bool has_ime_focus = 1;
+    optional string served_view = 2;
+    optional string next_served_view = 3;
+}
\ No newline at end of file
diff --git a/core/proto/android/view/imeinsetssourceconsumer.proto b/core/proto/android/view/imeinsetssourceconsumer.proto
new file mode 100644
index 0000000..6809163
--- /dev/null
+++ b/core/proto/android/view/imeinsetssourceconsumer.proto
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+import "frameworks/base/core/proto/android/view/inputmethod/editorinfo.proto";
+
+package android.view;
+
+option java_multiple_files = true;
+
+/**
+ * Represents a {@link android.view.ImeInsetsSourceConsumer} object.
+ */
+message ImeInsetsSourceConsumerProto {
+    optional .android.view.inputmethod.EditorInfoProto focused_editor = 1;
+    optional bool is_requested_visible_awaiting_control = 2;
+}
\ No newline at end of file
diff --git a/core/proto/android/view/inputmethod/editorinfo.proto b/core/proto/android/view/inputmethod/editorinfo.proto
new file mode 100644
index 0000000..f93096f
--- /dev/null
+++ b/core/proto/android/view/inputmethod/editorinfo.proto
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+package android.view.inputmethod;
+
+option java_multiple_files = true;
+
+/**
+ * Represents a {@link android.view.inputmethod.EditorInfo} object.
+ */
+message EditorInfoProto {
+    optional int32 input_type = 1;
+    optional int32 ime_options = 2;
+    optional string private_ime_options = 3;
+    optional string package_name = 4;
+    optional int32 field_id = 5;
+    optional int32 target_input_method_user_id = 6;
+}
\ No newline at end of file
diff --git a/core/proto/android/view/inputmethod/inputmethodeditortrace.proto b/core/proto/android/view/inputmethod/inputmethodeditortrace.proto
new file mode 100644
index 0000000..7322139
--- /dev/null
+++ b/core/proto/android/view/inputmethod/inputmethodeditortrace.proto
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+option java_outer_classname = "InputMethodEditorTraceProto";
+
+package android.view.inputmethod;
+
+import "frameworks/base/core/proto/android/view/inputmethod/inputmethodmanager.proto";
+import "frameworks/base/core/proto/android/view/viewrootimpl.proto";
+import "frameworks/base/core/proto/android/view/insetscontroller.proto";
+import "frameworks/base/core/proto/android/view/insetssourceconsumer.proto";
+import "frameworks/base/core/proto/android/view/imeinsetssourceconsumer.proto";
+import "frameworks/base/core/proto/android/view/inputmethod/editorinfo.proto";
+import "frameworks/base/core/proto/android/view/imefocuscontroller.proto";
+
+/**
+ * Represents a file full of input method editor trace entries.
+ * Encoded, it should start with 0x9 0x49 0x4d 0x45 0x54 0x52 0x41 0x43 0x45 (.IMETRACE), such
+ * that they can be easily identified.
+ */
+message InputMethodEditorTraceFileProto {
+
+    /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L
+       (this is needed because enums have to be 32 bits and there's no nice way to put 64bit
+        constants into .proto files.) */
+    enum MagicNumber {
+        INVALID = 0;
+        MAGIC_NUMBER_L = 0x54454d49;  /* IMET (little-endian ASCII) */
+        MAGIC_NUMBER_H = 0x45434152;  /* RACE (little-endian ASCII) */
+    }
+
+    /* Must be the first field to allow winscope to auto-detect the dump type. Set to value
+        in MagicNumber */
+    optional fixed64 magic_number = 1;
+    repeated InputMethodEditorProto entry = 2;
+}
+
+/* one input method editor dump entry. */
+message InputMethodEditorProto {
+
+    /* required: elapsed realtime in nanos since boot of when this entry was logged */
+    optional fixed64 elapsed_realtime_nanos = 1;
+    optional ClientSideProto client_side_dump = 2;
+
+    /* groups together the dump from ime related client side classes */
+    message ClientSideProto {
+        optional InputMethodManagerProto input_method_manager = 1;
+        optional ViewRootImplProto view_root_impl = 2;
+        optional InsetsControllerProto insets_controller = 3;
+        optional InsetsSourceConsumerProto insets_source_consumer = 4;
+        optional ImeInsetsSourceConsumerProto ime_insets_source_consumer = 5;
+        optional EditorInfoProto editor_info = 6;
+        optional ImeFocusControllerProto ime_focus_controller = 7;
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt b/core/proto/android/view/inputmethod/inputmethodmanager.proto
similarity index 61%
copy from packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt
copy to core/proto/android/view/inputmethod/inputmethodmanager.proto
index d0f7607..9fed0ef 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt
+++ b/core/proto/android/view/inputmethod/inputmethodmanager.proto
@@ -13,12 +13,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.systemui.bubbles.storage
 
-import android.annotation.UserIdInt
+syntax = "proto2";
 
-data class BubbleXmlEntity(
-    @UserIdInt val userId: Int,
-    val packageName: String,
-    val shortcutId: String
-)
+package android.view.inputmethod;
+
+option java_multiple_files = true;
+
+/**
+ * Represents a {@link android.view.inputmethod.InputMethodManager} object.
+ */
+message InputMethodManagerProto {
+    optional string cur_id = 1;
+    optional bool fullscreen_mode = 2;
+    optional int32 display_id = 3;
+    optional bool active = 4;
+    optional bool served_connecting = 5;
+}
\ No newline at end of file
diff --git a/core/proto/android/view/insetsanimationcontrolimpl.proto b/core/proto/android/view/insetsanimationcontrolimpl.proto
new file mode 100644
index 0000000..6eec37b
--- /dev/null
+++ b/core/proto/android/view/insetsanimationcontrolimpl.proto
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+package android.view;
+
+option java_multiple_files = true;
+
+/**
+ * Represents a {@link android.view.InsetsAnimationControlImpl} object.
+ */
+message InsetsAnimationControlImplProto {
+    optional bool is_cancelled = 1;
+    optional bool is_finished = 2;
+    optional string tmp_matrix = 3;
+    optional string pending_insets = 4;
+    optional float pending_fraction = 5;
+    optional bool shown_on_finish = 6;
+    optional float current_alpha = 7;
+    optional float pending_alpha = 8;
+}
\ No newline at end of file
diff --git a/core/proto/android/view/insetscontroller.proto b/core/proto/android/view/insetscontroller.proto
new file mode 100644
index 0000000..a8bf431
--- /dev/null
+++ b/core/proto/android/view/insetscontroller.proto
@@ -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.
+ */
+
+syntax = "proto2";
+
+import "frameworks/base/core/proto/android/view/insetsstate.proto";
+import "frameworks/base/core/proto/android/view/insetsanimationcontrolimpl.proto";
+
+package android.view;
+
+option java_multiple_files = true;
+
+/**
+ * Represents a {@link android.view.InsetsController} object.
+ */
+message InsetsControllerProto {
+    optional InsetsStateProto state = 1;
+    repeated InsetsAnimationControlImplProto control = 2;
+}
\ No newline at end of file
diff --git a/core/proto/android/view/insetssource.proto b/core/proto/android/view/insetssource.proto
new file mode 100644
index 0000000..41b9f43
--- /dev/null
+++ b/core/proto/android/view/insetssource.proto
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+import "frameworks/base/core/proto/android/graphics/rect.proto";
+
+package android.view;
+
+option java_multiple_files = true;
+
+/**
+ * Represents a {@link android.view.InsetsSource} object.
+ */
+message InsetsSourceProto {
+    optional string type = 1;
+    optional .android.graphics.RectProto frame = 2;
+    optional .android.graphics.RectProto visible_frame = 3;
+    optional bool visible = 4;
+}
\ No newline at end of file
diff --git a/core/proto/android/view/insetssourceconsumer.proto b/core/proto/android/view/insetssourceconsumer.proto
new file mode 100644
index 0000000..487e06c
--- /dev/null
+++ b/core/proto/android/view/insetssourceconsumer.proto
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+import "frameworks/base/core/proto/android/view/insetssourcecontrol.proto";
+import "frameworks/base/core/proto/android/graphics/rect.proto";
+
+package android.view;
+
+option java_multiple_files = true;
+
+/**
+ * Represents a {@link android.view.InsetsSourceConsumer} object.
+ */
+message InsetsSourceConsumerProto {
+    optional string internal_insets_type = 1;
+    optional bool has_window_focus = 2;
+    optional bool is_requested_visible = 3;
+    optional InsetsSourceControlProto source_control = 4;
+    optional .android.graphics.RectProto pending_frame = 5;
+    optional .android.graphics.RectProto pending_visible_frame = 6;
+}
\ No newline at end of file
diff --git a/core/proto/android/view/insetssourcecontrol.proto b/core/proto/android/view/insetssourcecontrol.proto
new file mode 100644
index 0000000..3ac3cbf
--- /dev/null
+++ b/core/proto/android/view/insetssourcecontrol.proto
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+import "frameworks/base/core/proto/android/graphics/point.proto";
+import "frameworks/base/core/proto/android/view/surfacecontrol.proto";
+
+package android.view;
+
+option java_multiple_files = true;
+
+/**
+ * Represents a {@link android.view.InsetsSourceControl} object.
+ */
+message InsetsSourceControlProto {
+    optional string type = 1;
+    optional .android.graphics.PointProto position = 2;
+    optional SurfaceControlProto leash = 3;
+}
\ No newline at end of file
diff --git a/core/proto/android/view/insetsstate.proto b/core/proto/android/view/insetsstate.proto
new file mode 100644
index 0000000..9e9933d
--- /dev/null
+++ b/core/proto/android/view/insetsstate.proto
@@ -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.
+ */
+
+syntax = "proto2";
+
+import "frameworks/base/core/proto/android/view/insetssource.proto";
+import "frameworks/base/core/proto/android/graphics/rect.proto";
+
+package android.view;
+
+option java_multiple_files = true;
+
+/**
+ * Represents a {@link android.view.InsetsState} object.
+ */
+message InsetsStateProto {
+    repeated InsetsSourceProto sources = 1;
+    optional .android.graphics.RectProto display_frame = 2;
+}
\ No newline at end of file
diff --git a/core/proto/android/view/viewrootimpl.proto b/core/proto/android/view/viewrootimpl.proto
new file mode 100644
index 0000000..0abe5e06
--- /dev/null
+++ b/core/proto/android/view/viewrootimpl.proto
@@ -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.
+ */
+
+syntax = "proto2";
+
+import "frameworks/base/core/proto/android/graphics/rect.proto";
+import "frameworks/base/core/proto/android/view/displaycutout.proto";
+import "frameworks/base/core/proto/android/view/windowlayoutparams.proto";
+
+package android.view;
+
+option java_multiple_files = true;
+
+/**
+ * Represents a {@link android.view.ViewRootImpl} object.
+ */
+message ViewRootImplProto {
+    optional string view = 1;
+    optional int32 display_id = 2;
+    optional bool app_visible = 3;
+    optional int32 width = 4;
+    optional int32 height = 5;
+    optional bool is_animating = 6;
+    optional .android.graphics.RectProto visible_rect = 7;
+    optional bool is_drawing = 8;
+    optional bool added = 9;
+    optional .android.graphics.RectProto win_frame = 10;
+    optional DisplayCutoutProto pending_display_cutout = 11;
+    optional string last_window_insets = 12;
+    optional string soft_input_mode = 13;
+    optional int32 scroll_y = 14;
+    optional int32 cur_scroll_y = 15;
+    optional bool removed = 16;
+    optional .android.view.WindowLayoutParamsProto window_attributes = 17;
+}
\ No newline at end of file
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0bf5045..f285d95 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2437,7 +2437,7 @@
 
     <!-- Allows interaction across profiles in the same profile group. -->
     <permission android:name="android.permission.INTERACT_ACROSS_PROFILES"
-        android:protectionLevel="signature|appop|documenter|wellbeing" />
+        android:protectionLevel="signature|appop" />
 
     <!-- Allows configuring apps to have the INTERACT_ACROSS_PROFILES permission so that they can
          interact across profiles in the same profile group.
@@ -5053,7 +5053,7 @@
                  android:forceQueryable="true"
                  android:directBootAware="true">
         <activity android:name="com.android.internal.app.ChooserActivity"
-                android:theme="@style/Theme.DeviceDefault.Resolver"
+                android:theme="@style/Theme.DeviceDefault.Chooser"
                 android:finishOnCloseSystemDialogs="true"
                 android:excludeFromRecents="true"
                 android:documentLaunchMode="never"
@@ -5474,15 +5474,17 @@
                  android:permission="android.permission.BIND_JOB_SERVICE">
         </service>
 
-        <service android:name="com.android.server.pm.PackageManagerShellCommandDataLoader">
+        <service android:name="com.android.server.pm.PackageManagerShellCommandDataLoader"
+            android:exported="false">
             <intent-filter>
-                <action android:name="android.intent.action.LOAD_DATA" />
+                <action android:name="android.intent.action.LOAD_DATA"/>
             </intent-filter>
         </service>
 
         <provider
             android:name="com.android.server.textclassifier.IconsContentProvider"
             android:authorities="com.android.textclassifier.icons"
+            android:singleUser="true"
             android:enabled="true"
             android:exported="true">
         </provider>
diff --git a/core/res/res/drawable/chooser_group_background.xml b/core/res/res/drawable/chooser_group_background.xml
new file mode 100644
index 0000000..036028d
--- /dev/null
+++ b/core/res/res/drawable/chooser_group_background.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/ic_chooser_group_arrow"
+          android:gravity="end|center_vertical"
+          android:width="12dp"
+          android:height="12dp"
+          android:start="4dp"
+          android:end="0dp" />
+</layer-list>
diff --git a/core/res/res/drawable/chooser_pinned_background.xml b/core/res/res/drawable/chooser_pinned_background.xml
new file mode 100644
index 0000000..fbbe8c1
--- /dev/null
+++ b/core/res/res/drawable/chooser_pinned_background.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/ic_chooser_pin"
+          android:gravity="start|center_vertical"
+          android:width="12dp"
+          android:height="12dp"
+          android:start="0dp"
+          android:end="4dp" />
+</layer-list>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_chooser_group_arrow.xml b/core/res/res/drawable/ic_chooser_group_arrow.xml
new file mode 100644
index 0000000..d42bb97
--- /dev/null
+++ b/core/res/res/drawable/ic_chooser_group_arrow.xml
@@ -0,0 +1,26 @@
+<!--
+  ~ 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.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="12dp"
+        android:height="12dp"
+        android:viewportWidth="12"
+        android:viewportHeight="12"
+        android:tint="?attr/textColorSecondary">
+    <path
+        android:pathData="M2,4L6,8L10,4L2,4Z"
+        android:fillColor="#FF000000"/>
+</vector>
diff --git a/core/res/res/drawable/ic_chooser_pin.xml b/core/res/res/drawable/ic_chooser_pin.xml
new file mode 100644
index 0000000..47851dcb
--- /dev/null
+++ b/core/res/res/drawable/ic_chooser_pin.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="12dp"
+        android:height="12dp"
+        android:viewportWidth="12"
+        android:viewportHeight="12"
+        android:tint="?attr/textColorSecondary">
+    <path
+        android:pathData="M8.5,2C8.5,1.45 8.055,1 7.5,1L4.5,1C3.95,1 3.5,1.45 3.5,2L3.5,5.5L2.5,7L2.5,8L5.5,8L5.5,10.5L6,11L6.5,10.5L6.5,8L9.5,8L9.5,7L8.5,5.5L8.5,2Z"
+        android:fillColor="#FF000000" />
+</vector>
diff --git a/core/res/res/layout/car_user_switching_dialog.xml b/core/res/res/layout/car_user_switching_dialog.xml
deleted file mode 100644
index d727434..0000000
--- a/core/res/res/layout/car_user_switching_dialog.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:fitsSystemWindows="true"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content">
-
-  <ImageView
-      android:id="@+id/user_loading_avatar"
-      android:layout_width="@dimen/car_fullscreen_user_pod_image_avatar_width"
-      android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height"
-      android:layout_centerHorizontal="true"/>
-
-  <TextView android:id="@+id/user_loading"
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content"
-      android:layout_marginTop="@dimen/car_padding_4"
-      android:textSize="@dimen/car_body1_size"
-      android:textColor="@color/car_body1"
-      android:layout_below="@id/user_loading_avatar"
-      android:gravity="center"/>
-
-</RelativeLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/resolve_grid_item.xml b/core/res/res/layout/resolve_grid_item.xml
index fdd965f..50e6f33 100644
--- a/core/res/res/layout/resolve_grid_item.xml
+++ b/core/res/res/layout/resolve_grid_item.xml
@@ -44,7 +44,7 @@
               android:layout_height="wrap_content"
               android:textAppearance="?attr/textAppearanceSmall"
               android:textColor="?attr/textColorPrimary"
-              android:textSize="14sp"
+              android:textSize="12sp"
               android:gravity="top|center_horizontal"
               android:lines="1"
               android:ellipsize="end" />
diff --git a/core/res/res/layout/resolver_empty_states.xml b/core/res/res/layout/resolver_empty_states.xml
index fe11769..196a0e8 100644
--- a/core/res/res/layout/resolver_empty_states.xml
+++ b/core/res/res/layout/resolver_empty_states.xml
@@ -59,7 +59,7 @@
         <Button
             android:id="@+id/resolver_empty_state_button"
             android:layout_below="@+id/resolver_empty_state_subtitle"
-            android:layout_marginTop="16dp"
+            android:layout_marginTop="8dp"
             android:text="@string/resolver_switch_on_work"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 425a47f..ae9a4e9 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1406,7 +1406,7 @@
     <string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"የሚከተለው ወይም ተጨማሪ መተግበሪያዎች ወደ መለያህ ለመድረስ አሁን እና ወደፊት ፈቃድ ትጠይቃለህ።"</string>
     <string name="grant_credentials_permission_message_footer" msgid="1886710210516246461">"ይህን ጥየቃ መፍቀድ ይፈልጋሉ?"</string>
     <string name="grant_permissions_header_text" msgid="3420736827804657201">"የመድረሻ ጥያቄ"</string>
-    <string name="allow" msgid="6195617008611933762">"ይፍቀዱ"</string>
+    <string name="allow" msgid="6195617008611933762">"ፍቀድ"</string>
     <string name="deny" msgid="6632259981847676572">"ያስተባብሉ"</string>
     <string name="permission_request_notification_title" msgid="1810025922441048273">"ፈቃድ ተጠይቋል"</string>
     <string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">\n" ለ<xliff:g id="ACCOUNT">%s</xliff:g> መለያ ፈቃድ ተጠይቋል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 06af5325..f64e0c9 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -239,7 +239,7 @@
     <string name="reboot_safemode_title" msgid="5853949122655346734">"إعادة تشغيل في الوضع الآمن"</string>
     <string name="reboot_safemode_confirm" msgid="1658357874737219624">"هل تريد إعادة تشغيل الكمبيوتر في الوضع الآمن؟ سيؤدي ذلك إلى إيقاف جميع تطبيقات الجهات الخارجية التي تم تثبيتها. ستتم استعادتها عند إعادة التشغيل مرة أخرى."</string>
     <string name="recent_tasks_title" msgid="8183172372995396653">"حديثة"</string>
-    <string name="no_recent_tasks" msgid="9063946524312275906">"ليست هناك تطبيقات حديثة."</string>
+    <string name="no_recent_tasks" msgid="9063946524312275906">"لم يتمّ استخدام تطبيقات مؤخرًا."</string>
     <string name="global_actions" product="tablet" msgid="4412132498517933867">"خيارات الجهاز اللوحي"</string>
     <string name="global_actions" product="tv" msgid="3871763739487450369">"‏خيارات Android TV"</string>
     <string name="global_actions" product="default" msgid="6410072189971495460">"خيارات الهاتف"</string>
@@ -1222,7 +1222,7 @@
     <string name="whichSendToApplication" msgid="77101541959464018">"إرسال باستخدام"</string>
     <string name="whichSendToApplicationNamed" msgid="3385686512014670003">"‏إرسال باستخدام %1$s"</string>
     <string name="whichSendToApplicationLabel" msgid="3543240188816513303">"إرسال"</string>
-    <string name="whichHomeApplication" msgid="8276350727038396616">"تحديد تطبيق شاشة رئيسية"</string>
+    <string name="whichHomeApplication" msgid="8276350727038396616">"اختيار تطبيق شاشة رئيسية"</string>
     <string name="whichHomeApplicationNamed" msgid="5855990024847433794">"‏استخدام %1$s كصفحة رئيسية"</string>
     <string name="whichHomeApplicationLabel" msgid="8907334282202933959">"التقاط صورة"</string>
     <string name="whichImageCaptureApplication" msgid="2737413019463215284">"التقاط صورة باستخدام"</string>
@@ -1886,8 +1886,8 @@
     <string name="package_updated_device_owner" msgid="7560272363805506941">"تم التحديث بواسطة المشرف"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"تم الحذف بواسطة المشرف"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"حسنًا"</string>
-    <string name="battery_saver_description_with_learn_more" msgid="5997766757551917769">"‏لإطالة عمر البطارية، تعمل \"توفير شحن البطارية\" على:\n\n• تفعيل \"المظهر الداكن\"\n• إيقاف أو تقييد النشاط في الخلفية وبعض التأثيرات المرئية والميزات الأخرى، مثل \"Ok Google\".\n\n"<annotation id="url">"مزيد من المعلومات"</annotation></string>
-    <string name="battery_saver_description" msgid="8587408568232177204">"‏لإطالة عمر البطارية، تعمل ميزة \"توفير شحن البطارية\" على:\n\n• تفعيل \"المظهر الداكن\"\n• إيقاف أو تقييد النشاط في الخلفية وبعض التأثيرات المرئية والميزات الأخرى، مثل \"Ok Google\"."</string>
+    <string name="battery_saver_description_with_learn_more" msgid="5997766757551917769">"‏لإطالة عمر البطارية، تعمل ميزة \"توفير شحن البطارية\" على:\n\n• تفعيل \"المظهر الداكن\"\n• إيقاف أو حظر النشاط في الخلفية وبعض التأثيرات المرئية والميزات الأخرى، مثل \"Ok Google\".\n\n"<annotation id="url">"مزيد من المعلومات"</annotation></string>
+    <string name="battery_saver_description" msgid="8587408568232177204">"‏لإطالة عمر البطارية، تعمل ميزة \"توفير شحن البطارية\" على:\n\n• تفعيل \"المظهر الداكن\"\n• إيقاف أو حظر النشاط في الخلفية وبعض التأثيرات المرئية والميزات الأخرى، مثل \"Ok Google\"."</string>
     <string name="data_saver_description" msgid="4995164271550590517">"للمساعدة في خفض استخدام البيانات، تمنع ميزة \"توفير البيانات\" بعض التطبيقات من إرسال البيانات وتلقّيها في الخلفية. يمكن للتطبيقات المتاحة لديك الآن استخدام البيانات، ولكن لا يمكنها الإكثار من ذلك. وهذا يعني أن الصور مثلاً لا تظهر حتى تنقر عليها."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"هل تريد تفعيل توفير البيانات؟"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"تفعيل"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 0f28222..9c45ff3 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -2087,7 +2087,7 @@
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Grupna konverzacija"</string>
     <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Lično"</string>
-    <string name="resolver_work_tab" msgid="2690019516263167035">"Poslovni"</string>
+    <string name="resolver_work_tab" msgid="2690019516263167035">"Poslovno"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Lični prikaz"</string>
     <string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Prikaz za posao"</string>
     <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Ne možete da delite ovaj sadržaj pomoću aplikacija za posao"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 64d8d31..c9605e0 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -567,10 +567,10 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícono de huella digital"</string>
-    <string name="permlab_manageFace" msgid="4569549381889283282">"administrar el hardware de Desbloqueo facial"</string>
+    <string name="permlab_manageFace" msgid="4569549381889283282">"administrar el hardware de desbloqueo facial"</string>
     <string name="permdesc_manageFace" msgid="6204569688492710471">"Permite que la app emplee métodos para agregar y borrar plantillas de rostros para su uso."</string>
-    <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"usar el hardware de Desbloqueo facial"</string>
-    <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Permite que la app use el hardware de Desbloqueo facial con fines de autenticación"</string>
+    <string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"usar el hardware de desbloqueo facial"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="3115697017684668012">"Permite que la app use el hardware de desbloqueo facial con fines de autenticación"</string>
     <string name="face_recalibrate_notification_name" msgid="6006095897989257026">"Desbloqueo facial"</string>
     <string name="face_recalibrate_notification_title" msgid="5944930528030496897">"Vuelve a registrar tu rostro"</string>
     <string name="face_recalibrate_notification_content" msgid="892757485125249962">"Para mejorar el reconocimiento, vuelve a registrar tu rostro"</string>
@@ -586,8 +586,8 @@
     <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Mira directamente al dispositivo."</string>
     <string name="face_acquired_not_detected" msgid="2945945257956443257">"Ubica el rostro directamente frente al teléfono."</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Te estás moviendo demasiado. No muevas el teléfono"</string>
-    <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Vuelve a registrar tu cara."</string>
-    <string name="face_acquired_too_different" msgid="4699657338753282542">"Ya no se reconoce la cara. Vuelve a intentarlo."</string>
+    <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Vuelve a registrar tu rostro."</string>
+    <string name="face_acquired_too_different" msgid="4699657338753282542">"Ya no se reconoce el rostro. Vuelve a intentarlo."</string>
     <string name="face_acquired_too_similar" msgid="7684650785108399370">"Es muy similar a la anterior. Haz otra pose."</string>
     <string name="face_acquired_pan_too_extreme" msgid="7822191262299152527">"Gira la cabeza un poco menos."</string>
     <string name="face_acquired_tilt_too_extreme" msgid="8119978324129248059">"Gira la cabeza un poco menos."</string>
@@ -597,15 +597,15 @@
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="5085202213036026288">"No se verificó el rostro. Hardware no disponible."</string>
-    <string name="face_error_timeout" msgid="522924647742024699">"Vuelve a probar el Desbloqueo facial."</string>
+    <string name="face_error_timeout" msgid="522924647742024699">"Vuelve a probar el desbloqueo facial."</string>
     <string name="face_error_no_space" msgid="5649264057026021723">"No hay espacio para datos faciales nuevos. Borra uno viejo."</string>
     <string name="face_error_canceled" msgid="2164434737103802131">"Se canceló el reconocimiento facial."</string>
-    <string name="face_error_user_canceled" msgid="8553045452825849843">"El usuario canceló el Desbloqueo facial."</string>
+    <string name="face_error_user_canceled" msgid="8553045452825849843">"El usuario canceló el desbloqueo facial."</string>
     <string name="face_error_lockout" msgid="7864408714994529437">"Demasiados intentos. Inténtalo de nuevo más tarde."</string>
-    <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Demasiados intentos. Se inhabilitó el Desbloqueo facial."</string>
-    <string name="face_error_unable_to_process" msgid="5723292697366130070">"No se pudo verificar la cara. Vuelve a intentarlo."</string>
-    <string name="face_error_not_enrolled" msgid="7369928733504691611">"No configuraste el Desbloqueo facial."</string>
-    <string name="face_error_hw_not_present" msgid="1070600921591729944">"No se admite el Desbloqueo facial en este dispositivo."</string>
+    <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Demasiados intentos. Se inhabilitó el desbloqueo facial."</string>
+    <string name="face_error_unable_to_process" msgid="5723292697366130070">"No se pudo verificar el rostro. Vuelve a intentarlo."</string>
+    <string name="face_error_not_enrolled" msgid="7369928733504691611">"No configuraste el desbloqueo facial."</string>
+    <string name="face_error_hw_not_present" msgid="1070600921591729944">"No se admite el desbloqueo facial en este dispositivo."</string>
     <string name="face_error_security_update_required" msgid="5076017208528750161">"Se inhabilitó temporalmente el sensor."</string>
     <string name="face_name_template" msgid="3877037340223318119">"Rostro <xliff:g id="FACEID">%d</xliff:g>"</string>
   <string-array name="face_error_vendor">
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index f19b65d..04d6ee3 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1661,7 +1661,7 @@
     <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"Para cambiar de una función a otra, mantén pulsado el botón Accesibilidad."</string>
     <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"Para cambiar de una función a otra, desliza hacia arriba con dos dedos y mantén pulsada la pantalla."</string>
     <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"Para cambiar de una función a otra, desliza tres dedos hacia arriba y mantén pulsada la pantalla."</string>
-    <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Ampliar"</string>
+    <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Ampliación"</string>
     <string name="user_switched" msgid="7249833311585228097">"Usuario actual: <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="user_switching_message" msgid="1912993630661332336">"Cambiando a <xliff:g id="NAME">%1$s</xliff:g>…"</string>
     <string name="user_logging_out_message" msgid="7216437629179710359">"Cerrando la sesión de <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1794,8 +1794,8 @@
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Actualizado por el administrador"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminado por el administrador"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Aceptar"</string>
-    <string name="battery_saver_description_with_learn_more" msgid="5997766757551917769">"Para que la batería dure más, Ahorro de batería:\n\n• Activa el tema oscuro\n•Desactiva o restringe actividad en segundo plano, algunos efectos visuales y otras funciones como \"Ok Google\"\n\n"<annotation id="url">"Más información"</annotation></string>
-    <string name="battery_saver_description" msgid="8587408568232177204">"Para que la batería dure más, Ahorro de batería:\n\n• Activa el tema oscuro\n•Desactiva o restringe actividad en segundo plano, algunos efectos visuales y otras funciones como \"Ok Google\""</string>
+    <string name="battery_saver_description_with_learn_more" msgid="5997766757551917769">"Para que la batería dure más, el modo Ahorro de batería hace lo siguiente:\n\n• Activa el tema oscuro\n•Desactiva o restringe actividad en segundo plano, algunos efectos visuales y otras funciones como \"Ok Google\"\n\n"<annotation id="url">"Más información"</annotation></string>
+    <string name="battery_saver_description" msgid="8587408568232177204">"Para que la batería dure más, el modo Ahorro de batería hace lo siguiente:\n\n• Activa el tema oscuro\n• Desactiva o restringe actividad en segundo plano, algunos efectos visuales y otras funciones como \"Ok Google\""</string>
     <string name="data_saver_description" msgid="4995164271550590517">"El modo Ahorro de datos evita que algunas aplicaciones envíen o reciban datos en segundo plano, lo que puede reducir el uso de datos. Una aplicación activa puede acceder a los datos, aunque con menos frecuencia. Esto significa que es posible que, por ejemplo, algunas imágenes no se muestren hasta que las toques."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"¿Activar Ahorro de datos?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Activar"</string>
@@ -2000,7 +2000,7 @@
     <string name="notification_appops_microphone_active" msgid="581333393214739332">"Micrófono"</string>
     <string name="notification_appops_overlay_active" msgid="5571732753262836481">"se muestra sobre otras aplicaciones que haya en la pantalla"</string>
     <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notificación sobre el modo rutina"</string>
-    <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Puede que se agote la batería antes de lo habitual"</string>
+    <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Quizás se agote la batería antes de lo habitual"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Se ha activado el modo Ahorro de batería para aumentar la duración de la batería"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Ahorro de batería"</string>
     <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Ahorro de batería desactivado"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index c77fd56..9fb8eff 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -173,10 +173,10 @@
     <string name="contentServiceSync" msgid="2341041749565687871">"همگام‌سازی"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="5766411446676388623">"همگام‌سازی نشد"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="4562226280528716090">"تعداد <xliff:g id="CONTENT_TYPE">%s</xliff:g> برای حذف بیش از حد مجاز شد."</string>
-    <string name="low_memory" product="tablet" msgid="5557552311566179924">"‏حافظه رایانهٔ لوحی پر است! برخی از فایل‎ها را حذف کنید تا فضا آزاد شود."</string>
+    <string name="low_memory" product="tablet" msgid="5557552311566179924">"‏فضای ذخیره‌سازی رایانهٔ لوحی پر است! برخی از فایل‎ها را حذف کنید تا فضا آزاد شود."</string>
     <string name="low_memory" product="watch" msgid="3479447988234030194">"حافظه ساعت پر است. برای آزادسازی فضا، چند فایل را حذف کنید."</string>
     <string name="low_memory" product="tv" msgid="6663680413790323318">"‏فضای ذخیره‌سازی دستگاه Android TV پر است. برخی از فایل‌ها را حذف کنید تا فضا آزاد شود."</string>
-    <string name="low_memory" product="default" msgid="2539532364144025569">"حافظه تلفن پر است. بعضی از فایل‌ها را حذف کنید تا فضا آزاد شود."</string>
+    <string name="low_memory" product="default" msgid="2539532364144025569">"فضای ذخیره‌سازی تلفن پر است. بعضی از فایل‌ها را حذف کنید تا فضا آزاد شود."</string>
     <plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
       <item quantity="one">مرجع صدور گواهی نصب شد</item>
       <item quantity="other">مراجع صدور گواهی نصب شدند</item>
@@ -383,7 +383,7 @@
     <string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"به برنامه امکان می‌دهد قسمت‌هایی از خود را در حافظه دائمی کند. این کار حافظه موجود را برای سایر برنامه‌ها محدود کرده و باعث کندی تلفن می‌شود."</string>
     <string name="permlab_foregroundService" msgid="1768855976818467491">"اجرای سرویس پیش‌زمینه"</string>
     <string name="permdesc_foregroundService" msgid="8720071450020922795">"به برنامه اجازه می‌دهد از سرویس‌های پیش‌زمینه استفاده کند."</string>
-    <string name="permlab_getPackageSize" msgid="375391550792886641">"اندازه گیری فضای حافظه برنامه"</string>
+    <string name="permlab_getPackageSize" msgid="375391550792886641">"اندازه‌گیری اندازه فضای ذخیره‌سازی برنامه"</string>
     <string name="permdesc_getPackageSize" msgid="742743530909966782">"‏به برنامه اجازه می‎دهد تا کدها، داده‎ها و اندازه‎های حافظهٔ پنهان خود را بازیابی کند"</string>
     <string name="permlab_writeSettings" msgid="8057285063719277394">"تغییر تنظیمات سیستم"</string>
     <string name="permdesc_writeSettings" msgid="8293047411196067188">"‏به برنامه اجازه می‎دهد تا داده‎های تنظیم سیستم را تغییر دهد. برنامه‎های مخرب می‎توانند پیکربندی سیستم شما را خراب کنند."</string>
@@ -617,10 +617,10 @@
     <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"به برنامه اجازه می‌دهد تنظیمات همگام‌سازی را برای حساب تغییر دهد. به‌عنوان مثال، از این ویژگی می‌توان برای فعال کردن همگام‌سازی برنامه «افراد» با یک حساب استفاده کرد."</string>
     <string name="permlab_readSyncStats" msgid="3747407238320105332">"خواندن اطلاعات آماری همگام‌سازی"</string>
     <string name="permdesc_readSyncStats" msgid="3867809926567379434">"به یک برنامه اجازه می‌دهد وضعیت همگام‌سازی یک حساب را بخواند، از جمله سابقه رویدادهای همگام‌سازی و میزان داده‌های همگام‌سازی شده."</string>
-    <string name="permlab_sdcardRead" msgid="5791467020950064920">"خواندن محتوای فضای ذخیره هم‌رسانی‌شده"</string>
+    <string name="permlab_sdcardRead" msgid="5791467020950064920">"خواندن محتوای فضای ذخیره‌سازی مشترک"</string>
     <string name="permdesc_sdcardRead" msgid="6872973242228240382">"به برنامه اجازه می‌دهد محتوای فضای ذخیره هم‌رسانی‌شده‌تان را بخواند."</string>
-    <string name="permlab_sdcardWrite" msgid="4863021819671416668">"تغییر یا حذف محتوای فضای ذخیره هم‌رسانی‌شده"</string>
-    <string name="permdesc_sdcardWrite" msgid="8376047679331387102">"به برنامه اجازه می‌دهد محتوای فضای ذخیره هم‌رسانی‌شده‌تان را بنویسد."</string>
+    <string name="permlab_sdcardWrite" msgid="4863021819671416668">"تغییر یا حذف محتوای فضای ذخیره‌سازی مشترک"</string>
+    <string name="permdesc_sdcardWrite" msgid="8376047679331387102">"به برنامه اجازه می‌دهد محتوای فضای ذخیره‌سازی مشترکتان را بنویسد."</string>
     <string name="permlab_use_sip" msgid="8250774565189337477">"‏تماس گرفتن/دریافت تماس از طریق SIP"</string>
     <string name="permdesc_use_sip" msgid="3590270893253204451">"‏به برنامه اجازه می‌دهد تماس‌های SIP بگیرد یا دریافت کند."</string>
     <string name="permlab_register_sim_subscription" msgid="1653054249287576161">"ثبت ارتباطات سیم کارت مخابراتی جدید"</string>
@@ -694,7 +694,7 @@
     <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"پروکسی کلی دستگاه را برای استفاده هنگام فعال بودن این خط‌مشی تنظیم می‌کند. تنها مالک دستگاه می‌تواند پروکسی کلی را تنظیم کند."</string>
     <string name="policylab_expirePassword" msgid="6015404400532459169">"تنظیم تاریخ انقضای گذرواژه قفل صفحه"</string>
     <string name="policydesc_expirePassword" msgid="9136524319325960675">"تغییر تعداد دفعاتی که گذرواژه، پین یا الگوی قفل صفحه باید تغییر کند."</string>
-    <string name="policylab_encryptedStorage" msgid="9012936958126670110">"تنظیم رمزگذاری حافظه"</string>
+    <string name="policylab_encryptedStorage" msgid="9012936958126670110">"تنظیم رمزگذاری فضای ذخیره‌سازی"</string>
     <string name="policydesc_encryptedStorage" msgid="1102516950740375617">"اطلاعات ذخیره شده برنامه باید رمزگذاری شود."</string>
     <string name="policylab_disableCamera" msgid="5749486347810162018">"غیرفعال کردن دوربین‌ها"</string>
     <string name="policydesc_disableCamera" msgid="3204405908799676104">"جلوگیری از استفاده از همه دوربین‌های دستگاه."</string>
@@ -1107,7 +1107,7 @@
     <string name="deleteText" msgid="4200807474529938112">"حذف"</string>
     <string name="inputMethod" msgid="1784759500516314751">"روش ورودی"</string>
     <string name="editTextMenuTitle" msgid="857666911134482176">"کنش‌های متنی"</string>
-    <string name="low_internal_storage_view_title" msgid="9024241779284783414">"حافظه درحال پر شدن است"</string>
+    <string name="low_internal_storage_view_title" msgid="9024241779284783414">"فضای ذخیره‌سازی درحال پر شدن است"</string>
     <string name="low_internal_storage_view_text" msgid="8172166728369697835">"برخی از عملکردهای سیستم ممکن است کار نکنند"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="7368968163411251788">"فضای ذخیره‌سازی سیستم کافی نیست. اطمینان حاصل کنید که دارای ۲۵۰ مگابایت فضای خالی هستید و سیستم را راه‌اندازی مجدد کنید."</string>
     <string name="app_running_notification_title" msgid="8985999749231486569">"<xliff:g id="APP_NAME">%1$s</xliff:g> در حال اجرا است"</string>
@@ -1504,7 +1504,7 @@
     <string name="action_menu_overflow_description" msgid="4579536843510088170">"سایر گزینه‌ها"</string>
     <string name="action_bar_home_description_format" msgid="5087107531331621803">"‎%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="4346835454749569826">"‎%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="8490227947584914460">"حافظه داخلی مشترک"</string>
+    <string name="storage_internal" msgid="8490227947584914460">"فضای ذخیره‌سازی داخلی مشترک"</string>
     <string name="storage_sd_card" msgid="3404740277075331881">"‏کارت SD"</string>
     <string name="storage_sd_card_label" msgid="7526153141147470509">"‏کارت SD ‏<xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb_drive" msgid="448030813201444573">"‏درایو USB"</string>
@@ -1921,7 +1921,7 @@
     <string name="app_category_news" msgid="1172762719574964544">"اخبار و مجله"</string>
     <string name="app_category_maps" msgid="6395725487922533156">"نقشه و پیمایش"</string>
     <string name="app_category_productivity" msgid="1844422703029557883">"بهره‌وری"</string>
-    <string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"حافظه دستگاه"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"فضای ذخیره‌سازی دستگاه"</string>
     <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"‏اشکال‌زدایی USB"</string>
     <string name="time_picker_hour_label" msgid="4208590187662336864">"ساعت"</string>
     <string name="time_picker_minute_label" msgid="8307452311269824553">"دقیقه"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index f7f2e94..d23a5bd 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -142,7 +142,7 @@
     <string name="wfcSpnFormat_wifi" msgid="1376356951297043426">"Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"Wi-Fi-puhelut"</string>
     <string name="wfcSpnFormat_vowifi" msgid="8371335230890725606">"VoWifi"</string>
-    <string name="wifi_calling_off_summary" msgid="5626710010766902560">"Ei käytössä"</string>
+    <string name="wifi_calling_off_summary" msgid="5626710010766902560">"Ei päällä"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Soita Wi-Fin kautta"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Soita mobiiliverkon kautta"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Vain Wi-Fi"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 3de09a0..000d03c 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1631,8 +1631,8 @@
     <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>
     <string name="accessibility_shortcut_off" msgid="3651336255403648739">"ON にしない"</string>
-    <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"オン"</string>
-    <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"オフ"</string>
+    <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"ON"</string>
+    <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"OFF"</string>
     <string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g> にデバイスのフル コントロールを許可しますか?"</string>
     <string name="accessibility_enable_service_encryption_warning" msgid="8603532708618236909">"<xliff:g id="SERVICE">%1$s</xliff:g> をオンにすると、デバイスデータの暗号化の強化に画面ロックは使用されなくなります。"</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"フル コントロールは、ユーザー補助機能を必要とするユーザーをサポートするアプリには適していますが、ほとんどのアプリには適していません。"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index d41aba6..6259e4f 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1230,7 +1230,7 @@
     <string name="volume_icon_description_media" msgid="4997633254078171233">"ລະດັບສຽງຂອງສື່"</string>
     <string name="volume_icon_description_notification" msgid="579091344110747279">"ລະດັບສຽງການແຈ້ງເຕືອນ"</string>
     <string name="ringtone_default" msgid="9118299121288174597">"ຣິງໂທນເລີ່ມຕົ້ນ"</string>
-    <string name="ringtone_default_with_actual" msgid="2709686194556159773">"Default (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <string name="ringtone_default_with_actual" msgid="2709686194556159773">"ຄ່າເລີ່ມຕົ້ນ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
     <string name="ringtone_silent" msgid="397111123930141876">"ບໍ່ມີ"</string>
     <string name="ringtone_picker_title" msgid="667342618626068253">"ຣິງໂທນ"</string>
     <string name="ringtone_picker_title_alarm" msgid="7438934548339024767">"Alarm sounds"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 3b57500c..fa0bb8b 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1231,8 +1231,8 @@
     <string name="dump_heap_ready_notification" msgid="2302452262927390268">"<xliff:g id="PROC">%1$s</xliff:g> kaudzes izraksts ir gatavs"</string>
     <string name="dump_heap_notification_detail" msgid="8431586843001054050">"Apkopots kaudzes izraksts. Pieskarieties, lai kopīgotu."</string>
     <string name="dump_heap_title" msgid="4367128917229233901">"Vai kopīgot kaudzes izrakstu?"</string>
-    <string name="dump_heap_text" msgid="1692649033835719336">"Process <xliff:g id="PROC">%1$s</xliff:g> pārsniedza atmiņas ierobežojumu (<xliff:g id="SIZE">%2$s</xliff:g>). Tika apkopots kaudzes izraksts, ko varat kopīgot ar procesa izstrādātāju. Ņemiet vērā: kaudzes izrakstā var būt ietverta jūsu personas informācija, kurai var piekļūt lietojumprogramma."</string>
-    <string name="dump_heap_system_text" msgid="6805155514925350849">"Process <xliff:g id="PROC">%1$s</xliff:g> pārsniedza atmiņas ierobežojumu (<xliff:g id="SIZE">%2$s</xliff:g>). Tika apkopots kaudzes izraksts, ko varat kopīgot. Ievērojiet piesardzību, jo kaudzes izrakstā var būt ietverta visa sensitīvā personas informācija, kurai var piekļūt process, tostarp jūsu rakstīts teksts."</string>
+    <string name="dump_heap_text" msgid="1692649033835719336">"Process <xliff:g id="PROC">%1$s</xliff:g> pārsniedza atmiņas ierobežojumu (<xliff:g id="SIZE">%2$s</xliff:g>). Tika vākts kaudzes izraksts, ko varat kopīgot ar procesa izstrādātāju. Ņemiet vērā: kaudzes izrakstā var būt ietverta jūsu personas informācija, kurai var piekļūt lietojumprogramma."</string>
+    <string name="dump_heap_system_text" msgid="6805155514925350849">"Process <xliff:g id="PROC">%1$s</xliff:g> pārsniedza atmiņas ierobežojumu (<xliff:g id="SIZE">%2$s</xliff:g>). Tika vākts kaudzes izraksts, ko varat kopīgot. Ievērojiet piesardzību, jo kaudzes izrakstā var būt ietverta visa sensitīvā personas informācija, kurai var piekļūt process, tostarp jūsu rakstīts teksts."</string>
     <string name="dump_heap_ready_text" msgid="5849618132123045516">"Ir pieejams procesa <xliff:g id="PROC">%1$s</xliff:g> kaudzes izraksts, ko varat kopīgot. Ievērojiet piesardzību, jo kaudzes izrakstā var būt ietverta visa sensitīvā personas informācija, kurai var piekļūt process, tostarp jūsu rakstīts teksts."</string>
     <string name="sendText" msgid="493003724401350724">"Izvēlieties darbību tekstam"</string>
     <string name="volume_ringtone" msgid="134784084629229029">"Zvanītāja skaļums"</string>
diff --git a/core/res/res/values-mcc334-mnc020/config.xml b/core/res/res/values-mcc334-mnc020/config.xml
index c64acc7..82b3ee6 100644
--- a/core/res/res/values-mcc334-mnc020/config.xml
+++ b/core/res/res/values-mcc334-mnc020/config.xml
@@ -19,6 +19,6 @@
 <resources>
     <bool name="config_use_sim_language_file">false</bool>
 
-    <bool name="config_pdp_rejeect_enable_retry">true</bool>
+    <bool name="config_pdp_reject_enable_retry">true</bool>
     <integer name="config_pdp_reject_retry_delay_ms">45000</integer>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 902aa16..238a4e6 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -268,7 +268,7 @@
     <string name="status_bar_notification_info_overflow" msgid="3330152558746563475">"999+"</string>
     <string name="notification_hidden_text" msgid="2835519769868187223">"Шинэ мэдэгдэл"</string>
     <string name="notification_channel_virtual_keyboard" msgid="6465975799223304567">"Виртуал гар"</string>
-    <string name="notification_channel_physical_keyboard" msgid="5417306456125988096">"Бодит гар"</string>
+    <string name="notification_channel_physical_keyboard" msgid="5417306456125988096">"Биет гар"</string>
     <string name="notification_channel_security" msgid="8516754650348238057">"Аюулгүй байдал"</string>
     <string name="notification_channel_car_mode" msgid="2123919247040988436">"Машины горим"</string>
     <string name="notification_channel_account" msgid="6436294521740148173">"Бүртгэлийн төлөв"</string>
@@ -1327,7 +1327,7 @@
     <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>
-    <string name="show_ime" msgid="6406112007347443383">"Бодит гар идэвхтэй үед үүнийг дэлгэцэнд харуулна уу"</string>
+    <string name="show_ime" msgid="6406112007347443383">"Биет гар идэвхтэй үед үүнийг дэлгэцэд харуулна уу"</string>
     <string name="hardware" msgid="1800597768237606953">"Хийсвэр гарыг харуулах"</string>
     <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Биет гарыг хэлбэрт оруулах"</string>
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Хэл болон бүдүүвчийг сонгохын тулд дарна уу"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index fbeb310..1840479 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -108,7 +108,7 @@
     <string name="serviceClassDataSync" msgid="7895071363569133704">"सिंक करा"</string>
     <string name="serviceClassPacket" msgid="1430642951399303804">"पॅकेट"</string>
     <string name="serviceClassPAD" msgid="6850244583416306321">"PAD"</string>
-    <string name="roamingText0" msgid="7793257871609854208">"रोमिंग दर्शक चालू"</string>
+    <string name="roamingText0" msgid="7793257871609854208">"रोमिंग दर्शक सुरू"</string>
     <string name="roamingText1" msgid="5073028598334616445">"रोमिंग दर्शक बंद"</string>
     <string name="roamingText2" msgid="2834048284153110598">"रोमिंग दर्शक फ्लॅशिंग"</string>
     <string name="roamingText3" msgid="831690234035748988">"अतिपरिचित क्षेत्राबाहेर"</string>
@@ -119,12 +119,12 @@
     <string name="roamingText8" msgid="7774800704373721973">"रोमिंग - प्रीमियम भागीदार"</string>
     <string name="roamingText9" msgid="1933460020190244004">"रोमिंग - पूर्ण सेवा कार्यक्षमता"</string>
     <string name="roamingText10" msgid="7434767033595769499">"रोमिंग - आंशिक सेवा कार्यक्षमता"</string>
-    <string name="roamingText11" msgid="5245687407203281407">"रोमिंग बॅनर चालू"</string>
+    <string name="roamingText11" msgid="5245687407203281407">"रोमिंग बॅनर सुरू"</string>
     <string name="roamingText12" msgid="673537506362152640">"रोमिंग बॅनर बंद"</string>
     <string name="roamingTextSearching" msgid="5323235489657753486">"सेवा शोधत आहे"</string>
     <string name="wfcRegErrorTitle" msgid="3193072971584858020">"वाय-फाय कॉलिंग सेट करता आले नाही"</string>
   <string-array name="wfcOperatorErrorAlertMessages">
-    <item msgid="468830943567116703">"वाय-फायवरून कॉल करण्यासाठी आणि मेसेज पाठवण्यासाठी आधी तुमच्या कॅरियरला ही सेवा सेट अप करण्यास सांगा. नंतर सेटिंग्जमधून वाय-फाय वापरून कॉल करणे पुन्हा चालू करा. (एरर कोड <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+    <item msgid="468830943567116703">"वाय-फायवरून कॉल करण्यासाठी आणि मेसेज पाठवण्यासाठी आधी तुमच्या कॅरियरला ही सेवा सेट अप करण्यास सांगा. नंतर सेटिंग्जमधून वाय-फाय वापरून कॉल करणे पुन्हा सुरू करा. (एरर कोड <xliff:g id="CODE">%1$s</xliff:g>)"</item>
   </string-array>
   <string-array name="wfcOperatorErrorNotificationMessages">
     <item msgid="4795145070505729156">"तुमच्या या वाहकासह वाय-फाय कॉलिंग नोंदणी करताना समस्या आली आहे:<xliff:g id="CODE">%1$s</xliff:g>"</item>
@@ -209,13 +209,13 @@
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV पर्याय"</string>
     <string name="power_dialog" product="default" msgid="1107775420270203046">"फोन पर्याय"</string>
     <string name="silent_mode" msgid="8796112363642579333">"मूक मोड"</string>
-    <string name="turn_on_radio" msgid="2961717788170634233">"वायरलेस चालू करा"</string>
+    <string name="turn_on_radio" msgid="2961717788170634233">"वायरलेस सुरू करा"</string>
     <string name="turn_off_radio" msgid="7222573978109933360">"वायरलेस बंद करा"</string>
     <string name="screen_lock" msgid="2072642720826409809">"स्क्रीन लॉक"</string>
     <string name="power_off" msgid="4111692782492232778">"बंद करा"</string>
     <string name="silent_mode_silent" msgid="5079789070221150912">"रिंगर बंद"</string>
     <string name="silent_mode_vibrate" msgid="8821830448369552678">"रिंगर व्हायब्रेट"</string>
-    <string name="silent_mode_ring" msgid="6039011004781526678">"रिंगर चालू"</string>
+    <string name="silent_mode_ring" msgid="6039011004781526678">"रिंगर सुरू"</string>
     <string name="reboot_to_update_title" msgid="2125818841916373708">"Android सिस्टम अपडेट"</string>
     <string name="reboot_to_update_prepare" msgid="6978842143587422365">"अपडेट करण्याची तयारी करत आहे…"</string>
     <string name="reboot_to_update_package" msgid="4644104795527534811">"अपडेट पॅकेज प्रक्रिया करत आहे…"</string>
@@ -317,7 +317,7 @@
     <string name="permgroupdesc_sensors" msgid="2610631290633747752">"आपल्‍या महत्त्वाच्या मापनांविषयी सेंसर डेटा अ‍ॅक्सेस करा"</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_title_canRequestTouchExploration" msgid="327598364696316213">"स्पर्श करून अन्वेषण सुरू करा"</string>
     <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"टॅप केलेले आयटम मोठ्‍याने बोलले जातील आणि जेश्चरचा वापर करून स्क्रीन एक्सप्लोर केली जाऊ शकते."</string>
     <string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"तुम्ही टाइप करता त्या मजकुराचे निरीक्षण करा"</string>
     <string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"यामध्ये क्रेडिट कार्ड नंबर आणि पासवर्ड यासारखा वैयक्तिक डेटा समाविष्‍ट आहे."</string>
@@ -374,7 +374,7 @@
     <string name="permlab_systemAlertWindow" msgid="5757218350944719065">"हा अ‍ॅप इतर अ‍ॅप्सच्या शीर्षस्थानी दिसू शकतो."</string>
     <string name="permdesc_systemAlertWindow" msgid="1145660714855738308">"हे अ‍ॅप इतर अ‍ॅप्सच्या शीर्षस्थानी किंवा स्क्रीनच्या इतर भागांवर दिसू शकतो. हे सामान्य अ‍ॅप वापरात व्यत्यय आणू शकते किंवा इतर अ‍ॅप्सची डिस्प्ले पद्धत बदलू शकते."</string>
     <string name="permlab_runInBackground" msgid="541863968571682785">"पार्श्वभूमीत चालवा"</string>
-    <string name="permdesc_runInBackground" msgid="4344539472115495141">"हे अ‍ॅप पार्श्वभूमीत चालू शकते. हे बॅटरी अधिक जलद संपवू शकते."</string>
+    <string name="permdesc_runInBackground" msgid="4344539472115495141">"हे अ‍ॅप पार्श्वभूमीत सुरू शकते. हे बॅटरी अधिक जलद संपवू शकते."</string>
     <string name="permlab_useDataInBackground" msgid="783415807623038947">"पार्श्वभूमीत डेटा वापरा"</string>
     <string name="permdesc_useDataInBackground" msgid="1230753883865891987">"हे अ‍ॅप पार्श्वभूमीत डेटा वापरू शकते. हे डेटाचा वापर वाढवू शकते."</string>
     <string name="permlab_persistentActivity" msgid="464970041740567970">"अ‍ॅप नेहमी चालवा"</string>
@@ -388,9 +388,9 @@
     <string name="permlab_writeSettings" msgid="8057285063719277394">"सिस्टम सेटिंग्ज सुधारित करा"</string>
     <string name="permdesc_writeSettings" msgid="8293047411196067188">"सिस्टीमचा सेटिंग्ज डेटा सुधारित करण्यासाठी अ‍ॅप ला अनुमती देते. दुर्भावनापूर्ण अ‍ॅप्स आपल्या सिस्टीमचे कॉन्फिगरेशन दूषित करू शकतात."</string>
     <string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"सुरूवातीस चालवा"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"जसे सिस्टम बूट करणे समाप्त करते तसे अ‍ॅप ला स्वतः प्रारंभ करण्यास अनुमती देते. यामुळे टॅबलेट प्रारंभ करण्यास वेळ लागू शकतो आणि नेहमी चालू राहून एकंदर टॅबलेटला धीमे करण्यास अ‍ॅप ला अनुमती देते."</string>
-    <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"सिस्टम बूट होणे संपल्यावर ॲपला स्वतः सुरू होण्याची अनुमती देते. यामुळे तुमच्या Android TV डिव्हाइसला सुरू होण्यास वेळ लागू शकतो आणि नेहमी चालू राहून एकंदर डिव्हाइसलाच धीमे करण्याची अनुमती ॲपला देते."</string>
-    <string name="permdesc_receiveBootCompleted" product="default" msgid="7912677044558690092">"जसे सिस्टम बूट करणे समाप्त करते तसे अ‍ॅप ला स्वतः प्रारंभ करण्यास अनुमती देते. यामुळे फोन प्रारंभ करण्यास वेळ लागू शकतो आणि नेहमी चालू राहून एकंदर फोनला धीमे करण्यास अ‍ॅप ला अनुमती देते."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"जसे सिस्टम बूट करणे समाप्त करते तसे अ‍ॅप ला स्वतः प्रारंभ करण्यास अनुमती देते. यामुळे टॅबलेट प्रारंभ करण्यास वेळ लागू शकतो आणि नेहमी सुरू राहून एकंदर टॅबलेटला धीमे करण्यास अ‍ॅप ला अनुमती देते."</string>
+    <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"सिस्टम बूट होणे संपल्यावर ॲपला स्वतः सुरू होण्याची अनुमती देते. यामुळे तुमच्या Android TV डिव्हाइसला सुरू होण्यास वेळ लागू शकतो आणि नेहमी सुरू राहून एकंदर डिव्हाइसलाच धीमे करण्याची अनुमती ॲपला देते."</string>
+    <string name="permdesc_receiveBootCompleted" product="default" msgid="7912677044558690092">"जसे सिस्टम बूट करणे समाप्त करते तसे अ‍ॅप ला स्वतः प्रारंभ करण्यास अनुमती देते. यामुळे फोन प्रारंभ करण्यास वेळ लागू शकतो आणि नेहमी सुरू राहून एकंदर फोनला धीमे करण्यास अ‍ॅप ला अनुमती देते."</string>
     <string name="permlab_broadcastSticky" msgid="4552241916400572230">"रोचक प्रसारण पाठवा"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="5058486069846384013">"रोचक प्रसारणे पाठविण्यासाठी अ‍ॅप ला अनुमती देते, जे प्रसारण समाप्त झाल्यानंतर देखील तसेच राहते. अत्याधिक वापरामुळे बरीच मेमरी वापरली जाऊन तो टॅब्लेटला धीमा किंवा अस्थिर करू शकतो."</string>
     <string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"चिकट प्रसारणे पाठविण्यासाठी ॲपला अनुमती देते, जे प्रसारण समाप्त झाल्यानंतर देखील तसेच राहते. अत्याधिक वापरामुळे बरीच मेमरी वापरली जाऊन तो तुमच्या Android TV डिव्हाइसला धीमा किंवा अस्थिर करू शकतो."</string>
@@ -613,7 +613,7 @@
     <string name="face_icon_content_description" msgid="465030547475916280">"चेहरा आयकन"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"सिंक सेटिंग्‍ज वाचा"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"खात्याच्या सिंक सेटिंग्ज वाचण्यासाठी अ‍ॅप ला अनुमती देते. उदाहरणार्थ, हे खात्यासह लोकांचा अ‍ॅप संकालित केला आहे किंवा नाही हे निर्धारित करू शकते."</string>
-    <string name="permlab_writeSyncSettings" msgid="6583154300780427399">"सिंक चालू आणि बंद करा टॉगल करा"</string>
+    <string name="permlab_writeSyncSettings" msgid="6583154300780427399">"सिंक सुरू आणि बंद करा टॉगल करा"</string>
     <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"खात्यासाठी सिंक सेटिंग्ज सुधारित करण्यासाठी अ‍ॅप ला अनुमती देते. उदाहरणार्थ, हे खात्यासह लोकांच्या अ‍ॅप चे सिंक सक्षम करण्यासाठी वापरले जाऊ शकते."</string>
     <string name="permlab_readSyncStats" msgid="3747407238320105332">"सिंक आकडेवारी वाचा"</string>
     <string name="permdesc_readSyncStats" msgid="3867809926567379434">"सिंक इव्हेंटचा इतिहास आणि किती डेटाचे सिंक केले आहे यासह, खात्याची सिंक स्थिती वाचण्यासाठी अ‍ॅप ला अनुमती देते."</string>
@@ -881,7 +881,7 @@
     <string name="lockscreen_glogin_account_recovery_hint" msgid="1683405808525090649">"तुमचे वापरकर्तानाव किंवा पासवर्ड विसरलात?\n "<b>"google.com/accounts/recovery"</b>" ला भेट द्या."</string>
     <string name="lockscreen_glogin_checking_password" msgid="2607271802803381645">"तपासत आहे..."</string>
     <string name="lockscreen_unlock_label" msgid="4648257878373307582">"अनलॉक करा"</string>
-    <string name="lockscreen_sound_on_label" msgid="1660281470535492430">"ध्वनी सुरु"</string>
+    <string name="lockscreen_sound_on_label" msgid="1660281470535492430">"ध्वनी सुरू"</string>
     <string name="lockscreen_sound_off_label" msgid="2331496559245450053">"ध्वनी बंद"</string>
     <string name="lockscreen_access_pattern_start" msgid="3778502525702613399">"पॅटर्न सुरू केला"</string>
     <string name="lockscreen_access_pattern_cleared" msgid="7493849102641167049">"पॅटर्न साफ केला"</string>
@@ -988,8 +988,8 @@
     <string name="searchview_description_submit" msgid="6771060386117334686">"क्वेरी सबमिट करा"</string>
     <string name="searchview_description_voice" msgid="42360159504884679">"व्हॉइस शोध"</string>
     <string name="enable_explore_by_touch_warning_title" msgid="5095399706284943314">"स्पर्श करून एक्सप्लोर करा सक्षम करायचे?"</string>
-    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> स्पर्श करून एक्सप्लोर करा सक्षम करू इच्छिते. स्पर्श करून एक्सप्लोर करा चालू असते, तेव्हा तुम्ही तुमच्या बोटाखाली काय आहे त्याचे वर्णन ऐकू किंवा पाहू शकता किंवा टॅब्लेटसह संवाद साधण्यासाठी जेश्चर करू शकता."</string>
-    <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> स्पर्श करून एक्सप्लोर करा सक्षम करू इच्छिते. स्पर्श करून एक्सप्लोर करा चालू असते, तेव्हा तुम्ही तुमच्या बोटाखाली काय आहे त्याचे वर्णन ऐकू किंवा पाहू शकता किंवा फोनसह संवाद साधण्यासाठी जेश्चर करू शकता."</string>
+    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> स्पर्श करून एक्सप्लोर करा सक्षम करू इच्छिते. स्पर्श करून एक्सप्लोर करा सुरू असते, तेव्हा तुम्ही तुमच्या बोटाखाली काय आहे त्याचे वर्णन ऐकू किंवा पाहू शकता किंवा टॅब्लेटसह संवाद साधण्यासाठी जेश्चर करू शकता."</string>
+    <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> स्पर्श करून एक्सप्लोर करा सक्षम करू इच्छिते. स्पर्श करून एक्सप्लोर करा सुरू असते, तेव्हा तुम्ही तुमच्या बोटाखाली काय आहे त्याचे वर्णन ऐकू किंवा पाहू शकता किंवा फोनसह संवाद साधण्यासाठी जेश्चर करू शकता."</string>
     <string name="oneMonthDurationPast" msgid="4538030857114635777">"1 महिन्यापूर्वी"</string>
     <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"1 महिन्यापूर्वी"</string>
     <plurals name="last_num_days" formatted="false" msgid="687443109145393632">
@@ -1203,7 +1203,7 @@
     <string name="heavy_weight_notification" msgid="8382784283600329576">"रन होणारे <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="heavy_weight_notification_detail" msgid="6802247239468404078">"गेमवर परत जाण्यासाठी टॅप करा"</string>
     <string name="heavy_weight_switcher_title" msgid="3861984210040100886">"गेम निवडा"</string>
-    <string name="heavy_weight_switcher_text" msgid="6814316627367160126">"अधिक चांगल्या कामगिरीसाठी, एकावेळी यापैकी केवळ एक गेम चालू ठेवता येईल."</string>
+    <string name="heavy_weight_switcher_text" msgid="6814316627367160126">"अधिक चांगल्या कामगिरीसाठी, एकावेळी यापैकी केवळ एक गेम सुरू ठेवता येईल."</string>
     <string name="old_app_action" msgid="725331621042848590">"<xliff:g id="OLD_APP">%1$s</xliff:g> वर परत जा"</string>
     <string name="new_app_action" msgid="547772182913269801">"<xliff:g id="NEW_APP">%1$s</xliff:g> उघडा"</string>
     <string name="new_app_description" msgid="1958903080400806644">"<xliff:g id="OLD_APP">%1$s</xliff:g> सेव्ह न करता बंद होईल"</string>
@@ -1262,7 +1262,7 @@
     <string name="decline" msgid="6490507610282145874">"नकार द्या"</string>
     <string name="select_character" msgid="3352797107930786979">"वर्ण घाला"</string>
     <string name="sms_control_title" msgid="4748684259903148341">"SMS मेसेज पाठवत आहे"</string>
-    <string name="sms_control_message" msgid="6574313876316388239">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; मोठ्या संख्येने SMS मेसेज पाठवत आहे. तुम्ही या अ‍ॅप ला मेसेज पाठविणे सुरु ठेवण्याची अनुमती देऊ इच्छिता?"</string>
+    <string name="sms_control_message" msgid="6574313876316388239">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; मोठ्या संख्येने SMS मेसेज पाठवत आहे. तुम्ही या अ‍ॅप ला मेसेज पाठविणे सुरू ठेवण्याची अनुमती देऊ इच्छिता?"</string>
     <string name="sms_control_yes" msgid="4858845109269524622">"अनुमती द्या"</string>
     <string name="sms_control_no" msgid="4845717880040355570">"नकार द्या"</string>
     <string name="sms_short_code_confirm_message" msgid="1385416688897538724">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; हा &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;वर एक मेसेज पाठवू इच्छितो."</string>
@@ -1297,10 +1297,10 @@
     <string name="dlg_ok" msgid="5103447663504839312">"ठीक"</string>
     <string name="usb_charging_notification_title" msgid="1674124518282666955">"हे डिव्हाइस USB ने चार्ज करत आहे"</string>
     <string name="usb_supplying_notification_title" msgid="5378546632408101811">"USB ने चार्ज करायला ठेवलेले डिव्हाइस"</string>
-    <string name="usb_mtp_notification_title" msgid="1065989144124499810">"USB फाइल ट्रान्सफर चालू केले"</string>
-    <string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB मार्फत PTP चालू केले"</string>
-    <string name="usb_tether_notification_title" msgid="8828527870612663771">"USB टेदरिंग चालू केले"</string>
-    <string name="usb_midi_notification_title" msgid="7404506788950595557">"USB मार्फत MIDI चालू केले"</string>
+    <string name="usb_mtp_notification_title" msgid="1065989144124499810">"USB फाइल ट्रान्सफर सुरू केले"</string>
+    <string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB मार्फत PTP सुरू केले"</string>
+    <string name="usb_tether_notification_title" msgid="8828527870612663771">"USB टेदरिंग सुरू केले"</string>
+    <string name="usb_midi_notification_title" msgid="7404506788950595557">"USB मार्फत MIDI सुरू केले"</string>
     <string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB अ‍ॅक्सेसरी कनेक्ट केली आहे"</string>
     <string name="usb_notification_message" msgid="4715163067192110676">"अधिक पर्यायांसाठी टॅप करा."</string>
     <string name="usb_power_notification_message" msgid="7284765627437897702">"चार्जर लावलेले डिव्हाइस. आणखी पर्यायांसाठी टॅप करा"</string>
@@ -1425,10 +1425,10 @@
     <string name="vpn_title_long" msgid="6834144390504619998">"<xliff:g id="APP">%s</xliff:g> द्वारे VPN सक्रिय केले आहे"</string>
     <string name="vpn_text" msgid="2275388920267251078">"नेटवर्क व्यवस्थापित करण्यासाठी टॅप करा."</string>
     <string name="vpn_text_long" msgid="278540576806169831">"<xliff:g id="SESSION">%s</xliff:g> शी कनेक्ट केले. नेटवर्क व्यवस्थापित करण्यासाठी टॅप करा."</string>
-    <string name="vpn_lockdown_connecting" msgid="6096725311950342607">"VPN कनेक्ट करणे नेहमी-चालू…"</string>
-    <string name="vpn_lockdown_connected" msgid="2853127976590658469">"VPN कनेक्ट केलेले नेहमी-चालू"</string>
-    <string name="vpn_lockdown_disconnected" msgid="5573611651300764955">"कायम चालू असलेल्या VPN मधून डिस्कनेक्ट केले"</string>
-    <string name="vpn_lockdown_error" msgid="4453048646854247947">"कायम चालू असलेल्या VPN शी कनेक्ट करता आले नाही"</string>
+    <string name="vpn_lockdown_connecting" msgid="6096725311950342607">"VPN कनेक्ट करणे नेहमी-सुरू…"</string>
+    <string name="vpn_lockdown_connected" msgid="2853127976590658469">"VPN कनेक्ट केलेले नेहमी-सुरू"</string>
+    <string name="vpn_lockdown_disconnected" msgid="5573611651300764955">"कायम सुरू असलेल्या VPN मधून डिस्कनेक्ट केले"</string>
+    <string name="vpn_lockdown_error" msgid="4453048646854247947">"कायम सुरू असलेल्या VPN शी कनेक्ट करता आले नाही"</string>
     <string name="vpn_lockdown_config" msgid="8331697329868252169">"नेटवर्क किंवा VPN सेटिंग्ज बदला"</string>
     <string name="upload_file" msgid="8651942222301634271">"फाईल निवडा"</string>
     <string name="no_file_chosen" msgid="4146295695162318057">"फाईल निवडली नाही"</string>
@@ -1587,7 +1587,7 @@
     <string name="kg_sim_pin_instructions" msgid="6479401489471690359">"सिम पिन एंटर करा"</string>
     <string name="kg_pin_instructions" msgid="7355933174673539021">"पिन एंटर करा"</string>
     <string name="kg_password_instructions" msgid="7179782578809398050">"पासवर्ड एंटर करा"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"सिम आता अक्षम केले आहे. सुरु ठेवण्यासाठी PUK कोड एंटर करा. तपशीलांसाठी वाहकाशी संपर्क साधा."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"सिम आता अक्षम केले आहे. सुरू ठेवण्यासाठी PUK कोड एंटर करा. तपशीलांसाठी वाहकाशी संपर्क साधा."</string>
     <string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"इच्छित पिन कोड एंटर करा"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"इच्छित पिन कोड ची पुष्टी करा"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="8871937892678885545">"सिम कार्ड अनलॉक करत आहे…"</string>
@@ -1797,7 +1797,7 @@
     <string name="battery_saver_description_with_learn_more" msgid="5997766757551917769">"बॅटरीचे आयुष्य वाढवण्यासाठी बॅटरी सेव्हर:\n\n•गडद थीम सुरू करते\n•बॅकग्राउंड ॲक्टिव्हिटी, काही व्हिज्युअल इफेक्ट आणि \"Ok Google\" यांसारखी वैशिष्ट्ये बंद किंवा मर्यादित करते.\n\n"<annotation id="url">"अधिक जाणून घ्या"</annotation></string>
     <string name="battery_saver_description" msgid="8587408568232177204">"बॅटरीचे आयुष्य वाढवण्यासाठी बॅटरी सेव्हर:\n\n•गडद थीम सुरू करते\n•बॅकग्राउंड ॲक्टिव्हिटी, काही व्हिज्युअल इफेक्ट आणि \"Ok Google\" यांसारखी वैशिष्ट्ये बंद किंवा मर्यादित करते."</string>
     <string name="data_saver_description" msgid="4995164271550590517">"डेटाचा वापर कमी करण्यात मदत करण्यासाठी काही अ‍ॅप्सना बॅकग्राउंडमध्ये डेटा पाठवण्यास किंवा मिळवण्यास डेटा सर्व्हर प्रतिबंध करतो. तुम्ही सध्या वापरत असलेले अ‍ॅप डेटा अ‍ॅक्सेस करू शकते, पण तसे खूप कमी वेळा होते. याचाच अर्थ असा की, तुम्ही इमेजवर टॅप करेपर्यंत त्या डिस्प्ले होणार नाहीत असे होऊ शकते."</string>
-    <string name="data_saver_enable_title" msgid="7080620065745260137">"डेटा सेव्हर चालू करायचे?"</string>
+    <string name="data_saver_enable_title" msgid="7080620065745260137">"डेटा सेव्हर सुरू करायचे?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"सुरू करा"</string>
     <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
       <item quantity="other">%1$d मिनिटांसाठी (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> पर्यंत)</item>
@@ -1890,7 +1890,7 @@
     <string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"अ‍ॅप उघडा"</string>
     <string name="work_mode_off_title" msgid="5503291976647976560">"कार्य प्रोफाइल सुरू ठेवायची?"</string>
     <string name="work_mode_off_message" msgid="8417484421098563803">"तुमची कार्य अ‍ॅप्स, सूचना, डेटा आणि अन्य कार्य प्रोफाइल वैशिष्ट्ये सुरू केली जातील"</string>
-    <string name="work_mode_turn_on" msgid="3662561662475962285">"चालू करा"</string>
+    <string name="work_mode_turn_on" msgid="3662561662475962285">"सुरू करा"</string>
     <string name="app_blocked_title" msgid="7353262160455028160">"ॲप उपलब्ध नाही"</string>
     <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> आता उपलब्ध नाही."</string>
     <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"हे अ‍ॅप Android च्या जुन्या आवृत्ती साठी तयार करण्यात आले होते आणि योग्यरितीने कार्य करू शकणार नाही. अपडेट आहेत का ते तपासून पाहा, किंवा डेव्हलपरशी संपर्क साधण्याचा प्रयत्न करा."</string>
@@ -2025,7 +2025,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> स्प्रेडशीट"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"सादरीकरण"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> सादरीकरण"</string>
-    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"विमान मोड दरम्यान ब्लूटूथ चालू राहील"</string>
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"विमान मोड दरम्यान ब्लूटूथ सुरू राहील"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"लोड होत आहे"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> फायली</item>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 79d0974..d9e3b0c 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -380,7 +380,7 @@
     <string name="permlab_persistentActivity" msgid="464970041740567970">"एपहरू जहिले पनि चल्ने बनाउनुहोस्"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="6055271149187369916">"यसको आफ्नै मेमोरीमा दृढ भएकोको अंश बनाउनको लागि एपलाई अनुमति दिन्छ। ट्याब्लेटलाई ढिलो गराउँदै गरेका अन्य अनुप्रयोगहरूलाई सीमित मात्रामा यसले मेमोरी उपलब्ध गराउन सक्छ।"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="6800526387664131321">"एपलाई आफ्ना केही अंशहरू मेमोरीमा स्थायी रूपमा राख्ने अनुमति दिन्छ। यसले गर्दा अन्य अनुप्रयोगहरूका लागि मेमोरीको अभाव हुन सक्ने भएकाले तपाईंको Android TV यन्त्र सुस्त हुन सक्छ।"</string>
-    <string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"एपलाई मेमोरीमा आफैंको निरन्तरको अंश बनाउन अनुमति दिन्छ। यसले फोनलाई ढिला बनाएर अन्य अनुप्रयोगहरूमा मेमोरी SIMित गर्न सक्दछन्।"</string>
+    <string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"एपलाई मेमोरीमा आफैंको निरन्तरको अंश बनाउन अनुमति दिन्छ। यसले फोनलाई ढिला बनाएर अन्य एपहरूमा मेमोरी SIMित गर्न सक्दछन्।"</string>
     <string name="permlab_foregroundService" msgid="1768855976818467491">"अग्रभूमिको सेवा सञ्चालन गर्नुहोस्"</string>
     <string name="permdesc_foregroundService" msgid="8720071450020922795">"एपलाई अग्रभूमिका सेवाहरू प्रयोग गर्ने अनुमति दिन्छ।"</string>
     <string name="permlab_getPackageSize" msgid="375391550792886641">"एप भण्डारण ठाउँको मापन गर्नुहोस्"</string>
@@ -614,7 +614,7 @@
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"समीकरण सेटिङहरू पढ्नुहोस्"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"एपलाई खाताको लागि सिंक सेटिङहरू पढ्न अनुमति दिन्छ। उदाहरणको लागि यसले व्यक्तिहरको एप खातासँग सिंक भएको नभएको निर्धारण गर्न सक्दछ।"</string>
     <string name="permlab_writeSyncSettings" msgid="6583154300780427399">"टगल सिंक खुला र बन्द"</string>
-    <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"अनुप्रयोगहरूलाई खाताको लागि सिंक सेटिङहरू परिमार्जन गर्न अनुमति दिन्छ। उदाहरणको लागि, यो खातासँग व्यक्ति अनुप्रयोगको सिंक सक्षम गर्न प्रयोग गर्न सकिन्छ।"</string>
+    <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"अनुप्रयोगहरूलाई खाताको लागि सिंक सेटिङहरू परिमार्जन गर्न अनुमति दिन्छ। उदाहरणको लागि, यो खातासँग व्यक्ति एपको सिंक सक्षम गर्न प्रयोग गर्न सकिन्छ।"</string>
     <string name="permlab_readSyncStats" msgid="3747407238320105332">"सिंक तथ्याङ्कहरू पढ्नुहोस्"</string>
     <string name="permdesc_readSyncStats" msgid="3867809926567379434">"एपलाई खाताको लागि समीकरणको आँकडा समीकरण घटनाहरूको  इतिहास र समीकरण गरिएको डेटाको मापन समेत, पढ्न अनुमति दिन्छ।"</string>
     <string name="permlab_sdcardRead" msgid="5791467020950064920">"आफ्नो आदान प्रदान गरिएको भण्डारणको सामग्रीहरूहरू पढ्नुहोस्"</string>
@@ -1187,7 +1187,7 @@
     <string name="screen_compat_mode_hint" msgid="4032272159093750908">"प्रणाली सेटिङहरूमा यसलाई पुनःसक्षम गराउनुहोस् &gt; एपहरू &gt; डाउनलोड गरेको।"</string>
     <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले हालको प्रदर्शनको आकार सम्बन्धी सेटिङलाई समर्थन गर्दैन र अप्रत्याशित तरिकाले व्यवहार गर्न सक्छ।"</string>
     <string name="unsupported_display_size_show" msgid="980129850974919375">"सधैँ देखाउनुहोस्"</string>
-    <string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"<xliff:g id="APP_NAME">%1$s</xliff:g> लाई Android OS को कुनै नमिल्दो संस्करणका लागि निर्माण गरिएको थियो र यसले अप्रत्याशित ढंगले कार्य गर्नसक्छ। उक्त अनुप्रयोगको कुनै अद्यावधिक संस्करण उपलब्ध हुनसक्छ।"</string>
+    <string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"<xliff:g id="APP_NAME">%1$s</xliff:g> लाई Android OS को कुनै नमिल्दो संस्करणका लागि निर्माण गरिएको थियो र यसले अप्रत्याशित ढंगले कार्य गर्नसक्छ। उक्त एपको कुनै अद्यावधिक संस्करण उपलब्ध हुनसक्छ।"</string>
     <string name="unsupported_compile_sdk_show" msgid="1601210057960312248">"जुनसुकै बेला देखाउनुहोस्"</string>
     <string name="unsupported_compile_sdk_check_update" msgid="1103639989147664456">"अद्यावधिकका लागि जाँच गर्नुहोस्"</string>
     <string name="smv_application" msgid="3775183542777792638">"एप <xliff:g id="APPLICATION">%1$s</xliff:g> (प्रक्रिया <xliff:g id="PROCESS">%2$s</xliff:g>) ले यसको स्वयं-लागु गरिएको स्ट्रिटमोड नीति उलङ्घन गरेको छ।"</string>
@@ -1217,7 +1217,7 @@
     <string name="dump_heap_ready_notification" msgid="2302452262927390268">"<xliff:g id="PROC">%1$s</xliff:g> हिप डम्प तयार छ"</string>
     <string name="dump_heap_notification_detail" msgid="8431586843001054050">"हिप डम्प सङ्‍कलन गरियो, ट्याप गरेर सेयर गर्नुहोस्।"</string>
     <string name="dump_heap_title" msgid="4367128917229233901">"हिप डम्प साझेदारी गर्नुहुन्छ?"</string>
-    <string name="dump_heap_text" msgid="1692649033835719336">"<xliff:g id="PROC">%1$s</xliff:g>प्रक्रियाले यसको मेमोरीको सीमा <xliff:g id="SIZE">%2$s</xliff:g> नाघेको छ। तपाईंका लागि विकासकर्तासँग साझेदारी गर्न एउटा हिप डम्प उपलब्ध छ। सावधान हुनुहोला: यो हिप डम्पमा अनुप्रयोगको पहुँच भएको तपाईंको जुनसुकै व्यक्तिगत जानकारी हुन सक्छ।"</string>
+    <string name="dump_heap_text" msgid="1692649033835719336">"<xliff:g id="PROC">%1$s</xliff:g>प्रक्रियाले यसको मेमोरीको सीमा <xliff:g id="SIZE">%2$s</xliff:g> नाघेको छ। तपाईंका लागि विकासकर्तासँग साझेदारी गर्न एउटा हिप डम्प उपलब्ध छ। सावधान हुनुहोला: यो हिप डम्पमा एपको पहुँच भएको तपाईंको जुनसुकै व्यक्तिगत जानकारी हुन सक्छ।"</string>
     <string name="dump_heap_system_text" msgid="6805155514925350849">"<xliff:g id="PROC">%1$s</xliff:g> प्रक्रियाले यसको मेमोरीको सीमा <xliff:g id="SIZE">%2$s</xliff:g> नाँघेको छ। आदान प्रदान गर्नका लागि तपाईंलाई एउटा हिप डम्प उपलब्ध छ। सावधान हुनुहोस्: यस हिप डम्पमा उक्त प्रक्रियाको पहुँच भएको जुनसुकै संवेदनशील व्यक्तिगत जानकारी समावेश हुन सक्छ जसमा तपाईंले टाइप गर्नुभएका कुराहरू पर्न सक्छन्।"</string>
     <string name="dump_heap_ready_text" msgid="5849618132123045516">"तपाईंसँग आदान प्रदान गर्नका लागि <xliff:g id="PROC">%1$s</xliff:g> को प्रक्रियासम्बन्धी हिप डम्प उपलब्ध छ। सावधान हुनुहोस्: यस हिप डम्पमा उक्त प्रक्रियाको पहुँच भएको जुनसुकै संवेदनशील व्यक्तिगत जानकारी समावेश हुन सक्छ जसमा तपाईंले टाइप गर्नुभएका कुराहरू पर्न सक्छन्।"</string>
     <string name="sendText" msgid="493003724401350724">"पाठको लागि एउटा प्रकार्य छान्नुहोस्"</string>
@@ -1340,8 +1340,8 @@
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="alert_windows_notification_channel_group_name" msgid="6063891141815714246">"अन्य अनुप्रयोगमा देखाउनुहोस्"</string>
-    <string name="alert_windows_notification_channel_name" msgid="3437528564303192620">"<xliff:g id="NAME">%s</xliff:g> अन्य अनुप्रयोगहरूमा देखिँदैछ"</string>
-    <string name="alert_windows_notification_title" msgid="6331662751095228536">"<xliff:g id="NAME">%s</xliff:g> अन्य अनुप्रयोगहरूमा देखिँदैछ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="3437528564303192620">"<xliff:g id="NAME">%s</xliff:g> अन्य एपहरूमा देखिँदैछ"</string>
+    <string name="alert_windows_notification_title" msgid="6331662751095228536">"<xliff:g id="NAME">%s</xliff:g> अन्य एपहरूमा देखिँदैछ"</string>
     <string name="alert_windows_notification_message" msgid="6538171456970725333">"तपाईं <xliff:g id="NAME">%s</xliff:g> ले यो विशेषता प्रयोग नगरेको चाहनुहुन्न भने सेटिङहरू खोली यसलाई निष्क्रिय पार्न ट्याप गर्नुहोस्।"</string>
     <string name="alert_windows_notification_turn_off_action" msgid="7805857234839123780">"निष्क्रिय पार्नुहोस्"</string>
     <string name="ext_media_checking_notification_title" msgid="8299199995416510094">"जाँच गर्दै <xliff:g id="NAME">%s</xliff:g>…"</string>
@@ -1643,7 +1643,7 @@
     <string name="accessibility_enable_service_encryption_warning" msgid="8603532708618236909">"तपाईंले <xliff:g id="SERVICE">%1$s</xliff:g> सक्रिय गर्नुभयो भने तपाईंको यन्त्रले डेटा इन्क्रिप्ट गर्ने सुविधाको स्तरोन्नति गर्न तपाईंको स्क्रिन लक सुविधाको प्रयोग गर्ने छैन।"</string>
     <string name="accessibility_service_warning_description" msgid="291674995220940133">"तपाईंलाई पहुँच राख्न आवश्यक पर्ने कुरामा सहयोग गर्ने अनुप्रयोगहरूमाथि पूर्ण नियन्त्रण गर्नु उपयुक्त हुन्छ तर अधिकांश अनुप्रयोगहरूका हकमा यस्तो नियन्त्रण उपयुक्त हुँदैन।"</string>
     <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"स्क्रिन हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string>
-    <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"यसले स्क्रिनमा देखिने सबै सामग्री पढ्न सक्छ र अन्य अनुप्रयोगहरूमा उक्त सामग्री देखाउन सक्छ।"</string>
+    <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"यसले स्क्रिनमा देखिने सबै सामग्री पढ्न सक्छ र अन्य एपहरूमा उक्त सामग्री देखाउन सक्छ।"</string>
     <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"कारबाहीहरू हेर्नुहोस् र तिनमा कार्य गर्नुहोस्"</string>
     <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"यसले कुनै एप वा हार्डवेयर सेन्सरसँग तपाईंले गर्ने अन्तर्क्रियाको ट्र्याक गर्न सक्छ र तपाईंका तर्फबाट एपहरूसँग अन्तर्क्रिया गर्न सक्छ।"</string>
     <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"अनुमति दिनुहोस्"</string>
@@ -1982,7 +1982,7 @@
     <string name="mmcc_illegal_me_msim_template" msgid="4802735138861422802">"SIM <xliff:g id="SIMNUMBER">%d</xliff:g> लाई अनुमति छैन"</string>
     <string name="popup_window_default_title" msgid="6907717596694826919">"पपअप विन्डो"</string>
     <string name="slice_more_content" msgid="3377367737876888459">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
-    <string name="shortcut_restored_on_lower_version" msgid="9206301954024286063">"या त अनुप्रयोगको संस्करण स्तरह्रास गरियो वा यो यस सर्टकटसँग मिल्दो छैन"</string>
+    <string name="shortcut_restored_on_lower_version" msgid="9206301954024286063">"या त एपको संस्करण स्तरह्रास गरियो वा यो यस सर्टकटसँग मिल्दो छैन"</string>
     <string name="shortcut_restore_not_supported" msgid="4763198938588468400">"अनुप्रयोगले ब्याकअप तथा पुनर्स्थापनालाई समर्थन नगर्ने हुँदा सर्टकट पुनर्स्थापित गर्न सकिएन"</string>
     <string name="shortcut_restore_signature_mismatch" msgid="579345304221605479">"अनुप्रयोगमा प्रयोग गरिने हस्ताक्षर नमिल्ने हुँदा सर्टकट पुनर्स्थापित गर्न सकिएन"</string>
     <string name="shortcut_restore_unknown_issue" msgid="2478146134395982154">"सर्टकट पुनर्स्थापित गर्न सकिएन"</string>
@@ -2004,7 +2004,7 @@
     <string name="notification_app_name_settings" msgid="9088548800899952531">"सेटिङहरू"</string>
     <string name="notification_appops_camera_active" msgid="8177643089272352083">"क्यामेरा"</string>
     <string name="notification_appops_microphone_active" msgid="581333393214739332">"माइक्रोफोन"</string>
-    <string name="notification_appops_overlay_active" msgid="5571732753262836481">"तपाईंको स्क्रिनका अन्य अनुप्रयोगहरूमा प्रदर्शन गरिँदै छ"</string>
+    <string name="notification_appops_overlay_active" msgid="5571732753262836481">"तपाईंको स्क्रिनका अन्य एपहरूमा प्रदर्शन गरिँदै छ"</string>
     <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"दिनचर्या मोडको जानकारीमूलक सूचना"</string>
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"प्रायः चार्ज गर्ने समय हुनुभन्दा पहिले नै ब्याट्री सकिन सक्छ"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ब्याट्रीको आयु बढाउन ब्याट्री सेभर सक्रिय गरियो"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 76864e9..3db4133 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1159,7 +1159,7 @@
     <string name="aerr_application_repeated" msgid="7804378743218496566">"<xliff:g id="APPLICATION">%1$s</xliff:g> continua a falhar"</string>
     <string name="aerr_process_repeated" msgid="1153152413537954974">"<xliff:g id="PROCESS">%1$s</xliff:g> continua a falhar"</string>
     <string name="aerr_restart" msgid="2789618625210505419">"Abrir app novamente"</string>
-    <string name="aerr_report" msgid="3095644466849299308">"Enviar comentários"</string>
+    <string name="aerr_report" msgid="3095644466849299308">"Enviar feedback"</string>
     <string name="aerr_close" msgid="3398336821267021852">"Fechar"</string>
     <string name="aerr_mute" msgid="2304972923480211376">"Desativar som até o dispositivo reiniciar"</string>
     <string name="aerr_wait" msgid="3198677780474548217">"Aguardar"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index d51c36f..492a83e 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1705,7 +1705,7 @@
     <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"Funkcie prepnete pridržaním tlačidla dostupnosti."</string>
     <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"Funkcie prepnete potiahnutím dvoma prstami nahor a pridržaním."</string>
     <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"Funkcie prepnete potiahnutím troma prstami nahor a pridržaním."</string>
-    <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Priblíženie"</string>
+    <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Zväčšenie"</string>
     <string name="user_switched" msgid="7249833311585228097">"Aktuálny používateľ je <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="user_switching_message" msgid="1912993630661332336">"Prepína sa na účet <xliff:g id="NAME">%1$s</xliff:g>…"</string>
     <string name="user_logging_out_message" msgid="7216437629179710359">"Prebieha odhlásenie používateľa <xliff:g id="NAME">%1$s</xliff:g>…"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 31346ea..b083cb8 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -2087,7 +2087,7 @@
     <string name="conversation_title_fallback_group_chat" msgid="456073374993104303">"Групна конверзација"</string>
     <string name="unread_convo_overflow" msgid="920517615597353833">"<xliff:g id="MAX_UNREAD_COUNT">%1$d</xliff:g>+"</string>
     <string name="resolver_personal_tab" msgid="2051260504014442073">"Лично"</string>
-    <string name="resolver_work_tab" msgid="2690019516263167035">"Пословни"</string>
+    <string name="resolver_work_tab" msgid="2690019516263167035">"Пословно"</string>
     <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Лични приказ"</string>
     <string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Приказ за посао"</string>
     <string name="resolver_cant_share_with_work_apps" msgid="637686613606502219">"Не можете да делите овај садржај помоћу апликација за посао"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 7135749..327d338 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1230,7 +1230,7 @@
     <string name="volume_icon_description_media" msgid="4997633254078171233">"మీడియా వాల్యూమ్"</string>
     <string name="volume_icon_description_notification" msgid="579091344110747279">"నోటిఫికేషన్ వాల్యూమ్"</string>
     <string name="ringtone_default" msgid="9118299121288174597">"డిఫాల్ట్ రింగ్‌టోన్"</string>
-    <string name="ringtone_default_with_actual" msgid="2709686194556159773">"డిఫాల్ట్ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <string name="ringtone_default_with_actual" msgid="2709686194556159773">"ఆటోమేటిక్ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
     <string name="ringtone_silent" msgid="397111123930141876">"ఏదీ వద్దు"</string>
     <string name="ringtone_picker_title" msgid="667342618626068253">"రింగ్‌టోన్‌లు"</string>
     <string name="ringtone_picker_title_alarm" msgid="7438934548339024767">"అలారం ధ్వనులు"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index f817696..087c8dd 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -857,7 +857,7 @@
     <string name="lockscreen_transport_stop_description" msgid="1449552232598355348">"Зупинити"</string>
     <string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"Перемотати назад"</string>
     <string name="lockscreen_transport_ffw_description" msgid="4763794746640196772">"Перемотати вперед"</string>
-    <string name="emergency_calls_only" msgid="3057351206678279851">"Лише аварійні виклики"</string>
+    <string name="emergency_calls_only" msgid="3057351206678279851">"Лише екстрені виклики"</string>
     <string name="lockscreen_network_locked_message" msgid="2814046965899249635">"Мережу заблок."</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="6618356415831082174">"SIM-карту заблоковано PUK."</string>
     <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"Перегляньте посібник користувача чи зверніться до служби підтримки."</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index b92bbd6..8a4676d 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -9230,4 +9230,7 @@
     </declare-styleable>
 
     <attr name="autoSizePresetSizes" />
+
+    <attr name="iconfactoryIconSize" format="dimension"/>
+    <attr name="iconfactoryBadgeSize" format="dimension"/>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 003c0da..ac808df 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -42,8 +42,10 @@
         <item><xliff:g id="id">@string/status_bar_phone_evdo_signal</xliff:g></item>
         <item><xliff:g id="id">@string/status_bar_phone_signal</xliff:g></item>
         <item><xliff:g id="id">@string/status_bar_secure</xliff:g></item>
+        <item><xliff:g id="id">@string/status_bar_media</xliff:g></item>
         <item><xliff:g id="id">@string/status_bar_managed_profile</xliff:g></item>
         <item><xliff:g id="id">@string/status_bar_cast</xliff:g></item>
+        <item><xliff:g id="id">@string/status_bar_screen_record</xliff:g></item>
         <item><xliff:g id="id">@string/status_bar_vpn</xliff:g></item>
         <item><xliff:g id="id">@string/status_bar_bluetooth</xliff:g></item>
         <item><xliff:g id="id">@string/status_bar_camera</xliff:g></item>
@@ -59,7 +61,6 @@
         <item><xliff:g id="id">@string/status_bar_airplane</xliff:g></item>
         <item><xliff:g id="id">@string/status_bar_battery</xliff:g></item>
         <item><xliff:g id="id">@string/status_bar_sensors_off</xliff:g></item>
-        <item><xliff:g id="id">@string/status_bar_screen_record</xliff:g></item>
     </string-array>
 
     <string translatable="false" name="status_bar_rotate">rotate</string>
@@ -96,6 +97,7 @@
     <string translatable="false" name="status_bar_airplane">airplane</string>
     <string translatable="false" name="status_bar_sensors_off">sensors_off</string>
     <string translatable="false" name="status_bar_screen_record">screen_record</string>
+    <string translatable="false" name="status_bar_media">media</string>
 
     <!-- Flag indicating whether the surface flinger has limited
          alpha compositing functionality in hardware.  If set, the window
@@ -3329,6 +3331,17 @@
     <!-- Controls the size of the back gesture inset. -->
     <dimen name="config_backGestureInset">0dp</dimen>
 
+    <!-- Array of values used in Gesture Navigation settings page to reduce/increase the back
+     gesture's inset size. These values will be multiplied into the default width, read from the
+     gesture navigation overlay package, in order to create 4 different sizes which are selectable
+     via a slider component. -->
+    <array name="config_backGestureInsetScales">
+        <item>0.75</item>
+        <item>1.00</item>
+        <item>1.33</item>
+        <item>1.66</item>
+    </array>
+
     <!-- Controls whether the navbar needs a scrim with
          {@link Window#setEnsuringNavigationBarContrastWhenTransparent}. -->
     <bool name="config_navBarNeedsScrim">true</bool>
@@ -4165,9 +4178,21 @@
      and a second time clipped to the fill level to indicate charge -->
     <bool name="config_batterymeterDualTone">false</bool>
 
-    <!-- The default peak refresh rate for a given device. Change this value if you want to allow
-         for higher refresh rates to be automatically used out of the box -->
-    <integer name="config_defaultPeakRefreshRate">60</integer>
+    <!-- The default refresh rate for a given device. Change this value to set a higher default
+         refresh rate. If the hardware composer on the device supports display modes with a higher
+         refresh rate than the default value specified here, the framework may use those higher
+         refresh rate modes if an app chooses one by setting preferredDisplayModeId or calling
+         setFrameRate().
+         If a non-zero value is set for config_defaultPeakRefreshRate, then
+         config_defaultRefreshRate may be set to 0, in which case the value set for
+         config_defaultPeakRefreshRate will act as the default frame rate. -->
+    <integer name="config_defaultRefreshRate">60</integer>
+
+    <!-- The default peak refresh rate for a given device. Change this value if you want to prevent
+         the framework from using higher refresh rates, even if display modes with higher refresh
+         rates are available from hardware composer. Only has an effect if the value is
+         non-zero. -->
+    <integer name="config_defaultPeakRefreshRate">0</integer>
 
     <!-- The display uses different gamma curves for different refresh rates. It's hard for panel
          vendor to tune the curves to have exact same brightness for different refresh rate. So
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 2ac61ec..c7ad5da 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -810,7 +810,8 @@
     <dimen name="chooser_header_scroll_elevation">4dp</dimen>
     <dimen name="chooser_max_collapsed_height">288dp</dimen>
     <dimen name="chooser_direct_share_label_placeholder_max_width">72dp</dimen>
-    <dimen name="chooser_icon_size">42dp</dimen>
+    <dimen name="chooser_icon_size">56dp</dimen>
+    <dimen name="chooser_badge_size">22dp</dimen>
     <dimen name="resolver_icon_size">32dp</dimen>
     <dimen name="resolver_button_bar_spacing">8dp</dimen>
     <dimen name="resolver_badge_size">18dp</dimen>
diff --git a/core/res/res/values/dimens_car.xml b/core/res/res/values/dimens_car.xml
index bd4c484..2c4f4c8 100644
--- a/core/res/res/values/dimens_car.xml
+++ b/core/res/res/values/dimens_car.xml
@@ -16,14 +16,7 @@
 */
 -->
 <resources>
-    <dimen name="car_fullscreen_user_pod_icon_text_size">64sp</dimen>
-    <dimen name="car_fullscreen_user_pod_width">243dp</dimen>
-    <dimen name="car_fullscreen_user_pod_height">356dp</dimen>
-    <dimen name="car_fullscreen_user_pod_image_avatar_width">96dp</dimen>
-    <dimen name="car_fullscreen_user_pod_image_avatar_height">96dp</dimen>
     <dimen name="car_large_avatar_size">96dp</dimen>
-
-
     <!-- Application Bar -->
     <dimen name="car_app_bar_height">80dp</dimen>
     <!-- Margin -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 35a7857..233f72ea 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -451,10 +451,14 @@
     <string name="personal_apps_suspension_text">
         Your personal apps are blocked until you turn on your work profile</string>
     <!-- Notification text. This notification lets a user know that their apps will be blocked
-        tomorrow due to a work policy from their IT admin, and that they need to turn on their work
-        profile to prevent the apps from being blocked. [CHAR LIMIT=NONE] -->
-    <string name="personal_apps_suspension_tomorrow_text">
-        Your personal apps will be blocked tomorrow</string>
+        at a particular time due to a work policy from their IT admin, and that they need to turn on
+        their work profile to prevent the apps from being blocked. It also explains for how many
+        days the profile is allowed to be off and this number is at least 3. [CHAR LIMIT=NONE] -->
+    <string name="personal_apps_suspension_soon_text">
+        Personal apps will be blocked on <xliff:g id="date" example="May 29">%1$s</xliff:g> at
+        <xliff:g id="time" example="5:20 PM">%2$s</xliff:g>. Your work profile can\u2019t stay off
+        for more than <xliff:g id="number" example="3">%3$d</xliff:g> days.
+    </string>
     <!-- Title for the button that turns work profile on. To be used in a notification
         [CHAR LIMIT=NONE] -->
     <string name="personal_apps_suspended_turn_profile_on">Turn on work profile</string>
@@ -1475,7 +1479,7 @@
     <string name="permdesc_mediaLocation">Allows the app to read locations from your media collection.</string>
 
     <!-- Title shown when the system-provided biometric dialog is shown, asking the user to authenticate. [CHAR LIMIT=40] -->
-    <string name="biometric_dialog_default_title">Verify it\u2018s you</string>
+    <string name="biometric_dialog_default_title">Verify it\u2019s you</string>
     <!-- Message shown when biometric hardware is not available [CHAR LIMIT=50] -->
     <string name="biometric_error_hw_unavailable">Biometric hardware unavailable</string>
     <!-- Message shown when biometric authentication was canceled by the user [CHAR LIMIT=50] -->
@@ -3595,31 +3599,37 @@
 
     <!-- Notification body when new external media is detected [CHAR LIMIT=30] -->
     <string name="ext_media_new_notification_title">New <xliff:g id="name" example="SD card">%s</xliff:g></string>
+    <!-- Automotive specific notification body when new external media is detected [CHAR LIMIT=30] -->
+    <string name="ext_media_new_notification_title" product="automotive"><xliff:g id="name" example="SD card">%s</xliff:g> isn\u2019t working</string>
     <!-- Notification body when new external media is detected [CHAR LIMIT=NONE] -->
     <string name="ext_media_new_notification_message">Tap to set up</string>
-    <!-- Automotive specific notification body when new external media is detected. Empty because there is no fix action (b/151671685) [CHAR LIMIT=NONE] -->
-    <string name="ext_media_new_notification_message" product="automotive"></string>
+    <!-- Automotive specific notification body when new external media is detected. [CHAR LIMIT=NONE] -->
+    <string name="ext_media_new_notification_message" product="automotive">You may need to reformat the device. Tap to eject.</string>
 
     <!-- Notification body when external media is ready for use [CHAR LIMIT=NONE] -->
     <string name="ext_media_ready_notification_message">For transferring photos and media</string>
 
     <!-- Notification title when external media is unmountable (corrupt) [CHAR LIMIT=30] -->
     <string name="ext_media_unmountable_notification_title">Issue with <xliff:g id="name" example="SD card">%s</xliff:g></string>
+    <!-- Automotive specific notification title when external media is unmountable (corrupt) [CHAR LIMIT=30] -->
+    <string name="ext_media_unmountable_notification_title" product="automotive"><xliff:g id="name" example="SD card">%s</xliff:g> isn\u2019t working</string>
     <!-- Notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] -->
     <string name="ext_media_unmountable_notification_message">Tap to fix</string>
     <!-- TV-specific notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] -->
     <string name="ext_media_unmountable_notification_message" product="tv"><xliff:g id="name" example="SD card">%s</xliff:g> is corrupt. Select to fix.</string>
-    <!-- Automotive specific notification body when external media is unmountable (corrupt). Empty because there is no fix action (b/151671685) [CHAR LIMIT=NONE] -->
-    <string name="ext_media_unmountable_notification_message" product="automotive"></string>
+    <!-- Automotive specific notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] -->
+    <string name="ext_media_unmountable_notification_message" product="automotive">You may need to reformat the device. Tap to eject.</string>
 
     <!-- Notification title when external media is unsupported [CHAR LIMIT=30] -->
     <string name="ext_media_unsupported_notification_title">Unsupported <xliff:g id="name" example="SD card">%s</xliff:g></string>
+    <!-- Automotive specific notification title when external media is unsupported [CHAR LIMIT=30] -->
+    <string name="ext_media_unsupported_notification_title" product="automotive"><xliff:g id="name" example="SD card">%s</xliff:g> isn\u2019t working</string>
     <!-- Notification body when external media is unsupported [CHAR LIMIT=NONE] -->
     <string name="ext_media_unsupported_notification_message">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Tap to set up in a supported format.</string>
     <!-- TV-specific notification body when external media is unsupported [CHAR LIMIT=NONE] -->
     <string name="ext_media_unsupported_notification_message" product="tv">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Select to set up in a supported format.</string>
-    <!-- Automotive specific notification body when external media is unsupported. No action is specified to fix (b/151671685) [CHAR LIMIT=NONE] -->
-    <string name="ext_media_unsupported_notification_message" product="automotive">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>.</string>
+    <!-- Automotive specific notification body when external media is unsupported [CHAR LIMIT=NONE] -->
+    <string name="ext_media_unsupported_notification_message" product="automotive">You may need to reformat the device</string>
 
     <!-- Notification title when external media is unsafely removed [CHAR LIMIT=30] -->
     <string name="ext_media_badremoval_notification_title"><xliff:g id="name" example="SD card">%s</xliff:g> unexpectedly removed</string>
@@ -4390,12 +4400,6 @@
     <!-- Used in multiple service warning to list current features. [CHAR LIMIT=none] -->
     <string name="accessibility_shortcut_multiple_service_list">\t• <xliff:g id="service" example="TalkBack">%1$s</xliff:g>\n</string>
 
-    <!-- Dialog title for dialog shown when the TalkBack shortcut is activated, and we want to confirm that the user understands what's going to happen. [CHAR LIMIT=none] -->
-    <string name="accessibility_shortcut_talkback_warning_title">Turn on TalkBack?</string>
-
-    <!-- Message shown in dialog when user is in the process of enabling the TalkBack via the volume buttons shortcut for the first time. [CHAR LIMIT=none] -->
-    <string name="accessibility_shortcut_talkback_warning">Holding down both volume keys for a few seconds turns on TalkBack, a screen reader that is helpful for people who are blind or have low vision. TalkBack completely changes how your device works.\n\nYou can change this shortcut to another feature in Settings > Accessibility.</string>
-
     <!-- Dialog title for dialog shown when this accessibility shortcut is activated, and we want to confirm that the user understands what's going to happen. [CHAR LIMIT=none] -->
     <string name="accessibility_shortcut_single_service_warning_title">Turn on <xliff:g id="service" example="TalkBack">%1$s</xliff:g>?</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 9f3ace5..758a4f7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1200,7 +1200,7 @@
   <java-symbol type="string" name="location_changed_notification_title" />
   <java-symbol type="string" name="location_changed_notification_text" />
   <java-symbol type="string" name="personal_apps_suspension_title" />
-  <java-symbol type="string" name="personal_apps_suspension_tomorrow_text" />
+  <java-symbol type="string" name="personal_apps_suspension_soon_text" />
   <java-symbol type="string" name="personal_apps_suspension_text" />
   <java-symbol type="string" name="personal_apps_suspended_turn_profile_on" />
   <java-symbol type="string" name="notification_work_profile_content_description" />
@@ -2534,6 +2534,7 @@
   <java-symbol type="style" name="TextAppearance.Material.TimePicker.TimeLabel" />
   <java-symbol type="attr" name="seekBarPreferenceStyle" />
   <java-symbol type="style" name="Theme.DeviceDefault.Resolver" />
+  <java-symbol type="style" name="Theme.DeviceDefault.Chooser" />
   <java-symbol type="style" name="Theme.DeviceDefault.System" />
   <java-symbol type="attr" name="preferenceActivityStyle" />
   <java-symbol type="attr" name="preferenceFragmentStyle" />
@@ -2744,6 +2745,10 @@
   <java-symbol type="id" name="chooser_row_text_option" />
   <java-symbol type="dimen" name="chooser_row_text_option_translate" />
   <java-symbol type="dimen" name="chooser_preview_image_max_dimen"/>
+  <java-symbol type="drawable" name="ic_chooser_group_arrow"/>
+  <java-symbol type="drawable" name="chooser_group_background"/>
+  <java-symbol type="drawable" name="ic_chooser_pin"/>
+  <java-symbol type="drawable" name="chooser_pinned_background"/>
   <java-symbol type="integer" name="config_maxShortcutTargetsPerApp" />
   <java-symbol type="layout" name="resolve_grid_item" />
   <java-symbol type="id" name="day_picker_view_pager" />
@@ -2813,6 +2818,7 @@
   <java-symbol type="bool" name="config_navBarNeedsScrim" />
   <java-symbol type="bool" name="config_allowSeamlessRotationDespiteNavBarMoving" />
   <java-symbol type="dimen" name="config_backGestureInset" />
+  <java-symbol type="array" name="config_backGestureInsetScales" />
   <java-symbol type="color" name="system_bar_background_semi_transparent" />
   <java-symbol type="bool" name="config_showGesturalNavigationHints" />
 
@@ -2910,6 +2916,7 @@
   <java-symbol type="string" name="status_bar_camera" />
   <java-symbol type="string" name="status_bar_sensors_off" />
   <java-symbol type="string" name="status_bar_screen_record" />
+  <java-symbol type="string" name="status_bar_media" />
 
   <!-- Locale picker -->
   <java-symbol type="id" name="locale_search_menu" />
@@ -3221,12 +3228,15 @@
   <java-symbol type="integer" name="config_debugSystemServerPssThresholdBytes" />
 
   <!-- Accessibility Shortcut -->
-  <java-symbol type="string" name="accessibility_shortcut_warning_dialog_title" />
-  <java-symbol type="string" name="accessibility_shortcut_toogle_warning" />
+  <java-symbol type="string" name="accessibility_shortcut_single_service_warning_title" />
+  <java-symbol type="string" name="accessibility_shortcut_single_service_warning" />
+  <java-symbol type="string" name="accessibility_shortcut_multiple_service_warning_title" />
+  <java-symbol type="string" name="accessibility_shortcut_multiple_service_warning" />
+  <java-symbol type="string" name="accessibility_shortcut_multiple_service_list" />
+  <java-symbol type="string" name="accessibility_shortcut_on" />
+  <java-symbol type="string" name="accessibility_shortcut_off" />
   <java-symbol type="string" name="accessibility_shortcut_enabling_service" />
   <java-symbol type="string" name="accessibility_shortcut_disabling_service" />
-  <java-symbol type="string" name="disable_accessibility_shortcut" />
-  <java-symbol type="string" name="leave_accessibility_shortcut_on" />
   <java-symbol type="string" name="color_inversion_feature_name" />
   <java-symbol type="string" name="color_correction_feature_name" />
   <java-symbol type="string" name="config_defaultAccessibilityService" />
@@ -3635,13 +3645,6 @@
   <java-symbol type="color" name="car_card_dark" />
   <java-symbol type="dimen" name="car_body1_size" />
   <java-symbol type="dimen" name="car_padding_4" />
-  <java-symbol type="dimen" name="car_fullscreen_user_pod_icon_text_size" />
-  <java-symbol type="dimen" name="car_fullscreen_user_pod_image_avatar_height" />
-  <java-symbol type="dimen" name="car_fullscreen_user_pod_image_avatar_width" />
-  <java-symbol type="dimen" name="car_large_avatar_size" />
-  <java-symbol type="layout" name="car_user_switching_dialog" />
-  <java-symbol type="id" name="user_loading_avatar" />
-  <java-symbol type="id" name="user_loading" />
   <java-symbol type="style" name="Theme.DeviceDefault.Light.Dialog.Alert.UserSwitchingDialog" />
 
   <java-symbol type="string" name="battery_saver_description_with_learn_more" />
@@ -3773,6 +3776,7 @@
   <java-symbol type="string" name="bluetooth_airplane_mode_toast" />
 
   <!-- For high refresh rate displays -->
+  <java-symbol type="integer" name="config_defaultRefreshRate" />
   <java-symbol type="integer" name="config_defaultPeakRefreshRate" />
   <java-symbol type="integer" name="config_defaultRefreshRateInZone" />
   <java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" />
@@ -3781,8 +3785,11 @@
   <!-- For Auto-Brightness -->
   <java-symbol type="string" name="config_displayLightSensorType" />
 
-  <java-symbol type="drawable" name="iconfactory_adaptive_icon_drawable_wrapper"/>
   <java-symbol type="dimen" name="notification_min_height" />
+
+  <java-symbol type="drawable" name="iconfactory_adaptive_icon_drawable_wrapper"/>
+  <java-symbol type="attr" name="iconfactoryIconSize"/>
+  <java-symbol type="attr" name="iconfactoryBadgeSize"/>
   <java-symbol type="dimen" name="resolver_icon_size"/>
   <java-symbol type="dimen" name="resolver_badge_size"/>
   <java-symbol type="dimen" name="resolver_button_bar_spacing"/>
@@ -3791,6 +3798,7 @@
   <java-symbol type="dimen" name="resolver_edge_margin"/>
   <java-symbol type="dimen" name="resolver_elevation"/>
   <java-symbol type="dimen" name="chooser_icon_size"/>
+  <java-symbol type="dimen" name="chooser_badge_size"/>
 
   <!-- For DropBox -->
   <java-symbol type="integer" name="config_dropboxLowPriorityBroadcastRateLimitPeriod" />
@@ -4016,4 +4024,5 @@
   <java-symbol type="string" name="config_pdp_reject_user_authentication_failed" />
   <java-symbol type="string" name="config_pdp_reject_service_not_subscribed" />
   <java-symbol type="string" name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" />
+
 </resources>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 81ec278..1afaf4f 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -1680,6 +1680,8 @@
         <item name="listPreferredItemPaddingEnd">?attr/dialogPreferredPadding</item>
         <item name="navigationBarColor">@android:color/transparent</item>
         <item name="tabWidgetStyle">@style/Widget.DeviceDefault.Resolver.TabWidget</item>
+        <item name="iconfactoryIconSize">@dimen/resolver_icon_size</item>
+        <item name="iconfactoryBadgeSize">@dimen/resolver_badge_size</item>
     </style>
 
     <style name="Widget.DeviceDefault.Resolver.TabWidget" parent="Widget.DeviceDefault.TabWidget">
@@ -1694,6 +1696,11 @@
         <item name="windowLightNavigationBar">true</item>
     </style>
 
+    <style name="Theme.DeviceDefault.Chooser" parent="Theme.DeviceDefault.Resolver">
+        <item name="iconfactoryIconSize">@dimen/chooser_icon_size</item>
+        <item name="iconfactoryBadgeSize">@dimen/chooser_badge_size</item>
+    </style>
+
     <style name="Animation.DeviceDefault.Activity.Resolver" parent="Animation.DeviceDefault.Activity">
         <item name="activityOpenEnterAnimation">@anim/resolver_launch_anim</item>
         <item name="taskOpenEnterAnimation">@anim/resolver_launch_anim</item>
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index a93dacf..000e870 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -20,6 +20,7 @@
 import static android.content.Intent.ACTION_VIEW;
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.view.Display.INVALID_DISPLAY;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -29,6 +30,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.testng.Assert.assertFalse;
 
+import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.ActivityThread;
 import android.app.IApplicationThread;
@@ -38,6 +40,7 @@
 import android.app.servertransaction.ActivityRelaunchItem;
 import android.app.servertransaction.ClientTransaction;
 import android.app.servertransaction.ClientTransactionItem;
+import android.app.servertransaction.ConfigurationChangeItem;
 import android.app.servertransaction.NewIntentItem;
 import android.app.servertransaction.ResumeActivityItem;
 import android.app.servertransaction.StopActivityItem;
@@ -225,7 +228,7 @@
     }
 
     @Test
-    public void testHandleActivityConfigurationChanged_PickNewerPendingConfiguration() {
+    public void testHandleActivityConfigurationChanged_SkipWhenNewerConfigurationPending() {
         final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
@@ -237,26 +240,91 @@
 
             final ActivityThread activityThread = activity.getActivityThread();
 
-            final Configuration pendingConfig = new Configuration();
-            pendingConfig.orientation = orientation == ORIENTATION_LANDSCAPE
-                    ? ORIENTATION_PORTRAIT
-                    : ORIENTATION_LANDSCAPE;
-            pendingConfig.seq = seq + 2;
+            final Configuration newerConfig = new Configuration();
+            newerConfig.orientation = orientation == ORIENTATION_LANDSCAPE
+                    ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
+            newerConfig.seq = seq + 2;
             activityThread.updatePendingActivityConfiguration(activity.getActivityToken(),
-                    pendingConfig);
+                    newerConfig);
 
-            final Configuration newConfig = new Configuration();
-            newConfig.orientation = orientation;
-            newConfig.seq = seq + 1;
+            final Configuration olderConfig = new Configuration();
+            olderConfig.orientation = orientation;
+            olderConfig.seq = seq + 1;
 
             activityThread.handleActivityConfigurationChanged(activity.getActivityToken(),
-                    newConfig, Display.INVALID_DISPLAY);
+                    olderConfig, INVALID_DISPLAY);
+            assertEquals(numOfConfig, activity.mNumOfConfigChanges);
+            assertEquals(olderConfig.orientation, activity.mConfig.orientation);
+
+            activityThread.handleActivityConfigurationChanged(activity.getActivityToken(),
+                    newerConfig, INVALID_DISPLAY);
             assertEquals(numOfConfig + 1, activity.mNumOfConfigChanges);
-            assertEquals(pendingConfig.orientation, activity.mConfig.orientation);
+            assertEquals(newerConfig.orientation, activity.mConfig.orientation);
         });
     }
 
     @Test
+    public void testHandleActivityConfigurationChanged_EnsureUpdatesProcessedInOrder()
+            throws Exception {
+        final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
+
+        final ActivityThread activityThread = activity.getActivityThread();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            final Configuration config = new Configuration();
+            config.seq = BASE_SEQ;
+            config.orientation = ORIENTATION_PORTRAIT;
+
+            activityThread.handleActivityConfigurationChanged(activity.getActivityToken(),
+                    config, INVALID_DISPLAY);
+        });
+
+        final IApplicationThread appThread = activityThread.getApplicationThread();
+        final int numOfConfig = activity.mNumOfConfigChanges;
+
+        final Configuration processConfigLandscape = new Configuration();
+        processConfigLandscape.windowConfiguration.setBounds(new Rect(0, 0, 100, 60));
+        processConfigLandscape.seq = BASE_SEQ + 1;
+
+        final Configuration activityConfigLandscape = new Configuration();
+        activityConfigLandscape.windowConfiguration.setBounds(new Rect(0, 0, 100, 50));
+        activityConfigLandscape.seq = BASE_SEQ + 2;
+
+        final Configuration processConfigPortrait = new Configuration();
+        processConfigPortrait.windowConfiguration.setBounds(new Rect(0, 0, 60, 100));
+        processConfigPortrait.seq = BASE_SEQ + 3;
+
+        final Configuration activityConfigPortrait = new Configuration();
+        activityConfigPortrait.windowConfiguration.setBounds(new Rect(0, 0, 50, 100));
+        activityConfigPortrait.seq = BASE_SEQ + 4;
+
+        activity.mConfigLatch = new CountDownLatch(1);
+        activity.mTestLatch = new CountDownLatch(1);
+
+        ClientTransaction transaction = newTransaction(activityThread, null);
+        transaction.addCallback(ConfigurationChangeItem.obtain(processConfigLandscape));
+        appThread.scheduleTransaction(transaction);
+
+        transaction = newTransaction(activityThread, activity.getActivityToken());
+        transaction.addCallback(ActivityConfigurationChangeItem.obtain(activityConfigLandscape));
+        transaction.addCallback(ConfigurationChangeItem.obtain(processConfigPortrait));
+        transaction.addCallback(ActivityConfigurationChangeItem.obtain(activityConfigPortrait));
+        appThread.scheduleTransaction(transaction);
+
+        activity.mTestLatch.await();
+        activity.mConfigLatch.countDown();
+
+        activity.mConfigLatch = null;
+        activity.mTestLatch = null;
+
+        // Check display metrics, bounds should match the portrait activity bounds.
+        final Rect bounds = activity.getWindowManager().getCurrentWindowMetrics().getBounds();
+        assertEquals(activityConfigPortrait.windowConfiguration.getBounds(), bounds);
+
+        // Ensure that Activity#onConfigurationChanged() is only called once.
+        assertEquals(numOfConfig + 1, activity.mNumOfConfigChanges);
+    }
+
+    @Test
     public void testHandleActivityConfigurationChanged_OnlyAppliesNewestConfiguration()
             throws Exception {
         final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
@@ -268,7 +336,7 @@
             config.orientation = ORIENTATION_PORTRAIT;
 
             activityThread.handleActivityConfigurationChanged(activity.getActivityToken(),
-                    config, Display.INVALID_DISPLAY);
+                    config, INVALID_DISPLAY);
         });
 
         final int numOfConfig = activity.mNumOfConfigChanges;
@@ -504,7 +572,7 @@
         config.orientation = ORIENTATION_PORTRAIT;
         config.seq = seq;
         activityThread.handleActivityConfigurationChanged(activity.getActivityToken(), config,
-                Display.INVALID_DISPLAY);
+                INVALID_DISPLAY);
 
         if (activity.mNumOfConfigChanges > numOfConfig) {
             return config.seq;
@@ -514,7 +582,7 @@
         config.orientation = ORIENTATION_LANDSCAPE;
         config.seq = seq + 1;
         activityThread.handleActivityConfigurationChanged(activity.getActivityToken(), config,
-                Display.INVALID_DISPLAY);
+                INVALID_DISPLAY);
 
         return config.seq;
     }
@@ -572,8 +640,12 @@
     }
 
     private static ClientTransaction newTransaction(Activity activity) {
-        final IApplicationThread appThread = activity.getActivityThread().getApplicationThread();
-        return ClientTransaction.obtain(appThread, activity.getActivityToken());
+        return newTransaction(activity.getActivityThread(), activity.getActivityToken());
+    }
+
+    private static ClientTransaction newTransaction(ActivityThread activityThread,
+            @Nullable IBinder activityToken) {
+        return ClientTransaction.obtain(activityThread.getApplicationThread(), activityToken);
     }
 
     // Test activity
diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
index 107fe3f..4654f63 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
@@ -63,7 +63,8 @@
 
     @Test
     public void testRecycleActivityConfigurationChangeItem() {
-        ActivityConfigurationChangeItem emptyItem = ActivityConfigurationChangeItem.obtain(null);
+        ActivityConfigurationChangeItem emptyItem =
+                ActivityConfigurationChangeItem.obtain(Configuration.EMPTY);
         ActivityConfigurationChangeItem item = ActivityConfigurationChangeItem.obtain(config());
         assertNotSame(item, emptyItem);
         assertFalse(item.equals(emptyItem));
@@ -144,11 +145,12 @@
         IBinder assistToken = new Binder();
 
         LaunchActivityItem emptyItem = LaunchActivityItem.obtain(null, 0, null, null, null, null,
-                null, null, 0, null, null, null, null, false, null, null);
+                null, null, 0, null, null, null, null, false, null, null, null);
         LaunchActivityItem item = LaunchActivityItem.obtain(intent, ident, activityInfo,
                 config(), overrideConfig, compat, referrer, null /* voiceInteractor */,
                 procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(),
-                true /* isForward */, null /* profilerInfo */, assistToken);
+                true /* isForward */, null /* profilerInfo */, assistToken,
+                null /* fixedRotationAdjustments */);
         assertNotSame(item, emptyItem);
         assertFalse(item.equals(emptyItem));
 
@@ -158,7 +160,8 @@
         LaunchActivityItem item2 = LaunchActivityItem.obtain(intent, ident, activityInfo,
                 config(), overrideConfig, compat, referrer, null /* voiceInteractor */,
                 procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(),
-                true /* isForward */, null /* profilerInfo */, assistToken);
+                true /* isForward */, null /* profilerInfo */, assistToken,
+                null /* fixedRotationAdjustments */);
         assertSame(item, item2);
         assertFalse(item2.equals(emptyItem));
     }
@@ -184,7 +187,7 @@
 
     @Test
     public void testRecycleMoveToDisplayItem() {
-        MoveToDisplayItem emptyItem = MoveToDisplayItem.obtain(0, null);
+        MoveToDisplayItem emptyItem = MoveToDisplayItem.obtain(0, Configuration.EMPTY);
         MoveToDisplayItem item = MoveToDisplayItem.obtain(4, config());
         assertNotSame(item, emptyItem);
         assertFalse(item.equals(emptyItem));
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
index 09ea1b1..3c32c71 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
@@ -267,7 +267,7 @@
                 null /* voiceInteractor */, 0 /* procState */, null /* state */,
                 null /* persistentState */, null /* pendingResults */,
                 null /* pendingNewIntents */, false /* isForward */, null /* profilerInfo */,
-                null /* assistToken*/));
+                null /* assistToken */, null /* fixedRotationAdjustments */));
         launchTransaction.addCallback(launchItem);
         mExecutor.execute(launchTransaction);
 
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index 47f9323..f11adef 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -52,6 +52,9 @@
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
+import android.view.DisplayCutout;
+import android.view.Surface;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -187,11 +190,14 @@
         bundle.putParcelable("data", new ParcelableData(1));
         PersistableBundle persistableBundle = new PersistableBundle();
         persistableBundle.putInt("k", 4);
+        FixedRotationAdjustments fixedRotationAdjustments = new FixedRotationAdjustments(
+                Surface.ROTATION_90, DisplayCutout.NO_CUTOUT);
 
         LaunchActivityItem item = LaunchActivityItem.obtain(intent, ident, activityInfo,
                 config(), overrideConfig, compat, referrer, null /* voiceInteractor */,
                 procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(),
-                true /* isForward */, null /* profilerInfo */, new Binder());
+                true /* isForward */, null /* profilerInfo */, new Binder(),
+                fixedRotationAdjustments);
         writeAndPrepareForReading(item);
 
         // Read from parcel and assert
@@ -340,6 +346,22 @@
         assertTrue(transaction.equals(result));
     }
 
+    @Test
+    public void testFixedRotationAdjustments() {
+        ClientTransaction transaction = ClientTransaction.obtain(new StubAppThread(),
+                null /* activityToken */);
+        transaction.addCallback(FixedRotationAdjustmentsItem.obtain(new Binder(),
+                new FixedRotationAdjustments(Surface.ROTATION_270, DisplayCutout.NO_CUTOUT)));
+
+        writeAndPrepareForReading(transaction);
+
+        // Read from parcel and assert
+        ClientTransaction result = ClientTransaction.CREATOR.createFromParcel(mParcel);
+
+        assertEquals(transaction.hashCode(), result.hashCode());
+        assertTrue(transaction.equals(result));
+    }
+
     /** Write to {@link #mParcel} and reset its position to prepare for reading from the start. */
     private void writeAndPrepareForReading(Parcelable parcelable) {
         parcelable.writeToParcel(mParcel, 0 /* flags */);
@@ -541,6 +563,11 @@
         }
 
         @Override
+        public void dumpCacheInfo(ParcelFileDescriptor parcelFileDescriptor, String[] strings)
+                throws RemoteException {
+        }
+
+        @Override
         public void dumpProvider(ParcelFileDescriptor parcelFileDescriptor, IBinder iBinder,
                 String[] strings) throws RemoteException {
         }
diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsPersistenceTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsPersistenceTest.java
new file mode 100644
index 0000000..4d04a7a
--- /dev/null
+++ b/core/tests/coretests/src/android/app/usage/UsageStatsPersistenceTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.app.usage;
+
+import static junit.framework.Assert.fail;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.ArrayUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+
+/**
+ * These tests verify that all fields defined in {@link UsageStats} and {@link UsageEvents.Event}
+ * are all known fields. This ensures that newly added fields or refactorings are accounted for in
+ * the usagestatsservice.proto and usagestatsservice_v2.proto files.
+ *
+ * Note: verification for {@link com.android.server.usage.IntervalStats} fields is located in
+ * {@link com.android.server.usage.IntervalStatsTests}.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class UsageStatsPersistenceTest {
+
+    // All fields in this list are defined in UsageStats and persisted - please ensure they're
+    // defined correctly in both usagestatsservice.proto and usagestatsservice_v2.proto
+    private static final String[] USAGESTATS_PERSISTED_FIELDS = {"mBeginTimeStamp", "mEndTimeStamp",
+            "mPackageName", "mPackageToken", "mLastEvent", "mAppLaunchCount", "mChooserCounts",
+            "mLastTimeUsed", "mTotalTimeInForeground", "mLastTimeForegroundServiceUsed",
+            "mTotalTimeForegroundServiceUsed", "mLastTimeVisible", "mTotalTimeVisible"};
+    // All fields in this list are defined in UsageStats but not persisted
+    private static final String[] USAGESTATS_IGNORED_FIELDS = {"CREATOR", "mActivities",
+            "mForegroundServices", "mLaunchCount", "mChooserCountsObfuscated"};
+
+    @Test
+    public void testUsageStatsFields() {
+        final UsageStats stats = new UsageStats();
+        final Field[] fields = stats.getClass().getDeclaredFields();
+        for (Field field : fields) {
+            if (!(ArrayUtils.contains(USAGESTATS_PERSISTED_FIELDS, field.getName())
+                    || ArrayUtils.contains(USAGESTATS_IGNORED_FIELDS, field.getName()))) {
+                fail("Found an unknown field: " + field.getName() + ". Please correctly update "
+                        + "either USAGESTATS_PERSISTED_FIELDS or USAGESTATS_IGNORED_FIELDS.");
+            }
+        }
+    }
+
+    // All fields in this list are defined in UsageEvents.Event and persisted - please ensure
+    // they're defined correctly in both usagestatsservice.proto and usagestatsservice_v2.proto
+    private static final String[] USAGEEVENTS_PERSISTED_FIELDS = {"mPackage", "mPackageToken",
+            "mClass", "mClassToken", "mTimeStamp", "mFlags", "mEventType", "mConfiguration",
+            "mShortcutId", "mShortcutIdToken", "mBucketAndReason", "mInstanceId",
+            "mNotificationChannelId", "mNotificationChannelIdToken", "mTaskRootPackage",
+            "mTaskRootPackageToken", "mTaskRootClass", "mTaskRootClassToken", "mLocusId",
+            "mLocusIdToken"};
+    // All fields in this list are defined in UsageEvents.Event but not persisted
+    private static final String[] USAGEEVENTS_IGNORED_FIELDS = {"mAction", "mContentAnnotations",
+            "mContentType", "DEVICE_EVENT_PACKAGE_NAME", "FLAG_IS_PACKAGE_INSTANT_APP",
+            "VALID_FLAG_BITS", "UNASSIGNED_TOKEN", "MAX_EVENT_TYPE"};
+    // All fields in this list are final constants defining event types and not persisted
+    private static final String[] EVENT_TYPES = {"NONE", "ACTIVITY_DESTROYED", "ACTIVITY_PAUSED",
+            "ACTIVITY_RESUMED", "ACTIVITY_STOPPED", "CHOOSER_ACTION", "CONFIGURATION_CHANGE",
+            "CONTINUE_PREVIOUS_DAY", "CONTINUING_FOREGROUND_SERVICE", "DEVICE_SHUTDOWN",
+            "DEVICE_STARTUP", "END_OF_DAY", "FLUSH_TO_DISK", "FOREGROUND_SERVICE_START",
+            "FOREGROUND_SERVICE_STOP", "KEYGUARD_HIDDEN", "KEYGUARD_SHOWN", "LOCUS_ID_SET",
+            "MOVE_TO_BACKGROUND", "MOVE_TO_FOREGROUND", "NOTIFICATION_INTERRUPTION",
+            "NOTIFICATION_SEEN", "ROLLOVER_FOREGROUND_SERVICE", "SCREEN_INTERACTIVE",
+            "SCREEN_NON_INTERACTIVE", "SHORTCUT_INVOCATION", "SLICE_PINNED", "SLICE_PINNED_PRIV",
+            "STANDBY_BUCKET_CHANGED", "SYSTEM_INTERACTION", "USER_INTERACTION", "USER_STOPPED",
+            "USER_UNLOCKED"};
+
+    @Test
+    public void testUsageEventsFields() {
+        final UsageEvents.Event event = new UsageEvents.Event();
+        final Field[] fields = event.getClass().getDeclaredFields();
+        for (Field field : fields) {
+            final String name = field.getName();
+            if (!(ArrayUtils.contains(USAGEEVENTS_PERSISTED_FIELDS, name)
+                    || ArrayUtils.contains(USAGEEVENTS_IGNORED_FIELDS, name)
+                    || ArrayUtils.contains(EVENT_TYPES, name))) {
+                fail("Found an unknown field: " + name + ". Please correctly update either "
+                        + "USAGEEVENTS_PERSISTED_FIELDS or USAGEEVENTS_IGNORED_FIELDS. If this "
+                        + "field is a new event type, please update EVENT_TYPES instead.");
+            }
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
index 4114b28..efcd458 100644
--- a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
+++ b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
@@ -259,4 +259,35 @@
         expectedConfig2.orientation = Configuration.ORIENTATION_LANDSCAPE;
         assertEquals(expectedConfig2, resources2.getConfiguration());
     }
+
+    @SmallTest
+    public void testOverrideDisplayAdjustments() {
+        final int originalOverrideDensity = 200;
+        final int overrideDisplayDensity = 400;
+        final Binder token = new Binder();
+        final Configuration overrideConfig = new Configuration();
+        overrideConfig.densityDpi = originalOverrideDensity;
+        final Resources resources = mResourcesManager.createBaseTokenResources(
+                token, APP_ONE_RES_DIR, null /* splitResDirs */, null /* overlayDirs */,
+                null /* libDirs */, Display.DEFAULT_DISPLAY, overrideConfig,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null /* classLoader */,
+                null /* loaders */);
+
+        // Update the override.
+        boolean handled = mResourcesManager.overrideTokenDisplayAdjustments(token,
+                adjustments -> adjustments.getConfiguration().densityDpi = overrideDisplayDensity);
+
+        assertTrue(handled);
+        assertTrue(resources.hasOverrideDisplayAdjustments());
+        assertEquals(overrideDisplayDensity,
+                resources.getDisplayAdjustments().getConfiguration().densityDpi);
+
+        // Clear the override.
+        handled = mResourcesManager.overrideTokenDisplayAdjustments(token, null /* override */);
+
+        assertTrue(handled);
+        assertFalse(resources.hasOverrideDisplayAdjustments());
+        assertEquals(originalOverrideDensity,
+                resources.getDisplayAdjustments().getConfiguration().densityDpi);
+    }
 }
diff --git a/core/tests/coretests/src/android/debug/AdbNotificationsTest.java b/core/tests/coretests/src/android/debug/AdbNotificationsTest.java
index 6c187ea..3496e2c 100644
--- a/core/tests/coretests/src/android/debug/AdbNotificationsTest.java
+++ b/core/tests/coretests/src/android/debug/AdbNotificationsTest.java
@@ -56,8 +56,11 @@
         // Verify that the adb notification for usb connections has the correct text.
         assertEquals(title, notification.extras.getCharSequence(Notification.EXTRA_TITLE, ""));
         assertEquals(message, notification.extras.getCharSequence(Notification.EXTRA_TEXT, ""));
-        // Verify the PendingIntent has an explicit intent (b/153356209).
-        assertFalse(TextUtils.isEmpty(notification.contentIntent.getIntent().getPackage()));
+        // Verify the PendingIntent has an explicit intent (b/153356209), if there is a
+        // PendingIntent attached.
+        if (notification.contentIntent != null) {
+            assertFalse(TextUtils.isEmpty(notification.contentIntent.getIntent().getPackage()));
+        }
     }
 
     @Test
@@ -73,7 +76,10 @@
         // Verify that the adb notification for usb connections has the correct text.
         assertEquals(title, notification.extras.getCharSequence(Notification.EXTRA_TITLE, ""));
         assertEquals(message, notification.extras.getCharSequence(Notification.EXTRA_TEXT, ""));
-        // Verify the PendingIntent has an explicit intent (b/153356209).
-        assertFalse(TextUtils.isEmpty(notification.contentIntent.getIntent().getPackage()));
+        // Verify the PendingIntent has an explicit intent (b/153356209), if there is a
+        // PendingIntent attached.
+        if (notification.contentIntent != null) {
+            assertFalse(TextUtils.isEmpty(notification.contentIntent.getIntent().getPackage()));
+        }
     }
 }
diff --git a/core/tests/coretests/src/android/hardware/display/OWNERS b/core/tests/coretests/src/android/hardware/display/OWNERS
new file mode 100644
index 0000000..9ca3910
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/display/OWNERS
@@ -0,0 +1,2 @@
+michaelwr@google.com
+santoscordon@google.com
diff --git a/core/tests/coretests/src/android/os/OWNERS b/core/tests/coretests/src/android/os/OWNERS
new file mode 100644
index 0000000..1a28b73
--- /dev/null
+++ b/core/tests/coretests/src/android/os/OWNERS
@@ -0,0 +1,9 @@
+# Display
+per-file BrightnessLimit.java = michaelwr@google.com, santoscordon@google.com
+
+# Haptics
+per-file ExternalVibrationTest.java = michaelwr@google.com
+per-file VibrationEffectTest.java = michaelwr@google.com
+
+# Power
+per-file PowerManager*.java = michaelwr@google.com, santoscordon@google.com
diff --git a/core/tests/coretests/src/android/view/DisplayAdjustmentsTests.java b/core/tests/coretests/src/android/view/DisplayAdjustmentsTests.java
index afbf8db..2fc42e9 100644
--- a/core/tests/coretests/src/android/view/DisplayAdjustmentsTests.java
+++ b/core/tests/coretests/src/android/view/DisplayAdjustmentsTests.java
@@ -19,6 +19,9 @@
 import static org.junit.Assert.assertEquals;
 
 import android.content.res.Configuration;
+import android.graphics.Point;
+import android.util.DisplayMetrics;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
@@ -67,4 +70,38 @@
 
         assertEquals(configuration, newAdjustments.getConfiguration());
     }
+
+    @Test
+    public void testFixedRotationAdjustments() {
+        final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
+        final int realRotation = Surface.ROTATION_0;
+        final int fixedRotation = Surface.ROTATION_90;
+
+        mDisplayAdjustments.setFixedRotationAdjustments(
+                new FixedRotationAdjustments(fixedRotation, null /* cutout */));
+
+        final int w = 1000;
+        final int h = 2000;
+        final Point size = new Point(w, h);
+        mDisplayAdjustments.adjustSize(size, realRotation);
+
+        assertEquals(fixedRotation, mDisplayAdjustments.getRotation(realRotation));
+        assertEquals(new Point(h, w), size);
+
+        final DisplayMetrics metrics = new DisplayMetrics();
+        metrics.xdpi = metrics.noncompatXdpi = w;
+        metrics.widthPixels = metrics.noncompatWidthPixels = w;
+        metrics.ydpi = metrics.noncompatYdpi = h;
+        metrics.heightPixels = metrics.noncompatHeightPixels = h;
+
+        final DisplayMetrics flippedMetrics = new DisplayMetrics();
+        flippedMetrics.xdpi = flippedMetrics.noncompatXdpi = h;
+        flippedMetrics.widthPixels = flippedMetrics.noncompatWidthPixels = h;
+        flippedMetrics.ydpi = flippedMetrics.noncompatYdpi = w;
+        flippedMetrics.heightPixels = flippedMetrics.noncompatHeightPixels = w;
+
+        mDisplayAdjustments.adjustMetrics(metrics, realRotation);
+
+        assertEquals(flippedMetrics, metrics);
+    }
 }
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index 5f12bf0..8eca650 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -26,11 +26,8 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 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.doAnswer;
-import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -98,8 +95,6 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        doNothing().when(mMockController).updateCompatSysUiVisibility(
-                anyInt(), anyBoolean(), anyBoolean());
         mTopLeash = new SurfaceControl.Builder(mSession)
                 .setName("testSurface")
                 .build();
diff --git a/core/tests/coretests/src/android/view/OWNERS b/core/tests/coretests/src/android/view/OWNERS
new file mode 100644
index 0000000..a3a3e7c
--- /dev/null
+++ b/core/tests/coretests/src/android/view/OWNERS
@@ -0,0 +1,4 @@
+# Input
+per-file *MotionEventTest.* = michaelwr@google.com, svv@google.com
+per-file *KeyEventTest.* = michaelwr@google.com, svv@google.com
+per-file VelocityTest.java = michaelwr@google.com, svv@google.com
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index ecc3b4f..5c16772 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -28,29 +28,23 @@
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 
-import static org.hamcrest.Matchers.equalTo;
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assume.assumeTrue;
+import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
-import android.graphics.Insets;
-import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.view.WindowInsets.Side;
 import android.view.WindowInsets.Type;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
-import androidx.test.platform.app.InstrumentationRegistry;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
 /**
  * Tests for {@link ViewRootImpl}
  *
@@ -62,59 +56,18 @@
 @RunWith(AndroidJUnit4.class)
 public class ViewRootImplTest {
 
-    private Context mContext;
-    private ViewRootImplAccessor mViewRootImpl;
+    private ViewRootImpl mViewRootImpl;
 
     @Before
     public void setUp() throws Exception {
-        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        final Context context = getInstrumentation().getTargetContext();
 
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
-            mViewRootImpl = new ViewRootImplAccessor(
-                    new ViewRootImpl(mContext, mContext.getDisplayNoVerify()));
-        });
-    }
-
-    @Test
-    public void negativeInsets_areSetToZero() throws Exception {
-        assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
-
-        mViewRootImpl.getAttachInfo().getContentInsets().set(-10, -20, -30 , -40);
-        mViewRootImpl.getAttachInfo().getStableInsets().set(-10, -20, -30 , -40);
-        final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
-
-        assertThat(insets.getSystemWindowInsets(), equalTo(Insets.NONE));
-        assertThat(insets.getStableInsets(), equalTo(Insets.NONE));
-    }
-
-    @Test
-    public void negativeInsets_areSetToZero_positiveAreLeftAsIs() throws Exception {
-        assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
-
-        mViewRootImpl.getAttachInfo().getContentInsets().set(-10, 20, -30 , 40);
-        mViewRootImpl.getAttachInfo().getStableInsets().set(10, -20, 30 , -40);
-        final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
-
-        assertThat(insets.getSystemWindowInsets(), equalTo(Insets.of(0, 20, 0, 40)));
-        assertThat(insets.getStableInsets(), equalTo(Insets.of(10, 0, 30, 0)));
-    }
-
-    @Test
-    public void positiveInsets_areLeftAsIs() throws Exception {
-        assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
-
-        mViewRootImpl.getAttachInfo().getContentInsets().set(10, 20, 30 , 40);
-        mViewRootImpl.getAttachInfo().getStableInsets().set(10, 20, 30 , 40);
-        final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
-
-        assertThat(insets.getSystemWindowInsets(), equalTo(Insets.of(10, 20, 30, 40)));
-        assertThat(insets.getStableInsets(), equalTo(Insets.of(10, 20, 30, 40)));
+        getInstrumentation().runOnMainSync(() ->
+                mViewRootImpl = new ViewRootImpl(context, context.getDisplayNoVerify()));
     }
 
     @Test
     public void adjustLayoutParamsForCompatibility_layoutFullscreen() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
-
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
         attrs.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
         ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
@@ -125,8 +78,6 @@
 
     @Test
     public void adjustLayoutParamsForCompatibility_layoutInScreen() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
-
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
         attrs.flags = FLAG_LAYOUT_IN_SCREEN;
         ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
@@ -137,8 +88,6 @@
 
     @Test
     public void adjustLayoutParamsForCompatibility_layoutHideNavigation() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
-
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
         attrs.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
         ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
@@ -149,28 +98,22 @@
 
     @Test
     public void adjustLayoutParamsForCompatibility_toast() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
-
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_TOAST);
         ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
 
-        assertEquals(true, attrs.isFitInsetsIgnoringVisibility());
+        assertTrue(attrs.isFitInsetsIgnoringVisibility());
     }
 
     @Test
     public void adjustLayoutParamsForCompatibility_systemAlert() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
-
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_SYSTEM_ALERT);
         ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
 
-        assertEquals(true, attrs.isFitInsetsIgnoringVisibility());
+        assertTrue(attrs.isFitInsetsIgnoringVisibility());
     }
 
     @Test
     public void adjustLayoutParamsForCompatibility_fitSystemBars() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
-
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
         ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
 
@@ -180,8 +123,6 @@
 
     @Test
     public void adjustLayoutParamsForCompatibility_noAdjustLayout() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
-
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
         final int types = Type.all();
         final int sides = Side.TOP | Side.LEFT;
@@ -201,11 +142,8 @@
 
     @Test
     public void adjustLayoutParamsForCompatibility_noAdjustAppearance() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
-
-        final ViewRootImpl viewRoot = mViewRootImpl.get();
-        final WindowInsetsController controller = viewRoot.getInsetsController();
-        final WindowManager.LayoutParams attrs = viewRoot.mWindowAttributes;
+        final WindowInsetsController controller = mViewRootImpl.getInsetsController();
+        final WindowManager.LayoutParams attrs = mViewRootImpl.mWindowAttributes;
         final int appearance = 0;
         controller.setSystemBarsAppearance(appearance, 0xffffffff);
         attrs.systemUiVisibility = SYSTEM_UI_FLAG_LOW_PROFILE
@@ -220,11 +158,8 @@
 
     @Test
     public void adjustLayoutParamsForCompatibility_noAdjustBehavior() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
-
-        final ViewRootImpl viewRoot = mViewRootImpl.get();
-        final WindowInsetsController controller = viewRoot.getInsetsController();
-        final WindowManager.LayoutParams attrs = viewRoot.mWindowAttributes;
+        final WindowInsetsController controller = mViewRootImpl.getInsetsController();
+        final WindowManager.LayoutParams attrs = mViewRootImpl.mWindowAttributes;
         final int behavior = BEHAVIOR_SHOW_BARS_BY_TOUCH;
         controller.setSystemBarsBehavior(behavior);
         attrs.systemUiVisibility = SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
@@ -234,59 +169,4 @@
         // setSystemBarsBehavior.
         assertEquals(behavior, controller.getSystemBarsBehavior());
     }
-
-    private static class ViewRootImplAccessor {
-
-        private final ViewRootImpl mViewRootImpl;
-
-        ViewRootImplAccessor(ViewRootImpl viewRootImpl) {
-            mViewRootImpl = viewRootImpl;
-        }
-
-        public ViewRootImpl get() {
-            return mViewRootImpl;
-        }
-
-        AttachInfoAccessor getAttachInfo() throws Exception {
-            return new AttachInfoAccessor(
-                    getField(mViewRootImpl, ViewRootImpl.class.getDeclaredField("mAttachInfo")));
-        }
-
-        WindowInsets getWindowInsets(boolean forceConstruct) throws Exception {
-            return (WindowInsets) invokeMethod(mViewRootImpl,
-                    ViewRootImpl.class.getDeclaredMethod("getWindowInsets", boolean.class),
-                    forceConstruct);
-        }
-
-        class AttachInfoAccessor {
-
-            private final Class<?> mClass;
-            private final Object mAttachInfo;
-
-            AttachInfoAccessor(Object attachInfo) throws Exception {
-                mAttachInfo = attachInfo;
-                mClass = ViewRootImpl.class.getClassLoader().loadClass(
-                        "android.view.View$AttachInfo");
-            }
-
-            Rect getContentInsets() throws Exception {
-                return (Rect) getField(mAttachInfo, mClass.getDeclaredField("mContentInsets"));
-            }
-
-            Rect getStableInsets() throws Exception {
-                return (Rect) getField(mAttachInfo, mClass.getDeclaredField("mStableInsets"));
-            }
-        }
-
-        private static Object getField(Object o, Field field) throws Exception {
-            field.setAccessible(true);
-            return field.get(o);
-        }
-
-        private static Object invokeMethod(Object o, Method method, Object... args)
-                throws Exception {
-            method.setAccessible(true);
-            return method.invoke(o, args);
-        }
-    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
index b21504c..c17c36e 100644
--- a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
@@ -93,6 +93,7 @@
 @RunWith(AndroidJUnit4.class)
 public class AccessibilityShortcutControllerTest {
     private static final String SERVICE_NAME_STRING = "fake.package/fake.service.name";
+    private static final CharSequence PACKAGE_NAME_STRING = "Service name";
     private static final String SERVICE_NAME_SUMMARY = "Summary";
     private static final long VIBRATOR_PATTERN_1 = 100L;
     private static final long VIBRATOR_PATTERN_2 = 150L;
@@ -150,6 +151,8 @@
                 new AccessibilityManager(mHandler, mAccessibilityManagerService, 0);
         when(mFrameworkObjectProvider.getAccessibilityManagerInstance(mContext))
                 .thenReturn(accessibilityManager);
+        when(mContext.getSystemService(Context.ACCESSIBILITY_SERVICE))
+                .thenReturn(accessibilityManager);
         when(mFrameworkObjectProvider.getAlertDialogBuilder(mContext))
                 .thenReturn(mAlertDialogBuilder);
         when(mFrameworkObjectProvider.makeToastFromText(eq(mContext), anyObject(), anyInt()))
@@ -166,13 +169,13 @@
         ResolveInfo resolveInfo = mock(ResolveInfo.class);
         resolveInfo.serviceInfo = mock(ServiceInfo.class);
         resolveInfo.serviceInfo.applicationInfo = mApplicationInfo;
-        when(resolveInfo.loadLabel(anyObject())).thenReturn("Service name");
+        when(resolveInfo.loadLabel(anyObject())).thenReturn(PACKAGE_NAME_STRING);
         when(mServiceInfo.getResolveInfo()).thenReturn(resolveInfo);
         when(mServiceInfo.getComponentName())
                 .thenReturn(ComponentName.unflattenFromString(SERVICE_NAME_STRING));
         when(mServiceInfo.loadSummary(any())).thenReturn(SERVICE_NAME_SUMMARY);
 
-        when(mAlertDialogBuilder.setTitle(anyInt())).thenReturn(mAlertDialogBuilder);
+        when(mAlertDialogBuilder.setTitle(anyObject())).thenReturn(mAlertDialogBuilder);
         when(mAlertDialogBuilder.setCancelable(anyBoolean())).thenReturn(mAlertDialogBuilder);
         when(mAlertDialogBuilder.setMessage(anyObject())).thenReturn(mAlertDialogBuilder);
         when(mAlertDialogBuilder.setPositiveButton(anyInt(), anyObject()))
@@ -324,7 +327,8 @@
 
         assertEquals(1, Settings.Secure.getInt(
                 mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0));
-        verify(mResources).getString(R.string.accessibility_shortcut_toogle_warning);
+        verify(mResources).getString(
+                R.string.accessibility_shortcut_single_service_warning_title, PACKAGE_NAME_STRING);
         verify(mAlertDialog).show();
         verify(mAccessibilityManagerService, atLeastOnce()).getInstalledAccessibilityServiceList(
                 anyInt());
@@ -376,16 +380,20 @@
 
         ArgumentCaptor<DialogInterface.OnClickListener> captor =
                 ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
-        verify(mAlertDialogBuilder).setNegativeButton(eq(R.string.disable_accessibility_shortcut),
+        verify(mAlertDialogBuilder).setPositiveButton(eq(R.string.accessibility_shortcut_off),
                 captor.capture());
-        // Call the button callback
-        captor.getValue().onClick(null, 0);
+        // Call the button callback, if one exists
+        if (captor.getValue() != null) {
+            captor.getValue().onClick(null, 0);
+        }
         assertTrue(TextUtils.isEmpty(
                 Settings.Secure.getString(mContentResolver, ACCESSIBILITY_SHORTCUT_TARGET_SERVICE)));
+        assertEquals(0, Settings.Secure.getInt(
+                mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN));
     }
 
     @Test
-    public void testClickingLeaveOnButtonInDialog_shouldLeaveShortcutReady() throws Exception {
+    public void testClickingTurnOnButtonInDialog_shouldLeaveShortcutReady() throws Exception {
         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
         configureValidShortcutService();
         Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0);
@@ -393,8 +401,8 @@
 
         ArgumentCaptor<DialogInterface.OnClickListener> captor =
             ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
-        verify(mAlertDialogBuilder).setPositiveButton(eq(R.string.leave_accessibility_shortcut_on),
-            captor.capture());
+        verify(mAlertDialogBuilder).setNegativeButton(eq(R.string.accessibility_shortcut_on),
+                captor.capture());
         // Call the button callback, if one exists
         if (captor.getValue() != null) {
             captor.getValue().onClick(null, 0);
@@ -402,7 +410,7 @@
         assertEquals(SERVICE_NAME_STRING,
                 Settings.Secure.getString(mContentResolver, ACCESSIBILITY_SHORTCUT_TARGET_SERVICE));
         assertEquals(1, Settings.Secure.getInt(
-            mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN));
+                mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN));
     }
 
     @Test
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index e23a3ca..dcecb5f 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -294,6 +294,60 @@
     }
 
     @Test
+    public void fourOptionsStackedIntoOneTarget() throws InterruptedException {
+        Intent sendIntent = createSendTextIntent();
+
+        // create 12 unique app targets to ensure the app ranking row can be filled, otherwise
+        // targets will not stack
+        List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(12);
+
+        // next create 4 targets in a single app that should be stacked into a single target
+        String packageName = "xxx.yyy";
+        String appName = "aaa";
+        ComponentName cn = new ComponentName(packageName, appName);
+        Intent intent = new Intent("fakeIntent");
+        List<ResolvedComponentInfo> infosToStack = new ArrayList<>();
+        for (int i = 0; i < 4; i++) {
+            ResolveInfo resolveInfo = ResolverDataProvider.createResolveInfo(i,
+                    UserHandle.USER_CURRENT);
+            resolveInfo.activityInfo.applicationInfo.name = appName;
+            resolveInfo.activityInfo.applicationInfo.packageName = packageName;
+            resolveInfo.activityInfo.packageName = packageName;
+            resolveInfo.activityInfo.name = "ccc" + i;
+            infosToStack.add(new ResolvedComponentInfo(cn, intent, resolveInfo));
+        }
+        resolvedComponentInfos.addAll(infosToStack);
+
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+        final ChooserWrapperActivity activity = mActivityRule
+                .launchActivity(Intent.createChooser(sendIntent, null));
+        waitForIdle();
+
+        // expect 12 unique targets + 1 group + 4 ranked app targets
+        assertThat(activity.getAdapter().getCount(), is(17));
+
+        ResolveInfo[] chosen = new ResolveInfo[1];
+        sOverrides.onSafelyStartCallback = targetInfo -> {
+            chosen[0] = targetInfo.getResolveInfo();
+            return true;
+        };
+
+        onView(withText(appName)).perform(click());
+        waitForIdle();
+
+        // clicking will launch a dialog to choose the activity within the app
+        onView(withText(appName)).check(matches(isDisplayed()));
+        int i = 0;
+        for (ResolvedComponentInfo rci: infosToStack) {
+            onView(withText("ccc" + i)).check(matches(isDisplayed()));
+            ++i;
+        }
+    }
+
+    @Test
     public void updateChooserCountsAndModelAfterUserSelection() throws InterruptedException {
         Intent sendIntent = createSendTextIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
@@ -1872,6 +1926,33 @@
                 .check(matches(isDisplayed()));
     }
 
+    @Test
+    public void testDeduplicateCallerTargetRankedTarget() {
+        // Create 4 ranked app targets.
+        List<ResolvedComponentInfo> personalResolvedComponentInfos =
+                createResolvedComponentsForTest(4);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class)))
+                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
+        // Create caller target which is duplicate with one of app targets
+        Intent chooserIntent = createChooserIntent(createSendTextIntent(),
+                new Intent[] {new Intent("action.fake")});
+        sOverrides.packageManager = mock(PackageManager.class);
+        ResolveInfo ri = ResolverDataProvider.createResolveInfo(0,
+                UserHandle.USER_CURRENT);
+        when(sOverrides.packageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(ri);
+        waitForIdle();
+
+        ChooserWrapperActivity activity = mActivityRule.launchActivity(chooserIntent);
+        waitForIdle();
+
+        // Total 4 targets (1 caller target, 3 ranked targets)
+        assertThat(activity.getAdapter().getCount(), is(4));
+        assertThat(activity.getAdapter().getCallerTargetCount(), is(1));
+        assertThat(activity.getAdapter().getRankedTargetCount(), is(3));
+    }
+
     private Intent createChooserIntent(Intent intent, Intent[] initialIntents) {
         Intent chooserIntent = new Intent();
         chooserIntent.setAction(Intent.ACTION_CHOOSER);
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index 0390ac6..1cdc75a 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -225,7 +225,8 @@
                     CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null /* referrer */,
                     null /* voiceInteractor */, null /* state */, null /* persistentState */,
                     null /* pendingResults */, null /* pendingNewIntents */, true /* isForward */,
-                    null /* profilerInfo */,  mThread /* client */, null /* asssitToken */);
+                    null /* profilerInfo */,  mThread /* client */, null /* asssitToken */,
+                    null /* fixedRotationAdjustments */);
         }
 
         @Override
diff --git a/core/tests/overlaytests/host/Android.bp b/core/tests/overlaytests/host/Android.bp
index 2b38cca..a2fcef5 100644
--- a/core/tests/overlaytests/host/Android.bp
+++ b/core/tests/overlaytests/host/Android.bp
@@ -16,7 +16,7 @@
     name: "OverlayHostTests",
     srcs: ["src/**/*.java"],
     libs: ["tradefed"],
-    test_suites: ["device-tests"],
+    test_suites: ["general-tests"],
     target_required: [
         "OverlayHostTests_NonPlatformSignatureOverlay",
         "OverlayHostTests_PlatformSignatureStaticOverlay",
diff --git a/core/tests/overlaytests/remount/src/com/android/overlaytest/remounted/PackagedUpgradedTest.java b/core/tests/overlaytests/remount/src/com/android/overlaytest/remounted/PackagedUpgradedTest.java
index 70e3423..a465640 100644
--- a/core/tests/overlaytests/remount/src/com/android/overlaytest/remounted/PackagedUpgradedTest.java
+++ b/core/tests/overlaytests/remount/src/com/android/overlaytest/remounted/PackagedUpgradedTest.java
@@ -47,6 +47,7 @@
     @Test
     public void testTargetRelocated() throws Exception {
         final String targetOverlaid = resourceName(TARGET_PACKAGE, "bool", "target_overlaid");
+        final String targetReference = resourceName(TARGET_PACKAGE, "bool", "target_reference");
         final String originalPath = "/product/app/OverlayTarget.apk";
 
         mPreparer.pushResourceFile(TARGET_APK, originalPath)
@@ -54,6 +55,7 @@
                 .installResourceApk(OVERLAY_APK, OVERLAY_PACKAGE)
                 .setOverlayEnabled(OVERLAY_PACKAGE, true);
 
+        assertResource(targetReference, "@" + 0x7f010000 + " -> true");
         assertResource(targetOverlaid, "true");
 
         mPreparer.remount();
@@ -61,6 +63,7 @@
         mPreparer.pushResourceFile(TARGET_UPGRADE_APK, "/product/app/OverlayTarget2.apk")
                 .reboot();
 
+        assertResource(targetReference, "@" + 0x7f0100ff + " -> true");
         assertResource(targetOverlaid, "true");
     }
 }
diff --git a/core/tests/utiltests/src/android/util/AtomicFileTest.java b/core/tests/utiltests/src/android/util/AtomicFileTest.java
new file mode 100644
index 0000000..a7d3b22
--- /dev/null
+++ b/core/tests/utiltests/src/android/util/AtomicFileTest.java
@@ -0,0 +1,302 @@
+/*
+ * 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.util;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Instrumentation;
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+@RunWith(Parameterized.class)
+public class AtomicFileTest {
+    private static final String BASE_NAME = "base";
+    private static final String NEW_NAME = BASE_NAME + ".new";
+    private static final String LEGACY_BACKUP_NAME = BASE_NAME + ".bak";
+    // The string isn't actually used, but we just need a different identifier.
+    private static final String BASE_NAME_DIRECTORY = BASE_NAME + ".dir";
+
+    private enum WriteAction {
+        FINISH,
+        FAIL,
+        ABORT,
+        READ_FINISH
+    }
+
+    private static final byte[] BASE_BYTES = "base".getBytes(StandardCharsets.UTF_8);
+    private static final byte[] EXISTING_NEW_BYTES = "unnew".getBytes(StandardCharsets.UTF_8);
+    private static final byte[] NEW_BYTES = "new".getBytes(StandardCharsets.UTF_8);
+    private static final byte[] LEGACY_BACKUP_BYTES = "bak".getBytes(StandardCharsets.UTF_8);
+
+    // JUnit wants every parameter to be used so make it happy.
+    @Parameterized.Parameter()
+    public String mUnusedTestName;
+    @Nullable
+    @Parameterized.Parameter(1)
+    public String[] mExistingFileNames;
+    @Nullable
+    @Parameterized.Parameter(2)
+    public WriteAction mWriteAction;
+    @Nullable
+    @Parameterized.Parameter(3)
+    public byte[] mExpectedBytes;
+
+    private final Instrumentation mInstrumentation =
+            InstrumentationRegistry.getInstrumentation();
+    private final Context mContext = mInstrumentation.getContext();
+
+    private final File mDirectory = mContext.getFilesDir();
+    private final File mBaseFile = new File(mDirectory, BASE_NAME);
+    private final File mNewFile = new File(mDirectory, NEW_NAME);
+    private final File mLegacyBackupFile = new File(mDirectory, LEGACY_BACKUP_NAME);
+
+    @Parameterized.Parameters(name = "{0}")
+    public static Object[][] data() {
+        return new Object[][] {
+                // Standard tests.
+                { "none + none = none", null, null, null },
+                { "none + finish = new", null, WriteAction.FINISH, NEW_BYTES },
+                { "none + fail = none", null, WriteAction.FAIL, null },
+                { "none + abort = none", null, WriteAction.ABORT, null },
+                { "base + none = base", new String[] { BASE_NAME }, null, BASE_BYTES },
+                { "base + finish = new", new String[] { BASE_NAME }, WriteAction.FINISH,
+                        NEW_BYTES },
+                { "base + fail = base", new String[] { BASE_NAME }, WriteAction.FAIL, BASE_BYTES },
+                { "base + abort = base", new String[] { BASE_NAME }, WriteAction.ABORT,
+                        BASE_BYTES },
+                { "new + none = none", new String[] { NEW_NAME }, null, null },
+                { "new + finish = new", new String[] { NEW_NAME }, WriteAction.FINISH, NEW_BYTES },
+                { "new + fail = none", new String[] { NEW_NAME }, WriteAction.FAIL, null },
+                { "new + abort = none", new String[] { NEW_NAME }, WriteAction.ABORT, null },
+                { "bak + none = bak", new String[] { LEGACY_BACKUP_NAME }, null,
+                        LEGACY_BACKUP_BYTES },
+                { "bak + finish = new", new String[] { LEGACY_BACKUP_NAME }, WriteAction.FINISH,
+                        NEW_BYTES },
+                { "bak + fail = bak", new String[] { LEGACY_BACKUP_NAME }, WriteAction.FAIL,
+                        LEGACY_BACKUP_BYTES },
+                { "bak + abort = bak", new String[] { LEGACY_BACKUP_NAME }, WriteAction.ABORT,
+                        LEGACY_BACKUP_BYTES },
+                { "base & new + none = base", new String[] { BASE_NAME, NEW_NAME }, null,
+                        BASE_BYTES },
+                { "base & new + finish = new", new String[] { BASE_NAME, NEW_NAME },
+                        WriteAction.FINISH, NEW_BYTES },
+                { "base & new + fail = base", new String[] { BASE_NAME, NEW_NAME },
+                        WriteAction.FAIL, BASE_BYTES },
+                { "base & new + abort = base", new String[] { BASE_NAME, NEW_NAME },
+                        WriteAction.ABORT, BASE_BYTES },
+                { "base & bak + none = bak", new String[] { BASE_NAME, LEGACY_BACKUP_NAME }, null,
+                        LEGACY_BACKUP_BYTES },
+                { "base & bak + finish = new", new String[] { BASE_NAME, LEGACY_BACKUP_NAME },
+                        WriteAction.FINISH, NEW_BYTES },
+                { "base & bak + fail = bak", new String[] { BASE_NAME, LEGACY_BACKUP_NAME },
+                        WriteAction.FAIL, LEGACY_BACKUP_BYTES },
+                { "base & bak + abort = bak", new String[] { BASE_NAME, LEGACY_BACKUP_NAME },
+                        WriteAction.ABORT, LEGACY_BACKUP_BYTES },
+                { "new & bak + none = bak", new String[] { NEW_NAME, LEGACY_BACKUP_NAME }, null,
+                        LEGACY_BACKUP_BYTES },
+                { "new & bak + finish = new", new String[] { NEW_NAME, LEGACY_BACKUP_NAME },
+                        WriteAction.FINISH, NEW_BYTES },
+                { "new & bak + fail = bak", new String[] { NEW_NAME, LEGACY_BACKUP_NAME },
+                        WriteAction.FAIL, LEGACY_BACKUP_BYTES },
+                { "new & bak + abort = bak", new String[] { NEW_NAME, LEGACY_BACKUP_NAME },
+                        WriteAction.ABORT, LEGACY_BACKUP_BYTES },
+                { "base & new & bak + none = bak",
+                        new String[] { BASE_NAME, NEW_NAME, LEGACY_BACKUP_NAME }, null,
+                        LEGACY_BACKUP_BYTES },
+                { "base & new & bak + finish = new",
+                        new String[] { BASE_NAME, NEW_NAME, LEGACY_BACKUP_NAME },
+                        WriteAction.FINISH, NEW_BYTES },
+                { "base & new & bak + fail = bak",
+                        new String[] { BASE_NAME, NEW_NAME, LEGACY_BACKUP_NAME }, WriteAction.FAIL,
+                        LEGACY_BACKUP_BYTES },
+                { "base & new & bak + abort = bak",
+                        new String[] { BASE_NAME, NEW_NAME, LEGACY_BACKUP_NAME }, WriteAction.ABORT,
+                        LEGACY_BACKUP_BYTES },
+                // Compatibility when there is a directory in the place of base file, by replacing
+                // no base with base.dir.
+                { "base.dir + none = none", new String[] { BASE_NAME_DIRECTORY }, null, null },
+                { "base.dir + finish = new", new String[] { BASE_NAME_DIRECTORY },
+                        WriteAction.FINISH, NEW_BYTES },
+                { "base.dir + fail = none", new String[] { BASE_NAME_DIRECTORY }, WriteAction.FAIL,
+                        null },
+                { "base.dir + abort = none", new String[] { BASE_NAME_DIRECTORY },
+                        WriteAction.ABORT, null },
+                { "base.dir & new + none = none", new String[] { BASE_NAME_DIRECTORY, NEW_NAME },
+                        null, null },
+                { "base.dir & new + finish = new", new String[] { BASE_NAME_DIRECTORY, NEW_NAME },
+                        WriteAction.FINISH, NEW_BYTES },
+                { "base.dir & new + fail = none", new String[] { BASE_NAME_DIRECTORY, NEW_NAME },
+                        WriteAction.FAIL, null },
+                { "base.dir & new + abort = none", new String[] { BASE_NAME_DIRECTORY, NEW_NAME },
+                        WriteAction.ABORT, null },
+                { "base.dir & bak + none = bak",
+                        new String[] { BASE_NAME_DIRECTORY, LEGACY_BACKUP_NAME }, null,
+                        LEGACY_BACKUP_BYTES },
+                { "base.dir & bak + finish = new",
+                        new String[] { BASE_NAME_DIRECTORY, LEGACY_BACKUP_NAME },
+                        WriteAction.FINISH, NEW_BYTES },
+                { "base.dir & bak + fail = bak",
+                        new String[] { BASE_NAME_DIRECTORY, LEGACY_BACKUP_NAME }, WriteAction.FAIL,
+                        LEGACY_BACKUP_BYTES },
+                { "base.dir & bak + abort = bak",
+                        new String[] { BASE_NAME_DIRECTORY, LEGACY_BACKUP_NAME }, WriteAction.ABORT,
+                        LEGACY_BACKUP_BYTES },
+                { "base.dir & new & bak + none = bak",
+                        new String[] { BASE_NAME_DIRECTORY, NEW_NAME, LEGACY_BACKUP_NAME }, null,
+                        LEGACY_BACKUP_BYTES },
+                { "base.dir & new & bak + finish = new",
+                        new String[] { BASE_NAME_DIRECTORY, NEW_NAME, LEGACY_BACKUP_NAME },
+                        WriteAction.FINISH, NEW_BYTES },
+                { "base.dir & new & bak + fail = bak",
+                        new String[] { BASE_NAME_DIRECTORY, NEW_NAME, LEGACY_BACKUP_NAME },
+                        WriteAction.FAIL, LEGACY_BACKUP_BYTES },
+                { "base.dir & new & bak + abort = bak",
+                        new String[] { BASE_NAME_DIRECTORY, NEW_NAME, LEGACY_BACKUP_NAME },
+                        WriteAction.ABORT, LEGACY_BACKUP_BYTES },
+                // Compatibility when openRead() is called between startWrite() and finishWrite() -
+                // the write should still succeed if it's the first write.
+                { "none + read & finish = new", null, WriteAction.READ_FINISH, NEW_BYTES },
+        };
+    }
+
+    @Before
+    @After
+    public void deleteFiles() {
+        mBaseFile.delete();
+        mNewFile.delete();
+        mLegacyBackupFile.delete();
+    }
+
+    @Test
+    public void testAtomicFile() throws Exception {
+        if (mExistingFileNames != null) {
+            for (String fileName : mExistingFileNames) {
+                switch (fileName) {
+                    case BASE_NAME:
+                        writeBytes(mBaseFile, BASE_BYTES);
+                        break;
+                    case NEW_NAME:
+                        writeBytes(mNewFile, EXISTING_NEW_BYTES);
+                        break;
+                    case LEGACY_BACKUP_NAME:
+                        writeBytes(mLegacyBackupFile, LEGACY_BACKUP_BYTES);
+                        break;
+                    case BASE_NAME_DIRECTORY:
+                        assertTrue(mBaseFile.mkdir());
+                        break;
+                    default:
+                        throw new AssertionError(fileName);
+                }
+            }
+        }
+
+        AtomicFile atomicFile = new AtomicFile(mBaseFile);
+        if (mWriteAction != null) {
+            try (FileOutputStream outputStream = atomicFile.startWrite()) {
+                outputStream.write(NEW_BYTES);
+                switch (mWriteAction) {
+                    case FINISH:
+                        atomicFile.finishWrite(outputStream);
+                        break;
+                    case FAIL:
+                        atomicFile.failWrite(outputStream);
+                        break;
+                    case ABORT:
+                        // Neither finishing nor failing is called upon abort.
+                        break;
+                    case READ_FINISH:
+                        // We are only using this action when there is no base file.
+                        assertThrows(FileNotFoundException.class, atomicFile::openRead);
+                        atomicFile.finishWrite(outputStream);
+                        break;
+                    default:
+                        throw new AssertionError(mWriteAction);
+                }
+            }
+        }
+
+        if (mExpectedBytes != null) {
+            try (FileInputStream inputStream = atomicFile.openRead()) {
+                assertArrayEquals(mExpectedBytes, readAllBytes(inputStream));
+            }
+        } else {
+            assertThrows(FileNotFoundException.class, atomicFile::openRead);
+        }
+    }
+
+    private static void writeBytes(@NonNull File file, @NonNull byte[] bytes) throws IOException {
+        try (FileOutputStream outputStream = new FileOutputStream(file)) {
+            outputStream.write(bytes);
+        }
+    }
+
+    // InputStream.readAllBytes() is introduced in Java 9. Our files are small enough so that a
+    // naive implementation is okay.
+    private static byte[] readAllBytes(@NonNull InputStream inputStream) throws IOException {
+        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
+            int b;
+            while ((b = inputStream.read()) != -1) {
+                outputStream.write(b);
+            }
+            return outputStream.toByteArray();
+        }
+    }
+
+    @NonNull
+    public static <T extends Throwable> T assertThrows(@NonNull Class<T> expectedType,
+            @NonNull ThrowingRunnable runnable) {
+        try {
+            runnable.run();
+        } catch (Throwable t) {
+            if (!expectedType.isInstance(t)) {
+                sneakyThrow(t);
+            }
+            //noinspection unchecked
+            return (T) t;
+        }
+        throw new AssertionError(String.format("Expected %s wasn't thrown",
+                expectedType.getSimpleName()));
+    }
+
+    private static <T extends Throwable> void sneakyThrow(@NonNull Throwable throwable) throws T {
+        //noinspection unchecked
+        throw (T) throwable;
+    }
+
+    private interface ThrowingRunnable {
+        void run() throws Throwable;
+    }
+}
diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp
index dfb7a16..1b1a624 100644
--- a/data/etc/car/Android.bp
+++ b/data/etc/car/Android.bp
@@ -87,6 +87,13 @@
 }
 
 prebuilt_etc {
+    name: "privapp_whitelist_com.android.car.secondaryhome",
+    sub_dir: "permissions",
+    src: "com.android.car.secondaryhome.xml",
+    filename_from_src: true,
+}
+
+prebuilt_etc {
     name: "privapp_whitelist_com.android.car.settings",
     sub_dir: "permissions",
     src: "com.android.car.settings.xml",
diff --git a/data/etc/car/com.android.car.secondaryhome.xml b/data/etc/car/com.android.car.secondaryhome.xml
index c74b86e..a8af906 100644
--- a/data/etc/car/com.android.car.secondaryhome.xml
+++ b/data/etc/car/com.android.car.secondaryhome.xml
@@ -20,5 +20,7 @@
         <permission name="android.permission.ACTIVITY_EMBEDDING"/>
         <!-- Required to send notification to current user-->
         <permission name="android.permission.MANAGE_USERS"/>
+        <!-- Required for CarNotificationLib -->
+        <permission name="android.permission.INTERACT_ACROSS_USERS"/>
     </privapp-permissions>
 </permissions>
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index 72827a9..a5a2221 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -16,6 +16,7 @@
   -->
 <permissions>
     <privapp-permissions package="com.android.systemui">
+        <permission name="android.permission.CAPTURE_AUDIO_OUTPUT"/>
         <permission name="android.permission.BATTERY_STATS"/>
         <permission name="android.permission.BIND_APPWIDGET"/>
         <permission name="android.permission.BLUETOOTH_PRIVILEGED"/>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 0389639..bdb6bcc 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -324,6 +324,7 @@
         <permission name="android.permission.MANAGE_ROLLBACKS"/>
         <permission name="android.permission.MANAGE_USB"/>
         <permission name="android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS"/>
+        <permission name="android.permission.MODIFY_DAY_NIGHT_MODE"/>
         <permission name="android.permission.MODIFY_PHONE_STATE"/>
         <permission name="android.permission.MOUNT_FORMAT_FILESYSTEMS"/>
         <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
diff --git a/data/keyboards/Vendor_28de_Product_1102.kl b/data/keyboards/Vendor_28de_Product_1102.kl
new file mode 100644
index 0000000..150a17a
--- /dev/null
+++ b/data/keyboards/Vendor_28de_Product_1102.kl
@@ -0,0 +1,74 @@
+# 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.
+
+#
+# Steam Controller - Model 1001 - USB
+#
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+key 304   BUTTON_A
+key 305   BUTTON_B
+key 307   BUTTON_X
+key 308   BUTTON_Y
+
+key 310   BUTTON_L1
+key 311   BUTTON_R1
+key 312   BUTTON_L2
+key 313   BUTTON_R2
+
+# Triggers.
+axis 0x15 LTRIGGER
+axis 0x14 RTRIGGER
+
+# Left and right stick.
+axis 0x00 X
+axis 0x01 Y
+
+# Right stick / mousepad
+axis 0x03 Z
+axis 0x04 RZ
+
+key 317   BUTTON_THUMBL
+key 318   BUTTON_THUMBR
+
+# Hat.
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Dpad (clicks)
+key 544 DPAD_UP
+key 545 DPAD_DOWN
+key 546 DPAD_LEFT
+key 547 DPAD_RIGHT
+
+# Touching the dpad (light touch without pressing down)
+key 289 BUTTON_1
+# Touching the "right stick" / mousepad (light touch without pressing down)
+key 290 BUTTON_2
+
+# Pressing the large paddle on the back, left (linux BTN_WHEEL / BTN_GEAR_DOWN)
+key 336 BUTTON_3
+# Pressing the large paddle on the back, right (linux BTN_GEAR_UP)
+key 337 BUTTON_4
+
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Left arrow
+key 314   BUTTON_SELECT
+# Right arrow
+key 315   BUTTON_START
+
+# Steam key
+key 316   BUTTON_MODE
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 97b448a..c8f065a 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -70,9 +70,9 @@
  *  {@link Bitmap} objects.
  *
  *  <p>To use it, first create a {@link Source Source} using one of the
- *  {@code createSource} overloads. For example, to decode from a {@link File}, call
- *  {@link #createSource(File)} and pass the result to {@link #decodeDrawable(Source)}
- *  or {@link #decodeBitmap(Source)}:
+ *  {@code createSource} overloads. For example, to decode from a {@link Uri}, call
+ *  {@link #createSource(ContentResolver, Uri)} and pass the result to
+ *  {@link #decodeDrawable(Source)} or {@link #decodeBitmap(Source)}:
  *
  *  <pre class="prettyprint">
  *  File file = new File(...);
@@ -1032,7 +1032,11 @@
 
     /**
      * Create a new {@link Source Source} from a {@link java.io.File}.
-     *
+     * <p>
+     * This method should only be used for files that you have direct access to;
+     * if you'd like to work with files hosted outside your app, use an API like
+     * {@link #createSource(Callable)} or
+     * {@link #createSource(ContentResolver, Uri)}.
      * @return a new Source object, which can be passed to
      *      {@link #decodeDrawable decodeDrawable} or
      *      {@link #decodeBitmap decodeBitmap}.
diff --git a/graphics/java/android/graphics/PorterDuff.java b/graphics/java/android/graphics/PorterDuff.java
index 1275cb9..eb940e2 100644
--- a/graphics/java/android/graphics/PorterDuff.java
+++ b/graphics/java/android/graphics/PorterDuff.java
@@ -30,8 +30,6 @@
     /**
      * {@usesMathJax}
      *
-     * <h3>Porter-Duff</h3>
-     *
      * <p>The name of the parent class is an homage to the work of Thomas Porter and
      * Tom Duff, presented in their seminal 1984 paper titled "Compositing Digital Images".
      * In this paper, the authors describe 12 compositing operators that govern how to
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index acd90a7..6df62c0 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -369,6 +369,13 @@
      * {@link Activity#RESULT_OK} will be returned if a credential was
      * successfully installed, otherwise {@link
      * Activity#RESULT_CANCELED} will be returned.
+     *
+     * <p>Starting from {@link android.os.Build.VERSION_CODES#R}, the intent returned by this
+     * method cannot be used for installing CA certificates. Since CA certificates can only be
+     * installed via Settings, the app should provide the user with a file containing the
+     * CA certificate. One way to do this would be to use the {@link android.provider.MediaStore}
+     * API to write the certificate to the {@link android.provider.MediaStore.Downloads}
+     * collection.
      */
     @NonNull
     public static Intent createInstallIntent() {
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
index 8dbb5f5..cc5286d 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -167,7 +167,7 @@
         boolean userAuthenticationRequired =
                 !keyCharacteristics.getBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
         long userAuthenticationValidityDurationSeconds =
-                keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, -1);
+                keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, 0);
         if (userAuthenticationValidityDurationSeconds > Integer.MAX_VALUE) {
             throw new ProviderException("User authentication timeout validity too long: "
                     + userAuthenticationValidityDurationSeconds + " seconds");
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/ExtensionHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/ExtensionHelper.java
index c4f11a0..c61f1ed 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/ExtensionHelper.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/ExtensionHelper.java
@@ -30,6 +30,8 @@
 import android.view.DisplayInfo;
 import android.view.Surface;
 
+import androidx.annotation.Nullable;
+
 /**
  * Toolkit class for calculation of the display feature bounds within the window.
  * NOTE: This sample implementation only works for Activity windows, because there is no public APIs
@@ -84,7 +86,7 @@
 
     /** Transform rectangle from absolute coordinate space to the window coordinate space. */
     static void transformToWindowSpaceRect(Rect inOutRect, IBinder windowToken) {
-        Rect windowRect = getWindowRect(windowToken);
+        Rect windowRect = getWindowBounds(windowToken);
         if (windowRect == null) {
             inOutRect.setEmpty();
             return;
@@ -101,13 +103,12 @@
      * Get the current window bounds in absolute coordinates.
      * NOTE: Only works with Activity windows.
      */
-    private static Rect getWindowRect(IBinder windowToken) {
+    @Nullable
+    private static Rect getWindowBounds(IBinder windowToken) {
         Activity activity = ActivityThread.currentActivityThread().getActivity(windowToken);
-        final Rect windowRect = new Rect();
-        if (activity != null) {
-            activity.getWindow().getDecorView().getWindowDisplayFrame(windowRect);
-        }
-        return windowRect;
+        return activity != null
+                ? activity.getWindowManager().getCurrentWindowMetrics().getBounds()
+                : null;
     }
 
     /**
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 8ea6883..ea7a556 100755
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1505,7 +1505,7 @@
     public void setSpeakerphoneOn(boolean on){
         final IAudioService service = getService();
         try {
-            service.setSpeakerphoneOn(on);
+            service.setSpeakerphoneOn(mICallBack, on);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java
index 98c2d7f..b44d7bb 100644
--- a/media/java/android/media/AudioManagerInternal.java
+++ b/media/java/android/media/AudioManagerInternal.java
@@ -16,6 +16,7 @@
 package android.media;
 
 import android.util.IntArray;
+
 import com.android.server.LocalServices;
 
 /**
@@ -28,13 +29,13 @@
 public abstract class AudioManagerInternal {
 
     public abstract void adjustSuggestedStreamVolumeForUid(int streamType, int direction,
-            int flags, String callingPackage, int uid);
+            int flags, String callingPackage, int uid, int pid);
 
     public abstract void adjustStreamVolumeForUid(int streamType, int direction, int flags,
-            String callingPackage, int uid);
+            String callingPackage, int uid, int pid);
 
     public abstract void setStreamVolumeForUid(int streamType, int direction, int flags,
-            String callingPackage, int uid);
+            String callingPackage, int uid, int pid);
 
     public abstract void setRingerModeDelegate(RingerModeDelegate delegate);
 
@@ -48,6 +49,18 @@
 
     public abstract void setAccessibilityServiceUids(IntArray uids);
 
+    /**
+     * Called by {@link com.android.server.inputmethod.InputMethodManagerService} to notify the UID
+     * of the currently used {@link android.inputmethodservice.InputMethodService}.
+     *
+     * <p>The caller is expected to take care of any performance implications, e.g. by using a
+     * background thread to call this method.</p>
+     *
+     * @param uid UID of the currently used {@link android.inputmethodservice.InputMethodService}.
+     *            {@link android.os.Process#INVALID_UID} if no IME is active.
+     */
+    public abstract void setInputMethodServiceUid(int uid);
+
     public interface RingerModeDelegate {
         /** Called when external ringer mode is evaluated, returns the new internal ringer mode */
         int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index e3b67f8..8137275 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -150,7 +150,7 @@
 
     oneway void avrcpSupportsAbsoluteVolume(String address, boolean support);
 
-    void setSpeakerphoneOn(boolean on);
+    void setSpeakerphoneOn(IBinder cb, boolean on);
 
     boolean isSpeakerphoneOn();
 
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index bbd7399..54675d0 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -321,6 +321,21 @@
     @UnsupportedAppUsage
     private long mNativeObject;
 
+    private String convertMuxerStateCodeToString(int aState) {
+        switch (aState) {
+            case MUXER_STATE_UNINITIALIZED:
+                return "UNINITIALIZED";
+            case MUXER_STATE_INITIALIZED:
+                return "INITIALIZED";
+            case MUXER_STATE_STARTED:
+                return "STARTED";
+            case MUXER_STATE_STOPPED:
+                return "STOPPED";
+            default:
+                return "UNKNOWN";
+        }
+    }
+
     /**
      * Constructor.
      * Creates a media muxer that writes to the specified path.
@@ -397,7 +412,7 @@
             nativeSetOrientationHint(mNativeObject, degrees);
         } else {
             throw new IllegalStateException("Can't set rotation degrees due" +
-                    " to wrong state.");
+                    " to wrong state(" + convertMuxerStateCodeToString(mState) + ")");
         }
     }
 
@@ -432,7 +447,8 @@
         if (mState == MUXER_STATE_INITIALIZED && mNativeObject != 0) {
             nativeSetLocation(mNativeObject, latitudex10000, longitudex10000);
         } else {
-            throw new IllegalStateException("Can't set location due to wrong state.");
+            throw new IllegalStateException("Can't set location due to wrong state("
+                                             + convertMuxerStateCodeToString(mState) + ")");
         }
     }
 
@@ -451,7 +467,8 @@
             nativeStart(mNativeObject);
             mState = MUXER_STATE_STARTED;
         } else {
-            throw new IllegalStateException("Can't start due to wrong state.");
+            throw new IllegalStateException("Can't start due to wrong state("
+                                             + convertMuxerStateCodeToString(mState) + ")");
         }
     }
 
@@ -462,10 +479,16 @@
      */
     public void stop() {
         if (mState == MUXER_STATE_STARTED) {
-            nativeStop(mNativeObject);
-            mState = MUXER_STATE_STOPPED;
+            try {
+                nativeStop(mNativeObject);
+            } catch (Exception e) {
+                throw e;
+            } finally {
+                mState = MUXER_STATE_STOPPED;
+            }
         } else {
-            throw new IllegalStateException("Can't stop due to wrong state.");
+            throw new IllegalStateException("Can't stop due to wrong state("
+                                             + convertMuxerStateCodeToString(mState) + ")");
         }
     }
 
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 7d14ef5..6179b48 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -98,7 +98,7 @@
 
     final Handler mHandler;
     @GuardedBy("sRouterLock")
-    private boolean mShouldUpdateRoutes;
+    private boolean mShouldUpdateRoutes = true;
     private volatile List<MediaRoute2Info> mFilteredRoutes = Collections.emptyList();
     private volatile OnGetControllerHintsListener mOnGetControllerHintsListener;
 
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 0dc019c..4ebfce8 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -100,6 +100,7 @@
                 .getSystemService(Context.MEDIA_SESSION_SERVICE);
         mPackageName = mContext.getPackageName();
         mHandler = new Handler(context.getMainLooper());
+        mHandler.post(this::getOrCreateClient);
     }
 
     /**
@@ -118,18 +119,6 @@
             Log.w(TAG, "Ignoring to add the same callback twice.");
             return;
         }
-
-        synchronized (sLock) {
-            if (mClient == null) {
-                Client client = new Client();
-                try {
-                    mMediaRouterService.registerManager(client, mPackageName);
-                    mClient = client;
-                } catch (RemoteException ex) {
-                    Log.e(TAG, "Unable to register media router manager.", ex);
-                }
-            }
-        }
     }
 
     /**
@@ -144,21 +133,6 @@
             Log.w(TAG, "unregisterCallback: Ignore unknown callback. " + callback);
             return;
         }
-
-        synchronized (sLock) {
-            if (mCallbackRecords.size() == 0) {
-                if (mClient != null) {
-                    try {
-                        mMediaRouterService.unregisterManager(mClient);
-                    } catch (RemoteException ex) {
-                        Log.e(TAG, "Unable to unregister media router manager", ex);
-                    }
-                    mClient = null;
-                }
-                mRoutes.clear();
-                mPreferredFeaturesMap.clear();
-            }
-        }
     }
 
     /**
@@ -314,10 +288,7 @@
      */
     @NonNull
     public List<RoutingSessionInfo> getActiveSessions() {
-        Client client;
-        synchronized (sLock) {
-            client = mClient;
-        }
+        Client client = getOrCreateClient();
         if (client != null) {
             try {
                 return mMediaRouterService.getActiveSessions(client);
@@ -380,10 +351,7 @@
             return;
         }
 
-        Client client;
-        synchronized (sLock) {
-            client = mClient;
-        }
+        Client client = getOrCreateClient();
         if (client != null) {
             try {
                 int requestId = mNextRequestId.getAndIncrement();
@@ -419,10 +387,7 @@
             return;
         }
 
-        Client client;
-        synchronized (sLock) {
-            client = mClient;
-        }
+        Client client = getOrCreateClient();
         if (client != null) {
             try {
                 int requestId = mNextRequestId.getAndIncrement();
@@ -451,10 +416,7 @@
             return;
         }
 
-        Client client;
-        synchronized (sLock) {
-            client = mClient;
-        }
+        Client client = getOrCreateClient();
         if (client != null) {
             try {
                 int requestId = mNextRequestId.getAndIncrement();
@@ -710,15 +672,12 @@
             return;
         }
 
-        Client client;
-        synchronized (sLock) {
-            client = mClient;
-        }
+        Client client = getOrCreateClient();
         if (client != null) {
             try {
                 int requestId = mNextRequestId.getAndIncrement();
                 mMediaRouterService.selectRouteWithManager(
-                        mClient, requestId, sessionInfo.getId(), route);
+                        client, requestId, sessionInfo.getId(), route);
             } catch (RemoteException ex) {
                 Log.e(TAG, "selectRoute: Failed to send a request.", ex);
             }
@@ -755,15 +714,12 @@
             return;
         }
 
-        Client client;
-        synchronized (sLock) {
-            client = mClient;
-        }
+        Client client = getOrCreateClient();
         if (client != null) {
             try {
                 int requestId = mNextRequestId.getAndIncrement();
                 mMediaRouterService.deselectRouteWithManager(
-                        mClient, requestId, sessionInfo.getId(), route);
+                        client, requestId, sessionInfo.getId(), route);
             } catch (RemoteException ex) {
                 Log.e(TAG, "deselectRoute: Failed to send a request.", ex);
             }
@@ -794,14 +750,11 @@
         int requestId = mNextRequestId.getAndIncrement();
         mTransferRequests.add(new TransferRequest(requestId, sessionInfo, route));
 
-        Client client;
-        synchronized (sLock) {
-            client = mClient;
-        }
+        Client client = getOrCreateClient();
         if (client != null) {
             try {
                 mMediaRouterService.transferToRouteWithManager(
-                        mClient, requestId, sessionInfo.getId(), route);
+                        client, requestId, sessionInfo.getId(), route);
             } catch (RemoteException ex) {
                 Log.e(TAG, "transferToRoute: Failed to send a request.", ex);
             }
@@ -821,15 +774,12 @@
     public void releaseSession(@NonNull RoutingSessionInfo sessionInfo) {
         Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
 
-        Client client;
-        synchronized (sLock) {
-            client = mClient;
-        }
+        Client client = getOrCreateClient();
         if (client != null) {
             try {
                 int requestId = mNextRequestId.getAndIncrement();
                 mMediaRouterService.releaseSessionWithManager(
-                        mClient, requestId, sessionInfo.getId());
+                        client, requestId, sessionInfo.getId());
             } catch (RemoteException ex) {
                 Log.e(TAG, "releaseSession: Failed to send a request", ex);
             }
@@ -857,6 +807,23 @@
                 sessionInfo.getOwnerPackageName());
     }
 
+    private Client getOrCreateClient() {
+        synchronized (sLock) {
+            if (mClient != null) {
+                return mClient;
+            }
+            Client client = new Client();
+            try {
+                mMediaRouterService.registerManager(client, mPackageName);
+                mClient = client;
+                return client;
+            } catch (RemoteException ex) {
+                Log.e(TAG, "Unable to register media router manager.", ex);
+            }
+        }
+        return null;
+    }
+
     /**
      * Interface for receiving events about media routing changes.
      */
diff --git a/media/java/android/media/projection/MediaProjectionManager.java b/media/java/android/media/projection/MediaProjectionManager.java
index b5e2213..c4d27ec 100644
--- a/media/java/android/media/projection/MediaProjectionManager.java
+++ b/media/java/android/media/projection/MediaProjectionManager.java
@@ -23,8 +23,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.media.projection.IMediaProjection;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -86,6 +84,12 @@
      * capture request. Will be null if the result from the
      * startActivityForResult() is anything other than RESULT_OK.
      *
+     * Starting from Android {@link android.os.Build.VERSION_CODES#R}, if your application requests
+     * the {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW} permission, and the
+     * user has not explicitly denied it, the permission will be automatically granted until the
+     * projection is stopped. This allows for user controls to be displayed on top of the screen
+     * being captured.
+     *
      * @param resultCode The result code from {@link android.app.Activity#onActivityResult(int,
      * int, android.content.Intent)}
      * @param resultData The resulting data from {@link android.app.Activity#onActivityResult(int,
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 50af60a..a458b16 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -23,6 +23,7 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.app.ActivityManager;
 import android.content.Context;
 import android.hardware.tv.tuner.V1_0.Constants;
 import android.media.tv.TvInputService;
@@ -55,6 +56,8 @@
 import android.os.Message;
 import android.util.Log;
 
+import com.android.internal.util.FrameworkStatsLog;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -208,7 +211,7 @@
     private FrontendInfo mFrontendInfo;
     private Integer mFrontendHandle;
     private int mFrontendType = FrontendSettings.TYPE_UNDEFINED;
-
+    private int mUserId;
     private Lnb mLnb;
     private Integer mLnbHandle;
     @Nullable
@@ -232,6 +235,11 @@
             new TunerResourceManager.ResourcesReclaimListener() {
                 @Override
                 public void onReclaimResources() {
+                    if (mFrontend != null) {
+                        FrameworkStatsLog
+                                .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
+                                    FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__UNKNOWN);
+                    }
                     mHandler.sendMessage(mHandler.obtainMessage(MSG_RESOURCE_LOST));
                 }
             };
@@ -261,6 +269,8 @@
                 profile, new HandlerExecutor(mHandler), mResourceListener, clientId);
         mClientId = clientId[0];
 
+        mUserId = ActivityManager.getCurrentUser();
+
         setFrontendInfoList();
         setLnbIds();
     }
@@ -358,6 +368,9 @@
                 TunerUtils.throwExceptionForResult(res, "failed to close frontend");
             }
             mTunerResourceManager.releaseFrontend(mFrontendHandle, mClientId);
+            FrameworkStatsLog
+                    .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
+                        FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__UNKNOWN);
             mFrontendHandle = null;
             mFrontend = null;
         }
@@ -557,9 +570,14 @@
      */
     @Result
     public int tune(@NonNull FrontendSettings settings) {
+        Log.d(TAG, "Tune to " + settings.getFrequency());
         mFrontendType = settings.getType();
         if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)) {
             mFrontendInfo = null;
+            Log.d(TAG, "Write Stats Log for tuning.");
+            FrameworkStatsLog
+                    .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
+                        FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__TUNING);
             return nativeTune(settings.getType(), settings);
         }
         return RESULT_UNAVAILABLE;
@@ -602,6 +620,9 @@
             mScanCallback = scanCallback;
             mScanCallbackExecutor = executor;
             mFrontendInfo = null;
+            FrameworkStatsLog
+                    .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
+                        FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__SCANNING);
             return nativeScan(settings.getType(), settings, scanType);
         }
         return RESULT_UNAVAILABLE;
@@ -620,6 +641,10 @@
      */
     @Result
     public int cancelScanning() {
+        FrameworkStatsLog
+                .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
+                    FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__SCAN_STOPPED);
+
         int retVal = nativeStopScan();
         mScanCallback = null;
         mScanCallbackExecutor = null;
@@ -779,12 +804,33 @@
     }
 
     private void onFrontendEvent(int eventType) {
+        Log.d(TAG, "Got event from tuning. Event type: " + eventType);
         if (mOnTunerEventExecutor != null && mOnTuneEventListener != null) {
             mOnTunerEventExecutor.execute(() -> mOnTuneEventListener.onTuneEvent(eventType));
         }
+
+        Log.d(TAG, "Wrote Stats Log for the events from tuning.");
+        if (eventType == OnTuneEventListener.SIGNAL_LOCKED) {
+            FrameworkStatsLog
+                    .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
+                        FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__LOCKED);
+        } else if (eventType == OnTuneEventListener.SIGNAL_NO_SIGNAL) {
+            FrameworkStatsLog
+                    .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
+                        FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__NOT_LOCKED);
+        } else if (eventType == OnTuneEventListener.SIGNAL_LOST_LOCK) {
+            FrameworkStatsLog
+                    .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
+                        FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__SIGNAL_LOST);
+        }
     }
 
     private void onLocked() {
+        Log.d(TAG, "Wrote Stats Log for locked event from scanning.");
+        FrameworkStatsLog
+                .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
+                    FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__LOCKED);
+
         if (mScanCallbackExecutor != null && mScanCallback != null) {
             mScanCallbackExecutor.execute(() -> mScanCallback.onLocked());
         }
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 331477f..43cb25f 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -43,7 +43,7 @@
 
 #include <android_runtime/android_hardware_HardwareBuffer.h>
 
-#include <binder/MemoryHeapBase.h>
+#include <binder/MemoryDealer.h>
 
 #include <cutils/compiler.h>
 
@@ -306,6 +306,7 @@
     CHECK(format->findString("mime", &mime));
     mGraphicOutput = (mime.startsWithIgnoreCase("video/") || mime.startsWithIgnoreCase("image/"))
             && !(flags & CONFIGURE_FLAG_ENCODE);
+    mHasCryptoOrDescrambler = (crypto != nullptr) || (descrambler != nullptr);
 
     return mCodec->configure(
             format, mSurfaceTextureClient, crypto, descrambler, flags);
@@ -1603,14 +1604,13 @@
         ScopedLocalRef<jobject> patternObj{
             env, env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoPatternID)};
 
-        CryptoPlugin::Pattern pattern;
         if (patternObj.get() == nullptr) {
-            pattern.mEncryptBlocks = 0;
-            pattern.mSkipBlocks = 0;
+            mPattern.mEncryptBlocks = 0;
+            mPattern.mSkipBlocks = 0;
         } else {
-            pattern.mEncryptBlocks = env->GetIntField(
+            mPattern.mEncryptBlocks = env->GetIntField(
                     patternObj.get(), gFields.patternEncryptBlocksID);
-            pattern.mSkipBlocks = env->GetIntField(
+            mPattern.mSkipBlocks = env->GetIntField(
                     patternObj.get(), gFields.patternSkipBlocksID);
         }
 
@@ -1679,6 +1679,18 @@
                 mIv = env->GetByteArrayElements(mIvObj.get(), nullptr);
             }
         }
+
+    }
+
+    explicit NativeCryptoInfo(jint size)
+        : mIvObj{nullptr, nullptr},
+          mKeyObj{nullptr, nullptr},
+          mMode{CryptoPlugin::kMode_Unencrypted},
+          mPattern{0, 0} {
+        mSubSamples = new CryptoPlugin::SubSample[1];
+        mNumSubSamples = 1;
+        mSubSamples[0].mNumBytesOfClearData = size;
+        mSubSamples[0].mNumBytesOfEncryptedData = 0;
     }
 
     ~NativeCryptoInfo() {
@@ -2128,10 +2140,13 @@
         if (env->GetBooleanField(bufferObj, gLinearBlockInfo.validId)) {
             JMediaCodecLinearBlock *context =
                 (JMediaCodecLinearBlock *)env->GetLongField(bufferObj, gLinearBlockInfo.contextId);
-            if (cryptoInfoObj != nullptr) {
+            if (codec->hasCryptoOrDescrambler()) {
                 memory = context->toHidlMemory();
+                // TODO: copy if memory is null
+                offset += context->mHidlMemoryOffset;
             } else {
                 buffer = context->toC2Buffer(offset, size);
+                // TODO: copy if buffer is null
             }
         }
         env->MonitorExit(lock.get());
@@ -2141,13 +2156,19 @@
     }
 
     AString errorDetailMsg;
-    if (cryptoInfoObj != nullptr) {
+    if (codec->hasCryptoOrDescrambler()) {
         if (!memory) {
+            ALOGI("queueLinearBlock: no ashmem memory for encrypted content");
             throwExceptionAsNecessary(env, BAD_VALUE);
             return;
         }
-
-        NativeCryptoInfo cryptoInfo{env, cryptoInfoObj};
+        NativeCryptoInfo cryptoInfo = [env, cryptoInfoObj, size]{
+            if (cryptoInfoObj == nullptr) {
+                return NativeCryptoInfo{size};
+            } else {
+                return NativeCryptoInfo{env, cryptoInfoObj};
+            }
+        }();
         err = codec->queueEncryptedLinearBlock(
                 index,
                 memory,
@@ -2162,6 +2183,7 @@
                 &errorDetailMsg);
     } else {
         if (!buffer) {
+            ALOGI("queueLinearBlock: no C2Buffer found");
             throwExceptionAsNecessary(env, BAD_VALUE);
             return;
         }
@@ -2955,13 +2977,13 @@
                 context->mLegacyBuffer->size(),
                 true,  // readOnly
                 true /* clearBuffer */);
-    } else if (context->mHeap) {
+    } else if (context->mMemory) {
         return CreateByteBuffer(
                 env,
-                static_cast<uint8_t *>(context->mHeap->getBase()) + context->mHeap->getOffset(),
-                context->mHeap->getSize(),
+                context->mMemory->unsecurePointer(),
+                context->mMemory->size(),
                 0,
-                context->mHeap->getSize(),
+                context->mMemory->size(),
                 false,  // readOnly
                 true /* clearBuffer */);
     }
@@ -3011,8 +3033,26 @@
         }
     }
     if (hasSecure && !hasNonSecure) {
-        context->mHeap = new MemoryHeapBase(capacity);
-        context->mMemory = hardware::fromHeap(context->mHeap);
+        constexpr size_t kInitialDealerCapacity = 1048576;  // 1MB
+        thread_local sp<MemoryDealer> sDealer = new MemoryDealer(
+                kInitialDealerCapacity, "JNI(1MB)");
+        context->mMemory = sDealer->allocate(capacity);
+        if (context->mMemory == nullptr) {
+            size_t newDealerCapacity = sDealer->getMemoryHeap()->getSize() * 2;
+            while (capacity * 2 > newDealerCapacity) {
+                newDealerCapacity *= 2;
+            }
+            ALOGI("LinearBlock.native_obtain: "
+                  "Dealer capacity increasing from %zuMB to %zuMB",
+                  sDealer->getMemoryHeap()->getSize() / 1048576,
+                  newDealerCapacity / 1048576);
+            sDealer = new MemoryDealer(
+                    newDealerCapacity,
+                    AStringPrintf("JNI(%zuMB)", newDealerCapacity).c_str());
+            context->mMemory = sDealer->allocate(capacity);
+        }
+        context->mHidlMemory = hardware::fromHeap(context->mMemory->getMemory(
+                    &context->mHidlMemoryOffset, &context->mHidlMemorySize));
     } else {
         context->mBlock = MediaCodec::FetchLinearBlock(capacity, names);
         if (!context->mBlock) {
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 400ce1b..5c34341 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -162,6 +162,8 @@
 
     void selectAudioPresentation(const int32_t presentationId, const int32_t programId);
 
+    bool hasCryptoOrDescrambler() { return mHasCryptoOrDescrambler; }
+
 protected:
     virtual ~JMediaCodec();
 
@@ -181,6 +183,7 @@
     sp<MediaCodec> mCodec;
     AString mNameAtCreation;
     bool mGraphicOutput{false};
+    bool mHasCryptoOrDescrambler{false};
     std::once_flag mReleaseFlag;
 
     sp<AMessage> mCallbackNotification;
diff --git a/media/jni/android_media_MediaCodecLinearBlock.h b/media/jni/android_media_MediaCodecLinearBlock.h
index 0843834..8f1d2fa 100644
--- a/media/jni/android_media_MediaCodecLinearBlock.h
+++ b/media/jni/android_media_MediaCodecLinearBlock.h
@@ -31,8 +31,10 @@
     std::shared_ptr<C2LinearBlock> mBlock;
     std::shared_ptr<C2WriteView> mReadWriteMapping;
 
-    sp<IMemoryHeap> mHeap;
-    sp<hardware::HidlMemory> mMemory;
+    sp<IMemory> mMemory;
+    sp<hardware::HidlMemory> mHidlMemory;
+    ssize_t mHidlMemoryOffset;
+    size_t mHidlMemorySize;
 
     sp<MediaCodecBuffer> mLegacyBuffer;
 
@@ -56,8 +58,8 @@
     }
 
     sp<hardware::HidlMemory> toHidlMemory() {
-        if (mMemory) {
-            return mMemory;
+        if (mHidlMemory) {
+            return mHidlMemory;
         }
         return nullptr;
     }
@@ -65,4 +67,4 @@
 
 }  // namespace android
 
-#endif  // _ANDROID_MEDIA_MEDIACODECLINEARBLOCK_H_
\ No newline at end of file
+#endif  // _ANDROID_MEDIA_MEDIACODECLINEARBLOCK_H_
diff --git a/media/jni/android_media_MediaMuxer.cpp b/media/jni/android_media_MediaMuxer.cpp
index 0c1e9a2..262ec76 100644
--- a/media/jni/android_media_MediaMuxer.cpp
+++ b/media/jni/android_media_MediaMuxer.cpp
@@ -26,15 +26,11 @@
 #include <unistd.h>
 #include <fcntl.h>
 
-#include <android/api-level.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaMuxer.h>
 
-extern "C" int android_get_application_target_sdk_version();
-
 namespace android {
 
 struct fields_t {
@@ -233,31 +229,11 @@
 
     status_t err = muxer->stop();
 
-    if (android_get_application_target_sdk_version() >= __ANDROID_API_R__) {
-        switch (err) {
-            case OK:
-                break;
-            case ERROR_IO: {
-                jniThrowException(env, "java/lang/UncheckedIOException",
-                                  "Muxer stopped unexpectedly");
-                return;
-            }
-            case ERROR_MALFORMED: {
-                jniThrowException(env, "java/io/IOError",
-                                  "Failure of reading or writing operation");
-                return;
-            }
-            default: {
-                jniThrowException(env, "java/lang/IllegalStateException",
-                                  "Failed to stop the muxer");
-                return;
-            }
-        }
-    } else {
-        if (err != OK) {
-            jniThrowException(env, "java/lang/IllegalStateException", "Failed to stop the muxer");
-            return;
-        }
+    if (err != OK) {
+        ALOGE("Error during stop:%d", err);
+        jniThrowException(env, "java/lang/IllegalStateException",
+                    "Error during stop(), muxer would have stopped already");
+        return;
     }
 }
 
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
index eee797a..c05c21c 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
@@ -603,6 +603,11 @@
         assertTrue(onSessionCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
     }
 
+    @Test
+    public void testGetActiveSessions_returnsNonEmptyList() {
+        assertFalse(mManager.getActiveSessions().isEmpty());
+    }
+
     Map<String, MediaRoute2Info> waitAndGetRoutesWithManager(List<String> routeFeatures)
             throws Exception {
         CountDownLatch addedLatch = new CountDownLatch(1);
diff --git a/packages/CarSystemUI/AndroidManifest.xml b/packages/CarSystemUI/AndroidManifest.xml
index 261b9f5..1dd0291 100644
--- a/packages/CarSystemUI/AndroidManifest.xml
+++ b/packages/CarSystemUI/AndroidManifest.xml
@@ -25,4 +25,6 @@
     <uses-permission android:name="android.car.permission.CAR_ENROLL_TRUST"/>
     <!-- This permission is required to get bluetooth broadcast. -->
     <uses-permission android:name="android.permission.BLUETOOTH" />
+    <!-- This permission is required to check the foreground user id. -->
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
 </manifest>
diff --git a/packages/CarSystemUI/res/layout/car_user_switching_dialog.xml b/packages/CarSystemUI/res/layout/car_user_switching_dialog.xml
new file mode 100644
index 0000000..0a29424
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/car_user_switching_dialog.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:fitsSystemWindows="true"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:gravity="center"
+    android:background="@color/car_user_switching_dialog_background_color">
+  <LinearLayout
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:orientation="vertical"
+      android:layout_gravity="center"
+      android:gravity="center_horizontal">
+    <ImageView
+        android:id="@+id/user_loading_avatar"
+        android:layout_width="@dimen/car_fullscreen_user_pod_image_avatar_width"
+        android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height"/>
+
+    <TextView
+        android:id="@+id/user_loading"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/car_user_switching_dialog_loading_text_margin_top"
+        android:textSize="@dimen/car_user_switching_dialog_loading_text_font_size"
+        android:textColor="@color/car_user_switching_dialog_loading_text_color"
+        android:layout_below="@id/user_loading_avatar"/>
+  </LinearLayout>
+</FrameLayout>
diff --git a/packages/CarSystemUI/res/layout/sysui_overlay_window.xml b/packages/CarSystemUI/res/layout/sysui_overlay_window.xml
index 3542323..2dc499c 100644
--- a/packages/CarSystemUI/res/layout/sysui_overlay_window.xml
+++ b/packages/CarSystemUI/res/layout/sysui_overlay_window.xml
@@ -39,4 +39,9 @@
               android:layout_height="match_parent"
               android:layout="@layout/car_fullscreen_user_switcher"/>
 
+    <ViewStub android:id="@+id/user_switching_dialog_stub"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:layout="@layout/car_user_switching_dialog"/>
+
 </FrameLayout>
\ No newline at end of file
diff --git a/packages/CarSystemUI/res/values-ar/strings.xml b/packages/CarSystemUI/res/values-ar/strings.xml
index 320df58..57181a8 100644
--- a/packages/CarSystemUI/res/values-ar/strings.xml
+++ b/packages/CarSystemUI/res/values-ar/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"مستخدم جديد"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"عند إضافة مستخدم جديد، على هذا المستخدم إعداد مساحته."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"يمكن لأي مستخدم تحديث التطبيقات لجميع المستخدمين الآخرين."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-as/strings.xml b/packages/CarSystemUI/res/values-as/strings.xml
index 87e27b3..b66bd93 100644
--- a/packages/CarSystemUI/res/values-as/strings.xml
+++ b/packages/CarSystemUI/res/values-as/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"নতুন ব্যৱহাৰকাৰী"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"আপুনি যেতিয়া এজন নতুন ব্যৱহাৰকাৰীক যোগ কৰে, তেতিয়া তেওঁ নিজৰ ঠাই ছেট আপ কৰাটো প্ৰয়োজন হয়।"</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"যিকোনো ব্যৱহাৰকাৰীয়ে অন্য ব্যৱহাৰকাৰীৰ বাবে এপ্‌সমূহ আপডে’ট কৰিব পাৰে।"</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-az/strings.xml b/packages/CarSystemUI/res/values-az/strings.xml
index 98dd49b..bc62c8c 100644
--- a/packages/CarSystemUI/res/values-az/strings.xml
+++ b/packages/CarSystemUI/res/values-az/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Yeni İstifadəçi"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Yeni istifadəçi əlavə etdiyinizdə həmin şəxs öz yerini təyin etməlidir."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"İstənilən istifadəçi digər bütün istifadəçilər üçün tətbiqləri güncəlləyə bilər."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-b+sr+Latn/strings.xml b/packages/CarSystemUI/res/values-b+sr+Latn/strings.xml
index 3f01a3a..9b6a866 100644
--- a/packages/CarSystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/CarSystemUI/res/values-b+sr+Latn/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Novi korisnik"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kada dodate novog korisnika, ta osoba treba da podesi svoj prostor."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Svaki korisnik može da ažurira aplikacije za sve ostale korisnike."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-be/strings.xml b/packages/CarSystemUI/res/values-be/strings.xml
index 1b26c37..11f8435 100644
--- a/packages/CarSystemUI/res/values-be/strings.xml
+++ b/packages/CarSystemUI/res/values-be/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Новы карыстальнік"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Калі вы дадаяце новага карыстальніка, яму трэба наладзіць свой профіль."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Кожны карыстальнік прылады можа абнаўляць праграмы для ўсіх іншых карыстальнікаў."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-bg/strings.xml b/packages/CarSystemUI/res/values-bg/strings.xml
index dda69ec..ae2db2d 100644
--- a/packages/CarSystemUI/res/values-bg/strings.xml
+++ b/packages/CarSystemUI/res/values-bg/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Нов потребител"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Когато добавите нов потребител, той трябва да настрои работната си област."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Всеки потребител може да актуализира приложенията за всички останали потребители."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Зарежда се"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Потребителят се зарежда (от <xliff:g id="FROM_USER">%1$d</xliff:g> до <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-bn/strings.xml b/packages/CarSystemUI/res/values-bn/strings.xml
index a41f672..263f0a7 100644
--- a/packages/CarSystemUI/res/values-bn/strings.xml
+++ b/packages/CarSystemUI/res/values-bn/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"নতুন ব্যবহারকারী"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"নতুন ব্যবহারকারী যোগ করলে, তার স্পেস তাকে সেট-আপ করে নিতে হবে।"</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"যেকোনও ব্যবহারকারী বাকি সব ব্যবহারকারীর জন্য অ্যাপ আপডেট করতে পারবেন।"</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-bs/strings.xml b/packages/CarSystemUI/res/values-bs/strings.xml
index 4b096d6..a8a6f6b 100644
--- a/packages/CarSystemUI/res/values-bs/strings.xml
+++ b/packages/CarSystemUI/res/values-bs/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Novi korisnik"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kada dodate novog korisnika, ta osoba treba postaviti svoj prostor."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Bilo koji korisnik može ažurirati aplikacije za sve druge korisnike."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Učitavanje"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Učitavanje korisnika (od <xliff:g id="FROM_USER">%1$d</xliff:g> do <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-ca/strings.xml b/packages/CarSystemUI/res/values-ca/strings.xml
index a78bff1..a4aa731 100644
--- a/packages/CarSystemUI/res/values-ca/strings.xml
+++ b/packages/CarSystemUI/res/values-ca/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Usuari nou"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Quan s\'afegeix un usuari nou, aquest usuari ha de configurar el seu espai."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Qualsevol usuari pot actualitzar les aplicacions de la resta d\'usuaris."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-cs/strings.xml b/packages/CarSystemUI/res/values-cs/strings.xml
index d2fdf36..a2c20f6 100644
--- a/packages/CarSystemUI/res/values-cs/strings.xml
+++ b/packages/CarSystemUI/res/values-cs/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Nový uživatel"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Každý nově přidaný uživatel si musí nastavit vlastní prostor."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Každý uživatel může aktualizovat aplikace všech ostatních uživatelů."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-da/strings.xml b/packages/CarSystemUI/res/values-da/strings.xml
index 90bd0ac..b19cdcb 100644
--- a/packages/CarSystemUI/res/values-da/strings.xml
+++ b/packages/CarSystemUI/res/values-da/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Ny bruger"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Når du tilføjer en ny bruger, skal vedkommende konfigurere sit område."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Alle brugere kan opdatere apps for alle andre brugere."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Indlæser"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Indlæser bruger (fra <xliff:g id="FROM_USER">%1$d</xliff:g> til <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-de/strings.xml b/packages/CarSystemUI/res/values-de/strings.xml
index 84c9b78..960f526 100644
--- a/packages/CarSystemUI/res/values-de/strings.xml
+++ b/packages/CarSystemUI/res/values-de/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Neuer Nutzer"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Wenn du einen neuen Nutzer hinzufügst, muss dieser seinen Bereich einrichten."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Jeder Nutzer kann Apps für alle anderen Nutzer aktualisieren."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-el/strings.xml b/packages/CarSystemUI/res/values-el/strings.xml
index fcbb0fd..e2d2cec 100644
--- a/packages/CarSystemUI/res/values-el/strings.xml
+++ b/packages/CarSystemUI/res/values-el/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Νέος χρήστης"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Κατά την προσθήκη ενός νέου χρήστη, αυτός θα πρέπει να ρυθμίσει τον χώρο του."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Οποιοσδήποτε χρήστης μπορεί να ενημερώσει τις εφαρμογές για όλους τους άλλους χρήστες."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Φόρτωση"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Φόρτωση χρήστη (από <xliff:g id="FROM_USER">%1$d</xliff:g> έως <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-en-rAU/strings.xml b/packages/CarSystemUI/res/values-en-rAU/strings.xml
index a87eb87..b8bf990 100644
--- a/packages/CarSystemUI/res/values-en-rAU/strings.xml
+++ b/packages/CarSystemUI/res/values-en-rAU/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"New user"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"When you add a new user, that person needs to set up their space."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Any user can update apps for all other users."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Loading"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Loading user (from <xliff:g id="FROM_USER">%1$d</xliff:g> to <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-en-rCA/strings.xml b/packages/CarSystemUI/res/values-en-rCA/strings.xml
index a87eb87..b8bf990 100644
--- a/packages/CarSystemUI/res/values-en-rCA/strings.xml
+++ b/packages/CarSystemUI/res/values-en-rCA/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"New user"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"When you add a new user, that person needs to set up their space."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Any user can update apps for all other users."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Loading"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Loading user (from <xliff:g id="FROM_USER">%1$d</xliff:g> to <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-en-rGB/strings.xml b/packages/CarSystemUI/res/values-en-rGB/strings.xml
index a87eb87..b8bf990 100644
--- a/packages/CarSystemUI/res/values-en-rGB/strings.xml
+++ b/packages/CarSystemUI/res/values-en-rGB/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"New user"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"When you add a new user, that person needs to set up their space."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Any user can update apps for all other users."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Loading"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Loading user (from <xliff:g id="FROM_USER">%1$d</xliff:g> to <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-en-rIN/strings.xml b/packages/CarSystemUI/res/values-en-rIN/strings.xml
index a87eb87..b8bf990 100644
--- a/packages/CarSystemUI/res/values-en-rIN/strings.xml
+++ b/packages/CarSystemUI/res/values-en-rIN/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"New user"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"When you add a new user, that person needs to set up their space."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Any user can update apps for all other users."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Loading"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Loading user (from <xliff:g id="FROM_USER">%1$d</xliff:g> to <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-en-rXC/strings.xml b/packages/CarSystemUI/res/values-en-rXC/strings.xml
index 6821c3e..1ffa5eb 100644
--- a/packages/CarSystemUI/res/values-en-rXC/strings.xml
+++ b/packages/CarSystemUI/res/values-en-rXC/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‎‎‏‏‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‎New User‎‏‎‎‏‎"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‏‎‏‏‏‎‎‎‎‎‎‎‎‏‏‎When you add a new user, that person needs to set up their space.‎‏‎‎‏‎"</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎‏‎‏‎‎‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‎Any user can update apps for all other users.‎‏‎‎‏‎"</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎Loading‎‏‎‎‏‎"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‏‎‎‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‎‎‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‎‎‏‎‏‏‎Loading user (from ‎‏‎‎‏‏‎<xliff:g id="FROM_USER">%1$d</xliff:g>‎‏‎‎‏‏‏‎ to ‎‏‎‎‏‏‎<xliff:g id="TO_USER">%2$d</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-es-rUS/strings.xml b/packages/CarSystemUI/res/values-es-rUS/strings.xml
index 060c812..c1c21d1 100644
--- a/packages/CarSystemUI/res/values-es-rUS/strings.xml
+++ b/packages/CarSystemUI/res/values-es-rUS/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Usuario nuevo"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Cuando agregues un usuario nuevo, esa persona deberá configurar su espacio."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Cualquier usuario podrá actualizar las apps de otras personas."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Cargando"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Cargando usuario (de <xliff:g id="FROM_USER">%1$d</xliff:g> a <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-es/strings.xml b/packages/CarSystemUI/res/values-es/strings.xml
index c3cc86a..58aab64 100644
--- a/packages/CarSystemUI/res/values-es/strings.xml
+++ b/packages/CarSystemUI/res/values-es/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Nuevo usuario"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Cuando añades un usuario, esa persona debe configurar su espacio."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Cualquier usuario puede actualizar las aplicaciones del resto de los usuarios."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-et/strings.xml b/packages/CarSystemUI/res/values-et/strings.xml
index 1bf7ce5..2fa71a9 100644
--- a/packages/CarSystemUI/res/values-et/strings.xml
+++ b/packages/CarSystemUI/res/values-et/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Uus kasutaja"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kui lisate uue kasutaja, siis peab ta seadistama oma ruumi."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Iga kasutaja saab rakendusi värskendada kõigi teiste kasutajate jaoks."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Laadimine"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Kasutaja laadimine (<xliff:g id="FROM_USER">%1$d</xliff:g> &gt; <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-eu/strings.xml b/packages/CarSystemUI/res/values-eu/strings.xml
index 1786381..36bcaae 100644
--- a/packages/CarSystemUI/res/values-eu/strings.xml
+++ b/packages/CarSystemUI/res/values-eu/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Erabiltzaile berria"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Erabiltzaile bat gehitzen duzunean, bere eremua konfiguratu beharko du."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Edozein erabiltzailek egunera ditzake beste erabiltzaile guztien aplikazioak."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Kargatzen"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Erabiltzailea kargatzen (<xliff:g id="FROM_USER">%1$d</xliff:g> izatetik<xliff:g id="TO_USER">%2$d</xliff:g> izatera igaroko da)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-fa/strings.xml b/packages/CarSystemUI/res/values-fa/strings.xml
index 0bd79ba..ec00e29 100644
--- a/packages/CarSystemUI/res/values-fa/strings.xml
+++ b/packages/CarSystemUI/res/values-fa/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"کاربر جدید"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"وقتی کاربر جدیدی اضافه می‌کنید، آن فرد باید فضای خود را تنظیم کند."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"هر کاربری می‌تواند برنامه‌ها را برای همه کاربران دیگر به‌روزرسانی کند."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-fi/strings.xml b/packages/CarSystemUI/res/values-fi/strings.xml
index 7aa5a54..3cc7f30 100644
--- a/packages/CarSystemUI/res/values-fi/strings.xml
+++ b/packages/CarSystemUI/res/values-fi/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Uusi käyttäjä"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kun lisäät uuden käyttäjän, hänen on valittava oman tilansa asetukset."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Kaikki käyttäjät voivat päivittää muiden käyttäjien sovelluksia."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-fr-rCA/strings.xml b/packages/CarSystemUI/res/values-fr-rCA/strings.xml
index 22b4409..18e68c0 100644
--- a/packages/CarSystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/CarSystemUI/res/values-fr-rCA/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Nouvel utilisateur"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Tout utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Chargement en cours…"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Chargement de l\'utilisateur (de <xliff:g id="FROM_USER">%1$d</xliff:g> vers <xliff:g id="TO_USER">%2$d</xliff:g>) en cours…"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-fr/strings.xml b/packages/CarSystemUI/res/values-fr/strings.xml
index b28c620..1a81695 100644
--- a/packages/CarSystemUI/res/values-fr/strings.xml
+++ b/packages/CarSystemUI/res/values-fr/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Nouvel utilisateur"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"N\'importe quel utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-gl/strings.xml b/packages/CarSystemUI/res/values-gl/strings.xml
index d2178ab..3fbb291 100644
--- a/packages/CarSystemUI/res/values-gl/strings.xml
+++ b/packages/CarSystemUI/res/values-gl/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Novo usuario"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Cando engadas un novo usuario, este deberá configurar o seu espazo."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Calquera usuario pode actualizar as aplicacións para o resto dos usuarios."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-gu/strings.xml b/packages/CarSystemUI/res/values-gu/strings.xml
index 5c69483..496f3b5 100644
--- a/packages/CarSystemUI/res/values-gu/strings.xml
+++ b/packages/CarSystemUI/res/values-gu/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"નવા વપરાશકર્તા"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"જ્યારે તમે કોઈ નવા વપરાશકર્તાને ઉમેરો છો, ત્યારે તે વ્યક્તિએ તેમની સ્પેસ સેટ કરવાની જરૂર રહે છે."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"કોઈપણ વપરાશકર્તા અન્ય બધા વપરાશકર્તાઓ માટે ઍપને અપડેટ કરી શકે છે."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-hi/strings.xml b/packages/CarSystemUI/res/values-hi/strings.xml
index fc8b4b5..89b6960 100644
--- a/packages/CarSystemUI/res/values-hi/strings.xml
+++ b/packages/CarSystemUI/res/values-hi/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"नया उपयोगकर्ता"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"जब आप कोई नया उपयोगकर्ता जोड़ते हैं, तब उसे अपनी जगह सेट करनी होती है."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"कोई भी उपयोगकर्ता, बाकी सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकता है."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"लोड हो रही है"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"उपयोगकर्ता को लोड किया जा रहा है (<xliff:g id="FROM_USER">%1$d</xliff:g> से <xliff:g id="TO_USER">%2$d</xliff:g> पर)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-hr/strings.xml b/packages/CarSystemUI/res/values-hr/strings.xml
index befdbe9..6baec74 100644
--- a/packages/CarSystemUI/res/values-hr/strings.xml
+++ b/packages/CarSystemUI/res/values-hr/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Novi korisnik"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kada dodate novog korisnika, ta osoba mora postaviti vlastiti prostor."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Svaki korisnik može ažurirati aplikacije za ostale korisnike."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Učitavanje"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Učitavanje korisnika (od <xliff:g id="FROM_USER">%1$d</xliff:g> do <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-hu/strings.xml b/packages/CarSystemUI/res/values-hu/strings.xml
index bd1e6dc..ffa512c 100644
--- a/packages/CarSystemUI/res/values-hu/strings.xml
+++ b/packages/CarSystemUI/res/values-hu/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Új felhasználó"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Ha új felhasználót ad hozzá, az illetőnek be kell állítania saját felületét."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Bármely felhasználó frissítheti az alkalmazásokat az összes felhasználó számára."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Betöltés"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Felhasználó betöltése (<xliff:g id="FROM_USER">%1$d</xliff:g> → <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-hy/strings.xml b/packages/CarSystemUI/res/values-hy/strings.xml
index 048d44a..2ff1cf1 100644
--- a/packages/CarSystemUI/res/values-hy/strings.xml
+++ b/packages/CarSystemUI/res/values-hy/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Նոր օգտատեր"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Երբ դուք նոր օգտատեր եք ավելացնում, նա պետք է կարգավորի իր պրոֆիլը։"</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Ցանկացած օգտատեր կարող է թարմացնել հավելվածները բոլոր մյուս հաշիվների համար։"</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-in/strings.xml b/packages/CarSystemUI/res/values-in/strings.xml
index d6d7cfb..901cbe7 100644
--- a/packages/CarSystemUI/res/values-in/strings.xml
+++ b/packages/CarSystemUI/res/values-in/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Pengguna Baru"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Saat Anda menambahkan pengguna baru, orang tersebut perlu menyiapkan ruangnya sendiri."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Setiap pengguna dapat mengupdate aplikasi untuk semua pengguna lain."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Memuat"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Memuat pengguna (dari <xliff:g id="FROM_USER">%1$d</xliff:g> menjadi <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-iw/strings.xml b/packages/CarSystemUI/res/values-iw/strings.xml
index 93f2401..0ca5f2e 100644
--- a/packages/CarSystemUI/res/values-iw/strings.xml
+++ b/packages/CarSystemUI/res/values-iw/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"משתמש חדש"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"בעת הוספת משתמש חדש, על משתמש זה להגדיר את המרחב שלו."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"כל משתמש יכול לעדכן אפליקציות לכל שאר המשתמשים."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-ja/strings.xml b/packages/CarSystemUI/res/values-ja/strings.xml
index 85bd0bf..aae7dbf 100644
--- a/packages/CarSystemUI/res/values-ja/strings.xml
+++ b/packages/CarSystemUI/res/values-ja/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"新しいユーザー"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"新しいユーザーを追加したら、そのユーザーは自分のスペースをセットアップする必要があります。"</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"どのユーザーも他のすべてのユーザーに代わってアプリを更新できます。"</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"読み込んでいます"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ユーザーを読み込んでいます(<xliff:g id="FROM_USER">%1$d</xliff:g>~<xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-ka/strings.xml b/packages/CarSystemUI/res/values-ka/strings.xml
index 0e67f2a..19894d1 100644
--- a/packages/CarSystemUI/res/values-ka/strings.xml
+++ b/packages/CarSystemUI/res/values-ka/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"ახალი მომხმარებელი"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"ახალი მომხმარებლის დამატებისას, ამ მომხმარებელს საკუთარი სივრცის გამართვა მოუწევს."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"ნებისმიერ მომხმარებელს შეუძლია აპები ყველა სხვა მომხმარებლისათვის განაახლოს."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"იტვირთება"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"იტვირთება მომხმარებელი (<xliff:g id="FROM_USER">%1$d</xliff:g>-დან <xliff:g id="TO_USER">%2$d</xliff:g>-მდე)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-kk/strings.xml b/packages/CarSystemUI/res/values-kk/strings.xml
index 94a192e..8b6cde8 100644
--- a/packages/CarSystemUI/res/values-kk/strings.xml
+++ b/packages/CarSystemUI/res/values-kk/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Жаңа пайдаланушы"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Енгізілген жаңа пайдаланушы өз профилін реттеуі керек."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Кез келген пайдаланушы қолданбаларды басқа пайдаланушылар үшін жаңарта алады."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-km/strings.xml b/packages/CarSystemUI/res/values-km/strings.xml
index 47b659f..fbcab84 100644
--- a/packages/CarSystemUI/res/values-km/strings.xml
+++ b/packages/CarSystemUI/res/values-km/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"អ្នក​ប្រើប្រាស់​ថ្មី"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"នៅពេលដែល​អ្នក​បញ្ចូល​អ្នក​ប្រើប្រាស់​ថ្មី បុគ្គល​នោះ​ត្រូវតែ​រៀបចំ​ទំហំ​ផ្ទុក​របស់គេ។"</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"អ្នកប្រើប្រាស់​ណាក៏​អាច​ដំឡើងកំណែ​កម្មវិធី​សម្រាប់​អ្នកប្រើប្រាស់ទាំងអស់​ផ្សេងទៀត​បានដែរ។"</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"កំពុងផ្ទុក"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"កំពុងផ្ទុក​អ្នកប្រើប្រាស់ (ពី <xliff:g id="FROM_USER">%1$d</xliff:g> ដល់ <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-kn/strings.xml b/packages/CarSystemUI/res/values-kn/strings.xml
index 50e1721..c3cb383 100644
--- a/packages/CarSystemUI/res/values-kn/strings.xml
+++ b/packages/CarSystemUI/res/values-kn/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"ಹೊಸ ಬಳಕೆದಾರ"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"ನೀವು ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿದಾಗ, ಆ ವ್ಯಕ್ತಿಯು ಅವರ ಸ್ಥಳವನ್ನು ಸೆಟಪ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"ಯಾವುದೇ ಬಳಕೆದಾರರು ಎಲ್ಲಾ ಇತರೆ ಬಳಕೆದಾರರಿಗಾಗಿ ಆ್ಯಪ್‌ಗಳನ್ನು ಅಪ್‌ಡೇಟ್‌ ಮಾಡಬಹುದು."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-ko/strings.xml b/packages/CarSystemUI/res/values-ko/strings.xml
index 75b16a8..6b670b0 100644
--- a/packages/CarSystemUI/res/values-ko/strings.xml
+++ b/packages/CarSystemUI/res/values-ko/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"신규 사용자"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"추가된 신규 사용자는 자신만의 공간을 설정해야 합니다."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"누구나 다른 모든 사용자를 위해 앱을 업데이트할 수 있습니다."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"로드 중"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"사용자 로드 중(<xliff:g id="FROM_USER">%1$d</xliff:g>님에서 <xliff:g id="TO_USER">%2$d</xliff:g>님으로)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-ky/strings.xml b/packages/CarSystemUI/res/values-ky/strings.xml
index e9da09d..8447f7d 100644
--- a/packages/CarSystemUI/res/values-ky/strings.xml
+++ b/packages/CarSystemUI/res/values-ky/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Жаңы колдонуучу"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Жаңы колдонуучу кошулганда, ал өзүнүн профилин жөндөп алышы керек."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Колдонмолорду бир колдонуучу калган бардык колдонуучулар үчүн да жаңырта алат."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-lo/strings.xml b/packages/CarSystemUI/res/values-lo/strings.xml
index 1721377..ea8e0fb 100644
--- a/packages/CarSystemUI/res/values-lo/strings.xml
+++ b/packages/CarSystemUI/res/values-lo/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"ຜູ້ໃຊ້ໃໝ່"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"ເມື່ອທ່ານເພີ່ມຜູ້ໃຊ້ໃໝ່, ບຸກຄົນນັ້ນຈຳເປັນຕ້ອງຕັ້ງຄ່າພື້ນທີ່ຂອງເຂົາເຈົ້າ."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"ຜູ້ໃຊ້ຕ່າງໆສາມາດອັບເດດແອັບສຳລັບຜູ້ໃຊ້ອື່ນທັງໝົດໄດ້."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-lv/strings.xml b/packages/CarSystemUI/res/values-lv/strings.xml
index 8a0be70..d7b4619 100644
--- a/packages/CarSystemUI/res/values-lv/strings.xml
+++ b/packages/CarSystemUI/res/values-lv/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Jauns lietotājs"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kad pievienojat jaunu lietotāju, viņam ir jāizveido savs profils."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Ikviens lietotājs var atjaunināt lietotnes visu lietotāju vārdā."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-mk/strings.xml b/packages/CarSystemUI/res/values-mk/strings.xml
index 63cea06..f8fd02c 100644
--- a/packages/CarSystemUI/res/values-mk/strings.xml
+++ b/packages/CarSystemUI/res/values-mk/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Нов корисник"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Кога додавате нов корисник, тоа лице треба да го постави својот простор."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Секој корисник може да ажурира апликации за сите други корисници."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Се вчитува"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Се вчитува корисникот (од <xliff:g id="FROM_USER">%1$d</xliff:g> до <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-ml/strings.xml b/packages/CarSystemUI/res/values-ml/strings.xml
index 9ee34304..7273241 100644
--- a/packages/CarSystemUI/res/values-ml/strings.xml
+++ b/packages/CarSystemUI/res/values-ml/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"പുതിയ ഉപയോക്താവ്"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"നിങ്ങളൊരു പുതിയ ഉപയോക്താവിനെ ചേർക്കുമ്പോൾ, ആ വ്യക്തി സ്വന്തം ഇടം സജ്ജീകരിക്കേണ്ടതുണ്ട്."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"ഏതൊരു ഉപയോക്താവിനും മറ്റെല്ലാ ഉപയോക്താക്കൾക്കുമായി ആപ്പുകൾ അപ്‌ഡേറ്റ് ചെയ്യാനാവും."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-mn/strings.xml b/packages/CarSystemUI/res/values-mn/strings.xml
index bae5c64..5bd76dc 100644
--- a/packages/CarSystemUI/res/values-mn/strings.xml
+++ b/packages/CarSystemUI/res/values-mn/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Шинэ хэрэглэгч"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Та шинэ хэрэглэгч нэмэх үед тухайн хэрэглэгч хувийн орон зайгаа тохируулах шаардлагатай."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Бусад бүх хэрэглэгчийн аппыг дурын хэрэглэгч шинэчлэх боломжтой."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Ачаалж байна"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Хэрэглэгчийг ачаалж байна (<xliff:g id="FROM_USER">%1$d</xliff:g>-с <xliff:g id="TO_USER">%2$d</xliff:g> хүртэл)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-mr/strings.xml b/packages/CarSystemUI/res/values-mr/strings.xml
index 27ee0a9..14a4002 100644
--- a/packages/CarSystemUI/res/values-mr/strings.xml
+++ b/packages/CarSystemUI/res/values-mr/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"नवीन वापरकर्ता"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"तुम्ही नवीन वापरकर्ता जोडता तेव्हा त्या व्यक्तीने त्यांची जागा सेट करणे आवश्यक असते."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"कोणताही वापरकर्ता इतर सर्व वापरकर्त्यांसाठी अ‍ॅप्स अपडेट करू शकतो."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-ms/strings.xml b/packages/CarSystemUI/res/values-ms/strings.xml
index 868a060..29ac83a 100644
--- a/packages/CarSystemUI/res/values-ms/strings.xml
+++ b/packages/CarSystemUI/res/values-ms/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Pengguna Baharu"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Apabila anda menambahkan pengguna baharu, orang itu perlu menyediakan ruang mereka."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Mana-mana pengguna boleh mengemas kini apl untuk semua pengguna lain."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Memuatkan"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Memuatkan pengguna (daripada <xliff:g id="FROM_USER">%1$d</xliff:g> hingga <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-my/strings.xml b/packages/CarSystemUI/res/values-my/strings.xml
index 231b41f..ba16155 100644
--- a/packages/CarSystemUI/res/values-my/strings.xml
+++ b/packages/CarSystemUI/res/values-my/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"အသုံးပြုသူ အသစ်"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"အသုံးပြုသူအသစ် ထည့်သည့်အခါ ထိုသူသည် မိမိ၏ နေရာကို စနစ်ထည့်သွင်းရပါမည်။"</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"မည်သူမဆို အသုံးပြုသူအားလုံးအတွက် အက်ပ်များကို အပ်ဒိတ်လုပ်နိုင်သည်။"</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-nb/strings.xml b/packages/CarSystemUI/res/values-nb/strings.xml
index 9141cfc..a882b83 100644
--- a/packages/CarSystemUI/res/values-nb/strings.xml
+++ b/packages/CarSystemUI/res/values-nb/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Ny bruker"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Når du legger til en ny bruker, må vedkommende konfigurere sitt eget område."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Alle brukere kan oppdatere apper for alle andre brukere."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-ne/strings.xml b/packages/CarSystemUI/res/values-ne/strings.xml
index 231559d..f9eef42 100644
--- a/packages/CarSystemUI/res/values-ne/strings.xml
+++ b/packages/CarSystemUI/res/values-ne/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"नयाँ प्रयोगकर्ता"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"तपाईंले नयाँ प्रयोगकर्ता थप्दा ती व्यक्तिले आफ्नो स्थान सेटअप गर्नु पर्छ।"</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"सबै प्रयोगकर्ताले अन्य प्रयोगकर्ताका अनुप्रयोगहरू अद्यावधिक गर्न सक्छन्।"</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-nl/strings.xml b/packages/CarSystemUI/res/values-nl/strings.xml
index 5ba7ce4..95a7646 100644
--- a/packages/CarSystemUI/res/values-nl/strings.xml
+++ b/packages/CarSystemUI/res/values-nl/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Nieuwe gebruiker"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Als je een nieuwe gebruiker toevoegt, moet die persoon een eigen profiel instellen."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Elke gebruiker kan apps updaten voor alle andere gebruikers"</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Laden"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Gebruiker laden (van <xliff:g id="FROM_USER">%1$d</xliff:g> naar <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-or/strings.xml b/packages/CarSystemUI/res/values-or/strings.xml
index 1badbf9..af895d0 100644
--- a/packages/CarSystemUI/res/values-or/strings.xml
+++ b/packages/CarSystemUI/res/values-or/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"ନୂଆ ଉପଯୋଗକର୍ତ୍ତା"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"ଜଣେ ନୂଆ ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ଯୋଗ କରିବା ବେଳେ ସେହି ବ୍ୟକ୍ତିଙ୍କୁ ତାଙ୍କ ସ୍ଥାନ ସେଟ୍ ଅପ୍ କରିବାର ଆବଶ୍ୟକତା ଅଛି।"</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"ଯେ କୌଣସି ଉପଯୋଗକର୍ତ୍ତା ଅନ୍ୟ ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ ଆପଗୁଡ଼ିକୁ ଅପଡେଟ୍ କରିପାରିବେ।"</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-pa/strings.xml b/packages/CarSystemUI/res/values-pa/strings.xml
index 4687aa7..446b49c 100644
--- a/packages/CarSystemUI/res/values-pa/strings.xml
+++ b/packages/CarSystemUI/res/values-pa/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"ਜਦੋਂ ਤੁਸੀਂ ਕੋਈ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਉਸ ਵਿਅਕਤੀ ਨੂੰ ਆਪਣੀ ਜਗ੍ਹਾ ਸੈੱਟਅੱਪ ਕਰਨ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ।"</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"ਕੋਈ ਵੀ ਵਰਤੋਂਕਾਰ ਹੋਰ ਸਾਰੇ ਵਰਤੋਂਕਾਰਾਂ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਅੱਪਡੇਟ ਕਰ ਸਕਦਾ ਹੈ।"</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-pl/strings.xml b/packages/CarSystemUI/res/values-pl/strings.xml
index 35d735b..9de0b02 100644
--- a/packages/CarSystemUI/res/values-pl/strings.xml
+++ b/packages/CarSystemUI/res/values-pl/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Nowy użytkownik"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Gdy dodasz nowego użytkownika, musi on skonfigurować swój profil."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Każdy użytkownik może aktualizować aplikacje wszystkich innych użytkowników."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-pt-rPT/strings.xml b/packages/CarSystemUI/res/values-pt-rPT/strings.xml
index 7b0ee14..182f5b5 100644
--- a/packages/CarSystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/CarSystemUI/res/values-pt-rPT/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Novo utilizador"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Ao adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Qualquer utilizador pode atualizar apps para todos os outros utilizadores."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"A carregar…"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"A carregar o utilizador (de <xliff:g id="FROM_USER">%1$d</xliff:g> para <xliff:g id="TO_USER">%2$d</xliff:g>)…"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-pt/strings.xml b/packages/CarSystemUI/res/values-pt/strings.xml
index fab603d..5c8394a 100644
--- a/packages/CarSystemUI/res/values-pt/strings.xml
+++ b/packages/CarSystemUI/res/values-pt/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Novo usuário"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Quando você adiciona um usuário novo, essa pessoa precisa configurar o espaço dela."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Qualquer usuário pode atualizar apps para os demais usuários."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Carregando"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Carregando usuário (de <xliff:g id="FROM_USER">%1$d</xliff:g> para <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-ro/strings.xml b/packages/CarSystemUI/res/values-ro/strings.xml
index adf83a3..b5efb3c 100644
--- a/packages/CarSystemUI/res/values-ro/strings.xml
+++ b/packages/CarSystemUI/res/values-ro/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Utilizator nou"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Când adăugați un utilizator nou, acesta trebuie să-și configureze spațiul."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Orice utilizator poate actualiza aplicațiile pentru toți ceilalți utilizatori."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-ru/strings.xml b/packages/CarSystemUI/res/values-ru/strings.xml
index 69ee939..1397ab5 100644
--- a/packages/CarSystemUI/res/values-ru/strings.xml
+++ b/packages/CarSystemUI/res/values-ru/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Новый пользователь"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Когда вы добавите пользователя, ему потребуется настроить профиль."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Любой пользователь устройства может обновлять приложения для всех аккаунтов."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-si/strings.xml b/packages/CarSystemUI/res/values-si/strings.xml
index 061d4ed..947cb0a 100644
--- a/packages/CarSystemUI/res/values-si/strings.xml
+++ b/packages/CarSystemUI/res/values-si/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"නව පරිශීලක"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"ඔබ අලුත් පරිශීලකයෙකු එක් කරන විට, එම පුද්ගලයා තමන්ගේ ඉඩ සකසා ගැනීමට අවශ්‍ය වේ."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"සියලුම අනෙක් පරිශීලකයින් සඳහා ඕනෑම පරිශීලකයෙකුට යෙදුම් යාවත්කාලීන කළ හැක."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"පූරණය වෙමින්"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"පරිශීලකයා පූරණය වෙමින් (<xliff:g id="FROM_USER">%1$d</xliff:g> සිට <xliff:g id="TO_USER">%2$d</xliff:g> වෙත)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-sk/strings.xml b/packages/CarSystemUI/res/values-sk/strings.xml
index b5e9416..1ce7f1e 100644
--- a/packages/CarSystemUI/res/values-sk/strings.xml
+++ b/packages/CarSystemUI/res/values-sk/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Nový používateľ"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Keď pridáte nového používateľa, musí si nastaviť vlastný priestor."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Ktorýkoľvek používateľ môže aktualizovať aplikácie všetkých ostatných používateľov."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-sl/strings.xml b/packages/CarSystemUI/res/values-sl/strings.xml
index b386591..3f2c0f4 100644
--- a/packages/CarSystemUI/res/values-sl/strings.xml
+++ b/packages/CarSystemUI/res/values-sl/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Nov uporabnik"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Ko dodate novega uporabnika, mora ta nastaviti svoj prostor."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Vsak uporabnik lahko posodobi aplikacije za vse druge uporabnike."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-sq/strings.xml b/packages/CarSystemUI/res/values-sq/strings.xml
index 21484f2..a9fa951 100644
--- a/packages/CarSystemUI/res/values-sq/strings.xml
+++ b/packages/CarSystemUI/res/values-sq/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Përdorues i ri"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kur shton një përdorues të ri, ai person duhet të konfigurojë hapësirën e vet."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Çdo përdorues mund t\'i përditësojë aplikacionet për të gjithë përdoruesit e tjerë."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-sr/strings.xml b/packages/CarSystemUI/res/values-sr/strings.xml
index 2096967..0a9c2eb 100644
--- a/packages/CarSystemUI/res/values-sr/strings.xml
+++ b/packages/CarSystemUI/res/values-sr/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Нови корисник"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Када додате новог корисника, та особа треба да подеси свој простор."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Сваки корисник може да ажурира апликације за све остале кориснике."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-sv/strings.xml b/packages/CarSystemUI/res/values-sv/strings.xml
index af3f5b8..349218b 100644
--- a/packages/CarSystemUI/res/values-sv/strings.xml
+++ b/packages/CarSystemUI/res/values-sv/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Ny användare"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"När du lägger till en ny användare måste den personen konfigurera sitt utrymme."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Alla användare kan uppdatera appar för andra användare."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-sw/strings.xml b/packages/CarSystemUI/res/values-sw/strings.xml
index 1aa0868..1466f13 100644
--- a/packages/CarSystemUI/res/values-sw/strings.xml
+++ b/packages/CarSystemUI/res/values-sw/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"Mtumiaji Mpya"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Ukiongeza mtumiaji mpya, ni lazima aweke kikundi chake."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Mtumiaji yeyote anaweza kusasisha programu za watumiaji wengine."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-ta/strings.xml b/packages/CarSystemUI/res/values-ta/strings.xml
index 9f76f77..849b40d 100644
--- a/packages/CarSystemUI/res/values-ta/strings.xml
+++ b/packages/CarSystemUI/res/values-ta/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"புதிய பயனர்"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"புதிய பயனரைச் சேர்க்கும்போது அவர் தனக்கான சேமிப்பிடத்தை அமைக்க வேண்டும்."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"எந்தப் பயனரும் பிற பயனர்கள் சார்பாக ஆப்ஸைப் புதுப்பிக்க முடியும்."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"ஏற்றுகிறது"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"பயனர் தகவலை ஏற்றுகிறது (<xliff:g id="FROM_USER">%1$d</xliff:g>லிருந்து <xliff:g id="TO_USER">%2$d</xliff:g> வரை)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-te/strings.xml b/packages/CarSystemUI/res/values-te/strings.xml
index e819034..ea04cc0 100644
--- a/packages/CarSystemUI/res/values-te/strings.xml
+++ b/packages/CarSystemUI/res/values-te/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"కొత్త యూజర్"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"మీరు కొత్త యూజర్‌ను జోడించినప్పుడు, ఆ వ్యక్తి తన స్పేస్‌ను సెటప్ చేసుకోవాలి."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"ఏ యూజర్ అయినా మిగతా యూజర్‌ల కోసం యాప్‌లను అప్‌డేట్ చేయవచ్చు."</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-th/strings.xml b/packages/CarSystemUI/res/values-th/strings.xml
index 57ac7dc..fa99ac1 100644
--- a/packages/CarSystemUI/res/values-th/strings.xml
+++ b/packages/CarSystemUI/res/values-th/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"ผู้ใช้ใหม่"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"เมื่อคุณเพิ่มผู้ใช้ใหม่ ผู้ใช้ดังกล่าวจะต้องตั้งค่าพื้นที่ของตนเอง"</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"ผู้ใช้ทุกคนจะอัปเดตแอปให้แก่ผู้ใช้คนอื่นๆ ได้"</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"กำลังโหลด"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"กำลังโหลดผู้ใช้ (จาก <xliff:g id="FROM_USER">%1$d</xliff:g> ถึง <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-tl/strings.xml b/packages/CarSystemUI/res/values-tl/strings.xml
index 5e0af6d..c6f5f59 100644
--- a/packages/CarSystemUI/res/values-tl/strings.xml
+++ b/packages/CarSystemUI/res/values-tl/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Bagong User"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Kapag nagdagdag ka ng bagong user, kailangang i-set up ng taong iyon ang kanyang espasyo."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Puwedeng i-update ng sinumang user ang mga app para sa lahat ng iba pang user."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Naglo-load"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Nilo-load ang user (mula kay <xliff:g id="FROM_USER">%1$d</xliff:g> papunta kay <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-tr/strings.xml b/packages/CarSystemUI/res/values-tr/strings.xml
index 7949329..a768127 100644
--- a/packages/CarSystemUI/res/values-tr/strings.xml
+++ b/packages/CarSystemUI/res/values-tr/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Yeni Kullanıcı"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Yeni kullanıcı eklediğinizde, bu kişinin alanını ayarlaması gerekir."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Herhangi bir kullanıcı, diğer tüm kullanıcılar için uygulamaları güncelleyebilir."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Yükleniyor"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Kullanıcı yükleniyor (<xliff:g id="FROM_USER">%1$d</xliff:g> kullanıcısından <xliff:g id="TO_USER">%2$d</xliff:g> kullanıcısına)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-ur/strings.xml b/packages/CarSystemUI/res/values-ur/strings.xml
index ddfccdc..b052c0f 100644
--- a/packages/CarSystemUI/res/values-ur/strings.xml
+++ b/packages/CarSystemUI/res/values-ur/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"نیا صارف"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"جب آپ ایک نیا صارف شامل کرتے ہیں تو اس شخص کو اپنی جگہ سیٹ کرنی ہوتی ہے۔"</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"کوئی بھی صارف دیگر سبھی صارفین کے لیے ایپس کو اپ ڈیٹ کر سکتا ہے۔"</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-uz/strings.xml b/packages/CarSystemUI/res/values-uz/strings.xml
index e0f8378..adef2ad 100644
--- a/packages/CarSystemUI/res/values-uz/strings.xml
+++ b/packages/CarSystemUI/res/values-uz/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Yangi foydalanuvchi"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Yangi profil kiritilgach, uni sozlash lozim."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Qurilmaning istalgan foydalanuvchisi ilovalarni barcha hisoblar uchun yangilashi mumkin."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Yuklanmoqda"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Foydalanuvchi profili yuklanmoqda (<xliff:g id="FROM_USER">%1$d</xliff:g> – <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-vi/strings.xml b/packages/CarSystemUI/res/values-vi/strings.xml
index ce1826bc..616b48f 100644
--- a/packages/CarSystemUI/res/values-vi/strings.xml
+++ b/packages/CarSystemUI/res/values-vi/strings.xml
@@ -26,4 +26,6 @@
     <string name="car_new_user" msgid="6637442369728092473">"Người dùng mới"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"Khi bạn thêm một người dùng mới, người đó cần thiết lập không gian của mình."</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"Bất kỳ người dùng nào cũng có thể cập nhật ứng dụng cho tất cả những người dùng khác."</string>
+    <string name="car_loading_profile" msgid="4507385037552574474">"Đang tải"</string>
+    <string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Đang tải hồ sơ người dùng (từ <xliff:g id="FROM_USER">%1$d</xliff:g> sang <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
 </resources>
diff --git a/packages/CarSystemUI/res/values-zh-rCN/strings.xml b/packages/CarSystemUI/res/values-zh-rCN/strings.xml
index 431fd62..5bdc384 100644
--- a/packages/CarSystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/CarSystemUI/res/values-zh-rCN/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"新用户"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"当您添加新用户时,该用户需要自行设置个人空间。"</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"任何用户均可为所有其他用户更新应用。"</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-zh-rHK/strings.xml b/packages/CarSystemUI/res/values-zh-rHK/strings.xml
index 24efc22..74a70e2 100644
--- a/packages/CarSystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/CarSystemUI/res/values-zh-rHK/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"新使用者"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"新增的使用者需要自行設定個人空間。"</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"任何使用者都可以為所有其他使用者更新應用程式。"</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values-zh-rTW/strings.xml b/packages/CarSystemUI/res/values-zh-rTW/strings.xml
index e1356ca..c93862b 100644
--- a/packages/CarSystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/CarSystemUI/res/values-zh-rTW/strings.xml
@@ -26,4 +26,8 @@
     <string name="car_new_user" msgid="6637442369728092473">"新使用者"</string>
     <string name="user_add_user_message_setup" msgid="1035578846007352323">"新使用者必須自行設定個人空間。"</string>
     <string name="user_add_user_message_update" msgid="7061671307004867811">"任何使用者都能為所有其他使用者更新應用程式。"</string>
+    <!-- no translation found for car_loading_profile (4507385037552574474) -->
+    <skip />
+    <!-- no translation found for car_loading_profile_developer_message (1660962766911529611) -->
+    <skip />
 </resources>
diff --git a/packages/CarSystemUI/res/values/colors.xml b/packages/CarSystemUI/res/values/colors.xml
index 3e44721..0e84d51 100644
--- a/packages/CarSystemUI/res/values/colors.xml
+++ b/packages/CarSystemUI/res/values/colors.xml
@@ -55,4 +55,7 @@
     <color name="list_divider_color">@*android:color/car_list_divider_light</color>
     <color name="car_volume_item_divider_color">@*android:color/car_list_divider</color>
     <color name="car_volume_item_background_color">@*android:color/car_card_dark</color>
+
+    <color name="car_user_switching_dialog_background_color">@android:color/black</color>
+    <color name="car_user_switching_dialog_loading_text_color">@*android:color/car_body1</color>
 </resources>
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml
index 67066d7..4bf0fca 100644
--- a/packages/CarSystemUI/res/values/config.xml
+++ b/packages/CarSystemUI/res/values/config.xml
@@ -70,11 +70,13 @@
         to a constant alpha percent value using the initial alpha. -->
     <integer name="config_finalNotificationBackgroundAlpha">100</integer>
 
-    <!-- Car System UI's OverlayViewsMediator-->
+    <!-- Car System UI's OverlayViewsMediator.
+         Whenever a new class is added, make sure to also add that class to OverlayWindowModule. -->
     <string-array name="config_carSystemUIOverlayViewsMediators" translatable="false">
         <item>@string/config_notificationPanelViewMediator</item>
         <item>com.android.systemui.car.keyguard.CarKeyguardViewMediator</item>
         <item>com.android.systemui.car.userswitcher.FullscreenUserSwitcherViewMediator</item>
+        <item>com.android.systemui.car.userswitcher.UserSwitchTransitionViewMediator</item>
     </string-array>
 
     <!--
diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml
index 9014eb1..ed0b485 100644
--- a/packages/CarSystemUI/res/values/dimens.xml
+++ b/packages/CarSystemUI/res/values/dimens.xml
@@ -15,6 +15,32 @@
   ~ limitations under the License
   -->
 <resources>
+    <!-- Text size for car -->
+    <dimen name="car_title_size">32sp</dimen>
+    <dimen name="car_title2_size">32sp</dimen>
+    <dimen name="car_headline1_size">45sp</dimen>
+    <dimen name="car_headline2_size">32sp</dimen>
+    <dimen name="car_headline3_size">24sp</dimen>
+    <dimen name="car_headline4_size">20sp</dimen>
+    <dimen name="car_body1_size">32sp</dimen>
+    <dimen name="car_body2_size">28sp</dimen>
+    <dimen name="car_body3_size">26sp</dimen>
+    <dimen name="car_body4_size">24sp</dimen>
+    <!-- car_body5_size is deprecated -->
+    <dimen name="car_body5_size">18sp</dimen>
+    <dimen name="car_label1_size">26sp</dimen>
+    <dimen name="car_label2_size">64sp</dimen>
+    <dimen name="car_action1_size">26sp</dimen>
+    <dimen name="car_action2_size">26sp</dimen>
+    <!-- Paddings -->
+    <dimen name="car_padding_0">4dp</dimen>
+    <dimen name="car_padding_1">8dp</dimen>
+    <dimen name="car_padding_2">16dp</dimen>
+    <dimen name="car_padding_3">24dp</dimen>
+    <dimen name="car_padding_4">32dp</dimen>
+    <dimen name="car_padding_5">64dp</dimen>
+    <dimen name="car_padding_6">96dp</dimen>
+
     <!--
        Note: status bar height and navigation bar heights are defined
        in frameworks/base/core package and thus will have no effect if
@@ -156,4 +182,10 @@
     <dimen name="car_user_switcher_container_height">420dp</dimen>
     <!-- This must be the negative of car_user_switcher_container_height for the animation. -->
     <dimen name="car_user_switcher_container_anim_height">-420dp</dimen>
+
+    <!-- dimensions for car user switching dialog -->
+    <dimen name="car_fullscreen_user_pod_image_avatar_width">96dp</dimen>
+    <dimen name="car_fullscreen_user_pod_image_avatar_height">96dp</dimen>
+    <dimen name="car_user_switching_dialog_loading_text_margin_top">@*android:dimen/car_padding_4</dimen>
+    <dimen name="car_user_switching_dialog_loading_text_font_size">@*android:dimen/car_body1_size</dimen>
 </resources>
diff --git a/packages/CarSystemUI/res/values/strings.xml b/packages/CarSystemUI/res/values/strings.xml
index 9fae4b3..67fd5bb 100644
--- a/packages/CarSystemUI/res/values/strings.xml
+++ b/packages/CarSystemUI/res/values/strings.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License.
   -->
 
-<resources>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- String to represent lowest setting of an HVAC system [CHAR LIMIT=10]-->
     <string name="hvac_min_text">Min</string>
     <!-- String to represent largest setting of an HVAC system [CHAR LIMIT=10]-->
@@ -34,4 +34,8 @@
     <string name="user_add_user_message_setup">When you add a new user, that person needs to set up their space.</string>
     <!-- Message to inform user that the newly created user will have permissions to update apps for all other users. [CHAR LIMIT=100] -->
     <string name="user_add_user_message_update">Any user can update apps for all other users.</string>
+    <!-- Message to inform user that the new user profile is loading. [CHAR LIMIT=20] -->
+    <string name="car_loading_profile">Loading</string>
+    <!-- Message to inform user that the new user profile is loading with additional information on the previous and the next user. [CHAR LIMIT=100] -->
+    <string name="car_loading_profile_developer_message">Loading user (from <xliff:g id="from_user" example="10">%1$d</xliff:g> to <xliff:g id="to_user" example="12">%2$d</xliff:g>)</string>
 </resources>
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index f8729c3..fe2be1d 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -30,6 +30,7 @@
 import com.android.systemui.car.keyguard.CarKeyguardViewController;
 import com.android.systemui.car.statusbar.CarStatusBar;
 import com.android.systemui.car.statusbar.CarStatusBarKeyguardViewManager;
+import com.android.systemui.car.statusbar.DozeServiceHost;
 import com.android.systemui.car.statusbar.DummyNotificationShadeWindowController;
 import com.android.systemui.car.volume.CarVolumeDialogComponent;
 import com.android.systemui.dagger.SystemUIRootComponent;
@@ -37,6 +38,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.dock.DockManagerImpl;
+import com.android.systemui.doze.DozeHost;
 import com.android.systemui.plugins.qs.QSFactory;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.power.EnhancedEstimates;
@@ -174,4 +176,7 @@
     @Binds
     abstract NotificationShadeWindowController bindNotificationShadeWindowController(
             DummyNotificationShadeWindowController notificationShadeWindowController);
+
+    @Binds
+    abstract DozeHost bindDozeHost(DozeServiceHost dozeServiceHost);
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
index aee7643..ab61b44 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
@@ -188,7 +188,7 @@
         stop();
         getOverlayViewGlobalStateController().setWindowFocusable(/* focusable= */ false);
         mKeyguardStateController.notifyKeyguardDoneFading();
-        mViewMediatorCallback.keyguardGone();
+        mHandler.post(mViewMediatorCallback::keyguardGone);
         notifyKeyguardUpdateMonitor();
     }
 
@@ -203,6 +203,11 @@
             }
             mKeyguardUpdateMonitor.sendKeyguardReset();
             notifyKeyguardUpdateMonitor();
+        } else {
+            // This is necessary in order to address an inconsistency between the keyguard service
+            // and the keyguard views.
+            // TODO: Investigate the source of the inconsistency.
+            show(/* options= */ null);
         }
     }
 
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java
index 893efdc..5c6472e 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java
@@ -16,9 +16,12 @@
 
 package com.android.systemui.car.navigationbar;
 
+import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.InsetsState.ITYPE_TOP_GESTURES;
 import static android.view.InsetsState.containsType;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
 
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
@@ -34,26 +37,31 @@
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.WindowInsetsController;
 import android.view.WindowManager;
 
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.RegisterStatusBarResult;
+import com.android.internal.view.AppearanceRegion;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.car.CarDeviceProvisionedController;
 import com.android.systemui.car.CarDeviceProvisionedListener;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
+import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.statusbar.AutoHideUiElement;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.AutoHideController;
 import com.android.systemui.statusbar.phone.BarTransitions;
+import com.android.systemui.statusbar.phone.LightBarController;
 import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy;
+import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import java.io.FileDescriptor;
@@ -69,6 +77,7 @@
 
     private final Resources mResources;
     private final CarNavigationBarController mCarNavigationBarController;
+    private final SysuiDarkIconDispatcher mStatusBarIconController;
     private final WindowManager mWindowManager;
     private final CarDeviceProvisionedController mCarDeviceProvisionedController;
     private final CommandQueue mCommandQueue;
@@ -106,6 +115,7 @@
     private boolean mDeviceIsSetUpForUser = true;
     private boolean mIsUserSetupInProgress = false;
 
+    private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0];
     @BarTransitions.TransitionMode
     private int mStatusBarMode;
     @BarTransitions.TransitionMode
@@ -117,6 +127,9 @@
     public CarNavigationBar(Context context,
             @Main Resources resources,
             CarNavigationBarController carNavigationBarController,
+            // TODO(b/156052638): Should not need to inject LightBarController
+            LightBarController lightBarController,
+            DarkIconDispatcher darkIconDispatcher,
             WindowManager windowManager,
             CarDeviceProvisionedController deviceProvisionedController,
             CommandQueue commandQueue,
@@ -133,6 +146,7 @@
         super(context);
         mResources = resources;
         mCarNavigationBarController = carNavigationBarController;
+        mStatusBarIconController = (SysuiDarkIconDispatcher) darkIconDispatcher;
         mWindowManager = windowManager;
         mCarDeviceProvisionedController = deviceProvisionedController;
         mCommandQueue = commandQueue;
@@ -166,6 +180,9 @@
             ex.rethrowFromSystemServer();
         }
 
+        onSystemBarAppearanceChanged(mDisplayId, result.mAppearance, result.mAppearanceRegions,
+                result.mNavbarColorManagedByIme);
+
         // StatusBarManagerService has a back up of IME token and it's restored here.
         setImeWindowStatus(mDisplayId, result.mImeToken, result.mImeWindowVis,
                 result.mImeBackDisposition, result.mShowImeSwitcher);
@@ -362,7 +379,7 @@
                             | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                     PixelFormat.TRANSLUCENT);
             lp.setTitle("TopCarNavigationBar");
-            lp.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR};
+            lp.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR, ITYPE_TOP_GESTURES};
             lp.setFitInsetsTypes(0);
             lp.windowAnimations = 0;
             lp.gravity = Gravity.TOP;
@@ -384,7 +401,7 @@
                             | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                     PixelFormat.TRANSLUCENT);
             lp.setTitle("BottomCarNavigationBar");
-            lp.providesInsetsTypes = new int[]{ITYPE_NAVIGATION_BAR};
+            lp.providesInsetsTypes = new int[]{ITYPE_NAVIGATION_BAR, ITYPE_BOTTOM_GESTURES};
             lp.windowAnimations = 0;
             lp.gravity = Gravity.BOTTOM;
             mWindowManager.addView(mBottomNavigationBarWindow, lp);
@@ -447,6 +464,64 @@
     }
 
     @Override
+    public void onSystemBarAppearanceChanged(
+            int displayId,
+            @WindowInsetsController.Appearance int appearance,
+            AppearanceRegion[] appearanceRegions,
+            boolean navbarColorManagedByIme) {
+        if (displayId != mDisplayId) {
+            return;
+        }
+        boolean barModeChanged = updateStatusBarMode(
+                mStatusBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT);
+        int numStacks = appearanceRegions.length;
+        boolean stackAppearancesChanged = mAppearanceRegions.length != numStacks;
+        for (int i = 0; i < numStacks && !stackAppearancesChanged; i++) {
+            stackAppearancesChanged |= !appearanceRegions[i].equals(mAppearanceRegions[i]);
+        }
+        if (stackAppearancesChanged || barModeChanged) {
+            mAppearanceRegions = appearanceRegions;
+            updateStatusBarAppearance();
+        }
+    }
+
+    private void updateStatusBarAppearance() {
+        int numStacks = mAppearanceRegions.length;
+        int numLightStacks = 0;
+
+        // We can only have maximum one light stack.
+        int indexLightStack = -1;
+
+        for (int i = 0; i < numStacks; i++) {
+            if (isLight(mAppearanceRegions[i].getAppearance())) {
+                numLightStacks++;
+                indexLightStack = i;
+            }
+        }
+
+        // If all stacks are light, all icons become dark.
+        if (numLightStacks == numStacks) {
+            mStatusBarIconController.setIconsDarkArea(null);
+            mStatusBarIconController.getTransitionsController().setIconsDark(
+                    /* dark= */ true, /* animate= */ false);
+        } else if (numLightStacks == 0) {
+            // If no one is light, all icons become white.
+            mStatusBarIconController.getTransitionsController().setIconsDark(
+                    /* dark= */ false, /* animate= */ false);
+        } else {
+            // Not the same for every stack, update icons in area only.
+            mStatusBarIconController.setIconsDarkArea(
+                    mAppearanceRegions[indexLightStack].getBounds());
+            mStatusBarIconController.getTransitionsController().setIconsDark(
+                    /* dark= */ true, /* animate= */ false);
+        }
+    }
+
+    private static boolean isLight(int appearance) {
+        return (appearance & APPEARANCE_LIGHT_STATUS_BARS) != 0;
+    }
+
+    @Override
     public void showTransient(int displayId, int[] types) {
         if (displayId != mDisplayId) {
             return;
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBar.java
index e2eb3fb..d18eadd 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBar.java
@@ -425,6 +425,11 @@
     }
 
     @Override
+    public void notifyBiometricAuthModeChanged() {
+        // No op.
+    }
+
+    @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         //When executing dump() function simultaneously, we need to serialize them
         //to get mStackScroller's position correctly.
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/DozeServiceHost.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/DozeServiceHost.java
new file mode 100644
index 0000000..d23660c
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/DozeServiceHost.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.car.statusbar;
+
+import com.android.systemui.doze.DozeHost;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/** No-op implementation of {@link DozeHost} for use by car sysui, which does not support dozing. */
+@Singleton
+public class DozeServiceHost implements DozeHost {
+
+    @Inject
+    public DozeServiceHost() {}
+
+    @Override
+    public void addCallback(Callback callback) {
+        // No op.
+    }
+
+    @Override
+    public void removeCallback(Callback callback) {
+        // No op.
+    }
+
+    @Override
+    public void startDozing() {
+        // No op.
+    }
+
+    @Override
+    public void pulseWhileDozing(PulseCallback callback, int reason) {
+        // No op.
+    }
+
+    @Override
+    public void stopDozing() {
+        // No op.
+    }
+
+    @Override
+    public void dozeTimeTick() {
+        // No op.
+    }
+
+    @Override
+    public boolean isPowerSaveActive() {
+        return false;
+    }
+
+    @Override
+    public boolean isPulsingBlocked() {
+        return true;
+    }
+
+    @Override
+    public boolean isProvisioned() {
+        return false;
+    }
+
+    @Override
+    public boolean isBlockingDoze() {
+        return true;
+    }
+
+    @Override
+    public void extendPulse(int reason) {
+        // No op.
+    }
+
+    @Override
+    public void setAnimateWakeup(boolean animateWakeup) {
+        // No op.
+    }
+
+    @Override
+    public void setAnimateScreenOff(boolean animateScreenOff) {
+        // No op.
+    }
+
+    @Override
+    public void onSlpiTap(float x, float y) {
+        // No op.
+    }
+
+    @Override
+    public void setDozeScreenBrightness(int value) {
+        // No op.
+    }
+
+    @Override
+    public void prepareForGentleSleep(Runnable onDisplayOffCallback) {
+        // No op.
+    }
+
+    @Override
+    public void cancelGentleSleep() {
+        // No op.
+    }
+
+    @Override
+    public void onIgnoreTouchWhilePulsing(boolean ignore) {
+        // No op.
+    }
+
+    @Override
+    public void stopPulsing() {
+        // No op.
+    }
+
+    @Override
+    public boolean isDozeSuppressed() {
+        return true;
+    }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullscreenUserSwitcherViewMediator.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullscreenUserSwitcherViewMediator.java
index 346c38c..8b399f8 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullscreenUserSwitcherViewMediator.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullscreenUserSwitcherViewMediator.java
@@ -34,16 +34,19 @@
     private final StatusBarStateController mStatusBarStateController;
     private final FullScreenUserSwitcherViewController mFullScreenUserSwitcherViewController;
     private final CarKeyguardViewController mCarKeyguardViewController;
+    private final UserSwitchTransitionViewController mUserSwitchTransitionViewController;
 
     @Inject
     public FullscreenUserSwitcherViewMediator(
             StatusBarStateController statusBarStateController,
             CarKeyguardViewController carKeyguardViewController,
+            UserSwitchTransitionViewController userSwitchTransitionViewController,
             FullScreenUserSwitcherViewController fullScreenUserSwitcherViewController) {
 
         mStatusBarStateController = statusBarStateController;
-        mFullScreenUserSwitcherViewController = fullScreenUserSwitcherViewController;
         mCarKeyguardViewController = carKeyguardViewController;
+        mUserSwitchTransitionViewController = userSwitchTransitionViewController;
+        mFullScreenUserSwitcherViewController = fullScreenUserSwitcherViewController;
     }
 
     @Override
@@ -74,6 +77,11 @@
     private void onUserSelected(UserGridRecyclerView.UserRecord record) {
         if (record.mType != UserGridRecyclerView.UserRecord.FOREGROUND_USER) {
             mCarKeyguardViewController.hideKeyguardToPrepareBouncer();
+            // If guest user, we cannot use record.mInfo.id and should listen to the User lifecycle
+            // event instead.
+            if (record.mType != UserGridRecyclerView.UserRecord.START_GUEST) {
+                mUserSwitchTransitionViewController.handleShow(record.mInfo.id);
+            }
         }
 
         hide();
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewController.java
new file mode 100644
index 0000000..775ef81
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewController.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.car.userswitcher;
+
+import static android.car.settings.CarSettings.Global.ENABLE_USER_SWITCH_DEVELOPER_MESSAGE;
+
+import android.annotation.UserIdInt;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.settingslib.drawable.CircleFramedDrawable;
+import com.android.systemui.R;
+import com.android.systemui.car.window.OverlayViewController;
+import com.android.systemui.car.window.OverlayViewGlobalStateController;
+import com.android.systemui.dagger.qualifiers.Main;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Handles showing and hiding UserSwitchTransitionView that is mounted to SystemUiOverlayWindow.
+ */
+@Singleton
+public class UserSwitchTransitionViewController extends OverlayViewController {
+    private static final String TAG = "UserSwitchTransitionViewController";
+    private static final String ENABLE_DEVELOPER_MESSAGE_TRUE = "true";
+
+    private final Context mContext;
+    private final Handler mHandler;
+    private final Resources mResources;
+    private final UserManager mUserManager;
+
+    @GuardedBy("this")
+    private boolean mShowing;
+    private int mPreviousUserId = UserHandle.USER_NULL;
+
+    @Inject
+    public UserSwitchTransitionViewController(
+            Context context,
+            @Main Handler handler,
+            @Main Resources resources,
+            UserManager userManager,
+            OverlayViewGlobalStateController overlayViewGlobalStateController) {
+
+        super(R.id.user_switching_dialog_stub, overlayViewGlobalStateController);
+
+        mContext = context;
+        mHandler = handler;
+        mResources = resources;
+        mUserManager = userManager;
+    }
+
+    /**
+     * Makes the user switch transition view appear and draws the content inside of it if a user
+     * that is different from the previous user is provided and if the dialog is not already
+     * showing.
+     */
+    void handleShow(@UserIdInt int newUserId) {
+        if (mPreviousUserId == newUserId || mShowing) return;
+        mShowing = true;
+        mHandler.post(() -> {
+            start();
+            populateDialog(mPreviousUserId, newUserId);
+            // next time a new user is selected, this current new user will be the previous user.
+            mPreviousUserId = newUserId;
+        });
+    }
+
+    void handleHide() {
+        if (!mShowing) return;
+        mShowing = false;
+        mHandler.post(this::stop);
+    }
+
+    private void populateDialog(@UserIdInt int previousUserId, @UserIdInt int newUserId) {
+        drawUserIcon(newUserId);
+        populateLoadingText(previousUserId, newUserId);
+    }
+
+    private void drawUserIcon(int newUserId) {
+        Bitmap bitmap = mUserManager.getUserIcon(newUserId);
+        if (bitmap != null) {
+            CircleFramedDrawable drawable = CircleFramedDrawable.getInstance(mContext, bitmap);
+            ((ImageView) getLayout().findViewById(R.id.user_loading_avatar))
+                    .setImageDrawable(drawable);
+        }
+    }
+
+    private void populateLoadingText(@UserIdInt int previousUserId, @UserIdInt int newUserId) {
+        TextView msgView = getLayout().findViewById(R.id.user_loading);
+
+        boolean showInfo = ENABLE_DEVELOPER_MESSAGE_TRUE.equals(
+                Settings.Global.getString(mContext.getContentResolver(),
+                        ENABLE_USER_SWITCH_DEVELOPER_MESSAGE));
+
+        if (showInfo && mPreviousUserId != UserHandle.USER_NULL) {
+            msgView.setText(
+                    mResources.getString(R.string.car_loading_profile_developer_message,
+                            previousUserId, newUserId));
+        } else {
+            msgView.setText(mResources.getString(R.string.car_loading_profile));
+        }
+    }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediator.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediator.java
new file mode 100644
index 0000000..aea6914
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediator.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.car.userswitcher;
+
+import android.app.ActivityManager;
+import android.car.Car;
+import android.car.user.CarUserManager;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.car.CarServiceProvider;
+import com.android.systemui.car.window.OverlayViewMediator;
+
+import javax.inject.Inject;
+
+/**
+ * Registers listeners that subscribe to events that show or hide CarUserSwitchingDialog that is
+ * mounted to SystemUiOverlayWindow.
+ */
+public class UserSwitchTransitionViewMediator implements OverlayViewMediator,
+        CarUserManager.UserSwitchUiCallback {
+    private static final String TAG = "UserSwitchTransitionViewMediator";
+
+    private final CarServiceProvider mCarServiceProvider;
+    private final UserSwitchTransitionViewController mUserSwitchTransitionViewController;
+
+    @Inject
+    public UserSwitchTransitionViewMediator(
+            CarServiceProvider carServiceProvider,
+            UserSwitchTransitionViewController userSwitchTransitionViewController) {
+        mCarServiceProvider = carServiceProvider;
+        mUserSwitchTransitionViewController = userSwitchTransitionViewController;
+    }
+
+    @Override
+    public void registerListeners() {
+        mCarServiceProvider.addListener(car -> {
+            CarUserManager carUserManager =
+                    (CarUserManager) car.getCarManager(Car.CAR_USER_SERVICE);
+
+            if (carUserManager != null) {
+                carUserManager.setUserSwitchUiCallback(this);
+                carUserManager.addListener(Runnable::run, this::handleUserLifecycleEvent);
+            } else {
+                Log.e(TAG, "registerListeners: CarUserManager could not be obtained.");
+            }
+        });
+    }
+
+    @Override
+    public void setupOverlayContentViewControllers() {
+        // no-op.
+    }
+
+    @Override
+    public void showUserSwitchDialog(int userId) {
+        mUserSwitchTransitionViewController.handleShow(userId);
+    }
+
+    @VisibleForTesting
+    void handleUserLifecycleEvent(CarUserManager.UserLifecycleEvent event) {
+        if (event.getEventType() == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STARTING
+                && ActivityManager.getCurrentUser() == event.getUserId()) {
+            mUserSwitchTransitionViewController.handleShow(event.getUserId());
+        }
+
+        if (event.getEventType() == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
+            mUserSwitchTransitionViewController.handleHide();
+        }
+    }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/volume/VolumeUI.java b/packages/CarSystemUI/src/com/android/systemui/car/volume/VolumeUI.java
index 2bdb85f..03b61e0 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/volume/VolumeUI.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/volume/VolumeUI.java
@@ -52,6 +52,15 @@
             new CarAudioManager.CarVolumeCallback() {
                 @Override
                 public void onGroupVolumeChanged(int zoneId, int groupId, int flags) {
+                    initVolumeDialogComponent();
+                }
+
+                @Override
+                public void onMasterMuteChanged(int zoneId, int flags) {
+                    initVolumeDialogComponent();
+                }
+
+                private void initVolumeDialogComponent() {
                     if (mVolumeDialogComponent == null) {
                         mMainHandler.post(() -> {
                             mVolumeDialogComponent = mVolumeDialogComponentLazy.get();
@@ -60,11 +69,6 @@
                         mCarAudioManager.unregisterCarVolumeCallback(mVolumeChangeCallback);
                     }
                 }
-
-                @Override
-                public void onMasterMuteChanged(int zoneId, int flags) {
-                    // ignored
-                }
             };
 
     private boolean mEnabled;
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewMediator.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewMediator.java
index ac574ed..3e7b4a2 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewMediator.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewMediator.java
@@ -23,6 +23,9 @@
 
     /**
      * Register listeners that could use ContentVisibilityAdjuster to show/hide content.
+     *
+     * Note that we do not unregister listeners because SystemUI components are expected to live
+     * for the lifecycle of the device.
      */
     void registerListeners();
 
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayWindowModule.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayWindowModule.java
index 484aa63..5a16efa 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayWindowModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayWindowModule.java
@@ -21,6 +21,7 @@
 import com.android.systemui.car.notification.NotificationPanelViewMediator;
 import com.android.systemui.car.notification.TopNotificationPanelViewMediator;
 import com.android.systemui.car.userswitcher.FullscreenUserSwitcherViewMediator;
+import com.android.systemui.car.userswitcher.UserSwitchTransitionViewMediator;
 
 import dagger.Binds;
 import dagger.Module;
@@ -67,4 +68,11 @@
     @ClassKey(FullscreenUserSwitcherViewMediator.class)
     public abstract OverlayViewMediator bindFullscreenUserSwitcherViewsMediator(
             FullscreenUserSwitcherViewMediator overlayViewsMediator);
+
+    /** Injects CarUserSwitchingDialogMediator. */
+    @Binds
+    @IntoMap
+    @ClassKey(UserSwitchTransitionViewMediator.class)
+    public abstract OverlayViewMediator bindUserSwitchTransitionViewMediator(
+            UserSwitchTransitionViewMediator userSwitchTransitionViewMediator);
 }
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java
index 1b4621f..38836d8 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java
@@ -32,6 +32,8 @@
 import android.view.LayoutInflater;
 import android.view.ViewGroup;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.ViewMediatorCallback;
@@ -58,6 +60,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
+@SmallTest
 public class CarKeyguardViewControllerTest extends SysuiTestCase {
 
     private TestableCarKeyguardViewController mCarKeyguardViewController;
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarTest.java
index 77eecac..04e0a73 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarTest.java
@@ -18,6 +18,8 @@
 
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -25,6 +27,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.graphics.Rect;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.testing.AndroidTestingRunner;
@@ -44,8 +47,11 @@
 import com.android.systemui.car.CarDeviceProvisionedController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.AutoHideController;
+import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.LightBarTransitionsController;
 import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
@@ -69,6 +75,12 @@
     @Mock
     private CarNavigationBarController mCarNavigationBarController;
     @Mock
+    private LightBarController mLightBarController;
+    @Mock
+    private SysuiDarkIconDispatcher mStatusBarIconController;
+    @Mock
+    private LightBarTransitionsController mLightBarTransitionsController;
+    @Mock
     private WindowManager mWindowManager;
     @Mock
     private CarDeviceProvisionedController mDeviceProvisionedController;
@@ -88,6 +100,7 @@
     private StatusBarIconController mIconController;
 
     private RegisterStatusBarResult mBarResult;
+    private AppearanceRegion[] mAppearanceRegions;
     private FakeExecutor mUiBgExecutor;
 
     @Before
@@ -96,11 +109,16 @@
         mTestableResources = mContext.getOrCreateTestableResources();
         mHandler = Handler.getMain();
         mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
+        when(mStatusBarIconController.getTransitionsController()).thenReturn(
+                mLightBarTransitionsController);
+        mAppearanceRegions = new AppearanceRegion[] {
+                new AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, new Rect())
+        };
         mBarResult = new RegisterStatusBarResult(
                 /* icons= */ new ArrayMap<>(),
                 /* disabledFlags1= */ 0,
                 /* appearance= */ 0,
-                /* appearanceRegions= */ new AppearanceRegion[]{},
+                mAppearanceRegions,
                 /* imeWindowVis= */ 0,
                 /* imeBackDisposition= */ 0,
                 /* showImeSwitcher= */ false,
@@ -116,10 +134,11 @@
             e.printStackTrace();
         }
         mCarNavigationBar = new CarNavigationBar(mContext, mTestableResources.getResources(),
-                mCarNavigationBarController, mWindowManager, mDeviceProvisionedController,
-                new CommandQueue(mContext), mAutoHideController, mButtonSelectionStateListener,
-                mHandler, mUiBgExecutor, mBarService, () -> mKeyguardStateController,
-                mButtonSelectionStateController, () -> mIconPolicy,  () -> mIconController);
+                mCarNavigationBarController, mLightBarController, mStatusBarIconController,
+                mWindowManager, mDeviceProvisionedController, new CommandQueue(mContext),
+                mAutoHideController, mButtonSelectionStateListener, mHandler, mUiBgExecutor,
+                mBarService, () -> mKeyguardStateController, mButtonSelectionStateController,
+                () -> mIconPolicy, () -> mIconController);
     }
 
     @Test
@@ -186,6 +205,26 @@
     }
 
     @Test
+    public void restartNavBars_lightAppearance_darkensAllIcons() {
+        mAppearanceRegions[0] = new AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, new Rect());
+
+        mCarNavigationBar.start();
+
+        verify(mLightBarTransitionsController).setIconsDark(
+                /* dark= */ true, /* animate= */ false);
+    }
+
+    @Test
+    public void restartNavBars_opaqueAppearance_lightensAllIcons() {
+        mAppearanceRegions[0] = new AppearanceRegion(APPEARANCE_OPAQUE_STATUS_BARS, new Rect());
+
+        mCarNavigationBar.start();
+
+        verify(mLightBarTransitionsController).setIconsDark(
+                /* dark= */ false, /* animate= */ false);
+    }
+
+    @Test
     public void showTransient_wrongDisplayId_transientModeNotUpdated() {
         mTestableResources.addOverride(R.bool.config_enableTopNavigationBar, true);
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewControllerTest.java
new file mode 100644
index 0000000..eab381c
--- /dev/null
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewControllerTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.car.userswitcher;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Handler;
+import android.os.UserManager;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableResources;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.car.window.OverlayViewGlobalStateController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class UserSwitchTransitionViewControllerTest extends SysuiTestCase {
+    private static final int TEST_USER_1 = 100;
+    private static final int TEST_USER_2 = 110;
+
+    private TestableUserSwitchTransitionViewController mCarUserSwitchingDialogController;
+    private TestableResources mTestableResources;
+    @Mock
+    private OverlayViewGlobalStateController mOverlayViewGlobalStateController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mTestableResources = mContext.getOrCreateTestableResources();
+        mCarUserSwitchingDialogController = new TestableUserSwitchTransitionViewController(
+                mContext,
+                Handler.getMain(),
+                mTestableResources.getResources(),
+                (UserManager) mContext.getSystemService(Context.USER_SERVICE),
+                mOverlayViewGlobalStateController
+        );
+
+        mCarUserSwitchingDialogController.inflate((ViewGroup) LayoutInflater.from(mContext).inflate(
+                R.layout.sysui_overlay_window, /* root= */ null));
+    }
+
+    @Test
+    public void onHandleShow_newUserSelected_showsDialog() {
+        mCarUserSwitchingDialogController.handleShow(/* currentUserId= */ TEST_USER_1);
+
+        verify(mOverlayViewGlobalStateController).showView(eq(mCarUserSwitchingDialogController),
+                any());
+    }
+
+    @Test
+    public void onHandleShow_alreadyShowing_ignoresRequest() {
+        mCarUserSwitchingDialogController.handleShow(/* currentUserId= */ TEST_USER_1);
+        mCarUserSwitchingDialogController.handleShow(/* currentUserId= */ TEST_USER_2);
+
+        // Verify that the request was processed only once.
+        verify(mOverlayViewGlobalStateController).showView(eq(mCarUserSwitchingDialogController),
+                any());
+    }
+
+    @Test
+    public void onHandleShow_sameUserSelected_ignoresRequest() {
+        mCarUserSwitchingDialogController.handleShow(/* currentUserId= */ TEST_USER_1);
+        mCarUserSwitchingDialogController.handleHide();
+        mCarUserSwitchingDialogController.handleShow(/* currentUserId= */ TEST_USER_1);
+
+        // Verify that the request was processed only once.
+        verify(mOverlayViewGlobalStateController).showView(eq(mCarUserSwitchingDialogController),
+                any());
+    }
+
+    @Test
+    public void onHide_currentlyShowing_hidesDialog() {
+        mCarUserSwitchingDialogController.handleShow(/* currentUserId= */ TEST_USER_1);
+        mCarUserSwitchingDialogController.handleHide();
+
+        verify(mOverlayViewGlobalStateController).hideView(eq(mCarUserSwitchingDialogController),
+                any());
+    }
+
+    @Test
+    public void onHide_notShowing_ignoresRequest() {
+        mCarUserSwitchingDialogController.handleShow(/* currentUserId= */ TEST_USER_1);
+        mCarUserSwitchingDialogController.handleHide();
+        mCarUserSwitchingDialogController.handleHide();
+
+        // Verify that the request was processed only once.
+        verify(mOverlayViewGlobalStateController).hideView(eq(mCarUserSwitchingDialogController),
+                any());
+    }
+
+    private final class TestableUserSwitchTransitionViewController extends
+            UserSwitchTransitionViewController {
+
+        private final Handler mHandler;
+
+        TestableUserSwitchTransitionViewController(Context context, Handler handler,
+                Resources resources, UserManager userManager,
+                OverlayViewGlobalStateController overlayViewGlobalStateController) {
+            super(context, handler, resources, userManager, overlayViewGlobalStateController);
+            mHandler = handler;
+        }
+
+        @Override
+        public void handleShow(int currentUserId) {
+            super.handleShow(currentUserId);
+            waitForIdleSync(mHandler);
+        }
+
+        @Override
+        public void handleHide() {
+            super.handleHide();
+            waitForIdleSync(mHandler);
+        }
+    }
+}
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediatorTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediatorTest.java
new file mode 100644
index 0000000..a808e2d
--- /dev/null
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediatorTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.car.userswitcher;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.car.user.CarUserManager;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.car.CarServiceProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class UserSwitchTransitionViewMediatorTest {
+    private static final int TEST_USER = 100;
+
+    private UserSwitchTransitionViewMediator mUserSwitchTransitionViewMediator;
+    @Mock
+    private CarServiceProvider mCarServiceProvider;
+    @Mock
+    private UserSwitchTransitionViewController mUserSwitchTransitionViewController;
+    @Mock
+    private CarUserManager.UserLifecycleEvent mUserLifecycleEvent;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mUserSwitchTransitionViewMediator = new UserSwitchTransitionViewMediator(
+                mCarServiceProvider, mUserSwitchTransitionViewController);
+
+    }
+
+    @Test
+    public void onUserLifecycleEvent_userStarting_callsHandleShow() {
+        when(mUserLifecycleEvent.getEventType()).thenReturn(
+                CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STARTING);
+        when(mUserLifecycleEvent.getUserId()).thenReturn(TEST_USER);
+        mUserSwitchTransitionViewMediator.handleUserLifecycleEvent(mUserLifecycleEvent);
+
+        verify(mUserSwitchTransitionViewController).handleShow(TEST_USER);
+    }
+
+    @Test
+    public void onUserLifecycleEvent_userSwitching_callsHandleHide() {
+        when(mUserLifecycleEvent.getEventType()).thenReturn(
+                CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING);
+        mUserSwitchTransitionViewMediator.handleUserLifecycleEvent(mUserLifecycleEvent);
+
+        verify(mUserSwitchTransitionViewController).handleHide();
+    }
+}
diff --git a/packages/CtsShim/apk/arm/CtsShim.apk b/packages/CtsShim/apk/arm/CtsShim.apk
index e153c91..180dfb6 100644
--- a/packages/CtsShim/apk/arm/CtsShim.apk
+++ b/packages/CtsShim/apk/arm/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/apk/arm/CtsShimPriv.apk b/packages/CtsShim/apk/arm/CtsShimPriv.apk
index 7fbeb3d..d87ea7f 100644
--- a/packages/CtsShim/apk/arm/CtsShimPriv.apk
+++ b/packages/CtsShim/apk/arm/CtsShimPriv.apk
Binary files differ
diff --git a/packages/CtsShim/apk/x86/CtsShim.apk b/packages/CtsShim/apk/x86/CtsShim.apk
index e153c91..180dfb6 100644
--- a/packages/CtsShim/apk/x86/CtsShim.apk
+++ b/packages/CtsShim/apk/x86/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/apk/x86/CtsShimPriv.apk b/packages/CtsShim/apk/x86/CtsShimPriv.apk
index f0eaf02..3124651 100644
--- a/packages/CtsShim/apk/x86/CtsShimPriv.apk
+++ b/packages/CtsShim/apk/x86/CtsShimPriv.apk
Binary files differ
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 0c70e10..8f919c3 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -275,6 +275,13 @@
         return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
     }
 
+    @Override
+    public Cursor queryChildDocumentsForManage(
+            String parentDocId, String[] projection, String sortOrder)
+            throws FileNotFoundException {
+        return queryChildDocumentsShowAll(parentDocId, projection, sortOrder);
+    }
+
     /**
      * Check that the directory is the root of storage or blocked file from tree.
      *
diff --git a/packages/InputDevices/OWNERS b/packages/InputDevices/OWNERS
new file mode 100644
index 0000000..0313a40
--- /dev/null
+++ b/packages/InputDevices/OWNERS
@@ -0,0 +1,2 @@
+michaelwr@google.com
+svv@google.com
diff --git a/packages/InputDevices/res/raw/keyboard_layout_croatian_and_slovenian.kcm b/packages/InputDevices/res/raw/keyboard_layout_croatian_and_slovenian.kcm
index eec9d27..96445a4 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_croatian_and_slovenian.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_croatian_and_slovenian.kcm
@@ -258,9 +258,9 @@
 }
 
 key SEMICOLON {
-    label:                              '\u010d'
-    base:                               '\u010c'
-    shift, capslock:                    '\u010d'
+    label:                              '\u010c'
+    base:                               '\u010d'
+    shift, capslock:                    '\u010c'
 }
 
 key APOSTROPHE {
diff --git a/packages/PackageInstaller/res/values-ne/strings.xml b/packages/PackageInstaller/res/values-ne/strings.xml
index d5faac2..60934b1 100644
--- a/packages/PackageInstaller/res/values-ne/strings.xml
+++ b/packages/PackageInstaller/res/values-ne/strings.xml
@@ -24,8 +24,8 @@
     <string name="installing_app" msgid="1165095864863849422">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> स्थापना गर्दै…"</string>
     <string name="install_done" msgid="5987363587661783896">"एप स्थापना गरियो।"</string>
     <string name="install_confirm_question" msgid="8176284075816604590">"तपाईं यो एप स्थापना गर्न चाहनुहुन्छ?"</string>
-    <string name="install_confirm_question_update" msgid="7942235418781274635">"तपाईं यो पहिलेदेखि नै विद्यमान अनुप्रयोगको साटो यसको अद्यावधिक संस्करण स्थापना गर्न चाहनुहुन्छ? तपाईंको विद्यमान डेटा गुम्ने छैन।"</string>
-    <string name="install_confirm_question_update_system" msgid="4713001702777910263">"तपाईं यो अन्तर्निर्मित अनुप्रयोगको साटो यसको अद्यावधिक संस्करण स्थापना गर्न चाहनुहुन्छ? तपाईंको विद्यमान डेटा गुम्ने छैन।"</string>
+    <string name="install_confirm_question_update" msgid="7942235418781274635">"तपाईं यो पहिलेदेखि नै विद्यमान एपको साटो यसको अद्यावधिक संस्करण स्थापना गर्न चाहनुहुन्छ? तपाईंको विद्यमान डेटा गुम्ने छैन।"</string>
+    <string name="install_confirm_question_update_system" msgid="4713001702777910263">"तपाईं यो अन्तर्निर्मित एपको साटो यसको अद्यावधिक संस्करण स्थापना गर्न चाहनुहुन्छ? तपाईंको विद्यमान डेटा गुम्ने छैन।"</string>
     <string name="install_failed" msgid="5777824004474125469">"एप स्थापना गरिएन।"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"यो प्याकेज स्थापना गर्ने क्रममा अवरोध गरियो।"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"प्याकेजका रूपमा स्थापना नगरिएको एप विद्यमान प्याकेजसँग मेल खाँदैन।"</string>
@@ -49,16 +49,16 @@
     <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"अनुमति छैन"</string>
     <string name="user_is_not_allowed_dlg_text" msgid="3468447791330611681">"हालका प्रयोगकर्तालाई यो स्थापना रद्द गर्ने कार्य गर्ने अनुमति छैन।"</string>
     <string name="generic_error_dlg_title" msgid="5863195085927067752">"त्रुटि"</string>
-    <string name="generic_error_dlg_text" msgid="5287861443265795232">"अनुप्रयोगको स्थापना रद्द गर्न सकिएन।"</string>
-    <string name="uninstall_application_title" msgid="4045420072401428123">"अनुप्रयोगको स्थापना रद्द गर्नु…"</string>
+    <string name="generic_error_dlg_text" msgid="5287861443265795232">"एपको स्थापना रद्द गर्न सकिएन।"</string>
+    <string name="uninstall_application_title" msgid="4045420072401428123">"एपको स्थापना रद्द गर्नु…"</string>
     <string name="uninstall_update_title" msgid="824411791011583031">"अद्यावधिकको स्थापना रद्द गर्नु…"</string>
-    <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> निम्न अनुप्रयोगको अंश हो:"</string>
-    <string name="uninstall_application_text" msgid="3816830743706143980">"तपाईं यो अनुप्रयोगको स्थापना रद्द गर्न चाहनुहुन्छ?"</string>
+    <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> निम्न एपको अंश हो:"</string>
+    <string name="uninstall_application_text" msgid="3816830743706143980">"तपाईं यो एपको स्थापना रद्द गर्न चाहनुहुन्छ?"</string>
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"तपाईं "<b>"सबै"</b>" प्रयोगकर्ताका लागि यो एपको स्थापना रद्द गर्न चाहनुहुन्छ? यन्त्रका "<b>"सबै"</b>" प्रयोगकर्ताहरूबाट उक्त एप र यसको डेटा हटाइने छ।"</string>
-    <string name="uninstall_application_text_user" msgid="498072714173920526">"तपाईं प्रयोगकर्ता <xliff:g id="USERNAME">%1$s</xliff:g> का लागि यो अनुप्रयोगको स्थापना रद्द गर्न चाहनुहुन्छ?"</string>
+    <string name="uninstall_application_text_user" msgid="498072714173920526">"तपाईं प्रयोगकर्ता <xliff:g id="USERNAME">%1$s</xliff:g> का लागि यो एपको स्थापना रद्द गर्न चाहनुहुन्छ?"</string>
     <string name="uninstall_update_text" msgid="863648314632448705">"यस एपलाई फ्याक्ट्रीको संस्करणले बदल्ने हो? सबै डेटा हटाइने छ।"</string>
     <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"यस एपलाई फ्याक्ट्रीको संस्करणले बदल्ने हो? सबै डेटा हटाइने छ। यसले यस यन्त्रका कार्य प्रोफाइल भएका लगायत सबै प्रयोगकर्ताहरूमा असर पार्छ।"</string>
-    <string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> अनुप्रयोगको डेटा राख्नुहोस्।"</string>
+    <string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> एपको डेटा राख्नुहोस्।"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"चलिरहेका स्थापना रद्द गर्ने कार्यहरू"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"असफल भएका स्थापना रद्द गर्ने कार्यहरू"</string>
     <string name="uninstalling" msgid="8709566347688966845">"स्थापना रद्द गर्दै…"</string>
@@ -67,12 +67,12 @@
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> को स्थापना रद्द गरियो"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"स्थापना रद्द गर्न सकिएन।"</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> को स्थापना रद्द गर्ने कार्य असफल भयो।"</string>
-    <string name="uninstall_failed_device_policy_manager" msgid="785293813665540305">"यन्त्रको सक्रिय प्रशासकीय अनुप्रयोगको स्थापना रद्द गर्न मिल्दैन"</string>
-    <string name="uninstall_failed_device_policy_manager_of_user" msgid="4813104025494168064">"<xliff:g id="USERNAME">%1$s</xliff:g> को यन्त्रको सक्रिय प्रशासकीय अनुप्रयोगको स्थापना रद्द गर्न मिल्दैन"</string>
-    <string name="uninstall_all_blocked_profile_owner" msgid="2009393666026751501">"अन्य प्रयोगकर्ताहरूका लागि यस अनुप्रयोगको स्थापना रद्द गरे पनि केही प्रयोगकर्ता वा प्रोफाइलहरूलाई यसको आवश्यकता पर्दछ"</string>
+    <string name="uninstall_failed_device_policy_manager" msgid="785293813665540305">"यन्त्रको सक्रिय प्रशासकीय एपको स्थापना रद्द गर्न मिल्दैन"</string>
+    <string name="uninstall_failed_device_policy_manager_of_user" msgid="4813104025494168064">"<xliff:g id="USERNAME">%1$s</xliff:g> को यन्त्रको सक्रिय प्रशासकीय एपको स्थापना रद्द गर्न मिल्दैन"</string>
+    <string name="uninstall_all_blocked_profile_owner" msgid="2009393666026751501">"अन्य प्रयोगकर्ताहरूका लागि यस एपको स्थापना रद्द गरे पनि केही प्रयोगकर्ता वा प्रोफाइलहरूलाई यसको आवश्यकता पर्दछ"</string>
     <string name="uninstall_blocked_profile_owner" msgid="6373897407002404848">"यो एप तपाईंको प्रोफाइलका लागि आवश्यक छ र यसको स्थापना रद्द गर्न सकिँदैन।"</string>
     <string name="uninstall_blocked_device_owner" msgid="6724602931761073901">"यो एप तपाईंको यन्त्रका प्रशासकका लागि आवश्यक छ र यसको स्थापना रद्द गर्न सकिँदैन।"</string>
-    <string name="manage_device_administrators" msgid="3092696419363842816">"यन्त्रका व्यवस्थापकीय अनुप्रयोगको व्यवस्थापन गर्नु…"</string>
+    <string name="manage_device_administrators" msgid="3092696419363842816">"यन्त्रका व्यवस्थापकीय एपको व्यवस्थापन गर्नु…"</string>
     <string name="manage_users" msgid="1243995386982560813">"प्रयोगकर्ताहरूको व्यवस्थापन गर्नुहोस्"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> को स्थापना रद्द गर्न सकिएन।"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"प्याकेजलाई पार्स गर्ने क्रममा समस्या भयो।"</string>
@@ -89,7 +89,7 @@
     <string name="anonymous_source_continue" msgid="4375745439457209366">"जारी राख्नुहोस्"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"सेटिङहरू"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"वेयर एपहरूको स्थापना/स्थापना रद्द गर्दै"</string>
-    <string name="app_installed_notification_channel_description" msgid="2695385797601574123">"अनुप्रयोगको स्थापना गरिएको सूचना"</string>
+    <string name="app_installed_notification_channel_description" msgid="2695385797601574123">"एपको स्थापना गरिएको सूचना"</string>
     <string name="notification_installation_success_message" msgid="6450467996056038442">"सफलतापूर्वक स्थापना गरियो"</string>
     <string name="notification_installation_success_status" msgid="3172502643504323321">"“<xliff:g id="APPNAME">%1$s</xliff:g>” सफलतापूर्वक स्थापना गरियो"</string>
 </resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
index 1709506..467a60e 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
@@ -231,11 +231,6 @@
         // Add the new printers, i.e. what is left.
         printers.addAll(discoveredPrinters.values());
 
-        // Do nothing if the printer list is not changed.
-        if (Objects.equals(mPrinters, printers)) {
-            return;
-        }
-
         // Update the list of printers.
         mPrinters.clear();
         mPrinters.addAll(printers);
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 1729027..66787c2 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Gedeaktiveer"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Geaktiveer"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Jou toestel moet herselflaai om hierdie verandering toe te pas. Herselflaai nou of kanselleer."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Werk-<xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index fad7a82..ead0ebf 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ተሰናክሏል"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ነቅቷል"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"የእርስዎን መሣሪያ ይህ ለው ለማመልከት እንደገና መነሣት አለበት። አሁን እንደገና ያስነሡ ወይም ይተዉት።"</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"የስራ <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index b3cc832..c1f4fd9 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -195,7 +195,7 @@
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"اختيار ملف شخصي"</string>
     <string name="category_personal" msgid="6236798763159385225">"شخصي"</string>
-    <string name="category_work" msgid="4014193632325996115">"العمل"</string>
+    <string name="category_work" msgid="4014193632325996115">"للعمل"</string>
     <string name="development_settings_title" msgid="140296922921597393">"خيارات مطور البرامج"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"تفعيل خيارات المطورين"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"تعيين خيارات تطوير التطبيق"</string>
@@ -279,7 +279,7 @@
     <string name="private_dns_mode_off" msgid="7065962499349997041">"غير مفعّل"</string>
     <string name="private_dns_mode_opportunistic" msgid="1947864819060442354">"تلقائي"</string>
     <string name="private_dns_mode_provider" msgid="3619040641762557028">"اسم مضيف مزوّد \"نظام أسماء النطاقات الخاص\""</string>
-    <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"يُرجى إدخال اسم مضيف \"مزوّد نظام أسماء النطاقات\""</string>
+    <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"‏يُرجى إدخال اسم مضيف DNS"</string>
     <string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"تعذّر الاتصال"</string>
     <string name="wifi_display_certification_summary" msgid="8111151348106907513">"عرض خيارات شهادة عرض شاشة لاسلكي"</string>
     <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"‏زيادة مستوى تسجيل Wi-Fi، وعرض لكل SSID RSSI في منتقي Wi-Fi"</string>
@@ -318,10 +318,10 @@
     <string name="hdcp_checking_title" msgid="3155692785074095986">"‏التحقق من HDCP"</string>
     <string name="hdcp_checking_dialog_title" msgid="7691060297616217781">"‏تعيين سلوك التحقق من HDCP"</string>
     <string name="debug_debugging_category" msgid="535341063709248842">"تصحيح الأخطاء"</string>
-    <string name="debug_app" msgid="8903350241392391766">"تحديد التطبيق لتصحيحه"</string>
+    <string name="debug_app" msgid="8903350241392391766">"اختيار التطبيق لتصحيحه"</string>
     <string name="debug_app_not_set" msgid="1934083001283807188">"لم يتم تعيين تطبيق لتصحيحه"</string>
     <string name="debug_app_set" msgid="6599535090477753651">"تطبيق التصحيح: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="select_application" msgid="2543228890535466325">"تحديد تطبيق"</string>
+    <string name="select_application" msgid="2543228890535466325">"اختيار تطبيق"</string>
     <string name="no_application" msgid="9038334538870247690">"لا شيء"</string>
     <string name="wait_for_debugger" msgid="7461199843335409809">"انتظار برنامج التصحيح"</string>
     <string name="wait_for_debugger_summary" msgid="6846330006113363286">"ينتظر التطبيق قيد التصحيح انضمام برنامج التصحيح قبل التنفيذ"</string>
@@ -557,6 +557,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"غير مفعّل"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"مفعّل"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"يجب إعادة تشغيل جهازك ليتم تطبيق هذا التغيير. يمكنك إعادة التشغيل الآن أو إلغاء التغيير."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> المخصّص للعمل"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index ad344c3..b5d642a 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -549,14 +549,11 @@
     <string name="guest_new_guest" msgid="3482026122932643557">"অতিথি যোগ কৰক"</string>
     <string name="guest_exit_guest" msgid="5908239569510734136">"অতিথি আঁতৰাওক"</string>
     <string name="guest_nickname" msgid="6332276931583337261">"অতিথি"</string>
-    <!-- no translation found for cached_apps_freezer_device_default (2616594131750144342) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_disabled (4816382260660472042) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_enabled (8866703500183051546) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_reboot_dialog_text (695330563489230096) -->
-    <skip />
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ডিভাইচ ডিফ’ল্ট"</string>
+    <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"অক্ষম কৰা আছে"</string>
+    <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"সক্ষম কৰা আছে"</string>
+    <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"এই সলনিটো কার্যকৰী হ’বলৈ আপোনাৰ ডিভাইচটো ৰিবুট কৰিবই লাগিব। এতিয়াই ৰিবুট কৰক অথবা বাতিল কৰক।"</string>
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"কৰ্মস্থান <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index ab7ea8c..aecaf70 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -155,7 +155,7 @@
     <string name="launch_defaults_some" msgid="3631650616557252926">"Bəzi susmaya görələr təyin edilib"</string>
     <string name="launch_defaults_none" msgid="8049374306261262709">"Susmaya görələr təyin edilməyib."</string>
     <string name="tts_settings" msgid="8130616705989351312">"Mətndən-danışığa parametrləri"</string>
-    <string name="tts_settings_title" msgid="7602210956640483039">"Mətndən-nitqə çıxışı"</string>
+    <string name="tts_settings_title" msgid="7602210956640483039">"Mətndən-nitqə daxiletmə"</string>
     <string name="tts_default_rate_title" msgid="3964187817364304022">"Nitq diapazonu"</string>
     <string name="tts_default_rate_summary" msgid="3781937042151716987">"Mətnin səsləndirilmə sürəti"</string>
     <string name="tts_default_pitch_title" msgid="6988592215554485479">"Pitç"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Deaktiv"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiv"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Bu dəyişikliyin tətbiq edilməsi üçün cihaz yenidən başladılmalıdır. İndi yenidən başladın və ya ləğv edin."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"İş <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index da47bf2..092bd42 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -554,6 +554,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Onemogućeno"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogućeno"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Morate da restartujete uređaj da bi se ova promena primenila. Restartujte ga odmah ili otkažite."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> za posao"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 2761d47..d610973 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -195,7 +195,7 @@
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"Выбраць профіль"</string>
     <string name="category_personal" msgid="6236798763159385225">"Асабісты"</string>
-    <string name="category_work" msgid="4014193632325996115">"Рабочы"</string>
+    <string name="category_work" msgid="4014193632325996115">"Працоўны"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Параметры распрацоўшчыка"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Уключыць параметры распрацоўшчыка"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Налада параметраў для распрацоўкі прыкладанняў"</string>
@@ -555,6 +555,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Выключана"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Уключана"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Перазагрузіце прыладу, каб прымяніць гэта змяненне. Перазагрузіце ці скасуйце."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> (праца)"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 8150710..5c3fe75 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -419,7 +419,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (червено – зелено)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (синьо – жълто)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекция на цветове"</string>
-    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Корекцията на цветове ви позволява да коригирате това, как цветовете се показват на устройството ви"</string>
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Функцията „Корекция на цветове“ ви позволява да коригирате това, как цветовете се показват на устройството ви"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Заменено от „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Още около <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -554,4 +554,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Активирано"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"За да бъде приложена тази промяна, устройството ви трябва да бъде рестартирано. Рестартирайте сега или анулирайте."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> за работа"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 7bae6ee..27d3707 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -195,7 +195,7 @@
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"প্রোফাইল বেছে নিন"</string>
     <string name="category_personal" msgid="6236798763159385225">"ব্যক্তিগত"</string>
-    <string name="category_work" msgid="4014193632325996115">"কর্মক্ষেত্র"</string>
+    <string name="category_work" msgid="4014193632325996115">"অফিস"</string>
     <string name="development_settings_title" msgid="140296922921597393">"ডেভেলপার বিকল্প"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"ডেভেলপার বিকল্প সক্ষম করুন"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"অ্যাপ্লিকেশান উন্নয়নের জন্য বিকল্পগুলি সেট করুন"</string>
@@ -485,7 +485,7 @@
     <string name="ims_reg_title" msgid="8197592958123671062">"IMS রেজিস্ট্রেশনের স্থিতি"</string>
     <string name="ims_reg_status_registered" msgid="884916398194885457">"রেজিস্টার করা"</string>
     <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"রেজিস্টার করা নয়"</string>
-    <string name="status_unavailable" msgid="5279036186589861608">"অনুপলব্ধ"</string>
+    <string name="status_unavailable" msgid="5279036186589861608">"অনুপলভ্য"</string>
     <string name="wifi_status_mac_randomized" msgid="466382542497832189">"MAC র‍্যান্ডমাইজ করা হয়েছে"</string>
     <plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139">
       <item quantity="one">%1$dটি ডিভাইস কানেক্ট</item>
@@ -549,14 +549,11 @@
     <string name="guest_new_guest" msgid="3482026122932643557">"অতিথি যোগ করুন"</string>
     <string name="guest_exit_guest" msgid="5908239569510734136">"অতিথি সরান"</string>
     <string name="guest_nickname" msgid="6332276931583337261">"অতিথি"</string>
-    <!-- no translation found for cached_apps_freezer_device_default (2616594131750144342) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_disabled (4816382260660472042) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_enabled (8866703500183051546) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_reboot_dialog_text (695330563489230096) -->
-    <skip />
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ডিভাইসের ডিফল্ট"</string>
+    <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"বন্ধ করা আছে"</string>
+    <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"চালু করা আছে"</string>
+    <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"এই পরিবর্তনটি প্রয়োগ করার জন্য আপনার ডিভাইসটি অবশ্যই রিবুট করতে হবে। এখন রিবুট করুন বা বাতিল করুন।"</string>
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"অফিস <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 6489cef..6595c22 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -40,7 +40,7 @@
     <item msgid="8339720953594087771">"Povezivanje na mrežu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
     <item msgid="3028983857109369308">"Autentifikacija s mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
     <item msgid="4287401332778341890">"Dobivanje IP adrese iz mreže <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
-    <item msgid="1043944043827424501">"Povezano na mrežu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item>
+    <item msgid="1043944043827424501">"Povezano s mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item>
     <item msgid="7445993821842009653">"Suspendirano"</item>
     <item msgid="1175040558087735707">"Prekidanje veze s mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
     <item msgid="699832486578171722">"Isključen"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index fe7f8c1..a9d9e70 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -452,7 +452,7 @@
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string>
     <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Sporo punjenje"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ne puni se"</string>
-    <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Priključen, trenutno se ne može puniti"</string>
+    <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Priključeno, trenutno se ne može puniti"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Puna"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Pod kontrolom administratora"</string>
     <string name="disabled" msgid="8017887509554714950">"Onemogućeno"</string>
@@ -554,5 +554,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Onemogućeno"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogućeno"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Morate ponovo pokrenuti uređaj da se ova promjena primijeni. Ponovo pokrenite odmah ili otkažite."</string>
-    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> za posao"</string>
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Poslovna aplikacija <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 7dad950..5ed0f1b 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -222,7 +222,7 @@
     <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Empremta digital del dispositiu: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
     <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"No s\'ha pogut connectar"</string>
     <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Assegura\'t que <xliff:g id="DEVICE_NAME">%1$s</xliff:g> estigui connectat a la xarxa correcta"</string>
-    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Vincular amb el dispositiu"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Vincula amb el dispositiu"</string>
     <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Codi de vinculació Wi‑Fi"</string>
     <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"No s\'ha pogut vincular"</string>
     <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Assegura\'t que el dispositiu estigui connectat a la mateixa xarxa."</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Desactivat"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activat"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Has de reiniciar el teu dispositiu perquè s\'apliquin els canvis. Reinicia\'l ara o cancel·la."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> de la feina"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 51548f5..d4d3735 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -555,6 +555,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Vypnuto"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Zapnuto"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Aby se tato změna projevila, je třeba zařízení restartovat. Restartujte zařízení nebo zrušte akci."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Pracovní <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 88f8e92..89dbf25 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -433,7 +433,7 @@
     <string name="power_discharge_by" msgid="4113180890060388350">"Bør holde indtil ca. <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"Bør holde indtil ca. <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharge_by_only_short" msgid="5883041507426914446">"Indtil <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Enheden løber muligvis tør for batteri inden <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Batteriet aflades muligvis inden <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"Der er mindre end <xliff:g id="THRESHOLD">%1$s</xliff:g> tilbage"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"Der er mindre end <xliff:g id="THRESHOLD">%1$s</xliff:g> tilbage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="446388082266121894">"Der er mere end <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Deaktiveret"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiveret"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Din enhed skal genstartes for at denne enhed bliver anvendt. Genstart nu, eller annuller."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> – arbejde"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index edd1580..c2030b1 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -231,7 +231,7 @@
     <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Das Gerät konnte nicht gekoppelt werden. Der QR-Code war nicht korrekt oder das Gerät ist nicht mit demselben Netzwerk verbunden."</string>
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-Adresse &amp; Port"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR-Code scannen"</string>
-    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Scanne einen QR-Code, um ein Gerät über WLAN zu koppeln"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Scanne einen QR-Code, um das Gerät über WLAN zu koppeln"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Bitte stell eine WLAN-Verbindung her"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"ADB, Debug, Dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Verknüpfung zu Fehlerbericht"</string>
@@ -507,7 +507,7 @@
     <string name="zen_mode_duration_settings_title" msgid="1553451650289651489">"Dauer"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Jedes Mal fragen"</string>
     <string name="zen_mode_forever" msgid="3339224497605461291">"Bis zur Deaktivierung"</string>
-    <string name="time_unit_just_now" msgid="3006134267292728099">"gerade eben"</string>
+    <string name="time_unit_just_now" msgid="3006134267292728099">"Gerade eben"</string>
     <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Smartphone-Lautsprecher"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Verbindung kann nicht hergestellt werden. Schalte das Gerät aus &amp; und wieder ein."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Netzbetriebenes Audiogerät"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Deaktiviert"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiviert"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Damit diese Änderung übernommen wird, musst du dein Gerät neu starten. Du kannst es jetzt neu starten oder den Vorgang abbrechen."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> (geschäftlich)"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index c5c0e07..bfc183e 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -194,8 +194,8 @@
     <item msgid="581904787661470707">"Ταχύτατη"</item>
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"Επιλογή προφίλ"</string>
-    <string name="category_personal" msgid="6236798763159385225">"Προσωπικό"</string>
-    <string name="category_work" msgid="4014193632325996115">"Εργασία"</string>
+    <string name="category_personal" msgid="6236798763159385225">"Προσωπικός"</string>
+    <string name="category_work" msgid="4014193632325996115">"Εργασίας"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Επιλογές για προγραμματιστές"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Ενεργοποίηση επιλογών για προγραμματιστές"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Ορισμός επιλογών για ανάπτυξη εφαρμογής"</string>
@@ -554,4 +554,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ενεργή"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Για να εφαρμοστεί αυτή η αλλαγή, θα πρέπει να επανεκκινήσετε τη συσκευή σας. Επανεκκίνηση τώρα ή ακύρωση."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Εργασία <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index a1c8b04..9d869ba 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -229,7 +229,7 @@
     <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Pair device over Wi‑Fi by scanning a QR code"</string>
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Pairing device…"</string>
     <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Failed to pair the device. Either the QR code was incorrect, or the device is not connected to the same network."</string>
-    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address &amp; port"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address and port"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scan QR code"</string>
     <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Pair device over Wi‑Fi by scanning a QR code"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Please connect to a Wi‑Fi network"</string>
@@ -554,4 +554,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Your device must be rebooted for this change to apply. Reboot now or cancel."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Work <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index a1c8b04..9d869ba 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -229,7 +229,7 @@
     <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Pair device over Wi‑Fi by scanning a QR code"</string>
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Pairing device…"</string>
     <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Failed to pair the device. Either the QR code was incorrect, or the device is not connected to the same network."</string>
-    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address &amp; port"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address and port"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scan QR code"</string>
     <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Pair device over Wi‑Fi by scanning a QR code"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Please connect to a Wi‑Fi network"</string>
@@ -554,4 +554,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Your device must be rebooted for this change to apply. Reboot now or cancel."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Work <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index a1c8b04..9d869ba 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -229,7 +229,7 @@
     <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Pair device over Wi‑Fi by scanning a QR code"</string>
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Pairing device…"</string>
     <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Failed to pair the device. Either the QR code was incorrect, or the device is not connected to the same network."</string>
-    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address &amp; port"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address and port"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scan QR code"</string>
     <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Pair device over Wi‑Fi by scanning a QR code"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Please connect to a Wi‑Fi network"</string>
@@ -554,4 +554,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Your device must be rebooted for this change to apply. Reboot now or cancel."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Work <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index a1c8b04..9d869ba 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -229,7 +229,7 @@
     <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Pair device over Wi‑Fi by scanning a QR code"</string>
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Pairing device…"</string>
     <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Failed to pair the device. Either the QR code was incorrect, or the device is not connected to the same network."</string>
-    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address &amp; port"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address and port"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scan QR code"</string>
     <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Pair device over Wi‑Fi by scanning a QR code"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Please connect to a Wi‑Fi network"</string>
@@ -554,4 +554,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Your device must be rebooted for this change to apply. Reboot now or cancel."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Work <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 38ac8f1..7765824 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -554,4 +554,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‏‎‎‎‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‏‎‏‎‎Enabled‎‏‎‎‏‎"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‎‎‏‎‎‎‎‎Your device must be rebooted for this change to apply. Reboot now or cancel.‎‏‎‎‏‎"</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‏‎‎‏‏‎‏‎‎‎‏‏‎‎‏‏‎‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‏‏‏‏‏‎‏‎Work ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index c6d0d56..6a76beb 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -61,7 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Media"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Muy rápida"</string>
-    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Vencido"</string>
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Vencida"</string>
     <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">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando…"</string>
@@ -153,7 +153,7 @@
     <string name="unknown" msgid="3544487229740637809">"Desconocido"</string>
     <string name="running_process_item_user_label" msgid="3988506293099805796">"Usuario: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
     <string name="launch_defaults_some" msgid="3631650616557252926">"Configuraciones predeterminadas establecidas"</string>
-    <string name="launch_defaults_none" msgid="8049374306261262709">"No hay configuraciones predeterminadas establecidas."</string>
+    <string name="launch_defaults_none" msgid="8049374306261262709">"No se establecieron configuraciones predeterminadas"</string>
     <string name="tts_settings" msgid="8130616705989351312">"Configuración de texto a voz"</string>
     <string name="tts_settings_title" msgid="7602210956640483039">"Salida de texto a voz"</string>
     <string name="tts_default_rate_title" msgid="3964187817364304022">"Velocidad de voz"</string>
@@ -213,7 +213,7 @@
     <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver y usar los dispositivos disponibles, activa la depuración inalámbrica"</string>
     <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Vincular dispositivo mediante código QR"</string>
     <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Vincular dispositivos nuevos mediante escáner de código QR"</string>
-    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Vincular dispositivo mediante código de sincroniz."</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Vincular dispositivo con código de sincronización"</string>
     <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Vincular dispositivos nuevos mediante código de seis dígitos"</string>
     <string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispositivos vinculados"</string>
     <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Conectado actualmente"</string>
@@ -235,7 +235,7 @@
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Conéctate a una red Wi-Fi"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Acceso directo para informes de errores"</string>
-    <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostrar un botón en el menú de encendido para realizar un informe de errores"</string>
+    <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Muestra un botón en el menú de encendido para realizar un informe de errores"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Permanecer activo"</string>
     <string name="keep_screen_on_summary" msgid="1510731514101925829">"La pantalla nunca quedará inactiva mientras el dispositivo se esté cargando."</string>
     <string name="bt_hci_snoop_log" msgid="7291287955649081448">"Registro de Bluetooth HCI"</string>
@@ -331,7 +331,7 @@
     <string name="media_category" msgid="8122076702526144053">"Multimedia"</string>
     <string name="debug_monitoring_category" msgid="1597387133765424994">"Supervisión"</string>
     <string name="strict_mode" msgid="889864762140862437">"Modo estricto"</string>
-    <string name="strict_mode_summary" msgid="1838248687233554654">"Destello por op. de apps en la conversación principal"</string>
+    <string name="strict_mode_summary" msgid="1838248687233554654">"Destello por op. de apps en el subproceso principal"</string>
     <string name="pointer_location" msgid="7516929526199520173">"Ubicación del puntero"</string>
     <string name="pointer_location_summary" msgid="957120116989798464">"Superponer capa en pant. para mostrar puntos tocados"</string>
     <string name="show_touches" msgid="8437666942161289025">"Mostrar presiones"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Inhabilitado"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Habilitado"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Debes reiniciar el dispositivo para que se aplique el cambio. Reinícialo ahora o cancela la acción."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> de trabajo"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 55b5cab..010b85b 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -61,7 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Media"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Muy rápida"</string>
-    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Caducado"</string>
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Caducada"</string>
     <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">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando…"</string>
@@ -506,7 +506,7 @@
     <string name="alarm_template_far" msgid="6382760514842998629">"Fecha: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="1553451650289651489">"Duración"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Preguntar siempre"</string>
-    <string name="zen_mode_forever" msgid="3339224497605461291">"Hasta que se desactive"</string>
+    <string name="zen_mode_forever" msgid="3339224497605461291">"Hasta que lo desactives"</string>
     <string name="time_unit_just_now" msgid="3006134267292728099">"justo ahora"</string>
     <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altavoz del teléfono"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"No se ha podido conectar; reinicia el dispositivo"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Inhabilitado"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Habilitado"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Es necesario reiniciar tu dispositivo para que se apliquen los cambios. Reiniciar ahora o cancelar."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> de trabajo"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 5a11590..ad2a561 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -419,7 +419,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaalia (punane-roheline)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaalia (sinine-kollane)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Värvide korrigeerimine"</string>
-    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Värvikorrigeerimine võimaldab kohandada seadmes kuvatavaid värve"</string>
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Värvide korrigeerimine võimaldab kohandada seadmes kuvatavaid värve"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Alistas <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Ligikaudu <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäänud"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Keelatud"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Lubatud"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Selle muudatuse rakendamiseks tuleb seade taaskäivitada. Taaskäivitage kohe või tühistage."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Töö: <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 1aed7e8..1ceb738 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -554,4 +554,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Gaituta"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Aldaketa aplikatzeko, berrabiarazi egin behar da gailua. Berrabiaraz ezazu orain, edo utzi bertan behera."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Laneko <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index 3b05075..94caa74 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -40,7 +40,7 @@
     <item msgid="8339720953594087771">"در حال اتصال به <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
     <item msgid="3028983857109369308">"در حال راستی‌آزمایی با <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
     <item msgid="4287401332778341890">"‏درحال دریافت نشانی IP از <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
-    <item msgid="1043944043827424501">"متصل شد به <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item>
+    <item msgid="1043944043827424501">"به <xliff:g id="NETWORK_NAME">%1$s</xliff:g> متصل شد"</item>
     <item msgid="7445993821842009653">"معلق"</item>
     <item msgid="1175040558087735707">"اتصال قطع شد از <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
     <item msgid="699832486578171722">"اتصال قطع شد"</item>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index a46d8cd..d3f1c56 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -94,12 +94,12 @@
     <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"‏صدای HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"‏صدای HD"</string>
     <string name="bluetooth_profile_hearing_aid" msgid="58154575573984914">"سمعک‌ها"</string>
-    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"متصل به سمعک‌ها"</string>
+    <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"به سمعک متصل شد"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"به رسانه صوتی متصل شد"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"به تلفن صوتی متصل شد"</string>
     <string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"به سرور انتقال فایل متصل شد"</string>
     <string name="bluetooth_map_profile_summary_connected" msgid="4141725591784669181">"به نقشه متصل شد"</string>
-    <string name="bluetooth_sap_profile_summary_connected" msgid="1280297388033001037">"‏متصل به SAP"</string>
+    <string name="bluetooth_sap_profile_summary_connected" msgid="1280297388033001037">"‏به SAP متصل شد"</string>
     <string name="bluetooth_opp_profile_summary_not_connected" msgid="3959741824627764954">"به سرور انتقال فایل متصل نیست"</string>
     <string name="bluetooth_hid_profile_summary_connected" msgid="3923653977051684833">"به دستگاه ورودی متصل شد"</string>
     <string name="bluetooth_pan_user_profile_summary_connected" msgid="380469653827505727">"برای دسترسی به اینترنت، به دستگاه متصل شد"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"غیرفعال"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"فعال"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"برای اعمال این تغییر، دستگاهتان باید راه‌اندازی مجدد شود. اکنون راه‌اندازی مجدد کنید یا لغو کنید."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> محل کار"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index af278cb..edfd951 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -156,7 +156,7 @@
     <item msgid="5001852592115448348">", aktiivinen (puhelin)"</item>
   </string-array>
   <string-array name="select_logd_size_titles">
-    <item msgid="1191094707770726722">"Ei käytössä"</item>
+    <item msgid="1191094707770726722">"Ei päällä"</item>
     <item msgid="7839165897132179888">"64 kt"</item>
     <item msgid="2715700596495505626">"256 kt"</item>
     <item msgid="7099386891713159947">"1 Mt"</item>
@@ -164,13 +164,13 @@
     <item msgid="8243549501764402572">"16 Mt"</item>
   </string-array>
   <string-array name="select_logd_size_lowram_titles">
-    <item msgid="1145807928339101085">"Ei käytössä"</item>
+    <item msgid="1145807928339101085">"Ei päällä"</item>
     <item msgid="4064786181089783077">"64 kt"</item>
     <item msgid="3052710745383602630">"256 kt"</item>
     <item msgid="3691785423374588514">"1 Mt"</item>
   </string-array>
   <string-array name="select_logd_size_summaries">
-    <item msgid="409235464399258501">"Ei käytössä"</item>
+    <item msgid="409235464399258501">"Ei päällä"</item>
     <item msgid="4195153527464162486">"64 kt / lokipuskuri"</item>
     <item msgid="7464037639415220106">"256 kt / lokipuskuri"</item>
     <item msgid="8539423820514360724">"1 Mt / lokipuskuri"</item>
@@ -178,13 +178,13 @@
     <item msgid="7892098981256010498">"16 Mt / lokipuskuri"</item>
   </string-array>
   <string-array name="select_logpersist_titles">
-    <item msgid="704720725704372366">"Ei käytössä"</item>
+    <item msgid="704720725704372366">"Ei päällä"</item>
     <item msgid="6014837961827347618">"Kaikki"</item>
     <item msgid="7387060437894578132">"Kaikki paitsi radio"</item>
     <item msgid="7300881231043255746">"vain kernel"</item>
   </string-array>
   <string-array name="select_logpersist_summaries">
-    <item msgid="97587758561106269">"Ei käytössä"</item>
+    <item msgid="97587758561106269">"Ei päällä"</item>
     <item msgid="7126170197336963369">"Kaikki lokipuskurit"</item>
     <item msgid="7167543126036181392">"Kaikki paitsi radiolokipuskurit"</item>
     <item msgid="5135340178556563979">"vain kernel-lokipuskuri"</item>
@@ -247,7 +247,7 @@
     <item msgid="5023908510820531131">"Kohteessa <xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>"</item>
   </string-array>
   <string-array name="debug_hw_overdraw_entries">
-    <item msgid="1968128556747588800">"Ei käytössä"</item>
+    <item msgid="1968128556747588800">"Ei päällä"</item>
     <item msgid="3033215374382962216">"Näytä päällekkäiset alueet"</item>
     <item msgid="3474333938380896988">"Näytä alueet puna-vihersokeille näkyvinä"</item>
   </string-array>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 8e82cb2..5ab01c4b 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -153,7 +153,7 @@
     <string name="unknown" msgid="3544487229740637809">"Tuntematon"</string>
     <string name="running_process_item_user_label" msgid="3988506293099805796">"Käyttäjä: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
     <string name="launch_defaults_some" msgid="3631650616557252926">"Joitakin oletuksia on asetettu"</string>
-    <string name="launch_defaults_none" msgid="8049374306261262709">"Oletuksia ei asetettu"</string>
+    <string name="launch_defaults_none" msgid="8049374306261262709">"Ei oletuksia valittuina"</string>
     <string name="tts_settings" msgid="8130616705989351312">"Tekstistä puheeksi -asetukset"</string>
     <string name="tts_settings_title" msgid="7602210956640483039">"Tekstistä puheeksi -toisto"</string>
     <string name="tts_default_rate_title" msgid="3964187817364304022">"Puheen nopeus"</string>
@@ -397,7 +397,7 @@
     <item msgid="1282170165150762976">"Digitaaliselle sisällölle parhaiten sopivat värit"</item>
   </string-array>
     <string name="inactive_apps_title" msgid="5372523625297212320">"Valmiustilasovellukset"</string>
-    <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Ei käytössä. Ota käyttöön koskettamalla."</string>
+    <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Ei päällä. Ota käyttöön koskettamalla."</string>
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiivinen. Vaihda koskettamalla."</string>
     <string name="standby_bucket_summary" msgid="5128193447550429600">"Sovelluksen valmiusluokka: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"Käynnissä olevat palvelut"</string>
@@ -533,8 +533,8 @@
     <string name="user_add_user_title" msgid="5457079143694924885">"Lisätäänkö uusi käyttäjä?"</string>
     <string name="user_add_user_message_long" msgid="1527434966294733380">"Voit jakaa tämän laitteen muiden kanssa luomalla lisää käyttäjiä. Kullakin käyttäjällä on oma tilansa, jota he voivat muokata esimerkiksi omilla sovelluksilla ja taustakuvilla. Käyttäjät voivat myös muokata laiteasetuksia, kuten Wi‑Fi-asetuksia, jotka vaikuttavat laitteen kaikkiin käyttäjiin.\n\nKun lisäät uuden käyttäjän, hänen tulee määrittää oman tilansa asetukset.\n\nKaikki käyttäjät voivat päivittää muiden käyttäjien sovelluksia. Esteettömyysominaisuuksia tai ‑palveluita ei välttämättä siirretä uudelle käyttäjälle."</string>
     <string name="user_add_user_message_short" msgid="3295959985795716166">"Kun lisäät uuden käyttäjän, hänen tulee määrittää oman tilansa asetukset.\n\nKaikki käyttäjät voivat päivittää sovelluksia muille käyttäjille."</string>
-    <string name="user_setup_dialog_title" msgid="8037342066381939995">"Määritetäänkö käyttäjän asetukset nyt?"</string>
-    <string name="user_setup_dialog_message" msgid="269931619868102841">"Varmista, että käyttäjä voi vastaanottaa laitteen ja määrittää oman tilansa."</string>
+    <string name="user_setup_dialog_title" msgid="8037342066381939995">"Lisätäänkö käyttäjä nyt?"</string>
+    <string name="user_setup_dialog_message" msgid="269931619868102841">"Varmista, että käyttäjä voi ottaa laitteen nyt ja määrittää oman tilansa."</string>
     <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Määritetäänkö profiilin asetukset nyt?"</string>
     <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Määritä nyt"</string>
     <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Ei nyt"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Ei käytössä"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Käytössä"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Laitteesi on käynnistettävä uudelleen, jotta muutos tulee voimaan. Käynnistä uudelleen nyt tai peruuta."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> (työ)"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index a144444..26e5042 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -195,7 +195,7 @@
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"Sélectionnez un profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Personnel"</string>
-    <string name="category_work" msgid="4014193632325996115">"Travail"</string>
+    <string name="category_work" msgid="4014193632325996115">"Professionnel"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Options pour les concepteurs"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Activer les options pour les concepteurs"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Définir les options pour le développement de l\'application"</string>
@@ -231,7 +231,7 @@
     <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Échec de l\'association de l\'appareil Soit le code QR est incorrect, soit l\'appareil n\'est pas connecté au même réseau."</string>
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adresse IP et port"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Numériser le code QR"</string>
-    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Associer un appareil par Wi-Fi en numérisant un code QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Associer l\'appareil par Wi-Fi en numérisant un code QR"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Veuillez vous connecter à un réseau Wi-Fi"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, débogage, concepteur"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Raccourci de rapport de bogue"</string>
@@ -496,7 +496,7 @@
     <string name="cancel" msgid="5665114069455378395">"Annuler"</string>
     <string name="okay" msgid="949938843324579502">"OK"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activer"</string>
-    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activer la fonction « Ne pas déranger »"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activer le mode Ne pas déranger"</string>
     <string name="zen_mode_settings_summary_off" msgid="3832876036123504076">"Jamais"</string>
     <string name="zen_interruption_level_priority" msgid="5392140786447823299">"Priorités seulement"</string>
     <string name="zen_mode_and_condition" msgid="8877086090066332516">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
@@ -554,4 +554,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activé"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Votre appareil doit être redémarré pour que ce changement prenne effet. Redémarrez-le maintenant ou annulez la modification."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> (travail)"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index f7bfad8..b8fc50d 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -231,7 +231,7 @@
     <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Échec de l\'association à l\'appareil. Le code QR est incorrect, ou l\'appareil n\'est pas connecté au même réseau."</string>
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adresse IP et port"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scanner un code QR"</string>
-    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Associer l\'appareil via le Wi‑Fi à l\'aide d\'un code QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Associez l\'appareil via le Wi‑Fi à l\'aide d\'un code QR"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Connectez-vous à un réseau Wi-Fi"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, débogage, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Raccourci vers rapport de bug"</string>
@@ -433,7 +433,7 @@
     <string name="power_discharge_by" msgid="4113180890060388350">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharge_by_only_short" msgid="5883041507426914446">"Jusqu\'à <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"La batterie risque d\'être épuisée à <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"La batterie risque d\'être épuisée d\'ici <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="446388082266121894">"Il reste plus de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Désactivé"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activé"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Vous devez redémarrer l\'appareil pour que cette modification soit appliquée. Redémarrez maintenant ou annulez l\'opération."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> (travail)"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 08d2eae..8dc58ef 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -207,7 +207,7 @@
     <string name="enable_adb_summary" msgid="3711526030096574316">"Modo de depuración de erros cando o USB está conectado"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Revogar as autorizacións de depuración por USB"</string>
     <string name="enable_adb_wireless" msgid="6973226350963971018">"Depuración sen fíos"</string>
-    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modo de depuración de erros ao conectarse a wifi"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modo de depuración de erros ao conectarse á wifi"</string>
     <string name="adb_wireless_error" msgid="721958772149779856">"Produciuse un erro"</string>
     <string name="adb_wireless_settings" msgid="2295017847215680229">"Depuración sen fíos"</string>
     <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver e usar os dispositivos dispoñibles, activa a depuración sen fíos"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Desactivado"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activado"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"É necesario reiniciar o teu dispositivo para aplicar este cambio. Reiníciao agora ou cancela o cambio."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Aplicación <xliff:g id="APP_NAME">%s</xliff:g> do traballo"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index b88126b..9f69a2c 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -468,7 +468,7 @@
     <string name="charge_length_format" msgid="6941645744588690932">"<xliff:g id="ID_1">%1$s</xliff:g> પહેલાં"</string>
     <string name="remaining_length_format" msgid="4310625772926171089">"<xliff:g id="ID_1">%1$s</xliff:g> બાકી"</string>
     <string name="screen_zoom_summary_small" msgid="6050633151263074260">"નાનું"</string>
-    <string name="screen_zoom_summary_default" msgid="1888865694033865408">"ડિફોલ્ટ"</string>
+    <string name="screen_zoom_summary_default" msgid="1888865694033865408">"ડિફૉલ્ટ"</string>
     <string name="screen_zoom_summary_large" msgid="4706951482598978984">"મોટું"</string>
     <string name="screen_zoom_summary_very_large" msgid="7317423942896999029">"વધુ મોટું"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="1438045624562358554">"સૌથી મોટું"</string>
@@ -534,7 +534,7 @@
     <string name="user_add_user_message_long" msgid="1527434966294733380">"તમે વધારાના વપરાશકર્તાઓ બનાવીને અન્ય લોકો સાથે આ ડિવાઇસને શેર કરી શકો છો. દરેક વપરાશકર્તા પાસે તેમની પોતાની સ્પેસ છે, જેને તેઓ ઍપ, વૉલપેપર, વગેરે સાથે કસ્ટમાઇઝ કરી શકે છે. વપરાશકર્તાઓ પ્રત્યેક વ્યક્તિને અસર કરતી હોય તેવી ડિવાઇસ સેટિંગ જેમ કે વાઇ-ફાઇને પણ સમાયોજિત કરી શકે છે.\n\nજ્યારે તમે કોઈ નવા વપરાશકર્તાને ઉમેરો છો, ત્યારે તે વ્યક્તિને તેમની સ્પેસ સેટ કરવાની જરૂર પડે છે.\n\nકોઈપણ વપરાશકર્તા અન્ય બધા વપરાશકર્તાઓ માટે ઍપને અપડેટ કરી શકે છે. નવા વપરાશકર્તાને ઍક્સેસિબિલિટી સેટિંગ અને સેવાઓ ટ્રાન્સફર ન પણ થાય."</string>
     <string name="user_add_user_message_short" msgid="3295959985795716166">"જ્યારે તમે કોઈ નવા વપરાશકર્તાને ઉમેરો છો, ત્યારે તે વ્યક્તિને તેમનું સ્થાન સેટ અપ કરવાની જરૂર પડે છે.\n\nકોઈપણ વપરાશકર્તા બધા અન્ય વપરાશકર્તાઓ માટે એપ્લિકેશન્સને અપડેટ કરી શકે છે."</string>
     <string name="user_setup_dialog_title" msgid="8037342066381939995">"અત્યારે જ વપરાશકર્તાને સેટ અપ કરીએ?"</string>
-    <string name="user_setup_dialog_message" msgid="269931619868102841">"ખાતરી કરો કે વ્યક્તિ ઉપકરણ લેવા અને તેમના સ્થાનનું સેટ અપ કરવા માટે ઉપલબ્ધ છે"</string>
+    <string name="user_setup_dialog_message" msgid="269931619868102841">"ખાતરી કરો કે વ્યક્તિ ડિવાઇસ લેવા અને તેમના સ્થાનનું સેટ અપ કરવા માટે ઉપલબ્ધ છે"</string>
     <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"હવે પ્રોફાઇલ સેટ કરીએ?"</string>
     <string name="user_setup_button_setup_now" msgid="1708269547187760639">"હવે સેટ કરો"</string>
     <string name="user_setup_button_setup_later" msgid="8712980133555493516">"હમણાં નહીં"</string>
@@ -549,14 +549,11 @@
     <string name="guest_new_guest" msgid="3482026122932643557">"અતિથિ ઉમેરો"</string>
     <string name="guest_exit_guest" msgid="5908239569510734136">"અતિથિને કાઢી નાખો"</string>
     <string name="guest_nickname" msgid="6332276931583337261">"અતિથિ"</string>
-    <!-- no translation found for cached_apps_freezer_device_default (2616594131750144342) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_disabled (4816382260660472042) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_enabled (8866703500183051546) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_reboot_dialog_text (695330563489230096) -->
-    <skip />
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ડિવાઇસ ડિફૉલ્ટ"</string>
+    <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"બંધ છે"</string>
+    <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ચાલુ છે"</string>
+    <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"આ ફેરફારને લાગુ કરવા માટે તમારા ડિવાઇસને રીબૂટ કરવાની જરૂર છે. હમણાં જ રીબૂટ કરો કે રદ કરો."</string>
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"ઑફિસ <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 7dda73d..dc8e28b 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -284,7 +284,7 @@
     <string name="wifi_display_certification_summary" msgid="8111151348106907513">"वायरलेस डिसप्ले सर्टिफ़िकेशन के विकल्प दिखाएं"</string>
     <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"वाई-फ़ाई लॉगिंग का स्तर बढ़ाएं, वाई-फ़ाई पिकर में प्रति SSID RSSI दिखाएं"</string>
     <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"बैटरी की खपत कम और नेटवर्क की परफ़ॉर्मेंस बेहतर होती है"</string>
-    <string name="wifi_enhanced_mac_randomization_summary" msgid="1210663439867489931">"जब यह मोड चालू होता है, तब नेटवर्क से कनेक्ट होने पर हर बार इस डिवाइस का MAC पता बदल सकता है. ऐसा तब होता है, जब डिवाइस किसी ऐसे नेटवर्क से जुड़ता है जिस पर MAC पते को बिना किसी तय नियम के बदलने की सुविधा चालू होती है."</string>
+    <string name="wifi_enhanced_mac_randomization_summary" msgid="1210663439867489931">"जब यह मोड चालू होता है, तब नेटवर्क से कनेक्ट होने पर हर बार इस डिवाइस का मैक पता बदल सकता है. ऐसा तब होता है, जब डिवाइस किसी ऐसे नेटवर्क से जुड़ता है जिस पर मैक पते को बिना किसी तय नियम के बदलने की सुविधा चालू होती है."</string>
     <string name="wifi_metered_label" msgid="8737187690304098638">"डेटा इस्तेमाल करने की सीमा तय की गई है"</string>
     <string name="wifi_unmetered_label" msgid="6174142840934095093">"डेटा इस्तेमाल करने की सीमा तय नहीं की गई है"</string>
     <string name="select_logd_size_title" msgid="1604578195914595173">"लॉगर बफ़र आकार"</string>
@@ -418,7 +418,7 @@
     <string name="daltonizer_mode_deuteranomaly" msgid="3507284319584683963">"लाल-हरे रंग की पहचान न कर पाना (लाल-हरा)"</string>
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"लाल रंग पहचान न पाना (लाल-हरा)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"नीला रंग पहचान न पाना (नीला-पीला)"</string>
-    <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"रंग सुधार"</string>
+    <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"रंग में सुधार करने की सुविधा"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"रंग में सुधार करने की सुविधा, आपके डिवाइस पर दिखने वाले रंगों में बदलाव करने में मदद करती है"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> के द्वारा ओवरराइड किया गया"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"बंद है"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"चालू है"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"बदली गई सेटिंग को लागू करने के लिए, अपने डिवाइस को फिर से चालू करें. डिवाइस को फिर से चालू करें या रद्द करें."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"ऑफ़िस वाला <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 1db40a8..f887839 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -251,7 +251,7 @@
     <string name="wifi_display_certification" msgid="1805579519992520381">"Certifikacija bežičnog prikaza"</string>
     <string name="wifi_verbose_logging" msgid="1785910450009679371">"Omogući opširnu prijavu na Wi-Fi"</string>
     <string name="wifi_scan_throttling" msgid="2985624788509913617">"Usporavanje traženja Wi-Fija"</string>
-    <string name="wifi_enhanced_mac_randomization" msgid="5437378364995776979">"Nasum. odabir MAC-a poboljšan Wi‑Fi‑jem"</string>
+    <string name="wifi_enhanced_mac_randomization" msgid="5437378364995776979">"Nasum. odabir MAC-a poboljšan Wi‑Fijem"</string>
     <string name="mobile_data_always_on" msgid="8275958101875563572">"Mobilni podaci uvijek aktivni"</string>
     <string name="tethering_hardware_offload" msgid="4116053719006939161">"Hardversko ubrzanje za modemsko povezivanje"</string>
     <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Prikaži Bluetooth uređaje bez naziva"</string>
@@ -534,8 +534,8 @@
     <string name="user_add_user_title" msgid="5457079143694924885">"Dodati novog korisnika?"</string>
     <string name="user_add_user_message_long" msgid="1527434966294733380">"Da biste ovaj uređaj dijelili s drugima, možete napraviti dodatne korisnike. Svaki korisnik ima svoj prostor koji može prilagoditi pomoću vlastitih aplikacija, pozadine i tako dalje. Korisnici mogu prilagoditi i postavke uređaja koje utječu na sve ostale korisnike, na primjer Wi‑Fi.\n\nKada dodate novog korisnika, ta osoba mora postaviti svoj prostor.\n\nBilo koji korisnik može ažurirati aplikacije za sve ostale korisnike. Postavke i usluge pristupačnosti možda se neće prenijeti na novog korisnika."</string>
     <string name="user_add_user_message_short" msgid="3295959985795716166">"Kada dodate novog korisnika, ta osoba mora postaviti vlastiti prostor.\n\nBilo koji korisnik može ažurirati aplikacije za sve ostale korisnike."</string>
-    <string name="user_setup_dialog_title" msgid="8037342066381939995">"Postaviti korisnika sada?"</string>
-    <string name="user_setup_dialog_message" msgid="269931619868102841">"Provjerite može li osoba uzeti uređaj i postaviti svoj prostor"</string>
+    <string name="user_setup_dialog_title" msgid="8037342066381939995">"Želite li postaviti korisnika?"</string>
+    <string name="user_setup_dialog_message" msgid="269931619868102841">"Uređaj morate dati toj osobi da sama postavi svoj prostor"</string>
     <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Želite li sada postaviti profil?"</string>
     <string name="user_setup_button_setup_now" msgid="1708269547187760639">"Postavi sada"</string>
     <string name="user_setup_button_setup_later" msgid="8712980133555493516">"Ne sad"</string>
@@ -555,4 +555,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogućeno"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Uređaj se mora ponovno pokrenuti da bi se ta promjena primijenila. Ponovo pokrenite uređaj odmah ili odustanite."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> za posao"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 4b2132b..d7d2694 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -433,7 +433,7 @@
     <string name="power_discharge_by" msgid="4113180890060388350">"Nagyjából eddig bírja: <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"Nagyjából eddig bírja: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharge_by_only_short" msgid="5883041507426914446">"Eddig: <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Az akkumulátor lemerülhet a következő időpontig: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Az akkumulátor lemerülhet: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"Kevesebb mint <xliff:g id="THRESHOLD">%1$s</xliff:g> van hátra"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"Kevesebb mint <xliff:g id="THRESHOLD">%1$s</xliff:g> van hátra (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="446388082266121894">"Több mint <xliff:g id="TIME_REMAINING">%1$s</xliff:g> van hátra (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Letiltva"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Engedélyezve"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Az eszközt újra kell indítani, hogy a módosítás megtörténjen. Indítsa újra most, vagy vesse el a módosítást."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Munkahelyi <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 11da054..a5ef6b5 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -433,7 +433,7 @@
     <string name="power_discharge_by" msgid="4113180890060388350">"Լիցքը (<xliff:g id="LEVEL">%2$s</xliff:g>) պետք է որ բավականացնի մինչև <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"Լիցքը պետք է որ բավականացնի մինչև <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharge_by_only_short" msgid="5883041507426914446">"Մինչև <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Մարտկոցի լիցքը կարող է սպառվել մինչև <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Լիցքը կարող է սպառվել մինչև <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"Մնացել է <xliff:g id="THRESHOLD">%1$s</xliff:g>-ից քիչ"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"Մնացել է <xliff:g id="THRESHOLD">%1$s</xliff:g>-ից քիչ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="446388082266121894">"Մնացել է ավելի քան <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -452,7 +452,7 @@
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Արագ լիցքավորում"</string>
     <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Դանդաղ լիցքավորում"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Չի լիցքավորվում"</string>
-    <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Միացված է հոսանքի աղբյուրին, սակայն այս պահին չի կարող լիցքավորվել"</string>
+    <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Միացված է հոսանքին, այս պահին չի կարող լիցքավորվել"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Լիցքավորված է"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Վերահսկվում է ադմինիստրատորի կողմից"</string>
     <string name="disabled" msgid="8017887509554714950">"Կասեցված է"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Անջատված է"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Միացված է"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Սարքն անհրաժեշտ է վերագործարկել, որպեսզի փոփոխությունը կիրառվի։ Վերագործարկեք հիմա կամ չեղարկեք փոփոխությունը։"</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Աշխատանքային <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 3b02fbf..04ca2f6 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -195,7 +195,7 @@
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"Pilih profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Pribadi"</string>
-    <string name="category_work" msgid="4014193632325996115">"Kantor"</string>
+    <string name="category_work" msgid="4014193632325996115">"Kerja"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opsi developer"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Aktifkan opsi developer"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Menyetel opsi untuk pengembangan apl"</string>
@@ -433,7 +433,7 @@
     <string name="power_discharge_by" msgid="4113180890060388350">"Akan bertahan kira-kira sampai pukul <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"Akan bertahan kira-kira sampai pukul <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharge_by_only_short" msgid="5883041507426914446">"Hingga <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Baterai mungkin habis pada <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Baterai mungkin habis pada pukul <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"Tersisa kurang dari <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"Tersisa kurang dari <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="446388082266121894">"Tersisa lebih dari <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Nonaktif"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktif"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Perangkat Anda harus di-reboot agar perubahan ini diterapkan. Reboot sekarang atau batalkan."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> kerja"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 6560de0..ce60eb5 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Slökkt"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Virkt"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Endurræsa þarf tækið til að þessi breyting taki gildi. Endurræstu núna eða hættu við."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> í vinnu"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index ece0ba4..bef644b 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Non attivo"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Attivo"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Devi riavviare il dispositivo per applicare questa modifica. Riavvia ora o annulla."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"App <xliff:g id="APP_NAME">%s</xliff:g> di lavoro"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 23e701d..ed79632 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -555,6 +555,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"מושבת"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"מופעל"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"צריך להפעיל מחדש את המכשיר כדי להחיל את השינוי. יש להפעיל מחדש עכשיו או לבטל."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> של עבודה"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 7640722..3f08a6a 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -210,7 +210,7 @@
     <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi-Fi 接続時にデバッグモード"</string>
     <string name="adb_wireless_error" msgid="721958772149779856">"エラー"</string>
     <string name="adb_wireless_settings" msgid="2295017847215680229">"ワイヤレス デバッグ"</string>
-    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"利用可能なデバイスを確認して使用するには、ワイヤレス デバッグをオンにしてください"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"利用可能なデバイスを確認して使用するには、ワイヤレス デバッグを ON にしてください"</string>
     <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR コードによるデバイスのペア設定"</string>
     <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"QR コードスキャナを使って新しいデバイスをペア設定します"</string>
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"ペア設定コードによるデバイスのペア設定"</string>
@@ -235,7 +235,7 @@
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Wi-Fi ネットワークに接続してください"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, デバッグ, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"バグレポートのショートカット"</string>
-    <string name="bugreport_in_power_summary" msgid="1885529649381831775">"電源メニューにバグレポートを取得するボタンを表示する"</string>
+    <string name="bugreport_in_power_summary" msgid="1885529649381831775">"電源ボタン メニューにバグレポートを取得するボタンを表示する"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"スリープモードにしない"</string>
     <string name="keep_screen_on_summary" msgid="1510731514101925829">"充電中に画面をスリープにしない"</string>
     <string name="bt_hci_snoop_log" msgid="7291287955649081448">"Bluetooth HCI スヌープログ"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"無効"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"有効"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"この変更を適用するには、デバイスの再起動が必要です。今すぐ再起動してください。キャンセルすることもできます。"</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"仕事の<xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 985188f..2ebc3ee 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -554,4 +554,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ჩართული"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ამ ცვლილების ასამოქმედებლად თქვენი მოწყობილობა უნდა გადაიტვირთოს. გადატვირთეთ ახლავე ან გააუქმეთ."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"სამსახურის <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index a5308e4..91e5488 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -42,7 +42,7 @@
     <string name="connected_via_app" msgid="3532267661404276584">"<xliff:g id="NAME">%1$s</xliff:g> арқылы жалғанған"</string>
     <string name="available_via_passpoint" msgid="1716000261192603682">"%1$s арқылы қолжетімді"</string>
     <string name="tap_to_sign_up" msgid="5356397741063740395">"Тіркелу үшін түртіңіз."</string>
-    <string name="wifi_connected_no_internet" msgid="5087420713443350646">"Интернетпен байланыс жоқ."</string>
+    <string name="wifi_connected_no_internet" msgid="5087420713443350646">"Интернетпен байланыс жоқ"</string>
     <string name="private_dns_broken" msgid="1984159464346556931">"Жеке DNS серверіне кіру мүмкін емес."</string>
     <string name="wifi_limited_connection" msgid="1184778285475204682">"Шектеулі байланыс"</string>
     <string name="wifi_status_no_internet" msgid="3799933875988829048">"Интернетпен байланыс жоқ"</string>
@@ -61,7 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Орташа"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Жылдам"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Өте жылдам"</string>
-    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Мерзімі өтті."</string>
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Мерзімі өтті"</string>
     <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">"Ажыратылған"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ажыратылуда…"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Өшірулі"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Қосулы"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Бұл өзгеріс күшіне енуі үшін, құрылғыны қайта жүктеу керек. Қазір қайта жүктеңіз не бас тартыңыз."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> (жұмыс)"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 0ff48e1..143f5f9 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -445,8 +445,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"ថេប្លេត​អាចនឹង​បិទក្នុង​ពេលបន្តិច​ទៀត (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"ឧបករណ៍​អាចនឹង​បិទក្នុង​ពេលបន្តិច​ទៀត (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ទៀតទើប​ត្រូវសាក"</string>
-    <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើប​ត្រូវសាក"</string>
+    <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ទៀតទើបសាកថ្មពេញ"</string>
+    <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើប​សាកថ្មពេញ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"មិន​ស្គាល់"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"កំពុងបញ្ចូល​ថ្ម"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string>
@@ -537,7 +537,7 @@
     <string name="user_setup_dialog_message" msgid="269931619868102841">"សូម​ប្រាកដ​ថា​​អ្នក​ប្រើ​ប្រាស់នេះ​អាច​យក​​ឧបករណ៍ ​និង​រៀបចំ​​ទំហំ​ផ្ទុករបស់​គេបាន"</string>
     <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"រៀបចំ​ប្រវត្តិរូប​ឥឡូវ?"</string>
     <string name="user_setup_button_setup_now" msgid="1708269547187760639">"រៀបចំ​ឥឡូវ"</string>
-    <string name="user_setup_button_setup_later" msgid="8712980133555493516">"កុំអាល"</string>
+    <string name="user_setup_button_setup_later" msgid="8712980133555493516">"កុំទាន់"</string>
     <string name="user_add_user_type_title" msgid="551279664052914497">"បន្ថែម"</string>
     <string name="user_new_user_name" msgid="60979820612818840">"អ្នក​ប្រើថ្មី"</string>
     <string name="user_new_profile_name" msgid="2405500423304678841">"ប្រវត្តិរូប​ថ្មី"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"បានបិទ"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"បានបើក"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ត្រូវតែ​ចាប់ផ្ដើម​ឧបករណ៍​របស់អ្នក​ឡើងវិញ ទើប​ការផ្លាស់ប្ដូរ​នេះ​ត្រូវបានអនុវត្ត​។ ចាប់ផ្ដើមឡើងវិញ​ឥឡូវនេះ ឬ​បោះបង់​។"</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> សម្រាប់ការងារ"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 52e3b99..1df141c 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -549,14 +549,11 @@
     <string name="guest_new_guest" msgid="3482026122932643557">"ಅತಿಥಿಯನ್ನು ಸೇರಿಸಿ"</string>
     <string name="guest_exit_guest" msgid="5908239569510734136">"ಅತಿಥಿಯನ್ನು ತೆಗೆದುಹಾಕಿ"</string>
     <string name="guest_nickname" msgid="6332276931583337261">"ಅತಿಥಿ"</string>
-    <!-- no translation found for cached_apps_freezer_device_default (2616594131750144342) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_disabled (4816382260660472042) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_enabled (8866703500183051546) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_reboot_dialog_text (695330563489230096) -->
-    <skip />
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ಸಾಧನದ ಡೀಫಾಲ್ಟ್"</string>
+    <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ಈ ಬದಲಾವಣೆ ಅನ್ವಯವಾಗಲು ನಿಮ್ಮ ಸಾಧನವನ್ನು ರೀಬೂಟ್ ಮಾಡಬೇಕು. ಇದೀಗ ರೀಬೂಟ್ ಮಾಡಿ ಅಥವಾ ರದ್ದುಗೊಳಿಸಿ."</string>
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"ಉದ್ಯೋಗ <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index b8d587b..86e1650 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -495,7 +495,7 @@
     <string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"시간 줄이기"</string>
     <string name="cancel" msgid="5665114069455378395">"취소"</string>
     <string name="okay" msgid="949938843324579502">"확인"</string>
-    <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"켜기"</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"사용 설정"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"방해 금지 모드 사용 설정"</string>
     <string name="zen_mode_settings_summary_off" msgid="3832876036123504076">"사용 안함"</string>
     <string name="zen_interruption_level_priority" msgid="5392140786447823299">"중요 알림만 허용"</string>
@@ -530,7 +530,7 @@
     <string name="user_add_profile_item_summary" msgid="5418602404308968028">"내 계정의 앱 및 콘텐츠에 대한 액세스를 제한할 수 있습니다."</string>
     <string name="user_add_user_item_title" msgid="2394272381086965029">"사용자"</string>
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"제한된 프로필"</string>
-    <string name="user_add_user_title" msgid="5457079143694924885">"새 사용자를 추가할까요?"</string>
+    <string name="user_add_user_title" msgid="5457079143694924885">"신규 사용자를 추가할까요?"</string>
     <string name="user_add_user_message_long" msgid="1527434966294733380">"추가 사용자를 만들어 다른 사용자와 기기를 공유할 수 있습니다. 각 사용자는 앱, 배경화면 등으로 맞춤설정할 수 있는 자신만의 공간을 갖게 됩니다. 또한 모든 사용자에게 영향을 미치는 Wi‑Fi와 같은 기기 설정도 조정할 수 있습니다.\n\n추가된 신규 사용자는 자신의 공간을 설정해야 합니다.\n\n모든 사용자가 앱을 업데이트할 수 있으며, 업데이트는 다른 사용자에게도 적용됩니다. 접근성 설정 및 서비스는 신규 사용자에게 이전되지 않을 수도 있습니다."</string>
     <string name="user_add_user_message_short" msgid="3295959985795716166">"추가된 새로운 사용자는 자신의 공간을 설정해야 합니다.\n\n모든 사용자는 다른 사용자들을 위하여 앱을 업데이트할 수 있습니다."</string>
     <string name="user_setup_dialog_title" msgid="8037342066381939995">"지금 사용자를 설정하시겠습니까?"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"사용 중지됨"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"사용 설정됨"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"변경사항을 적용하려면 기기를 재부팅해야 합니다. 지금 재부팅하거나 취소하세요."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"직장용 <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 3c57c79..925f4a7 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -224,7 +224,7 @@
     <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> туура тармакка туташып турганын текшериңиз"</string>
     <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Түзмөктү жупташтыруу"</string>
     <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi жупташтыруучу коду"</string>
-    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Жупташтырылган жок"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Туташкан жок"</string>
     <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Түзмөк бир тармакка туташып турушу керек."</string>
     <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR кодун скандап, түзмөктү Wi‑Fi аркылуу жупташтырыңыз"</string>
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Түзмөк жупташтырылууда…"</string>
@@ -302,7 +302,7 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Мүмкүнчүлүккө жараша, модем режиминде аппарат тезирээк иштей баштайт"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB аркылуу жөндөөгө уруксат бересизби?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB-жөндөө - өндүрүү максатында гана  түзүлгөн. Аны компүтериңиз менен түзмөгүңүздүн ортосунда берилиштерди алмашуу, түзмөгүңүзгө колдонмолорду эскертүүсүз орнотуу жана лог берилиштерин окуу үчүн колдонсоңуз болот."</string>
-    <string name="adbwifi_warning_title" msgid="727104571653031865">"Мүчүлүштүктөрдү Wi-Fi аркылуу оңдоого уруксат берилсинби?"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Мүчүлүштүктөрдү Wi-Fi аркылуу оңдоого уруксат бересизби?"</string>
     <string name="adbwifi_warning_message" msgid="8005936574322702388">"Мүчүлүштүктөрдү Wi-Fi аркылуу аныктоо – өндүрүү максатында гана түзүлгөн. Аны компьютериңиз менен түзмөгүңүздүн ортосунда маалыматты алмашуу, колдонмолорду түзмөгүңүзгө эскертүүсүз орнотуу жана маалыматтар таржымалын окуу үчүн колдонсоңуз болот."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Сиз мурун USB жөндөөлөрүнө уруксат берген бардык компүтерлердин жеткиси жокко чыгарылсынбы?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Жөндөөлөрдү өзгөртүү"</string>
@@ -445,8 +445,8 @@
     <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Планшет бир аздан кийин өчүп калышы мүмкүн (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Түзмөк бир аздан кийин өчүп калышы мүмкүн (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> кийин кубатталат"</string>
-    <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> кийин кубатталат"</string>
+    <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> кийин толук кубатталып бүтөт"</string>
+    <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> кийин толук кубатталып бүтөт"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Белгисиз"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Кубатталууда"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ыкчам кубатталууда"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Өчүк"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Күйүк"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Бул өзгөртүүнү колдонуу үчүн түзмөктү өчүрүп күйгүзүңүз. Азыр өчүрүп күйгүзүңүз же жокко чыгарыңыз."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Жумуш <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 02f73b5..3bf1996 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -554,4 +554,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ເປີດການນຳໃຊ້ແລ້ວ"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ທ່ານຕ້ອງປິດເປີດອຸປະກອນຄືນໃໝ່ເພື່ອນຳໃຊ້ການປ່ຽນແປງນີ້. ປິດເປີດໃໝ່ດຽວນີ້ ຫຼື ຍົກເລີກ."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"​ບ່ອນ​ເຮັດ​ວຽກ <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index dc6347a..153c995 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -555,6 +555,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Išjungta"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Įgalinta"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Kad pakeitimas būtų pritaikytas, įrenginį reikia paleisti iš naujo. Dabar paleiskite iš naujo arba atšaukite."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Darbo „<xliff:g id="APP_NAME">%s</xliff:g>“"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 0a185d0..f6e7f35 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -168,7 +168,7 @@
     <string name="tts_play_example_summary" msgid="634044730710636383">"Atskaņot īsu runas sintēzes demonstrāciju"</string>
     <string name="tts_install_data_title" msgid="1829942496472751703">"Instalēt balss datus"</string>
     <string name="tts_install_data_summary" msgid="3608874324992243851">"Instalēt runas sintēzei nepieciešamos balss datus"</string>
-    <string name="tts_engine_security_warning" msgid="3372432853837988146">"Lietojot šo runas sintēzes programmu, var tikt apkopots viss ierunātais teksts, tostarp tāda personīgā informācija kā paroles un kredītkaršu numuri. Tā ir no <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> programmas. Vai iespējot šīs runas sintēzes programmas lietošanu?"</string>
+    <string name="tts_engine_security_warning" msgid="3372432853837988146">"Lietojot šo runas sintēzes programmu, var tikt vākts viss ierunātais teksts, tostarp tāda personīgā informācija kā paroles un kredītkaršu numuri. Tā ir no <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> programmas. Vai iespējot šīs runas sintēzes programmas lietošanu?"</string>
     <string name="tts_engine_network_required" msgid="8722087649733906851">"Lai izmantotu teksta pārveidošanu runā šajā valodā, ir nepieciešams aktīvs tīkla savienojums."</string>
     <string name="tts_default_sample_string" msgid="6388016028292967973">"Šis ir runas sintēzes piemērs."</string>
     <string name="tts_status_title" msgid="8190784181389278640">"Noklusējuma valodas statuss"</string>
@@ -554,6 +554,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Atspējots"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Iespējots"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Lai šīs izmaiņas tiktu piemērotas, nepieciešama ierīces atkārtota palaišana. Atkārtoti palaidiet to tūlīt vai atceliet izmaiņas."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Darbā: <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index e0cc38d..d55f1af 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Оневозможено"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Овозможено"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"За да се примени променава, уредот мора да се рестартира. Рестартирајте сега или откажете."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Работна <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 1a3f068..c5267d6 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -549,14 +549,11 @@
     <string name="guest_new_guest" msgid="3482026122932643557">"അതിഥിയെ ചേർക്കുക"</string>
     <string name="guest_exit_guest" msgid="5908239569510734136">"അതിഥിയെ നീക്കം ചെയ്യുക"</string>
     <string name="guest_nickname" msgid="6332276931583337261">"അതിഥി"</string>
-    <!-- no translation found for cached_apps_freezer_device_default (2616594131750144342) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_disabled (4816382260660472042) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_enabled (8866703500183051546) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_reboot_dialog_text (695330563489230096) -->
-    <skip />
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ഉപകരണത്തിന്റെ ഡിഫോൾട്ട് പ്രവർത്തനം"</string>
+    <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"പ്രവർത്തനരഹിതമാക്കി"</string>
+    <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"പ്രവർത്തനക്ഷമമാക്കി"</string>
+    <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ഈ മാറ്റം ബാധകമാകുന്നതിന് നിങ്ങളുടെ ഉപകരണം റീബൂട്ട് ചെയ്യേണ്ടതുണ്ട്. ഇപ്പോൾ റീബൂട്ട് ചെയ്യുകയോ റദ്ദാക്കുകയോ ചെയ്യുക."</string>
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"ഔദ്യോഗികം <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index a342862..0a01f84 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -419,7 +419,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномаль (улаан-ногоон)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомаль (цэнхэр-шар)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Өнгө тохируулах"</string>
-    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Өнгө залруулга нь төхөөрөмж дээрээ өнгийг хэрхэн үзүүлэхийг тохируулах боломжийг танд олгодог"</string>
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"Өнгө тохируулга нь танд төхөөрөмж дээрээ өнгө хэрхэн харагдахыг тохируулах боломжийг олгодог"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Давхарласан <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Ойролцоогоор <xliff:g id="TIME_REMAINING">%1$s</xliff:g> үлдсэн"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Идэвхгүй болгосон"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Идэвхжүүлсэн"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Энэ өөрчлөлтийг хэрэгжүүлэхийн тулд таны төхөөрөмжийг дахин асаах ёстой. Одоо дахин асаах эсвэл болино уу."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Ажлын <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 0895cd4..075c748 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -243,7 +243,7 @@
     <string name="oem_unlock_enable" msgid="5334869171871566731">"OEM अनलॉक करणे"</string>
     <string name="oem_unlock_enable_summary" msgid="5857388174390953829">"बूटलोडर अनलॉक करण्यासाठी अनुमती द्या"</string>
     <string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"OEM अनलॉक करण्यास अनुमती द्यायची?"</string>
-    <string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"चेतावणी: हे सेटिंग चालू असताना या डिव्हाइस वर डिव्हाइस संरक्षण वैशिष्ट्ये काम करणार नाहीत."</string>
+    <string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"चेतावणी: हे सेटिंग सुरू असताना या डिव्हाइस वर डिव्हाइस संरक्षण वैशिष्ट्ये काम करणार नाहीत."</string>
     <string name="mock_location_app" msgid="6269380172542248304">"बनावट स्थान अ‍ॅप निवडा"</string>
     <string name="mock_location_app_not_set" msgid="6972032787262831155">"कोणताही बनावट स्थान अ‍ॅप सेट केला नाही"</string>
     <string name="mock_location_app_set" msgid="4706722469342913843">"बनावट स्थान अ‍ॅप: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -298,7 +298,7 @@
     <string name="allow_mock_location" msgid="2102650981552527884">"बनावट स्थानांना अनुमती द्या"</string>
     <string name="allow_mock_location_summary" msgid="179780881081354579">"बनावट स्थानांना अनुमती द्या"</string>
     <string name="debug_view_attributes" msgid="3539609843984208216">"दृश्‍य विशेषता तपासणी सुरू करा"</string>
-    <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"वाय-फाय चालू असतानाही मोबाइल डेटा नेहमी सुरू ठेवा (नेटवर्क जलदरीत्या स्विच करण्यासाठी)."</string>
+    <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"वाय-फाय सुरू असतानाही मोबाइल डेटा नेहमी सुरू ठेवा (नेटवर्क जलदरीत्या स्विच करण्यासाठी)."</string>
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"उपलब्ध असल्यास टेदरिंग हार्डवेअर ॲक्सिलरेशन वापरा"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB डीबग करण्यास अनुमती द्यायची?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB डीबग करण्याचा हेतू फक्त विकास उद्देशांसाठी आहे. याचा वापर तुमचा कॉंप्युटर आणि तुमचे डिव्हाइस यांच्या दरम्यान डेटा कॉपी करण्यासाठी करा, सूचनेशिवाय तुमच्या डिव्हाइस वर अ‍ॅप्स इंस्टॉल करा आणि लॉग डेटा वाचा."</string>
@@ -409,7 +409,7 @@
     <string name="convert_to_file_encryption_enabled" msgid="840757431284311754">"रूपांतरित करा..."</string>
     <string name="convert_to_file_encryption_done" msgid="8965831011811180627">"फाईल आधीपासून एंक्रिप्ट होती"</string>
     <string name="title_convert_fbe" msgid="5780013350366495149">"फाईल आधारित कूटबद्धीकरणावर रूपांतरित करणे"</string>
-    <string name="convert_to_fbe_warning" msgid="34294381569282109">"फाईल आधारित कूटबद्धीकरणावर डेटा विभाजक रूपांतरित करा.\n !!चेतावणी!! हे आपल्‍या सर्व डेटास मिटवेल.\n हे वैशिष्ट्य अल्‍फा आहे आणि कदाचित योग्यरित्या कार्य करू शकत नाही.\n सुरु ठेवण्‍यासाठी \'पुसा आणि रूपांतरित करा...\' दाबा."</string>
+    <string name="convert_to_fbe_warning" msgid="34294381569282109">"फाईल आधारित कूटबद्धीकरणावर डेटा विभाजक रूपांतरित करा.\n !!चेतावणी!! हे आपल्‍या सर्व डेटास मिटवेल.\n हे वैशिष्ट्य अल्‍फा आहे आणि कदाचित योग्यरित्या कार्य करू शकत नाही.\n सुरू ठेवण्‍यासाठी \'पुसा आणि रूपांतरित करा...\' दाबा."</string>
     <string name="button_convert_fbe" msgid="1159861795137727671">"पुसा आणि रुपांतरित करा..."</string>
     <string name="picture_color_mode" msgid="1013807330552931903">"चित्र रंग मोड"</string>
     <string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB वापरा"</string>
@@ -495,8 +495,8 @@
     <string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"कमी वेळ."</string>
     <string name="cancel" msgid="5665114069455378395">"रद्द करा"</string>
     <string name="okay" msgid="949938843324579502">"ठीक आहे"</string>
-    <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"चालू करा"</string>
-    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"व्यत्यय आणू नका चालू करा"</string>
+    <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"सुरू करा"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"व्यत्यय आणू नका सुरू करा"</string>
     <string name="zen_mode_settings_summary_off" msgid="3832876036123504076">"कधीही नाही"</string>
     <string name="zen_interruption_level_priority" msgid="5392140786447823299">"केवळ प्राधान्य"</string>
     <string name="zen_mode_and_condition" msgid="8877086090066332516">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
@@ -549,14 +549,11 @@
     <string name="guest_new_guest" msgid="3482026122932643557">"अतिथी जोडा"</string>
     <string name="guest_exit_guest" msgid="5908239569510734136">"अतिथी काढून टाका"</string>
     <string name="guest_nickname" msgid="6332276931583337261">"अतिथी"</string>
-    <!-- no translation found for cached_apps_freezer_device_default (2616594131750144342) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_disabled (4816382260660472042) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_enabled (8866703500183051546) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_reboot_dialog_text (695330563489230096) -->
-    <skip />
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"डिव्हाइस डीफॉल्ट"</string>
+    <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"बंद केले आहे"</string>
+    <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"सुरू केले आहे"</string>
+    <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"हा बदल लागू करण्यासाठी तुमचे डिव्हाइस रीबूट करणे आवश्यक आहे. आता रीबूट करा किंवा रद्द करा."</string>
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"कार्य <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index a1c6782..cdf32a7 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Dilumpuhkan"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Didayakan"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Peranti anda mesti dibut semula supaya perubahan ini berlaku. But semula sekarang atau batalkan."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Kerja <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 0edc100..2bd3b45 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -153,7 +153,7 @@
     <string name="unknown" msgid="3544487229740637809">"မသိ"</string>
     <string name="running_process_item_user_label" msgid="3988506293099805796">"အသုံးပြုသူ- <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
     <string name="launch_defaults_some" msgid="3631650616557252926">"မူရင်းအချို့ သတ်မှတ်ပြီး"</string>
-    <string name="launch_defaults_none" msgid="8049374306261262709">"ပုံမှန်သတ်မှတ်ထားခြင်းမရှိ"</string>
+    <string name="launch_defaults_none" msgid="8049374306261262709">"မူရင်း သတ်မှတ်မထားပါ။"</string>
     <string name="tts_settings" msgid="8130616705989351312">"စာသားမှစကားပြောပြောင်း ဆက်တင်များ"</string>
     <string name="tts_settings_title" msgid="7602210956640483039">"စာသားမှ စကားပြောသို့ အထွက်"</string>
     <string name="tts_default_rate_title" msgid="3964187817364304022">"စကားပြောနှုန်း"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ပိတ်ထားသည်"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ဖွင့်ထားသည်"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ဤအပြောင်းအလဲ ထည့်သွင်းရန် သင့်စက်ကို ပြန်လည်စတင်ရမည်။ ယခု ပြန်လည်စတင်ပါ သို့မဟုတ် ပယ်ဖျက်ပါ။"</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"အလုပ် <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index d683070..de5bed6 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Slått av"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Slått på"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Enheten din må startes på nytt for at denne endringen skal tre i kraft. Start på nytt nå eller avbryt."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Jobb-<xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index ee22c60..bfe295a 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -399,7 +399,7 @@
     <string name="inactive_apps_title" msgid="5372523625297212320">"स्ट्यान्डबाई एपहरू"</string>
     <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"निष्क्रिय। टगल गर्न ट्याप गर्नुहोस्।"</string>
     <string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय। टगल गर्न ट्याप गर्नुहोस्।"</string>
-    <string name="standby_bucket_summary" msgid="5128193447550429600">"अनुप्रयोगको स्ट्यान्डबाई अवस्था:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
+    <string name="standby_bucket_summary" msgid="5128193447550429600">"एपको स्ट्यान्डबाई अवस्था:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
     <string name="runningservices_settings_title" msgid="6460099290493086515">"चलिरहेका सेवाहरू"</string>
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"हाल चालु भइरहेका सेवाहरू हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView कार्यान्वयन"</string>
@@ -549,14 +549,11 @@
     <string name="guest_new_guest" msgid="3482026122932643557">"अतिथि थप्नुहोस्"</string>
     <string name="guest_exit_guest" msgid="5908239569510734136">"अतिथि हटाउनुहोस्"</string>
     <string name="guest_nickname" msgid="6332276931583337261">"अतिथि"</string>
-    <!-- no translation found for cached_apps_freezer_device_default (2616594131750144342) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_disabled (4816382260660472042) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_enabled (8866703500183051546) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_reboot_dialog_text (695330563489230096) -->
-    <skip />
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"पूर्वनिर्धारित यन्त्र"</string>
+    <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"असक्षम पारिएको छ"</string>
+    <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"सक्षम पारिएको छ"</string>
+    <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"यो परिवर्तन लागू गर्न तपाईंको यन्त्र अनिवार्य रूपमा रिबुट गर्नु पर्छ। अहिले रिबुट गर्नुहोस् वा रद्द गर्नुहोस्।"</string>
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"कार्यालयको प्रोफाइल <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index dc5f8f2..a822719 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -554,4 +554,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ingeschakeld"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Je apparaat moet opnieuw worden opgestart om deze wijziging toe te passen. Start nu opnieuw op of annuleer de wijziging."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> voor werk"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 18cc9e3..ab9fbc3 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -235,7 +235,7 @@
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"ଦୟାକରି ଏକ ୱାଇ-ଫାଇ ନେଟୱାର୍କରେ ସଂଯୋଗ କରନ୍ତୁ"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ଡିବଗ୍, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"ବଗ୍ ରିପୋର୍ଟ ସର୍ଟକଟ୍‌"</string>
-    <string name="bugreport_in_power_summary" msgid="1885529649381831775">"ବଗ୍ ରିପୋର୍ଟ ଦେବାପାଇଁ ପାୱାର୍‌ ମେନୁରେ ଏକ ବଟନ୍‌ ଦେଖନ୍ତୁ"</string>
+    <string name="bugreport_in_power_summary" msgid="1885529649381831775">"ବଗ୍ ରିପୋର୍ଟ ଦେବା ପାଇଁ ପାୱାର୍‌ ମେନୁରେ ଏକ ବଟନ୍‌ ଦେଖାନ୍ତୁ"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"ଜାଗ୍ରତ ରଖନ୍ତୁ"</string>
     <string name="keep_screen_on_summary" msgid="1510731514101925829">"ଚାର୍ଜ ହେବାବେଳେ ସ୍କ୍ରୀନ୍‌ ଆଦୌ ବନ୍ଦ ହେବନାହିଁ"</string>
     <string name="bt_hci_snoop_log" msgid="7291287955649081448">"ବ୍ଲୁଟୂଥ୍‍‌ HCI ସ୍ନୁପ୍‌ ଲଗ୍‌ ସକ୍ଷମ କରନ୍ତୁ"</string>
@@ -245,7 +245,7 @@
     <string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"OEM ଅନଲକ୍‌ କରିବା ଅନୁମତି ଦେବେ?"</string>
     <string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"ଚେତାବନୀ: ଏହି ସେଟିଙ୍ଗ ଚାଲୁ ଥିବାବେଳେ ଡିଭାଇସ୍‌ର ସୁରକ୍ଷା ବୈଶିଷ୍ଟ୍ୟ କାମ କରିବ ନାହିଁ"</string>
     <string name="mock_location_app" msgid="6269380172542248304">"ମକ୍ ଲୋକେସନ୍‌ ଆପ୍‌ର ଚୟନ କରନ୍ତୁ"</string>
-    <string name="mock_location_app_not_set" msgid="6972032787262831155">"କୌଣସି ନକଲି ଲୋକେଶନ ଆପ୍ ସେଟ୍ କରାଯାଇନାହିଁ"</string>
+    <string name="mock_location_app_not_set" msgid="6972032787262831155">"କୌଣସି ମକ୍ ଲୋକେସନ ଆପ୍ ସେଟ୍ କରାଯାଇନାହିଁ"</string>
     <string name="mock_location_app_set" msgid="4706722469342913843">"ମକ୍ ଲୋକେସନ୍‌ ଆପ୍‌: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="debug_networking_category" msgid="6829757985772659599">"ନେଟ୍‌ୱର୍କିଙ୍ଗ"</string>
     <string name="wifi_display_certification" msgid="1805579519992520381">"ୱାୟରଲେସ୍‌ ଡିସ୍‌ପ୍ଲେ ସାର୍ଟିଫିକେସନ୍"</string>
@@ -549,14 +549,11 @@
     <string name="guest_new_guest" msgid="3482026122932643557">"ଅତିଥି ଯୋଗ କରନ୍ତୁ"</string>
     <string name="guest_exit_guest" msgid="5908239569510734136">"ଅତିଥିଙ୍କୁ କାଢ଼ି ଦିଅନ୍ତୁ"</string>
     <string name="guest_nickname" msgid="6332276931583337261">"ଅତିଥି"</string>
-    <!-- no translation found for cached_apps_freezer_device_default (2616594131750144342) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_disabled (4816382260660472042) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_enabled (8866703500183051546) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_reboot_dialog_text (695330563489230096) -->
-    <skip />
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ଡିଭାଇସ୍ ଡିଫଲ୍ଟ"</string>
+    <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ଅକ୍ଷମ କରାଯାଇଛି"</string>
+    <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ସକ୍ଷମ କରାଯାଇଛି"</string>
+    <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ଏହି ପରିବର୍ତ୍ତନ ଲାଗୁ କରିବା ପାଇଁ ଆପଣଙ୍କ ଡିଭାଇସକୁ ନିଶ୍ଚିତ ରୂପେ ରିବୁଟ୍ କରାଯିବା ଆବଶ୍ୟକ। ବର୍ତ୍ତମାନ ରିବୁଟ୍ କରନ୍ତୁ କିମ୍ବା ବାତିଲ୍ କରନ୍ତୁ।"</string>
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"ୱାର୍କ <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index b502f3f..35d8cba 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -549,14 +549,11 @@
     <string name="guest_new_guest" msgid="3482026122932643557">"ਮਹਿਮਾਨ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="guest_exit_guest" msgid="5908239569510734136">"ਮਹਿਮਾਨ ਹਟਾਓ"</string>
     <string name="guest_nickname" msgid="6332276931583337261">"ਮਹਿਮਾਨ"</string>
-    <!-- no translation found for cached_apps_freezer_device_default (2616594131750144342) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_disabled (4816382260660472042) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_enabled (8866703500183051546) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_reboot_dialog_text (695330563489230096) -->
-    <skip />
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ਪੂਰਵ-ਨਿਰਧਾਰਤ ਡੀਵਾਈਸ"</string>
+    <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ਬੰਦ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ਇਸ ਤਬਦੀਲੀ ਨੂੰ ਲਾਗੂ ਕਰਨ ਲਈ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨੂੰ ਰੀਬੂਟ ਕਰਨਾ ਲਾਜ਼ਮੀ ਹੈ। ਹੁਣੇ ਰੀਬੂਟ ਕਰੋ ਜਾਂ ਰੱਦ ਕਰੋ।"</string>
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"ਕੰਮ <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 8a29bf0..54ed131 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -195,7 +195,7 @@
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"Wybierz profil"</string>
     <string name="category_personal" msgid="6236798763159385225">"Osobiste"</string>
-    <string name="category_work" msgid="4014193632325996115">"Do pracy"</string>
+    <string name="category_work" msgid="4014193632325996115">"Służbowe"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opcje programistyczne"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Włącz opcje dla programistów"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Ustaw opcje związane z programowaniem aplikacji."</string>
@@ -555,6 +555,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Wyłączono"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Włączono"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Wprowadzenie zmiany wymaga ponownego uruchomienia urządzenia. Uruchom ponownie teraz lub anuluj."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> (do pracy)"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 58a13cd..c6dc1d3 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -61,7 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Média"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Muito rápida"</string>
-    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Expirado"</string>
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Expirada"</string>
     <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">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando…"</string>
@@ -554,4 +554,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ativado"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"É necessário reinicializar o dispositivo para que a mudança seja aplicada. Faça isso agora ou cancele."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"App <xliff:g id="APP_NAME">%s</xliff:g> de trabalho"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index ca85151..999e684 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -212,9 +212,9 @@
     <string name="adb_wireless_settings" msgid="2295017847215680229">"Depuração sem fios"</string>
     <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver e utilizar dispositivos disponíveis, ative a depuração sem fios."</string>
     <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Sincronize o dispositivo com o código QR"</string>
-    <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Sincronize novos dispositivos com o leitor de códigos QR."</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Sincroniza novos dispositivos com o leitor de códigos QR."</string>
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Sincronize dispositivo com código de sincronização"</string>
-    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Sincronize novos dispositivos através do código de seis dígitos."</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Sincroniza novos dispositivos através do código de seis dígitos."</string>
     <string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispositivos sincronizados"</string>
     <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Atualmente ligado."</string>
     <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Detalhes do dispositivo"</string>
@@ -554,4 +554,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ativada"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"É necessário reiniciar o dispositivo para aplicar esta alteração. Reinicie agora ou cancele."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> de trabalho"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 58a13cd..c6dc1d3 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -61,7 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Média"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Muito rápida"</string>
-    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Expirado"</string>
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Expirada"</string>
     <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">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando…"</string>
@@ -554,4 +554,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ativado"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"É necessário reinicializar o dispositivo para que a mudança seja aplicada. Faça isso agora ou cancele."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"App <xliff:g id="APP_NAME">%s</xliff:g> de trabalho"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index f967c8c..ba2f36f 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -554,6 +554,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Dezactivat"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activat"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Pentru ca modificarea să se aplice, trebuie să reporniți dispozitivul. Reporniți-l acum sau anulați."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> de serviciu"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index e41b3b7..8ec3875 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -210,7 +210,7 @@
     <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Режим отладки при подключении к сети Wi‑Fi"</string>
     <string name="adb_wireless_error" msgid="721958772149779856">"Ошибка"</string>
     <string name="adb_wireless_settings" msgid="2295017847215680229">"Отладка по Wi-Fi"</string>
-    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Чтобы посмотреть и использовать доступные устройства, включите отладку по Wi-Fi"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Чтобы увидеть и использовать доступные устройства, включите отладку по Wi-Fi."</string>
     <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Подключить устройство с помощью QR-кода"</string>
     <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Подключение новых устройств с помощью сканера QR-кодов"</string>
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Подключить устройство с помощью кода подключения"</string>
@@ -223,7 +223,7 @@
     <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Не удалось установить подключение"</string>
     <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Убедитесь, что устройство \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" подключено к нужной сети."</string>
     <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Подключение к устройству"</string>
-    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Код подключения к сети Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Код подключения по сети Wi‑Fi"</string>
     <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Не удалось подключить устройство"</string>
     <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Устройство должно быть подключено к той же самой сети."</string>
     <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Подключение устройства через Wi‑Fi с использованием QR-кода"</string>
@@ -555,6 +555,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Отключено"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Включено"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Чтобы изменение вступило в силу, необходимо перезапустить устройство. Вы можете сделать это сейчас или позже."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Рабочее приложение \"<xliff:g id="APP_NAME">%s</xliff:g>\""</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 5710985..01c3634 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"අබල කළා"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"සබලයි"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"මෙම වෙනස යෙදීමට ඔබේ උපාංගය නැවත පණ ගැන්විය යුතුය. දැන් නැවත පණ ගන්වන්න හෝ අවලංගු කරන්න."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"කාර්යාල <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index b3848a9..b5cbf43 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -61,7 +61,7 @@
     <string name="speed_label_medium" msgid="9078405312828606976">"Stredná"</string>
     <string name="speed_label_fast" msgid="2677719134596044051">"Rýchla"</string>
     <string name="speed_label_very_fast" msgid="8215718029533182439">"Veľmi rýchla"</string>
-    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Platnosť vypršala"</string>
+    <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Vypršalo"</string>
     <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">"Odpojený"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Prebieha odpájanie..."</string>
@@ -195,7 +195,7 @@
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"Výber profilu"</string>
     <string name="category_personal" msgid="6236798763159385225">"Osobné"</string>
-    <string name="category_work" msgid="4014193632325996115">"Práca"</string>
+    <string name="category_work" msgid="4014193632325996115">"Pracovné"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Pre vývojárov"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Povolenie možností vývojára"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Možnosti nastavenia vývoja aplikácií"</string>
@@ -508,7 +508,7 @@
     <string name="alarm_template_far" msgid="6382760514842998629">"o <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="zen_mode_duration_settings_title" msgid="1553451650289651489">"Trvanie"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Vždy sa opýtať"</string>
-    <string name="zen_mode_forever" msgid="3339224497605461291">"Dokiaľ túto funkciu nevypnete"</string>
+    <string name="zen_mode_forever" msgid="3339224497605461291">"Dokým funkciu nevypnete"</string>
     <string name="time_unit_just_now" msgid="3006134267292728099">"Teraz"</string>
     <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Reproduktor telefónu"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Pri pripájaní sa vyskytol problém. Zariadenie vypnite a znova zapnite."</string>
@@ -555,6 +555,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Vypnuté"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Zapnuté"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Táto zmena sa uplatní až po reštartovaní zariadenia. Zariadenie reštartujte alebo zmenu zrušte."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Pracovná aplikácia <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 658c192..86cccb8 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -214,7 +214,7 @@
     <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Seznanjanje naprave s kodo QR"</string>
     <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Seznanitev novih naprav z optičnim bralnikom kod QR"</string>
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Seznanjanje naprave s kodo za seznanjanje"</string>
-    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Seznanjanje novih naprav s šestmestno kodo"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Seznanitev novih naprav s šestmestno kodo"</string>
     <string name="adb_paired_devices_title" msgid="5268997341526217362">"Seznanjene naprave"</string>
     <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Trenutno povezano"</string>
     <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Podrobnosti o napravi"</string>
@@ -509,7 +509,7 @@
     <string name="zen_mode_duration_settings_title" msgid="1553451650289651489">"Trajanje"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Vedno vprašaj"</string>
     <string name="zen_mode_forever" msgid="3339224497605461291">"Dokler ne izklopite"</string>
-    <string name="time_unit_just_now" msgid="3006134267292728099">"pravkar"</string>
+    <string name="time_unit_just_now" msgid="3006134267292728099">"Pravkar"</string>
     <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Zvočnik telefona"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Težava pri povezovanju. Napravo izklopite in znova vklopite."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žična zvočna naprava"</string>
@@ -556,4 +556,6 @@
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogočeno"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Napravo je treba znova zagnati, da bo ta sprememba uveljavljena. Znova zaženite zdaj ali prekličite."</string>
     <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> za delo"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 17d2d50..bd3353c 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -207,7 +207,7 @@
     <string name="enable_adb_summary" msgid="3711526030096574316">"Korrigjo gabimet e modalitetit kur UBS-ja është e lidhur"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Anulo autorizimet e korrigjimeve të gabimeve të USB-së"</string>
     <string name="enable_adb_wireless" msgid="6973226350963971018">"Korrigjimi përmes Wi-Fi"</string>
-    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Regjimi i korrigjimit kur Wi‑Fi është i lidhur"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modaliteti i korrigjimit kur Wi‑Fi është i lidhur"</string>
     <string name="adb_wireless_error" msgid="721958772149779856">"Gabim"</string>
     <string name="adb_wireless_settings" msgid="2295017847215680229">"Korrigjimi përmes Wi-Fi"</string>
     <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Për të parë dhe përdorur pajisjet e disponueshme, aktivizo korrigjimin përmes Wi-Fi"</string>
@@ -446,7 +446,7 @@
     <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Pajisja mund të fiket së shpejti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> të mbetura deri në karikim"</string>
-    <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> deri sa të karikohen"</string>
+    <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të karikohet"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"I panjohur"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Po karikohet"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Po ngarkon me shpejtësi"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Joaktiv"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiv"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Pajisja jote duhet të riniset që ky ndryshim të zbatohet. Rinise tani ose anuloje."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> për punën"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index e0a7d0b..29f23b4 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -554,6 +554,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Онемогућено"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Омогућено"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Морате да рестартујете уређај да би се ова промена применила. Рестартујте га одмах или откажите."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> за посао"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index f6745b2..a40100e 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -183,19 +183,19 @@
     <string name="tts_reset_speech_pitch_title" msgid="7149398585468413246">"Återställ tonhöjden för tal"</string>
     <string name="tts_reset_speech_pitch_summary" msgid="6822904157021406449">"Återställ tonhöjden för talad text till standardinställningen."</string>
   <string-array name="tts_rate_entries">
-    <item msgid="9004239613505400644">"Mycket långsamt"</item>
-    <item msgid="1815382991399815061">"Långsamt"</item>
-    <item msgid="3075292553049300105">"Normalt"</item>
-    <item msgid="1158955023692670059">"Snabbt"</item>
+    <item msgid="9004239613505400644">"Mycket långsam"</item>
+    <item msgid="1815382991399815061">"Långsam"</item>
+    <item msgid="3075292553049300105">"Normal"</item>
+    <item msgid="1158955023692670059">"Snabb"</item>
     <item msgid="5664310435707146591">"Snabbare"</item>
-    <item msgid="5491266922147715962">"Mycket snabbt"</item>
-    <item msgid="7659240015901486196">"Supersnabbt"</item>
-    <item msgid="7147051179282410945">"Turbosnabbt"</item>
+    <item msgid="5491266922147715962">"Mycket snabb"</item>
+    <item msgid="7659240015901486196">"Supersnabb"</item>
+    <item msgid="7147051179282410945">"Turbosnabb"</item>
     <item msgid="581904787661470707">"Snabbast"</item>
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"Välj profil"</string>
-    <string name="category_personal" msgid="6236798763159385225">"Personligt"</string>
-    <string name="category_work" msgid="4014193632325996115">"Arbetet"</string>
+    <string name="category_personal" msgid="6236798763159385225">"Privat"</string>
+    <string name="category_work" msgid="4014193632325996115">"Jobb"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Utvecklaralternativ"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Aktivera utvecklaralternativ"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Ange alternativ för apputveckling"</string>
@@ -213,9 +213,9 @@
     <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Aktivera trådlös felsökning om du vill se tillgängliga enheter"</string>
     <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Parkoppla enheten med en QR-kod"</string>
     <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Parkoppla nya enheter med QR-kodsläsare"</string>
-    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Koppla enheten med en kopplingskod"</string>
-    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Koppla nya enheter med en sexsiffrig kod"</string>
-    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Kopplade enheter"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Parkoppla enheten med en parkopplingskod"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Parkoppla nya enheter med en sexsiffrig kod"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Parkopplade enheter"</string>
     <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Anslutna just nu"</string>
     <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Enhetsinformation"</string>
     <string name="adb_device_forget" msgid="193072400783068417">"Glöm"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Inaktiverat"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiverat"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Enheten måste startas om för att ändringen ska börja gälla. Starta om nu eller avbryt."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> för arbetet"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index a29b74e..af39356 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -40,7 +40,7 @@
     <item msgid="8339720953594087771">"Inaunganisha kwa <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
     <item msgid="3028983857109369308">"Uhalalishaji kwa <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
     <item msgid="4287401332778341890">"Inamiliki anwani ya IP kutoka <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
-    <item msgid="1043944043827424501">" Umeunganishwa kwa<xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item>
+    <item msgid="1043944043827424501">"Umeunganishwa kwa <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item>
     <item msgid="7445993821842009653">"Imesimamishwa"</item>
     <item msgid="1175040558087735707">"inakatisha muunganisho kutoka <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
     <item msgid="699832486578171722">"Muunganisho Umekatika"</item>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 7df39d5..fedf1c8 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -195,7 +195,7 @@
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"Chagua wasifu"</string>
     <string name="category_personal" msgid="6236798763159385225">"Ya Kibinafsi"</string>
-    <string name="category_work" msgid="4014193632325996115">"Kazini"</string>
+    <string name="category_work" msgid="4014193632325996115">"Ya Kazini"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Chaguo za wasanidi"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"Washa chaguo za wasanidi programu"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Weka chaguo kwa ajili ya maendeleo ya programu"</string>
@@ -485,7 +485,7 @@
     <string name="ims_reg_title" msgid="8197592958123671062">"Hali ya usajili wa IMS"</string>
     <string name="ims_reg_status_registered" msgid="884916398194885457">"Imesajiliwa"</string>
     <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"Haijasajiliwa"</string>
-    <string name="status_unavailable" msgid="5279036186589861608">"Haipatikani"</string>
+    <string name="status_unavailable" msgid="5279036186589861608">"Hamna"</string>
     <string name="wifi_status_mac_randomized" msgid="466382542497832189">"Imechagua anwani ya MAC kwa nasibu"</string>
     <plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139">
       <item quantity="other">Imeunganisha vifaa %1$d</item>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Imezimwa"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Imewashwa"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Ni lazima uwashe tena kifaa chako ili mabadiliko haya yatekelezwe. Washa tena sasa au ughairi."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Ya kazini <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index fa922ea..345f0a7 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"முடக்கப்பட்டது"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"இயக்கப்பட்டது"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"இந்த மாற்றங்கள் செயல்படுத்தப்பட உங்கள் சாதனத்தை மறுபடி தொடங்க வேண்டும். இப்போதே மறுபடி தொடங்கவும் அல்லது ரத்துசெய்யவும்."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"பணியிடம் <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 0e36c5f..c4fda01 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -153,9 +153,9 @@
     <string name="unknown" msgid="3544487229740637809">"తెలియదు"</string>
     <string name="running_process_item_user_label" msgid="3988506293099805796">"వినియోగదారు: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
     <string name="launch_defaults_some" msgid="3631650616557252926">"కొన్ని డిఫాల్ట్‌లు సెట్ చేయబడ్డాయి"</string>
-    <string name="launch_defaults_none" msgid="8049374306261262709">"ఆటోమేటిక్ ఆప్ష‌న్‌లు వేటినీ సెట్ చేయ‌‌లేదు"</string>
+    <string name="launch_defaults_none" msgid="8049374306261262709">"ఆటోమేటిక్ ఆప్ష‌న్‌లు ఏవీ సెట్ చేయ‌‌లేదు"</string>
     <string name="tts_settings" msgid="8130616705989351312">"వచనం నుండి ప్రసంగం సెట్టింగ్‌లు"</string>
-    <string name="tts_settings_title" msgid="7602210956640483039">"వచనం నుండి మాట అవుట్‌పుట్"</string>
+    <string name="tts_settings_title" msgid="7602210956640483039">"టెక్స్ట్-టు-స్పీచ్ అవుట్‌పుట్"</string>
     <string name="tts_default_rate_title" msgid="3964187817364304022">"ప్రసంగం రేట్"</string>
     <string name="tts_default_rate_summary" msgid="3781937042151716987">"వచనాన్ని చదివి వినిపించాల్సిన వేగం"</string>
     <string name="tts_default_pitch_title" msgid="6988592215554485479">"పిచ్"</string>
@@ -195,7 +195,7 @@
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"ప్రొఫైల్‌ను ఎంచుకోండి"</string>
     <string name="category_personal" msgid="6236798763159385225">"వ్యక్తిగతం"</string>
-    <string name="category_work" msgid="4014193632325996115">"కార్యాలయం"</string>
+    <string name="category_work" msgid="4014193632325996115">"ఆఫీస్"</string>
     <string name="development_settings_title" msgid="140296922921597393">"డెవలపర్ ఎంపికలు"</string>
     <string name="development_settings_enable" msgid="4285094651288242183">"డెవలపర్ ఎంపికలను ప్రారంభించండి"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"అనువర్తన అభివృద్ధి కోసం ఎంపికలను సెట్ చేయండి"</string>
@@ -229,7 +229,7 @@
     <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR కోడ్‌ను స్కాన్ చేయడం ద్వారా Wi-Fiని ఉపయోగించి పరికరాన్ని పెయిర్ చెయ్యండి"</string>
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"పరికరం పెయిర్ చేయబడుతోంది…"</string>
     <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"పరికరాన్ని పెయిర్ చేయడం విఫలమైంది. QR కోడ్ తప్పుగా ఉండడం గాని, లేదా పరికరం అదే నెట్‌వర్క్‌కు కనెక్ట్ అయి లేకపోవడం గాని జరిగింది."</string>
-    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP చిరునామా &amp; పోర్ట్"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP అడ్రస్ &amp; పోర్ట్"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR కోడ్‌ను స్కాన్ చేయండి"</string>
     <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"QR కోడ్‌ను స్కాన్ చేయడం ద్వారా Wi-Fiని ఉపయోగించి పరికరాన్ని పెయిర్ చెయ్యండి"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"దయచేసి Wi-Fi నెట్‌వర్క్‌కు కనెక్ట్ చేయండి"</string>
@@ -418,8 +418,8 @@
     <string name="daltonizer_mode_deuteranomaly" msgid="3507284319584683963">"డ్యూటెరానోమలీ (ఎరుపు-ఆకుపచ్చ)"</string>
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ప్రొటానోమలీ (ఎరుపు-ఆకుపచ్చ రంగు)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ట్రైటనోమలీ (నీలం-పసుపు రంగు)"</string>
-    <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"రంగు సవరణ"</string>
-    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"రంగులు సరి చేసే ఫీచర్ సాయంతో, మీ పరికరంలో రంగులు కనిపించే పద్ధతిని మీరు సర్దుబాటు చేయగలుగుతారు"</string>
+    <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"కలర్ సరిచేయడం"</string>
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"\'కలర్ సరిచేయడం\' అనే ఫీచర్ సాయంతో, మీ పరికరంలో రంగులు కనిపించే పద్ధతిని మీరు మార్చగలుగుతారు"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string>
@@ -533,7 +533,7 @@
     <string name="user_add_user_title" msgid="5457079143694924885">"కొత్త వినియోగదారుని జోడించాలా?"</string>
     <string name="user_add_user_message_long" msgid="1527434966294733380">"అదనపు యూజర్‌లను సృష్టించడం ద్వారా మీరు ఈ దేవైజ్‌ను ఇతరులతో షేర్ చేయవచ్చు. ప్రతి యూజర్‌కు‌ వారికంటూ ప్రత్యేక స్థలం ఉంటుంది, వారు ఆ స్థలాన్ని యాప్‌లు, వాల్‌పేపర్ మొదలైనవాటితో అనుకూలీకరించవచ్చు. యూజర్‌లు ప్రతి ఒక్కరిపై ప్రభావం చూపే Wi‑Fi వంటి పరికర సెట్టింగ్‌లను కూడా సర్దుబాటు చేయవచ్చు.\n\nమీరు కొత్త యూజర్ ను జోడించినప్పుడు, ఆ వ్యక్తి వారికంటూ స్వంత స్థలం సెట్ చేసుకోవాలి.\n\nఏ వినియోగదారు అయినా మిగిలిన అందరు యూజర్‌ల కోసం యాప్‌లను అప్‌డేట్ చేయవచ్చు. యాక్సెస్ సామర్ధ్యం సెట్టింగ్‌లు మరియు సేవలు కొత్త యూజర్‌కి బదిలీ కాకపోవచ్చు."</string>
     <string name="user_add_user_message_short" msgid="3295959985795716166">"మీరు కొత్త వినియోగదారుని జోడించినప్పుడు, ఆ వ్యక్తి తన స్థలాన్ని సెటప్ చేసుకోవాలి.\n\nఏ వినియోగదారు అయినా మిగతా అందరు వినియోగదారుల కోసం యాప్‌లను అప్‌డేట్‌ చేయగలరు."</string>
-    <string name="user_setup_dialog_title" msgid="8037342066381939995">"ఇప్పుడు వినియోగదారుని సెటప్ చేయాలా?"</string>
+    <string name="user_setup_dialog_title" msgid="8037342066381939995">"యూజర్‌ను ఇప్పుడే సెటప్ చేయాలా?"</string>
     <string name="user_setup_dialog_message" msgid="269931619868102841">"పరికరాన్ని తీసుకోవడానికి వ్యక్తి అందుబాటులో ఉన్నారని నిర్ధారించుకొని, ఆపై వారికి నిల్వ స్థలాన్ని సెటప్ చేయండి"</string>
     <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"ఇప్పుడు ప్రొఫైల్‌ను సెటప్ చేయాలా?"</string>
     <string name="user_setup_button_setup_now" msgid="1708269547187760639">"ఇప్పుడే సెట‌ప్ చేయి"</string>
@@ -549,14 +549,11 @@
     <string name="guest_new_guest" msgid="3482026122932643557">"అతిథిని జోడించండి"</string>
     <string name="guest_exit_guest" msgid="5908239569510734136">"అతిథిని తీసివేయండి"</string>
     <string name="guest_nickname" msgid="6332276931583337261">"అతిథి"</string>
-    <!-- no translation found for cached_apps_freezer_device_default (2616594131750144342) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_disabled (4816382260660472042) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_enabled (8866703500183051546) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_reboot_dialog_text (695330563489230096) -->
-    <skip />
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"పరికర ఆటోమేటిక్ సెట్టింగ్"</string>
+    <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"డిజేబుల్ చేయబడింది"</string>
+    <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ఎనేబుల్ చేయబడింది"</string>
+    <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ఈ మార్పును వర్తింపజేయాలంటే మీరు మీ పరికరాన్ని తప్పనిసరిగా రీబూట్ చేయాలి. ఇప్పుడే రీబూట్ చేయండి లేదా రద్దు చేయండి."</string>
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"ఆఫీసు <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 0e958e9..a9032eb 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ปิดใช้"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"เปิดใช้"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"คุณต้องรีบูตอุปกรณ์เพื่อให้การเปลี่ยนแปลงนี้มีผล รีบูตเลยหรือยกเลิก"</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> ในโปรไฟล์งาน"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 5ce89eb..712c06b 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -433,7 +433,7 @@
     <string name="power_discharge_by" msgid="4113180890060388350">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"Tatagal hanggang mga <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharge_by_only_short" msgid="5883041507426914446">"Hanggang <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Posibleng maubos ang baterya sa loob ng <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Baka maubos ang baterya sa loob ng <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"Wala nang <xliff:g id="THRESHOLD">%1$s</xliff:g> ang natitira"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"Wala nang <xliff:g id="THRESHOLD">%1$s</xliff:g> ang natitira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="446388082266121894">"Mahigit <xliff:g id="TIME_REMAINING">%1$s</xliff:g> pa ang natitira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Naka-disable"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Na-enable"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Dapat i-reboot ang iyong device para mailapat ang pagbabagong ito. Mag-reboot ngayon o kanselahin."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> sa Trabaho"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 1e887d1..8818498 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Devre dışı"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Etkin"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Bu değişikliğin geçerli olması için cihazının yeniden başlatılması gerekir. Şimdi yeniden başlatın veya iptal edin."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> (İş)"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index a95105b..f6568e3 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -226,12 +226,12 @@
     <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Код підключення Wi‑Fi"</string>
     <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Помилка підключення"</string>
     <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Переконайтеся, що пристрій підключено до тієї ж мережі."</string>
-    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Підключати пристрій через Wi‑Fi за допомогою QR-коду"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Підключіть пристрій через Wi‑Fi за допомогою QR-коду"</string>
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Підключення пристрою…"</string>
     <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Не вдалося підключитися до пристрою. Надано неправильний QR-код або пристрій не підключено до тієї ж мережі."</string>
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-адреса та порт"</string>
-    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Сканувати QR-код"</string>
-    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Підключати пристрій через Wi‑Fi за допомогою QR-коду"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Відскануйте QR-код"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Підключіть пристрій через Wi‑Fi за допомогою QR-коду"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Підключіть пристрій до мережі Wi-Fi"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, налагодження, розробка"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Ярлик звіту про помилки"</string>
@@ -555,6 +555,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Вимкнено"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Увімкнено"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Щоб застосувати ці зміни, перезапустіть пристрій. Перезапустіть пристрій або скасуйте зміни."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Робочий додаток <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index e056c1c..3776503 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -26,7 +26,7 @@
     <item msgid="6050951078202663628">"مربوط ہو رہا ہے…"</item>
     <item msgid="8356618438494652335">"توثیق ہو رہی ہے…"</item>
     <item msgid="2837871868181677206">"‏IP پتہ حاصل کر رہا ہے…"</item>
-    <item msgid="4613015005934755724">"مربوط ہو گیا"</item>
+    <item msgid="4613015005934755724">"منسلک"</item>
     <item msgid="3763530049995655072">"معطل شدہ"</item>
     <item msgid="7852381437933824454">"منقطع کیا جارہا ہے…"</item>
     <item msgid="5046795712175415059">"منقطع ہو گیا"</item>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 463c161..f13f8fb 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -433,7 +433,7 @@
     <string name="power_discharge_by" msgid="4113180890060388350">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی"</string>
     <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> تک"</string>
-    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"<xliff:g id="TIME">%1$s</xliff:g> تک بیٹری ختم ہو سکتی ہے"</string>
+    <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"‫<xliff:g id="TIME">%1$s</xliff:g> تک بیٹری ختم ہو سکتی ہے"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"<xliff:g id="THRESHOLD">%1$s</xliff:g> سے کم باقی ہے"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"<xliff:g id="THRESHOLD">%1$s</xliff:g> سے کم باقی ہے (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="446388082266121894">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> سے زیادہ باقی ہے (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -549,14 +549,11 @@
     <string name="guest_new_guest" msgid="3482026122932643557">"مہمان کو شامل کریں"</string>
     <string name="guest_exit_guest" msgid="5908239569510734136">"مہمان کو ہٹائیں"</string>
     <string name="guest_nickname" msgid="6332276931583337261">"مہمان"</string>
-    <!-- no translation found for cached_apps_freezer_device_default (2616594131750144342) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_disabled (4816382260660472042) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_enabled (8866703500183051546) -->
-    <skip />
-    <!-- no translation found for cached_apps_freezer_reboot_dialog_text (695330563489230096) -->
-    <skip />
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"آلہ ڈیفالٹ"</string>
+    <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"غیر فعال"</string>
+    <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"فعال"</string>
+    <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"اس تبدیلی کو لاگو کرنے کے ليے آپ کے آلہ کو ریبوٹ کرنا ضروری ہے۔ ابھی ریبوٹ کریں یا منسوخ کریں۔"</string>
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"دفتر <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 762a246..7b8f627 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Yoqilmagan"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Yoniq"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Oʻzgarishlar qurilma oʻchib yonganda bajariladi. Hoziroq oʻchib yoqish yoki bekor qilish."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Ish <xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 12241f1..35cecc1 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Đã tắt"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Đã bật"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Bạn phải khởi động lại thiết bị để áp dụng sự thay đổi này. Hãy khởi động lại ngay hoặc hủy."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"<xliff:g id="APP_NAME">%s</xliff:g> dành cho công việc"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 0a3ca12..c69ea2d 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -419,7 +419,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"红色弱视(红绿不分)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"蓝色弱视(蓝黄不分)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色彩校正"</string>
-    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"借助颜色校正功能,您可以调整设备上的颜色显示方式"</string>
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1284746051652993443">"借助色彩校正功能,您可以调整设备上的颜色显示方式"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"已被“<xliff:g id="TITLE">%1$s</xliff:g>”覆盖"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"大约还可使用 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"已停用"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"已启用"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"设备必须重新启动才能应用此更改。您可以立即重新启动或取消。"</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"工作资料中的<xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 495cc22..b0324d9 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -222,7 +222,7 @@
     <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"裝置指紋:<xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
     <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"連線失敗"</string>
     <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"請確認<xliff:g id="DEVICE_NAME">%1$s</xliff:g> 已連線至相同的網絡。"</string>
-    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"與裝置配對"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"配對裝置"</string>
     <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi-Fi 配對碼"</string>
     <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"配對失敗"</string>
     <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"請確認裝置已連線至相同的網絡。"</string>
@@ -452,7 +452,7 @@
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充電"</string>
     <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"正在慢速充電"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"非充電中"</string>
-    <string name="battery_info_status_not_charging" msgid="8330015078868707899">"已插入電源插座,但目前無法充電"</string>
+    <string name="battery_info_status_not_charging" msgid="8330015078868707899">"已連接電源插頭,但目前無法充電"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"電量已滿"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"已由管理員停用"</string>
     <string name="disabled" msgid="8017887509554714950">"已停用"</string>
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"已停用"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"已啟用"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"您的裝置必須重新開機,才能套用此變更。請立即重新開機或取消。"</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"工作設定檔入面嘅「<xliff:g id="APP_NAME">%s</xliff:g>」"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 9445268..0574c7e 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"已停用"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"已啟用"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"裝置必須重新啟動才能套用這項變更。請立即重新啟動或取消變更。"</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"工作資料夾中的<xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 86698f4..b60553a 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -553,6 +553,7 @@
     <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Ikhutshaziwe"</string>
     <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Inikwe amandla"</string>
     <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Kufanele idivayisi yakho iqaliswe ukuze lolu shintsho lusebenze. Qalisa manje noma khansela."</string>
-    <!-- no translation found for accessibility_work_profile_app_description (5470883112342119165) -->
+    <string name="accessibility_work_profile_app_description" msgid="5470883112342119165">"Umsebenzi we-<xliff:g id="APP_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
     <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index e42e438..3dbf5a4 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1376,4 +1376,7 @@
 
     <!-- A content description for work profile app [CHAR LIMIT=35] -->
     <string name="accessibility_work_profile_app_description">Work <xliff:g id="app_name" example="Camera">%s</xliff:g></string>
+
+    <!-- Name of the 3.5mm and usb audio device. [CHAR LIMIT=40] -->
+    <string name="media_transfer_wired_usb_device_name">Wired headphone</string>
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java b/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java
index 57d9594..4f86afaa9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java
@@ -67,7 +67,7 @@
 
     /**
      * Version of {@link #convertGammaToLinear} that takes and returns float values.
-     * TODO: brightnessfloat Merge with above method later.
+     * TODO(flc): refactor Android Auto to use float version
      *
      * @param val The slider value.
      * @param min The minimum acceptable value for the setting.
@@ -83,9 +83,13 @@
             ret = MathUtils.exp((normalizedVal - C) / A) + B;
         }
 
-        // HLG is normalized to the range [0, 12], so we need to re-normalize to the range [0, 1]
+        // HLG is normalized to the range [0, 12], ensure that value is within that range,
+        // it shouldn't be out of bounds.
+        final float normalizedRet = MathUtils.constrain(ret, 0, 12);
+
+        // Re-normalize to the range [0, 1]
         // in order to derive the correct setting value.
-        return MathUtils.lerp(min, max, ret / 12);
+        return MathUtils.lerp(min, max, normalizedRet / 12);
     }
 
     /**
@@ -111,16 +115,7 @@
      * @return The corresponding slider value
      */
     public static final int convertLinearToGamma(int val, int min, int max) {
-        // For some reason, HLG normalizes to the range [0, 12] rather than [0, 1]
-        final float normalizedVal = MathUtils.norm(min, max, val) * 12;
-        final float ret;
-        if (normalizedVal <= 1f) {
-            ret = MathUtils.sqrt(normalizedVal) * R;
-        } else {
-            ret = A * MathUtils.log(normalizedVal - B) + C;
-        }
-
-        return Math.round(MathUtils.lerp(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, ret));
+        return convertLinearToGammaFloat((float) val, (float) min, (float) max);
     }
 
     /**
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index 1d06df0..008a433 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -475,5 +475,10 @@
         public void onRequestFailed(int reason) {
             dispatchOnRequestFailed(reason);
         }
+
+        @Override
+        public void onSessionUpdated(RoutingSessionInfo sessionInfo) {
+            dispatchDataChanged();
+        }
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index 887a49b..7d95f19 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -15,6 +15,8 @@
  */
 package com.android.settingslib.media;
 
+import static android.media.MediaRoute2ProviderService.REASON_UNKNOWN_ERROR;
+
 import android.app.Notification;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
@@ -25,6 +27,7 @@
 import android.util.Log;
 
 import androidx.annotation.IntDef;
+import androidx.annotation.Nullable;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.bluetooth.A2dpProfile;
@@ -65,6 +68,7 @@
     }
 
     private final Collection<DeviceCallback> mCallbacks = new CopyOnWriteArrayList<>();
+    private final Object mMediaDevicesLock = new Object();
     @VisibleForTesting
     final MediaDeviceCallback mMediaDeviceCallback = new MediaDeviceCallback();
 
@@ -143,9 +147,17 @@
     /**
      * Connect the MediaDevice to transfer media
      * @param connectDevice the MediaDevice
+     * @return {@code true} if successfully call, otherwise return {@code false}
      */
-    public void connectDevice(MediaDevice connectDevice) {
-        final MediaDevice device = getMediaDeviceById(mMediaDevices, connectDevice.getId());
+    public boolean connectDevice(MediaDevice connectDevice) {
+        MediaDevice device = null;
+        synchronized (mMediaDevicesLock) {
+            device = getMediaDeviceById(mMediaDevices, connectDevice.getId());
+        }
+        if (device == null) {
+            Log.w(TAG, "connectDevice() connectDevice not in the list!");
+            return false;
+        }
         if (device instanceof BluetoothMediaDevice) {
             final CachedBluetoothDevice cachedDevice =
                     ((BluetoothMediaDevice) device).getCachedDevice();
@@ -153,13 +165,13 @@
                 mOnTransferBluetoothDevice = connectDevice;
                 device.setState(MediaDeviceState.STATE_CONNECTING);
                 cachedDevice.connect();
-                return;
+                return true;
             }
         }
 
         if (device == mCurrentConnectedDevice) {
             Log.d(TAG, "connectDevice() this device all ready connected! : " + device.getName());
-            return;
+            return false;
         }
 
         if (mCurrentConnectedDevice != null) {
@@ -172,6 +184,7 @@
         } else {
             device.connect();
         }
+        return true;
     }
 
     void dispatchSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state) {
@@ -184,15 +197,18 @@
      * Start scan connected MediaDevice
      */
     public void startScan() {
-        mMediaDevices.clear();
+        synchronized (mMediaDevicesLock) {
+            mMediaDevices.clear();
+        }
         mInfoMediaManager.registerCallback(mMediaDeviceCallback);
         mInfoMediaManager.startScan();
     }
 
     void dispatchDeviceListUpdate() {
-        Collections.sort(mMediaDevices, COMPARATOR);
+        final List<MediaDevice> mediaDevices = new ArrayList<>(mMediaDevices);
+        Collections.sort(mediaDevices, COMPARATOR);
         for (DeviceCallback callback : getCallbacks()) {
-            callback.onDeviceListUpdate(new ArrayList<>(mMediaDevices));
+            callback.onDeviceListUpdate(mediaDevices);
         }
     }
 
@@ -241,9 +257,11 @@
      * @return MediaDevice
      */
     public MediaDevice getMediaDeviceById(String id) {
-        for (MediaDevice mediaDevice : mMediaDevices) {
-            if (TextUtils.equals(mediaDevice.getId(), id)) {
-                return mediaDevice;
+        synchronized (mMediaDevicesLock) {
+            for (MediaDevice mediaDevice : mMediaDevices) {
+                if (TextUtils.equals(mediaDevice.getId(), id)) {
+                    return mediaDevice;
+                }
             }
         }
         Log.i(TAG, "Unable to find device " + id);
@@ -255,6 +273,7 @@
      *
      * @return MediaDevice
      */
+    @Nullable
     public MediaDevice getCurrentConnectedDevice() {
         return mCurrentConnectedDevice;
     }
@@ -366,18 +385,29 @@
         return mInfoMediaManager.getActiveMediaSession();
     }
 
+    /**
+     * Gets the current package name.
+     *
+     * @return current package name
+     */
+    public String getPackageName() {
+        return mPackageName;
+    }
+
     private MediaDevice updateCurrentConnectedDevice() {
-        MediaDevice phoneMediaDevice = null;
-        for (MediaDevice device : mMediaDevices) {
-            if (device instanceof  BluetoothMediaDevice) {
-                if (isActiveDevice(((BluetoothMediaDevice) device).getCachedDevice())) {
+        synchronized (mMediaDevicesLock) {
+            for (MediaDevice device : mMediaDevices) {
+                if (device instanceof BluetoothMediaDevice) {
+                    if (isActiveDevice(((BluetoothMediaDevice) device).getCachedDevice())) {
+                        return device;
+                    }
+                } else if (device instanceof PhoneMediaDevice) {
                     return device;
                 }
-            } else if (device instanceof PhoneMediaDevice) {
-                phoneMediaDevice = device;
             }
         }
-        return mMediaDevices.contains(phoneMediaDevice) ? phoneMediaDevice : null;
+        Log.w(TAG, "updateCurrentConnectedDevice() can't found current connected device");
+        return null;
     }
 
     private boolean isActiveDevice(CachedBluetoothDevice device) {
@@ -392,17 +422,26 @@
     class MediaDeviceCallback implements MediaManager.MediaDeviceCallback {
         @Override
         public void onDeviceAdded(MediaDevice device) {
-            if (!mMediaDevices.contains(device)) {
-                mMediaDevices.add(device);
+            boolean isAdded = false;
+            synchronized (mMediaDevicesLock) {
+                if (!mMediaDevices.contains(device)) {
+                    mMediaDevices.add(device);
+                    isAdded = true;
+                }
+            }
+
+            if (isAdded) {
                 dispatchDeviceListUpdate();
             }
         }
 
         @Override
         public void onDeviceListAdded(List<MediaDevice> devices) {
-            mMediaDevices.clear();
-            mMediaDevices.addAll(devices);
-            mMediaDevices.addAll(buildDisconnectedBluetoothDevice());
+            synchronized (mMediaDevicesLock) {
+                mMediaDevices.clear();
+                mMediaDevices.addAll(devices);
+                mMediaDevices.addAll(buildDisconnectedBluetoothDevice());
+            }
 
             final MediaDevice infoMediaDevice = mInfoMediaManager.getCurrentConnectedDevice();
             mCurrentConnectedDevice = infoMediaDevice != null
@@ -411,6 +450,8 @@
             if (mOnTransferBluetoothDevice != null && mOnTransferBluetoothDevice.isConnected()) {
                 connectDevice(mOnTransferBluetoothDevice);
                 mOnTransferBluetoothDevice.setState(MediaDeviceState.STATE_CONNECTED);
+                dispatchSelectedDeviceStateChanged(mOnTransferBluetoothDevice,
+                        MediaDeviceState.STATE_CONNECTED);
                 mOnTransferBluetoothDevice = null;
             }
         }
@@ -469,30 +510,42 @@
 
         @Override
         public void onDeviceRemoved(MediaDevice device) {
-            if (mMediaDevices.contains(device)) {
-                mMediaDevices.remove(device);
+            boolean isRemoved = false;
+            synchronized (mMediaDevicesLock) {
+                if (mMediaDevices.contains(device)) {
+                    mMediaDevices.remove(device);
+                    isRemoved = true;
+                }
+            }
+            if (isRemoved) {
                 dispatchDeviceListUpdate();
             }
         }
 
         @Override
         public void onDeviceListRemoved(List<MediaDevice> devices) {
-            mMediaDevices.removeAll(devices);
+            synchronized (mMediaDevicesLock) {
+                mMediaDevices.removeAll(devices);
+            }
             dispatchDeviceListUpdate();
         }
 
         @Override
         public void onConnectedDeviceChanged(String id) {
-            MediaDevice connectDevice = getMediaDeviceById(mMediaDevices, id);
+            MediaDevice connectDevice = null;
+            synchronized (mMediaDevicesLock) {
+                connectDevice = getMediaDeviceById(mMediaDevices, id);
+            }
             connectDevice = connectDevice != null
                     ? connectDevice : updateCurrentConnectedDevice();
-            if (connectDevice != null) {
-                connectDevice.setState(MediaDeviceState.STATE_CONNECTED);
-            }
 
             mCurrentConnectedDevice = connectDevice;
-            dispatchSelectedDeviceStateChanged(mCurrentConnectedDevice,
-                    MediaDeviceState.STATE_CONNECTED);
+            if (connectDevice != null) {
+                connectDevice.setState(MediaDeviceState.STATE_CONNECTED);
+
+                dispatchSelectedDeviceStateChanged(mCurrentConnectedDevice,
+                        MediaDeviceState.STATE_CONNECTED);
+            }
         }
 
         @Override
@@ -502,9 +555,11 @@
 
         @Override
         public void onRequestFailed(int reason) {
-            for (MediaDevice device : mMediaDevices) {
-                if (device.getState() == MediaDeviceState.STATE_CONNECTING) {
-                    device.setState(MediaDeviceState.STATE_CONNECTING_FAILED);
+            synchronized (mMediaDevicesLock) {
+                for (MediaDevice device : mMediaDevices) {
+                    if (device.getState() == MediaDeviceState.STATE_CONNECTING) {
+                        device.setState(MediaDeviceState.STATE_CONNECTING_FAILED);
+                    }
                 }
             }
             dispatchOnRequestFailed(reason);
@@ -575,6 +630,7 @@
                 // Failed to connect
                 mOnTransferBluetoothDevice.setState(MediaDeviceState.STATE_DISCONNECTED);
                 mOnTransferBluetoothDevice = null;
+                dispatchOnRequestFailed(REASON_UNKNOWN_ERROR);
             }
             dispatchDeviceAttributesChanged();
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
index 139a12c..8a178a9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
@@ -49,7 +49,8 @@
     private static final String TAG = "MediaDevice";
 
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({MediaDeviceType.TYPE_USB_C_AUDIO_DEVICE,
+    @IntDef({MediaDeviceType.TYPE_UNKNOWN,
+            MediaDeviceType.TYPE_USB_C_AUDIO_DEVICE,
             MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE,
             MediaDeviceType.TYPE_FAST_PAIR_BLUETOOTH_DEVICE,
             MediaDeviceType.TYPE_BLUETOOTH_DEVICE,
@@ -57,6 +58,7 @@
             MediaDeviceType.TYPE_CAST_GROUP_DEVICE,
             MediaDeviceType.TYPE_PHONE_DEVICE})
     public @interface MediaDeviceType {
+        int TYPE_UNKNOWN = 0;
         int TYPE_USB_C_AUDIO_DEVICE = 1;
         int TYPE_3POINT5_MM_AUDIO_DEVICE = 2;
         int TYPE_FAST_PAIR_BLUETOOTH_DEVICE = 3;
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
index 8ea5ff1..9a3ae1b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
@@ -61,11 +61,11 @@
         switch (mRouteInfo.getType()) {
             case TYPE_WIRED_HEADSET:
             case TYPE_WIRED_HEADPHONES:
-                name = mContext.getString(R.string.media_transfer_wired_device_name);
-                break;
             case TYPE_USB_DEVICE:
             case TYPE_USB_HEADSET:
             case TYPE_USB_ACCESSORY:
+                name = mContext.getString(R.string.media_transfer_wired_usb_device_name);
+                break;
             case TYPE_DOCK:
             case TYPE_HDMI:
                 name = mRouteInfo.getName();
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index cefe690..8968340 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -83,7 +83,16 @@
  * <p>An AccessPoint, which would be more fittingly named "WifiNetwork", is an aggregation of
  * {@link ScanResult ScanResults} along with pertinent metadata (e.g. current connection info,
  * network scores) required to successfully render the network to the user.
+ *
+ * @deprecated WifiTracker/AccessPoint is no longer supported, and will be removed in a future
+ * release. Clients that need a dynamic list of available wifi networks should migrate to one of the
+ * newer tracker classes,
+ * {@link com.android.wifitrackerlib.WifiPickerTracker},
+ * {@link com.android.wifitrackerlib.SavedNetworkTracker},
+ * {@link com.android.wifitrackerlib.NetworkDetailsTracker},
+ * in conjunction with {@link com.android.wifitrackerlib.WifiEntry} to represent each wifi network.
  */
+@Deprecated
 public class AccessPoint implements Comparable<AccessPoint> {
     static final String TAG = "SettingsLib.AccessPoint";
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 586c154..d1cd043 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -77,7 +77,16 @@
 
 /**
  * Tracks saved or available wifi networks and their state.
+ *
+ * @deprecated WifiTracker/AccessPoint is no longer supported, and will be removed in a future
+ * release. Clients that need a dynamic list of available wifi networks should migrate to one of the
+ * newer tracker classes,
+ * {@link com.android.wifitrackerlib.WifiPickerTracker},
+ * {@link com.android.wifitrackerlib.SavedNetworkTracker},
+ * {@link com.android.wifitrackerlib.NetworkDetailsTracker},
+ * in conjunction with {@link com.android.wifitrackerlib.WifiEntry} to represent each wifi network.
  */
+@Deprecated
 public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestroy {
     /**
      * Default maximum age in millis of cached scored networks in
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/display/BrightnessUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/display/BrightnessUtilsTest.java
index c0924d9..1b20f2c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/display/BrightnessUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/display/BrightnessUtilsTest.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.display;
 
 import static com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MAX;
+import static com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MIN;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -27,26 +28,40 @@
 @RunWith(RobolectricTestRunner.class)
 public class BrightnessUtilsTest {
 
-    private static final int MIN = 1;
-    private static final int MAX = 255;
+    private static final int MIN_INT = 1;
+    private static final int MAX_INT = 255;
+    private static final float MIN_FLOAT = 0.0f;
+    private static final float MAX_FLOAT = 1.0f;
 
     @Test
-    public void linearToGamma_minValue_shouldReturn0() {
-        assertThat(BrightnessUtils.convertLinearToGamma(MIN, MIN, MAX)).isEqualTo(0);
+    public void linearToGamma_minValue_shouldReturnMin() {
+        assertThat(BrightnessUtils.convertLinearToGamma(MIN_INT, MIN_INT, MAX_INT))
+                .isEqualTo(GAMMA_SPACE_MIN);
+        assertThat(BrightnessUtils.convertLinearToGammaFloat(MIN_FLOAT, MIN_FLOAT, MAX_FLOAT))
+                .isEqualTo(GAMMA_SPACE_MIN);
     }
 
     @Test
     public void linearToGamma_maxValue_shouldReturnGammaSpaceMax() {
-        assertThat(BrightnessUtils.convertLinearToGamma(MAX, MIN, MAX)).isEqualTo(GAMMA_SPACE_MAX);
+        assertThat(BrightnessUtils.convertLinearToGamma(MAX_INT, MIN_INT, MAX_INT))
+                .isEqualTo(GAMMA_SPACE_MAX);
+        assertThat(BrightnessUtils.convertLinearToGammaFloat(MAX_FLOAT, MIN_FLOAT, MAX_FLOAT))
+                .isEqualTo(GAMMA_SPACE_MAX);
     }
 
     @Test
     public void gammaToLinear_minValue_shouldReturnMin() {
-        assertThat(BrightnessUtils.convertGammaToLinear(MIN, MIN, MAX)).isEqualTo(MIN);
+        assertThat(BrightnessUtils.convertGammaToLinear(GAMMA_SPACE_MIN, MIN_INT, MAX_INT))
+                .isEqualTo(MIN_INT);
+        assertThat(BrightnessUtils.convertGammaToLinearFloat(GAMMA_SPACE_MIN, MIN_FLOAT, MAX_FLOAT))
+                .isEqualTo(MIN_FLOAT);
     }
 
     @Test
     public void gammaToLinear_gammaSpaceValue_shouldReturnMax() {
-        assertThat(BrightnessUtils.convertGammaToLinear(GAMMA_SPACE_MAX, MIN, MAX)).isEqualTo(MAX);
+        assertThat(BrightnessUtils.convertGammaToLinear(GAMMA_SPACE_MAX, MIN_INT, MAX_INT))
+                .isEqualTo(MAX_INT);
+        assertThat(BrightnessUtils.convertGammaToLinearFloat(GAMMA_SPACE_MAX, MIN_FLOAT, MAX_FLOAT))
+                .isEqualTo(MAX_FLOAT);
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
index 99c568a..734866f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
@@ -625,6 +625,15 @@
     }
 
     @Test
+    public void onSessionUpdated_shouldDispatchDataChanged() {
+        mInfoMediaManager.registerCallback(mCallback);
+
+        mInfoMediaManager.mMediaRouterCallback.onSessionUpdated(mock(RoutingSessionInfo.class));
+
+        verify(mCallback).onDeviceAttributesChanged();
+    }
+
+    @Test
     public void addMediaDevice_verifyDeviceTypeCanCorrespondToMediaDevice() {
         final MediaRoute2Info route2Info = mock(MediaRoute2Info.class);
         final CachedBluetoothDeviceManager cachedBluetoothDeviceManager =
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
index 365a16c..517071b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
@@ -141,7 +141,7 @@
         when(currentDevice.getId()).thenReturn(TEST_CURRENT_DEVICE_ID);
 
         mLocalMediaManager.registerCallback(mCallback);
-        mLocalMediaManager.connectDevice(device);
+        assertThat(mLocalMediaManager.connectDevice(device)).isTrue();
 
         verify(currentDevice).disconnect();
         verify(device).connect();
@@ -154,7 +154,7 @@
         mLocalMediaManager.mCurrentConnectedDevice = mInfoMediaDevice1;
 
         mLocalMediaManager.registerCallback(mCallback);
-        mLocalMediaManager.connectDevice(mInfoMediaDevice2);
+        assertThat(mLocalMediaManager.connectDevice(mInfoMediaDevice2)).isTrue();
 
         assertThat(mInfoMediaDevice2.getState()).isEqualTo(LocalMediaManager.MediaDeviceState
                 .STATE_CONNECTING);
@@ -167,7 +167,7 @@
         mLocalMediaManager.mCurrentConnectedDevice = mInfoMediaDevice1;
 
         mLocalMediaManager.registerCallback(mCallback);
-        mLocalMediaManager.connectDevice(mInfoMediaDevice1);
+        assertThat(mLocalMediaManager.connectDevice(mInfoMediaDevice1)).isFalse();
 
         assertThat(mInfoMediaDevice1.getState()).isNotEqualTo(LocalMediaManager.MediaDeviceState
                 .STATE_CONNECTING);
@@ -185,7 +185,7 @@
         when(cachedDevice.isBusy()).thenReturn(false);
 
         mLocalMediaManager.registerCallback(mCallback);
-        mLocalMediaManager.connectDevice(device);
+        assertThat(mLocalMediaManager.connectDevice(device)).isTrue();
 
         verify(cachedDevice).connect();
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java
index 47f6fe3..421e5c0 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java
@@ -100,12 +100,12 @@
         when(mInfo.getName()).thenReturn(deviceName);
 
         assertThat(mPhoneMediaDevice.getName())
-                .isEqualTo(mContext.getString(R.string.media_transfer_wired_device_name));
+                .isEqualTo(mContext.getString(R.string.media_transfer_wired_usb_device_name));
 
         when(mInfo.getType()).thenReturn(TYPE_USB_DEVICE);
 
         assertThat(mPhoneMediaDevice.getName())
-                .isEqualTo(deviceName);
+                .isEqualTo(mContext.getString(R.string.media_transfer_wired_usb_device_name));
 
         when(mInfo.getType()).thenReturn(TYPE_BUILTIN_SPEAKER);
 
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 29c31ea..e537b76 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -588,8 +588,9 @@
                     Settings.Global.POWER_BUTTON_VERY_LONG_PRESS,
                     Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS, // Temporary for R beta
                     Settings.Global.INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER,
-                    Settings.Global.ADVANCED_BATTERY_USAGE_AMOUNT,
-                    Settings.Global.CACHED_APPS_FREEZER_ENABLED);
+                    Settings.Global.CACHED_APPS_FREEZER_ENABLED,
+                    Settings.Global.APP_INTEGRITY_VERIFICATION_TIMEOUT,
+                    Settings.Global.ADVANCED_BATTERY_USAGE_AMOUNT);
 
     private static final Set<String> BACKUP_BLACKLISTED_SECURE_SETTINGS =
              newHashSet(
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 96caf31..b85c771 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -233,6 +233,9 @@
     <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
     <uses-permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"/>
 
+    <!-- Permission required for CTS test - BatterySaverTest -->
+    <uses-permission android:name="android.permission.MODIFY_DAY_NIGHT_MODE"/>
+
     <!-- Permission required for CTS test - UiModeManagerTest -->
     <uses-permission android:name="android.permission.ENTER_CAR_MODE_PRIORITIZED"/>
 
@@ -343,22 +346,6 @@
                   android:excludeFromRecents="true"
                   android:exported="false" />
 
-        <!--
-        The following is used as a no-op/null home activity when
-        no other MAIN/HOME activity is present (e.g., in CSI).
-        -->
-        <activity android:name=".NullHome"
-                  android:excludeFromRecents="true"
-                  android:label=""
-                  android:screenOrientation="nosensor">
-            <!-- The priority here is set to be lower than that for Settings -->
-            <intent-filter android:priority="-1100">
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.HOME" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity>
-
         <receiver
             android:name=".BugreportRequestedReceiver"
             android:permission="android.permission.TRIGGER_SHELL_BUGREPORT">
diff --git a/packages/Shell/res/layout/null_home_finishing_boot.xml b/packages/Shell/res/layout/null_home_finishing_boot.xml
deleted file mode 100644
index 5f9563a..0000000
--- a/packages/Shell/res/layout/null_home_finishing_boot.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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
-  -->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="#80000000"
-    android:forceHasOverlappingRendering="false">
-    <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:layout_gravity="center"
-        android:layout_marginStart="16dp"
-        android:layout_marginEnd="16dp">
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textSize="40sp"
-            android:textColor="?android:attr/textColorPrimary"
-            android:text="@*android:string/android_start_title"/>
-        <ProgressBar
-            style="@android:style/Widget.Material.ProgressBar.Horizontal"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="12.75dp"
-            android:colorControlActivated="?android:attr/textColorPrimary"
-            android:indeterminate="true"/>
-    </LinearLayout>
-</FrameLayout>
diff --git a/packages/Shell/res/values-ar/strings.xml b/packages/Shell/res/values-ar/strings.xml
index b81a904..302971f 100644
--- a/packages/Shell/res/values-ar/strings.xml
+++ b/packages/Shell/res/values-ar/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"اختر لمشاركة تقرير الأخطاء بدون لقطة شاشة أو انتظر حتى انتهاء لقطة الشاشة"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"انقر لمشاركة تقرير الأخطاء بدون لقطة شاشة أو انتظر حتى انتهاء لقطة الشاشة"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"انقر لمشاركة تقرير الأخطاء بدون لقطة شاشة أو انتظر حتى انتهاء لقطة الشاشة"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"تحتوي تقارير الأخطاء على بيانات من عدة ملفات سجلات في النظام، بما في ذلك بيانات قد ترى أنها حساسة (مثل بيانات استخدام التطبيقات وبيانات الموقع). ولذلك احرص على عدم مشاركة تقارير الأخطاء إلا مع من تثق به من الأشخاص والتطبيقات."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"تحتوي تقارير الأخطاء على بيانات من عدة ملفات سجلات في النظام، بما قد يشمل بيانات تعتبرها حساسة (مثل بيانات استخدام التطبيقات وبيانات الموقع الجغرافي). ولذلك احرص على عدم مشاركة تقارير الأخطاء إلا مع من تثق به من الأشخاص والتطبيقات."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"عدم الإظهار مرة أخرى"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"تقارير الأخطاء"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"تعذرت قراءة ملف تقرير الخطأ."</string>
diff --git a/packages/Shell/res/values-az/strings.xml b/packages/Shell/res/values-az/strings.xml
index 40800bb..1522f3f 100644
--- a/packages/Shell/res/values-az/strings.xml
+++ b/packages/Shell/res/values-az/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Baq hesabatını skrinşot olmadan paylaşmaq üçün seçin, skrinşotun tamamlanması üçün isə gözləyin"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"baq hesabatınızı skrinşot olmadan paylaşmaq üçün tıklayın, skrinşotun tamamlanması üçün isə gözləyin"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"baq hesabatınızı skrinşot olmadan paylaşmaq üçün tıklayın, skrinşotun tamamlanması üçün isə gözləyin"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"Baq raportları sistemin müxtəlif jurnal fayllarından həssas təyin etdiyiniz data (tətbiq istifadəsi və məkan datası kimi) içərir. Baq raportlarını yalnız inandığınız tətbiq və adamlarla paylaşın."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"Baq hesabatları sistemin müxtəlif jurnal fayllarından həssas təyin etdiyiniz data (tətbiq istifadəsi və məkan datası kimi) içərir. Baq raportlarını yalnız inandığınız tətbiq və adamlarla paylaşın."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Daha göstərməyin"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Baq hesabatları"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Baq hesabat faylı oxunmur"</string>
diff --git a/packages/Shell/res/values-be/strings.xml b/packages/Shell/res/values-be/strings.xml
index bea1c30..ce369c3 100644
--- a/packages/Shell/res/values-be/strings.xml
+++ b/packages/Shell/res/values-be/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Выберыце, каб абагуліць справаздачу пра памылку без здымка экрана, або чакайце атрымання здымка"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Краніце, каб абагуліць справаздачу пра памылку без здымка экрана, або чакайце атрымання здымка."</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Краніце, каб абагуліць справаздачу пра памылку без здымка экрана, або чакайце атрымання здымка."</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"Справаздачы пра памылкі ўтрымліваюць даныя з розных файлаў журналаў сістэмы, якія могуць уключаць даныя, што вы лічыце канфідэнцыяльнымі (напрыклад, пра выкарыстанне праграм і даныя аб месцазнаходжанні). Абагульвайце справаздачы пра памылкі толькі з тымі людзьмі і праграмамі, якім вы давяраеце."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"Справаздачы пра памылкі ўтрымліваюць інфармацыю з розных файлаў журналаў сістэмы, у тым ліку і канфідэнцыяльную (напрыклад, даныя, якія датычацца выкарыстання праграм і месцазнаходжання прылады). Абагульвайце справаздачы пра памылкі толькі з тымі людзьмі і праграмамі, якім вы давяраеце."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Не паказваць зноў"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Справадзачы пра памылкі"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Немагчыма прачытаць файл справаздачы пра памылкі"</string>
diff --git a/packages/Shell/res/values-da/strings.xml b/packages/Shell/res/values-da/strings.xml
index d9bf877..c23efc3 100644
--- a/packages/Shell/res/values-da/strings.xml
+++ b/packages/Shell/res/values-da/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Vælg for at dele din fejlrapport uden et screenshot, eller vent på, at et screenshot er klar"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tryk for at dele din fejlrapport uden et screenshot, eller vent på, at screenshott fuldføres"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tryk for at dele din fejlrapport uden et screenshot, eller vent på, at screenshott fuldføres"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"Fejlrapporter indeholder data fra systemets forskellige logfiler, som kan være data, du mener er følsomme, f.eks. appforbrug og placeringsdata. Del kun fejlrapporter med personer og apps, du har tillid til."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"Fejlrapporter indeholder data fra systemets forskellige logfiler, og der kan være følsomme data imellem (f.eks. appforbrug og placeringsdata). Del kun fejlrapporter med personer og apps, du har tillid til."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Vis ikke igen"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Fejlrapporter"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Fejlrapportfilen kunne ikke læses"</string>
diff --git a/packages/Shell/res/values-eu/strings.xml b/packages/Shell/res/values-eu/strings.xml
index 2957dab..5d32cab 100644
--- a/packages/Shell/res/values-eu/strings.xml
+++ b/packages/Shell/res/values-eu/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Hautatu hau akatsen txostena argazkirik gabe partekatzeko edo itxaron pantaila-argazkia atera arte"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Sakatu akatsen txostena argazkirik gabe partekatzeko edo itxaron pantaila-argazkia atera arte"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Sakatu akatsen txostena argazkirik gabe partekatzeko edo itxaron pantaila-argazkia atera arte"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"Errore-txostenek sistemaren erregistro-fitxategietako datuak dauzkate eta, haietan, kontuzkotzat jotzen duzun informazioa ager daiteke (adibidez, aplikazioen erabilera eta kokapen-datuak). Errore-txostenak partekatzen badituzu, partekatu soilik pertsona eta aplikazio fidagarriekin."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"Errore-txostenek sistemaren erregistro-fitxategietako datuak dauzkate, eta, haietan, kontuzkotzat jotzen duzun informazioa ager daiteke (adibidez, aplikazioen erabilera eta kokapen-datuak). Errore-txostenak partekatzen badituzu, partekatu soilik pertsona eta aplikazio fidagarriekin."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Ez erakutsi berriro"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Akatsen txostenak"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Ezin izan da irakurri akatsen txostena"</string>
diff --git a/packages/Shell/res/values-fr/strings.xml b/packages/Shell/res/values-fr/strings.xml
index 6fa6f6e..3933557 100644
--- a/packages/Shell/res/values-fr/strings.xml
+++ b/packages/Shell/res/values-fr/strings.xml
@@ -28,9 +28,9 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Sélectionner pour partager le rapport de bug sans capture d\'écran ou attendre la fin de la capture"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Appuyer pour partager rapport de bug sans capture d\'écran ou attendre finalisation capture d\'écran"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Appuyer pour partager rapport de bug sans capture d\'écran ou attendre finalisation capture d\'écran"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"Les rapports de bug contiennent des données des fichiers journaux du système, y compris des informations que vous considérez sensibles concernant, par exemple, la consommation par application et la localisation. Nous vous recommandons de ne partager ces rapports qu\'avec des personnes et des applications que vous estimez fiables."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"Les rapports de bugs contiennent des données des fichiers journaux du système, y compris des informations que vous considérez sensibles concernant, par exemple, la consommation par application et la localisation. Nous vous recommandons de ne partager ces rapports qu\'avec des personnes et des applications que vous estimez fiables."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Ne plus afficher"</string>
-    <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapports d\'erreur"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapports de bugs"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Impossible de lire le fichier de rapport de bug."</string>
     <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Impossible d\'ajouter les détails du rapport de bug au fichier .zip"</string>
     <string name="bugreport_unnamed" msgid="2800582406842092709">"sans nom"</string>
diff --git a/packages/Shell/res/values-hr/strings.xml b/packages/Shell/res/values-hr/strings.xml
index 9cbc09d..4764d17 100644
--- a/packages/Shell/res/values-hr/strings.xml
+++ b/packages/Shell/res/values-hr/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Odaberite za dijeljenje izvješća o pogrešci bez snimke zaslona ili pričekajte da se izradi snimka"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Dodirnite za dijeljenje izvješća o pogrešci bez snimke zaslona ili pričekajte da se izradi snimka"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Dodirnite za dijeljenje izvješća o pogrešci bez snimke zaslona ili pričekajte da se izradi snimka"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"Izvješća o programskim pogreškama sadržavaju podatke iz različitih datoteka zapisnika sustava, što može uključivati podatke koje smatrate osjetljivima (na primjer podatke o upotrebi aplikacije i lokaciji). Izvješća o programskim pogreškama dijelite samo s osobama i aplikacijama koje smatrate pouzdanima."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"Izvješća o programskim pogreškama sadržavaju podatke iz različitih datoteka zapisnika sustava, što može uključivati podatke koje smatrate osjetljivim (na primjer podatke o upotrebi aplikacije i lokaciji). Izvješća o programskim pogreškama dijelite samo s osobama i aplikacijama koje smatrate pouzdanim."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Ne prikazuj ponovo"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Izvj. o prog. pogreš."</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Izvješće o programskoj pogrešci nije pročitano"</string>
diff --git a/packages/Shell/res/values-is/strings.xml b/packages/Shell/res/values-is/strings.xml
index b8c0412..4989e87 100644
--- a/packages/Shell/res/values-is/strings.xml
+++ b/packages/Shell/res/values-is/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Veldu að deila villutilkynningunni án skjámyndar eða hinkraðu þangað til skjámyndin er tilbúin"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Ýttu til að deila villutilkynningunni án skjámyndar eða hinkraðu þangað til skjámyndin er tilbúin"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Ýttu til að deila villutilkynningunni án skjámyndar eða hinkraðu þangað til skjámyndin er tilbúin"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"Villutilkynningar innihalda gögn úr ýmsum annálaskrám kerfisins, sem gætu innihaldið upplýsingar sem þú telur viðkvæmar (eins og um notkun forrita og staðsetningarupplýsingar). Deildu villutilkynningum bara með fólki og forritum sem þú treystir."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"Villutilkynningar innihalda gögn úr ýmsum annálaskrám kerfisins sem gætu innihaldið upplýsingar sem þú telur viðkvæmar (til dæmis notkun forrita og staðsetningarupplýsingar). Deildu villutilkynningum bara með fólki og forritum sem þú treystir."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Ekki sýna þetta aftur"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Villutilkynningar"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Ekki var hægt að lesa úr villuskýrslunni"</string>
diff --git a/packages/Shell/res/values-km/strings.xml b/packages/Shell/res/values-km/strings.xml
index ec75687..0ab3b68 100644
--- a/packages/Shell/res/values-km/strings.xml
+++ b/packages/Shell/res/values-km/strings.xml
@@ -28,9 +28,9 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"ជ្រើសរើស​ដើម្បី​ចែករំលែក​របាយការណ៍​អំពី​បញ្ហា​របស់​អ្នក​ដោយ​មិនចាំបាច់​មាន​រូបថត​អេក្រង់ ឬ​រង់ចាំ​រូបថត​អេក្រង់ដើម្បីបញ្ចប់"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ប៉ះដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នកដោយមិនចាំបាច់មានរូបថតអេក្រង់ ឬរង់ចាំការបញ្ចប់ការថតអេក្រង់"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ប៉ះដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នកដោយមិនចាំបាច់មានរូបថតអេក្រង់ ឬរង់ចាំការបញ្ចប់ការថតអេក្រង់"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"របាយការណ៍ផ្ទុកទិន្នន័យពីឯកសារកំណត់ហេតុផ្សេងៗរបស់ប្រព័ន្ធ ដែលអាចមានផ្ទុកទិន្នន័យដែលអ្នកចាត់ទុកថាជាទិន្នន័យរសើប (ដូចជាការប្រើប្រាស់កម្មវិធី និងទិន្នន័យទីតាំង)។ ចែករំលែករបាយការណ៍កំហុសជាមួយមនុស្ស និងកម្មវិធីដែលអ្នកជឿជាក់ប៉ុណ្ណោះ។"</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"របាយការណ៍អំពីបញ្ហាផ្ទុកទិន្នន័យពីឯកសារកំណត់ហេតុផ្សេងៗរបស់ប្រព័ន្ធ ដែលអាចរួមបញ្ចូលទិន្នន័យដែលអ្នកចាត់ទុកថាមានលក្ខណៈរសើប (ដូចជាការប្រើប្រាស់កម្មវិធី និងទិន្នន័យទីតាំង)។ ចែករំលែករបាយការណ៍អំពីបញ្ហាជាមួយមនុស្ស និងកម្មវិធីដែលអ្នកជឿជាក់តែប៉ុណ្ណោះ។"</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"កុំបង្ហាញម្ដងទៀត"</string>
-    <string name="bugreport_storage_title" msgid="5332488144740527109">"រាយការណ៍ពីកំហុស"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"របាយការណ៍អំពីបញ្ហា"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"មិនអាចអានឯកសាររបាយកាណ៍កំហុសបានទេ"</string>
     <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"មិនអាចបន្ថែមព័ត៌មានលម្អិតនៃរបាយការណ៍កំហុសទៅឯកសារ zip បានទេ"</string>
     <string name="bugreport_unnamed" msgid="2800582406842092709">"គ្មានឈ្មោះ"</string>
diff --git a/packages/Shell/res/values-ko/strings.xml b/packages/Shell/res/values-ko/strings.xml
index 68d4139..545dfa7 100644
--- a/packages/Shell/res/values-ko/strings.xml
+++ b/packages/Shell/res/values-ko/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"스크린샷 없이 버그 신고를 공유하려면 선택하고 그렇지 않으면 스크린샷이 완료될 때까지 기다려 주세요."</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"스크린샷 없이 버그 신고서를 공유하려면 탭하고 그렇지 않으면 스크린샷이 완료될 때까지 기다려 주세요."</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"스크린샷 없이 버그 신고서를 공유하려면 탭하고 그렇지 않으면 스크린샷이 완료될 때까지 기다려 주세요."</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"버그 신고서에는 시스템의 다양한 로그 파일 데이터가 포함되며 여기에는 사용자가 중요하다고 생각하는 데이터(예: 앱 사용 및 위치 데이터)가 포함되었을 수 있습니다. 신뢰할 수 있는 앱과 사용자에게만 버그 신고서를 공유하세요."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"버그 신고서에는 시스템의 다양한 로그 파일 데이터가 포함되며 여기에는 사용자가 민감하다고 생각하는 데이터(예: 앱 사용 및 위치 데이터)가 포함되었을 수 있습니다. 신뢰할 수 있는 앱과 사용자에게만 버그 신고서를 공유하세요."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"다시 표시 안함"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"버그 신고"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"버그 신고 파일을 읽을 수 없습니다."</string>
diff --git a/packages/Shell/res/values-ky/strings.xml b/packages/Shell/res/values-ky/strings.xml
index 2499aba..969e9ed 100644
--- a/packages/Shell/res/values-ky/strings.xml
+++ b/packages/Shell/res/values-ky/strings.xml
@@ -30,7 +30,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Мүчүлүштүк тууралуу билдирүүңүздү скриншотсуз бөлүшүү үчүн таптап коюңуз же скриншот даяр болгуча күтө туруңуз"</string>
     <string name="bugreport_confirm" msgid="5917407234515812495">"Мүчүлүштүктөр тууралуу билдирүүлөрдө тутумдун ар кандай таржымалдарынан алынган дайындар, ошондой эле купуя маалымат камтылышы мүмкүн (мисалы, жайгашкан жер сыяктуу). Мындай билдирүүлөрдү бир гана ишеничтүү адамдар жана колдонмолор менен бөлүшүңүз."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Экинчи көрсөтүлбөсүн"</string>
-    <string name="bugreport_storage_title" msgid="5332488144740527109">"Мүчүлүштүктөрдү кабарлоолор"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Мүчүлүштүктөрдү кабарлоо"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Мүчүлүштүк тууралуу кабарлаган файл окулбай койду"</string>
     <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Мүчүлүштүктөр жөнүндө кабардын чоо-жайы zip файлына кошулбай койду"</string>
     <string name="bugreport_unnamed" msgid="2800582406842092709">"аталышы жок"</string>
diff --git a/packages/Shell/res/values-ml/strings.xml b/packages/Shell/res/values-ml/strings.xml
index 5c1842a..78b43bb 100644
--- a/packages/Shell/res/values-ml/strings.xml
+++ b/packages/Shell/res/values-ml/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"സ്ക്രീൻഷോട്ട് കൂടാതെയോ സ്ക്രീൻഷോട്ട് പൂർത്തിയാകുന്നതിന് കാക്കാതെയോ ബഗ് റിപ്പോർട്ട് പങ്കിടുക"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"സ്ക്രീൻഷോട്ട് കൂടാതെയോ സ്ക്രീൻഷോട്ട് പൂർത്തിയാകുന്നതിന് കാക്കാതെയോ നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ ടാപ്പുചെയ്യുക"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"സ്ക്രീൻഷോട്ട് കൂടാതെയോ സ്ക്രീൻഷോട്ട് പൂർത്തിയാകുന്നതിന് കാക്കാതെയോ നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ ടാപ്പുചെയ്യുക"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"ബഗ് റിപ്പോർട്ടുകളിൽ സിസ്റ്റത്തിന്റെ നിരവധി ലോഗ് ഫയലുകളിൽ നിന്നുള്ള വിവരങ്ങൾ അടങ്ങിയിരിക്കുന്നു, ഇതിൽ നിങ്ങൾ രഹസ്വസ്വഭാവമുള്ളവയായി പരിഗണിക്കുന്ന വിവരങ്ങളും (ആപ്പ് ഉപയോഗ വിവരങ്ങൾ, ലൊക്കേഷൻ വിവരങ്ങൾ എന്നിവ പോലെ) ഉൾപ്പെടാം. നിങ്ങൾ വിശ്വസിക്കുന്ന ആപ്‌സിനും ആളുകൾക്കും മാത്രം ബഗ് റിപ്പോർട്ടുകൾ പങ്കിടുക."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"ബഗ് റിപ്പോർട്ടുകളിൽ സിസ്റ്റത്തിന്റെ നിരവധി ലോഗ് ഫയലുകളിൽ നിന്നുള്ള വിവരങ്ങൾ അടങ്ങിയിരിക്കുന്നു, ഇതിൽ നിങ്ങൾ രഹസ്യ സ്വഭാവമുള്ളവയായി പരിഗണിക്കുന്ന വിവരങ്ങളും (ആപ്പ് ഉപയോഗ വിവരങ്ങൾ, ലൊക്കേഷൻ വിവരങ്ങൾ എന്നിവ പോലെ) ഉൾപ്പെടാം. നിങ്ങൾ വിശ്വസിക്കുന്ന ആപ്പുകൾക്കും ആളുകൾക്കും മാത്രം ബഗ് റിപ്പോർട്ടുകൾ പങ്കിടുക."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"വീണ്ടും കാണിക്കരുത്"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"ബഗ് റിപ്പോർട്ടുകൾ"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"ബഗ് റിപ്പോർട്ട് ഫയൽ വായിക്കാനായില്ല"</string>
diff --git a/packages/Shell/res/values-ne/strings.xml b/packages/Shell/res/values-ne/strings.xml
index 7cc2e6b..3c58796 100644
--- a/packages/Shell/res/values-ne/strings.xml
+++ b/packages/Shell/res/values-ne/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"तपाईंको बग रिपोर्ट स्क्रिनसट बिना आदान प्रदान गर्नाका लागि चयन गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुने प्रतीक्षा गर्नुहोस्"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नाका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुन प्रतीक्षा गर्नुहोस्"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नाका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुन प्रतीक्षा गर्नुहोस्"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"बग रिपोर्टमा प्रणालीका विभिन्न लग फाइलहरूको डेटा हुन्छ। यस रिपोर्टमा (अनुप्रयोगको प्रयोग र स्थानसम्बन्धी डेटा जस्ता) जसमा तपाईंका संवेदनशील डेटा समावेश हुन सक्छ । आफूले विश्वास गर्ने व्यक्ति र अनुप्रयोगहरूसँग मात्र बग रिपोर्ट सेयर गर्नुहोस्।"</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"बग रिपोर्टमा प्रणालीका विभिन्न लग फाइलहरूको डेटा हुन्छ। यस रिपोर्टमा (एपको प्रयोग र स्थानसम्बन्धी डेटा जस्ता) जसमा तपाईंका संवेदनशील डेटा समावेश हुन सक्छ । आफूले विश्वास गर्ने व्यक्ति र अनुप्रयोगहरूसँग मात्र बग रिपोर्ट सेयर गर्नुहोस्।"</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"फेरि नदेखाउनुहोस्"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"बग रिपोर्टहरू"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"बग रिपोर्ट फाइल पढ्न सकिएन"</string>
diff --git a/packages/Shell/res/values-pa/strings.xml b/packages/Shell/res/values-pa/strings.xml
index 8894814..d0c2905 100644
--- a/packages/Shell/res/values-pa/strings.xml
+++ b/packages/Shell/res/values-pa/strings.xml
@@ -30,7 +30,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਬਿਨਾਂ ਆਪਣੀ ਬੱਗ ਰਿਪੋਰਟ ਨੂੰ ਸਾਂਝੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ ਜਾਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਪੂਰੇ ਹੋਣ ਦੀ ਉਡੀਕ ਕਰੋ"</string>
     <string name="bugreport_confirm" msgid="5917407234515812495">"ਬੱਗ ਰਿਪੋਰਟਾਂ ਵਿੱਚ ਸਿਸਟਮ ਦੀਆਂ ਵੱਖ-ਵੱਖ ਲੌਗ ਫ਼ਾਈਲਾਂ ਦਾ ਡਾਟਾ ਸ਼ਾਮਲ ਹੁੰਦਾ ਹੈ, ਜਿਸ ਵਿੱਚ ਉਹ ਡਾਟਾ ਸ਼ਾਮਲ ਹੋ ਸਕਦਾ ਹੈ ਜਿਸ ਨੂੰ ਤੁਸੀਂ ਸੰਵੇਦਨਸ਼ੀਲ ਮੰਨਦੇ ਹੋ (ਜਿਵੇਂ ਕਿ ਐਪ-ਵਰਤੋਂ ਅਤੇ ਟਿਕਾਣਾ ਡਾਟਾ)। ਬੱਗ ਰਿਪੋਰਟਾਂ ਨੂੰ ਸਿਰਫ਼ ਆਪਣੇ ਭਰੋਸੇਯੋਗ ਲੋਕਾਂ ਅਤੇ ਐਪਾਂ ਨਾਲ ਸਾਂਝਾ ਕਰੋ।"</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"ਦੁਬਾਰਾ ਨਾ  ਦਿਖਾਓ"</string>
-    <string name="bugreport_storage_title" msgid="5332488144740527109">"ਬਗ ਰਿਪੋਰਟਾਂ"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"ਬੱਗ ਰਿਪੋਰਟਾਂ"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"ਬਗ ਰਿਪੋਰਟ ਫ਼ਾਈਲ ਪੜ੍ਹੀ ਨਹੀਂ ਜਾ ਸਕੀ"</string>
     <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"ਬੱਗ ਰਿਪੋਰਟ ਵੇਰਵਿਆਂ ਨੂੰ ਜ਼ਿਪ ਫ਼ਾਈਲ ਵਿੱਚ ਸ਼ਾਮਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
     <string name="bugreport_unnamed" msgid="2800582406842092709">"ਬਿਨਾਂ-ਨਾਮ"</string>
diff --git a/packages/Shell/res/values-pt-rPT/strings.xml b/packages/Shell/res/values-pt-rPT/strings.xml
index 3d11d4d..34013fa 100644
--- a/packages/Shell/res/values-pt-rPT/strings.xml
+++ b/packages/Shell/res/values-pt-rPT/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Selecione para partilhar o relatório de erro sem uma captura de ecrã ou aguarde a conclusão da mesma"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toque para partilhar o relatório de erro sem uma captura de ecrã ou aguarde a conclusão da mesma"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toque para partilhar o relatório de erro sem uma captura de ecrã ou aguarde a conclusão da mesma"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"Os relatórios de erros contêm dados de vários ficheiros de registo do sistema, que podem incluir dados que considere confidenciais (tais como dados de utilização de aplicações e de localização). Partilhe os relatórios de erros apenas com aplicações fidedignas e pessoas em quem confia."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"Os relatórios de erros contêm dados de vários ficheiros de registo do sistema, que podem incluir dados que considere confidenciais (tais como dados de utilização de apps e de localização). Partilhe os relatórios de erros apenas com apps fidedignas e pessoas em quem confia."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Não mostrar de novo"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Relatórios de erros"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Não foi possível ler o ficheiro de relatório de erro"</string>
diff --git a/packages/Shell/res/values-sk/strings.xml b/packages/Shell/res/values-sk/strings.xml
index 61a2467..ecceb55 100644
--- a/packages/Shell/res/values-sk/strings.xml
+++ b/packages/Shell/res/values-sk/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Klepnutím zdieľajte hlásenie chyby bez snímky obrazovky alebo počkajte na dokončenie snímky obrazovky"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Klepnutím zdieľajte hlásenie chyby bez snímky obrazovky alebo počkajte na dokončenie snímky obrazovky"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Klepnutím zdieľajte hlásenie chyby bez snímky obrazovky alebo počkajte na dokončenie snímky obrazovky"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"Hlásenia chýb obsahujú údaje z rôznych súborov denníkov systému, ktoré môžu zahŕňať údaje považované za citlivé (napr. údaje o využití aplikácie a polohe). Zdieľajte ich preto iba s dôveryhodnými ľuďmi a aplikáciami."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"Hlásenia chýb obsahujú údaje z rôznych denníkov systému a môžu zahŕňať údaje, ktoré považujete za citlivé (napríklad údaje o využití aplikácií a polohe). Zdieľajte hlásenia chýb iba s ľuďmi a aplikáciami, ktorým dôverujete."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Nabudúce nezobrazovať"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Hlásenia chýb"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Súbor s hlásením chyby sa nepodarilo prečítať"</string>
diff --git a/packages/Shell/res/values-te/strings.xml b/packages/Shell/res/values-te/strings.xml
index bb0496a..6050c1f 100644
--- a/packages/Shell/res/values-te/strings.xml
+++ b/packages/Shell/res/values-te/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="3701846017049540910">"షెల్"</string>
-    <string name="bugreport_notification_channel" msgid="2574150205913861141">"బగ్ నివేదికలు"</string>
+    <string name="bugreport_notification_channel" msgid="2574150205913861141">"బగ్ రిపోర్ట్స్"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"బగ్ నివేదిక <xliff:g id="ID">#%d</xliff:g> ఉత్పాదించబడుతోంది"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"బగ్ నివేదిక <xliff:g id="ID">#%d</xliff:g> సంగ్రహించబడింది"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"బగ్ నివేదికకు వివరాలను జోడిస్తోంది"</string>
@@ -28,9 +28,9 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"స్క్రీన్‌షాట్ లేకుండా మీ బగ్ నివేదికను భాగస్వామ్యం చేయడానికి ఎంచుకోండి లేదా స్క్రీన్‌షాట్ ముగిసేదాకా వేచి ఉండండి"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"స్క్రీన్‌షాట్ లేకుండా మీ బగ్ నివే. భాగ. చేయడానికి నొక్కండి లేదా స్క్రీన్‌షాట్ ముగిసేదాకా వేచి ఉండండి"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"స్క్రీన్‌షాట్ లేకుండా మీ బగ్ నివే. భాగ. చేయడానికి నొక్కండి లేదా స్క్రీన్‌షాట్ ముగిసేదాకా వేచి ఉండండి"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"బగ్ నివేదికల్లో మీరు గోప్యమైనదిగా పరిగణించే (యాప్ వినియోగం, లొకేష‌న్‌ డేటా వంటి) డేటాతో పాటు సిస్టమ్‌కు సంబంధించిన విభిన్న లాగ్ ఫైల్‌ల డేటా ఉంటుంది. బగ్ నివేదికలను మీరు విశ్వసించే యాప్‌లు, వ్యక్తులతో మాత్రమే షేర్ చేయండి."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"బగ్ రిపోర్ట్స్‌లో మీరు గోప్యమైనదిగా పరిగణించే (యాప్ వినియోగం, లొకేష‌న్‌ డేటా వంటి) డేటాతో పాటు సిస్టమ్‌కు సంబంధించిన విభిన్న లాగ్ ఫైల్‌ల డేటా ఉంటుంది. బగ్ నివేదికలను మీరు విశ్వసించే యాప్‌లు, వ్యక్తులతో మాత్రమే షేర్ చేయండి."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"మళ్లీ చూపవద్దు"</string>
-    <string name="bugreport_storage_title" msgid="5332488144740527109">"బగ్ నివేదికలు"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"బగ్ రిపోర్ట్స్"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"బగ్ నివేదిక ఫైల్‌ను చదవడం సాధ్యపడలేదు"</string>
     <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"బగ్ నివేదిక వివరాలను జిప్ ఫైల్‌కు జోడించడం సాధ్యపడలేదు"</string>
     <string name="bugreport_unnamed" msgid="2800582406842092709">"పేరు లేనివి"</string>
diff --git a/packages/Shell/res/values-zh-rHK/strings.xml b/packages/Shell/res/values-zh-rHK/strings.xml
index 8298d15..ccbea4d 100644
--- a/packages/Shell/res/values-zh-rHK/strings.xml
+++ b/packages/Shell/res/values-zh-rHK/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"選擇以分享錯誤報告 (不包含螢幕擷取畫面),或等待螢幕畫面擷取完成"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"輕按以分享錯誤報告 (不包含螢幕擷圖),或等待螢幕畫面擷取完成"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"輕按以分享錯誤報告 (不包含螢幕擷圖),或等待螢幕畫面擷取完成"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"錯誤報告包含來自系統各個記錄檔案的資料,並可能涉及敏感資料 (例如應用程式使用情況和位置資料)。您只應與信任的人和應用程式分享錯誤報告。"</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"錯誤報告包含來自系統多個記錄檔案的資料,並可能涉及對您而言敏感的資料 (例如應用程式使用情況和位置資料)。您只應與信任的人和應用程式分享錯誤報告。"</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"不要再顯示"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"錯誤報告"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"無法讀取錯誤報告檔案"</string>
diff --git a/packages/Shell/src/com/android/shell/NullHome.java b/packages/Shell/src/com/android/shell/NullHome.java
deleted file mode 100644
index bd97561..0000000
--- a/packages/Shell/src/com/android/shell/NullHome.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.shell;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.util.Log;
-
-/**
- * This covers the fallback case where no launcher is available.
- * Usually Settings.apk has one fallback home activity.
- * Settings.apk, however, is not part of CSI, which needs to be
- * standalone (bootable and testable).
- */
-public class NullHome extends Activity {
-    private static final String TAG = "NullHome";
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        Log.i(TAG, "onCreate");
-        setContentView(R.layout.null_home_finishing_boot);
-    }
-
-    protected void onDestroy() {
-        super.onDestroy();
-        Log.i(TAG, "onDestroy");
-    }
-}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 61b1e30..055b2be 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -155,6 +155,7 @@
     <!-- Screen Recording -->
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT"/>
 
     <!-- Assist -->
     <uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" />
@@ -259,6 +260,9 @@
     <!-- Permission to register process observer -->
     <uses-permission android:name="android.permission.SET_ACTIVITY_WATCHER"/>
 
+    <!-- Restore settings (used by QS) even if they have been modified -->
+    <uses-permission android:name="android.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE" />
+
     <protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" />
     <protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" />
     <protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" />
@@ -682,6 +686,7 @@
         </activity>
 
         <activity android:name=".controls.management.ControlsEditingActivity"
+                  android:label="@string/controls_menu_edit"
                   android:theme="@style/Theme.ControlsManagement"
                   android:excludeFromRecents="true"
                   android:noHistory="true"
@@ -759,7 +764,8 @@
         <provider
             android:name="com.android.keyguard.clock.ClockOptionsProvider"
             android:authorities="com.android.keyguard.clock"
-            android:exported="true"
+            android:enabled="false"
+            android:exported="false"
             android:grantUriPermissions="true">
         </provider>
 
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
index aeedc16..e246917 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
@@ -66,14 +66,6 @@
 
     void destroy();
 
-    /**
-      * return true if the tile supports detail views, and not
-      * only boolean states
-      */
-    default boolean supportsDetailView() {
-        return false;
-    }
-
     CharSequence getTileLabel();
 
     State getState();
diff --git a/packages/SystemUI/res/anim/media_button_state_list_animator.xml b/packages/SystemUI/res/anim/media_button_state_list_animator.xml
new file mode 100644
index 0000000..62ebbaa
--- /dev/null
+++ b/packages/SystemUI/res/anim/media_button_state_list_animator.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <set>
+            <objectAnimator
+                android:interpolator="@interpolator/control_state"
+                android:duration="50"
+                android:propertyName="scaleX"
+                android:valueTo="0.9"
+                android:valueType="floatType" />
+            <objectAnimator
+                android:interpolator="@interpolator/control_state"
+                android:duration="50"
+                android:propertyName="scaleY"
+                android:valueTo="0.9"
+                android:valueType="floatType" />
+        </set>
+    </item>
+    <item>
+        <set>
+            <objectAnimator
+                android:interpolator="@interpolator/control_state"
+                android:duration="250"
+                android:propertyName="scaleX"
+                android:valueTo="1"
+                android:valueType="floatType" />
+            <objectAnimator
+                android:interpolator="@interpolator/control_state"
+                android:duration="250"
+                android:propertyName="scaleY"
+                android:valueTo="1"
+                android:valueType="floatType" />
+        </set>
+    </item>
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/kg_user_switcher_rounded_background_color.xml b/packages/SystemUI/res/color/kg_user_switcher_rounded_background_color.xml
index b16d038..3660dc4 100644
--- a/packages/SystemUI/res/color/kg_user_switcher_rounded_background_color.xml
+++ b/packages/SystemUI/res/color/kg_user_switcher_rounded_background_color.xml
@@ -17,6 +17,7 @@
   -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_activated="true" android:color="@color/kg_user_switcher_activated_background_color" />
+    <item android:state_activated="true" android_state_enabled="true" android:color="@color/kg_user_switcher_activated_background_color" />
+    <item android:state_pressed="true" android:state_enabled="true" android:color="@color/kg_user_switcher_activated_background_color" />
     <item android:color="@android:color/transparent" />
-</selector>
\ No newline at end of file
+</selector>
diff --git a/packages/SystemUI/res/drawable/control_no_favorites_background.xml b/packages/SystemUI/res/drawable/control_no_favorites_background.xml
index 947c77b..d895dd0 100644
--- a/packages/SystemUI/res/drawable/control_no_favorites_background.xml
+++ b/packages/SystemUI/res/drawable/control_no_favorites_background.xml
@@ -16,7 +16,22 @@
 * limitations under the License.
 */
 -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-  <stroke android:width="1dp" android:color="@*android:color/foreground_material_dark"/>
-  <corners android:radius="@dimen/control_corner_radius" />
-</shape>
+<!-- Should be kept in sync with the wallet plugin, as both share a similar
+     design: packages/apps/QuickAccessWallet -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?android:attr/colorControlHighlight">
+    <item android:id="@android:id/mask">
+        <shape android:shape="rectangle">
+            <solid android:color="#000000" />
+            <corners android:radius="@dimen/control_corner_radius" />
+        </shape>
+    </item>
+    <item>
+        <shape>
+            <stroke
+                android:width="1dp"
+                android:color="#4DFFFFFF" />
+            <corners android:radius="@dimen/control_corner_radius"/>
+        </shape>
+    </item>
+</ripple>
diff --git a/packages/SystemUI/res/drawable/control_spinner_background.xml b/packages/SystemUI/res/drawable/control_spinner_background.xml
index 7a8728d..46a9dad 100644
--- a/packages/SystemUI/res/drawable/control_spinner_background.xml
+++ b/packages/SystemUI/res/drawable/control_spinner_background.xml
@@ -21,11 +21,6 @@
             android:paddingLeft="0dp"
             android:paddingRight="0dp">
     <item
-        android:gravity="end|fill_vertical"
-        android:width="40dp"
-        android:drawable="@*android:drawable/control_background_40dp_material" />
-
-    <item
         android:drawable="@drawable/ic_ksh_key_down"
         android:gravity="end|bottom"
         android:paddingBottom="6dp"
diff --git a/packages/SystemUI/res/drawable/ic_screen_record_background.xml b/packages/SystemUI/res/drawable/ic_screen_record_background.xml
index 9195305..59eb023 100644
--- a/packages/SystemUI/res/drawable/ic_screen_record_background.xml
+++ b/packages/SystemUI/res/drawable/ic_screen_record_background.xml
@@ -13,13 +13,11 @@
     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="24dp"
-    android:height="24dp"
-    android:tint="?android:attr/colorError"
-    android:viewportWidth="24.0"
-    android:viewportHeight="24.0">
-    <path
-        android:pathData="M10,0L14,0A10,10 0,0 1,24 10L24,10A10,10 0,0 1,14 20L10,20A10,10 0,0 1,0 10L0,10A10,10 0,0 1,10 0z"
-        android:fillColor="@android:color/white"/>
-</vector>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+        android:shape="rectangle">
+    <solid
+        android:color="@color/screenrecord_status_color"
+        android:width="@dimen/screenrecord_status_icon_width"
+        android:height="@dimen/screenrecord_status_icon_height" />
+    <corners android:radius="@dimen/screenrecord_status_icon_bg_radius" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_screenrecord.xml b/packages/SystemUI/res/drawable/ic_screenrecord.xml
index 6d8bd0d..d4f807a 100644
--- a/packages/SystemUI/res/drawable/ic_screenrecord.xml
+++ b/packages/SystemUI/res/drawable/ic_screenrecord.xml
@@ -1,7 +1,7 @@
 <!--
-    Copyright (C) 2020 The Android Open Source Project
+Copyright (C) 2020 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the "License");
+   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
 
@@ -14,12 +14,12 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24.0"
-    android:viewportHeight="24.0"
-    android:tint="?android:attr/colorControlNormal">
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorControlNormal">
     <path
-        android:pathData="M12,12m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
-        android:fillColor="#FFFFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12,16c-2.21,0 -4,-1.79 -4,-4c0,-2.21 1.79,-4 4,-4c2.21,0 4,1.79 4,4C16,14.21 14.21,16 12,16zM11.99,1.99c-2.22,0 -4.26,0.73 -5.92,1.96l1.44,1.44c1.28,-0.87 2.82,-1.39 4.49,-1.39c1.67,0 3.21,0.52 4.5,1.4l1.44,-1.44C16.26,2.72 14.22,1.99 11.99,1.99zM16.48,18.6c-1.28,0.87 -2.82,1.39 -4.49,1.39c-1.66,0 -3.2,-0.52 -4.47,-1.39l-1.44,1.44c1.66,1.22 3.7,1.95 5.91,1.95c2.22,0 4.26,-0.73 5.92,-1.95L16.48,18.6zM5.39,16.49c-0.88,-1.28 -1.4,-2.83 -1.4,-4.5c0,-1.66 0.52,-3.21 1.39,-4.49L3.95,6.07c-1.22,1.66 -1.95,3.7 -1.95,5.92c0,2.22 0.73,4.27 1.96,5.93L5.39,16.49zM20.04,6.08l-1.44,1.44c0.87,1.28 1.39,2.82 1.39,4.47c0,1.66 -0.52,3.2 -1.39,4.49l1.44,1.44c1.22,-1.66 1.96,-3.7 1.96,-5.92C21.99,9.78 21.26,7.73 20.04,6.08z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/pip_resize_handle.xml b/packages/SystemUI/res/drawable/pip_resize_handle.xml
new file mode 100644
index 0000000..0a8cbc4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pip_resize_handle.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="12.0dp"
+    android:height="12.0dp"
+    android:viewportWidth="12"
+    android:viewportHeight="12">
+    <group
+        android:translateX="12"
+        android:rotation="90">
+        <path
+          android:fillColor="#FFFFFF"
+          android:pathData="M3.41421 0L2 1.41422L10.4853 9.8995L11.8995 8.48528L3.41421 0ZM2.41421 4.24268L1 5.65689L6.65685 11.3137L8.07107 9.89953L2.41421 4.24268Z" />
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/qs_media_background.xml b/packages/SystemUI/res/drawable/qs_media_background.xml
index e79c9a4..80db3be 100644
--- a/packages/SystemUI/res/drawable/qs_media_background.xml
+++ b/packages/SystemUI/res/drawable/qs_media_background.xml
@@ -19,4 +19,4 @@
     systemui:rippleMinSize="30dp"
     systemui:rippleMaxSize="135dp"
     systemui:highlight="15"
-    systemui:cornerRadius="@dimen/qs_media_corner_radius" />
\ No newline at end of file
+    systemui:cornerRadius="?android:attr/dialogCornerRadius" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_media.xml b/packages/SystemUI/res/drawable/stat_sys_media.xml
new file mode 100644
index 0000000..d48db7b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_media.xml
@@ -0,0 +1,31 @@
+<!--
+  ~ 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.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M5,7.81l0,8.38l6,-4.19z"
+      android:fillColor="#000000"/>
+  <path
+      android:pathData="M13,8h2v8h-2z"
+      android:fillColor="#000000"/>
+  <path
+      android:pathData="M17,8h2v8h-2z"
+      android:fillColor="#000000"/>
+</vector>
diff --git a/packages/SystemUI/res/layout-land/auth_credential_password_view.xml b/packages/SystemUI/res/layout-land/auth_credential_password_view.xml
index d89f329..da76c8d 100644
--- a/packages/SystemUI/res/layout-land/auth_credential_password_view.xml
+++ b/packages/SystemUI/res/layout-land/auth_credential_password_view.xml
@@ -40,7 +40,7 @@
         android:layout_height="wrap_content"
         style="@style/TextAppearance.AuthCredential.Description"/>
 
-    <EditText
+    <ImeAwareEditText
         android:id="@+id/lockPassword"
         android:layout_width="208dp"
         android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout-land/global_screenshot_preview.xml b/packages/SystemUI/res/layout-land/global_screenshot_preview.xml
new file mode 100644
index 0000000..b1f4cb7
--- /dev/null
+++ b/packages/SystemUI/res/layout-land/global_screenshot_preview.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/global_screenshot_preview"
+    android:layout_width="wrap_content"
+    android:layout_height="@dimen/global_screenshot_x_scale"
+    android:layout_gravity="center"
+    android:layout_marginStart="@dimen/screenshot_offset_x"
+    android:layout_marginBottom="@dimen/screenshot_offset_y"
+    android:scaleType="fitStart"
+    android:elevation="@dimen/screenshot_preview_elevation"
+    android:visibility="gone"
+    android:background="@drawable/screenshot_rounded_corners"
+    android:adjustViewBounds="true"
+    android:contentDescription="@string/screenshot_preview_description"
+    app:layout_constraintBottom_toBottomOf="parent"
+    app:layout_constraintStart_toStartOf="parent"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/bubble_overflow_view.xml b/packages/SystemUI/res/layout/bubble_overflow_view.xml
index 1ed1f07..1218fba 100644
--- a/packages/SystemUI/res/layout/bubble_overflow_view.xml
+++ b/packages/SystemUI/res/layout/bubble_overflow_view.xml
@@ -30,9 +30,8 @@
 
     <TextView
         android:id="@+id/bubble_view_name"
-        android:fontFamily="@*android:string/config_bodyFontFamily"
-        android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body2"
-        android:textColor="?android:attr/textColorSecondary"
+        android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+        android:textSize="13sp"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:maxLines="1"
diff --git a/packages/SystemUI/res/layout/controls_dialog_pin.xml b/packages/SystemUI/res/layout/controls_dialog_pin.xml
index 832c48e..170b32b 100644
--- a/packages/SystemUI/res/layout/controls_dialog_pin.xml
+++ b/packages/SystemUI/res/layout/controls_dialog_pin.xml
@@ -26,6 +26,7 @@
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:minHeight="48dp"
+      android:longClickable="false"
       android:inputType="numberPassword" />
   <CheckBox
       android:id="@+id/controls_pin_use_alpha"
diff --git a/packages/SystemUI/res/layout/controls_icon.xml b/packages/SystemUI/res/layout/controls_icon.xml
index cc46ced..12bc5f6 100644
--- a/packages/SystemUI/res/layout/controls_icon.xml
+++ b/packages/SystemUI/res/layout/controls_icon.xml
@@ -19,8 +19,8 @@
 
 <ImageView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="28dp"
-    android:layout_height="28dp"
+    android:layout_width="24dp"
+    android:layout_height="24dp"
     android:scaleType="fitCenter"
-    android:layout_marginLeft="2dp"
-    android:layout_marginRight="2dp" />
+    android:layout_marginLeft="5dp"
+    android:layout_marginRight="5dp" />
diff --git a/packages/SystemUI/res/layout/controls_no_favorites.xml b/packages/SystemUI/res/layout/controls_no_favorites.xml
index 4128230..1b24ee9 100644
--- a/packages/SystemUI/res/layout/controls_no_favorites.xml
+++ b/packages/SystemUI/res/layout/controls_no_favorites.xml
@@ -24,11 +24,10 @@
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical"
-      android:paddingTop="40dp"
-      android:paddingBottom="40dp"
-      android:layout_marginLeft="10dp"
-      android:layout_marginRight="10dp"
-      android:layout_marginTop="@dimen/controls_top_margin"
+      android:paddingVertical="@dimen/controls_setup_vertical_padding"
+      android:layout_marginLeft="@dimen/global_actions_side_margin"
+      android:layout_marginRight="@dimen/global_actions_side_margin"
+      android:layout_marginTop="@dimen/controls_setup_top_margin"
       android:background="@drawable/control_no_favorites_background">
 
     <LinearLayout
@@ -37,7 +36,7 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center"
         android:orientation="horizontal"
-        android:paddingBottom="8dp" />
+        android:layout_marginBottom="16dp" />
 
     <TextView
         style="@style/TextAppearance.ControlSetup.Title"
diff --git a/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml
index 477ec6a..99b9ced 100644
--- a/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml
@@ -14,57 +14,39 @@
      limitations under the License.
 -->
 
-<!-- RelativeLayouts have an issue enforcing minimum heights, so just
-     work around this for now with LinearLayouts. -->
-<LinearLayout
+<com.android.systemui.globalactions.GlobalActionsItem
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="0dp"
     android:layout_weight="1"
-    android:layout_height="wrap_content"
-    android:gravity="center"
-    android:paddingTop="@dimen/global_actions_grid_item_vertical_margin"
-    android:paddingBottom="@dimen/global_actions_grid_item_vertical_margin"
+    android:layout_height="98dp"
+    android:gravity="bottom|center_horizontal"
+    android:orientation="vertical"
+    android:paddingTop="12dp"
+    android:paddingBottom="12dp"
     android:paddingLeft="@dimen/global_actions_grid_item_side_margin"
     android:paddingRight="@dimen/global_actions_grid_item_side_margin"
     android:layout_marginRight="@dimen/control_base_item_margin"
     android:layout_marginLeft="@dimen/control_base_item_margin"
     android:stateListAnimator="@anim/control_state_list_animator"
     android:background="@drawable/control_background">
-    <LinearLayout
-        android:layout_width="@dimen/global_actions_grid_item_width"
-        android:layout_height="@dimen/global_actions_grid_item_height"
-        android:gravity="top|center_horizontal"
-        android:orientation="vertical">
         <ImageView
             android:id="@*android:id/icon"
-            android:layout_width="@dimen/global_actions_grid_item_icon_width"
-            android:layout_height="@dimen/global_actions_grid_item_icon_height"
-            android:layout_marginTop="@dimen/global_actions_grid_item_icon_top_margin"
-            android:layout_marginBottom="@dimen/global_actions_grid_item_icon_bottom_margin"
-            android:layout_marginLeft="@dimen/global_actions_grid_item_icon_side_margin"
-            android:layout_marginRight="@dimen/global_actions_grid_item_icon_side_margin"
+            android:layout_width="20dp"
+            android:layout_height="20dp"
+            android:layout_marginBottom="14dp"
             android:scaleType="centerInside"
-            android:tint="@color/control_default_foreground" />
-
+            android:tint="@color/control_primary_text" />
         <TextView
             android:id="@*android:id/message"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:ellipsize="marquee"
+            android:ellipsize="end"
             android:marqueeRepeatLimit="marquee_forever"
-            android:singleLine="true"
+            android:maxLines="2"
+            android:textSize="12sp"
             android:gravity="center"
-            android:textSize="12dp"
-            android:textColor="@color/control_default_foreground"
+            android:textColor="@color/control_primary_text"
+            android:breakStrategy="high_quality"
+            android:hyphenationFrequency="full"
             android:textAppearance="?android:attr/textAppearanceSmall" />
-
-        <TextView
-            android:visibility="gone"
-            android:id="@*android:id/status"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:gravity="center"
-            android:textColor="@color/control_default_foreground"
-            android:textAppearance="?android:attr/textAppearanceSmall" />
-    </LinearLayout>
-</LinearLayout>
+</com.android.systemui.globalactions.GlobalActionsItem>
diff --git a/packages/SystemUI/res/layout/global_actions_grid_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_v2.xml
index e4e9d29..7d45de3f 100644
--- a/packages/SystemUI/res/layout/global_actions_grid_v2.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid_v2.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/global_actions_container"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -43,41 +44,50 @@
     </LinearLayout>
   </com.android.systemui.globalactions.GlobalActionsFlatLayout>
 
+  <androidx.constraintlayout.widget.ConstraintLayout
+      android:id="@+id/global_actions_lock_message_container"
+      android:layout_width="match_parent"
+      android:layout_height="match_parent"
+      android:visibility="gone">
+    <TextView
+        android:id="@+id/global_actions_lock_message"
+        style="@style/TextAppearance.Control.Title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="@dimen/global_actions_side_margin"
+        android:drawablePadding="12dp"
+        android:gravity="center"
+        android:text="@string/global_action_lock_message"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintVertical_bias="0.35"/>
+  </androidx.constraintlayout.widget.ConstraintLayout>
+
   <com.android.systemui.globalactions.MinHeightScrollView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
-      android:paddingBottom="@dimen/global_actions_grid_container_shadow_offset"
-      android:layout_marginBottom="@dimen/global_actions_grid_container_negative_shadow_offset"
       android:orientation="vertical"
-      android:scrollbars="none"
-  >
+      android:scrollbars="none">
+
     <LinearLayout
         android:id="@+id/global_actions_grid_root"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:clipChildren="false"
         android:orientation="vertical"
-        android:clipToPadding="false"
-    >
-      <LinearLayout
-          android:id="@+id/global_actions_panel"
+        android:clipToPadding="false">
+
+      <FrameLayout
+          android:id="@+id/global_actions_wallet"
           android:layout_width="match_parent"
-          android:layout_height="wrap_content"
-          android:orientation="vertical"
-      >
-        <FrameLayout
-            android:id="@+id/global_actions_panel_container"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-        />
-      </LinearLayout>
+          android:layout_height="wrap_content"/>
 
       <LinearLayout
           android:id="@+id/global_actions_controls"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
-          android:orientation="vertical"
-      />
+          android:orientation="vertical"/>
+
     </LinearLayout>
   </com.android.systemui.globalactions.MinHeightScrollView>
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/global_screenshot.xml b/packages/SystemUI/res/layout/global_screenshot.xml
index 1dbb38d..d469e0f 100644
--- a/packages/SystemUI/res/layout/global_screenshot.xml
+++ b/packages/SystemUI/res/layout/global_screenshot.xml
@@ -71,21 +71,7 @@
         android:elevation="@dimen/screenshot_preview_elevation"
         android:background="@drawable/screenshot_rounded_corners"
         android:adjustViewBounds="true"/>
-    <ImageView
-        android:id="@+id/global_screenshot_preview"
-        android:layout_width="@dimen/global_screenshot_x_scale"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:layout_marginStart="@dimen/screenshot_offset_x"
-        android:layout_marginBottom="@dimen/screenshot_offset_y"
-        android:scaleType="fitEnd"
-        android:elevation="@dimen/screenshot_preview_elevation"
-        android:visibility="gone"
-        android:background="@drawable/screenshot_rounded_corners"
-        android:adjustViewBounds="true"
-        android:contentDescription="@string/screenshot_preview_description"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toStartOf="parent"/>
+    <include layout="@layout/global_screenshot_preview"/>
     <FrameLayout
         android:id="@+id/global_screenshot_dismiss_button"
         android:layout_width="@dimen/screenshot_dismiss_button_tappable_size"
diff --git a/packages/SystemUI/res/layout/global_screenshot_action_chip.xml b/packages/SystemUI/res/layout/global_screenshot_action_chip.xml
index e4ae7c1..46396e3 100644
--- a/packages/SystemUI/res/layout/global_screenshot_action_chip.xml
+++ b/packages/SystemUI/res/layout/global_screenshot_action_chip.xml
@@ -20,23 +20,29 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_marginEnd="@dimen/screenshot_action_chip_margin_right"
+    android:paddingVertical="@dimen/screenshot_action_chip_margin_vertical"
     android:layout_gravity="center"
-    android:paddingVertical="@dimen/screenshot_action_chip_padding_vertical"
-    android:background="@drawable/action_chip_background"
-    android:alpha="0.0"
-    android:gravity="center">
-    <ImageView
-        android:id="@+id/screenshot_action_chip_icon"
-        android:layout_width="@dimen/screenshot_action_chip_icon_size"
-        android:layout_height="@dimen/screenshot_action_chip_icon_size"
-        android:layout_marginStart="@dimen/screenshot_action_chip_padding_start"
-        android:layout_marginEnd="@dimen/screenshot_action_chip_padding_middle"/>
-    <TextView
-        android:id="@+id/screenshot_action_chip_text"
+    android:gravity="center"
+    android:alpha="0.0">
+    <LinearLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginEnd="@dimen/screenshot_action_chip_padding_end"
-        android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
-        android:textSize="@dimen/screenshot_action_chip_text_size"
-        android:textColor="@color/global_screenshot_button_text"/>
+        android:paddingVertical="@dimen/screenshot_action_chip_padding_vertical"
+        android:background="@drawable/action_chip_background"
+        android:gravity="center">
+        <ImageView
+            android:id="@+id/screenshot_action_chip_icon"
+            android:layout_width="@dimen/screenshot_action_chip_icon_size"
+            android:layout_height="@dimen/screenshot_action_chip_icon_size"
+            android:layout_marginStart="@dimen/screenshot_action_chip_padding_start"
+            android:layout_marginEnd="@dimen/screenshot_action_chip_padding_middle"/>
+        <TextView
+            android:id="@+id/screenshot_action_chip_text"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="@dimen/screenshot_action_chip_padding_end"
+            android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+            android:textSize="@dimen/screenshot_action_chip_text_size"
+            android:textColor="@color/global_screenshot_button_text"/>
+    </LinearLayout>
 </com.android.systemui.screenshot.ScreenshotActionChip>
diff --git a/packages/SystemUI/res/layout/global_screenshot_preview.xml b/packages/SystemUI/res/layout/global_screenshot_preview.xml
new file mode 100644
index 0000000..e6295f5
--- /dev/null
+++ b/packages/SystemUI/res/layout/global_screenshot_preview.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2011 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.
+  -->
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/global_screenshot_preview"
+    android:layout_width="@dimen/global_screenshot_x_scale"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:layout_marginStart="@dimen/screenshot_offset_x"
+    android:layout_marginBottom="@dimen/screenshot_offset_y"
+    android:scaleType="fitEnd"
+    android:elevation="@dimen/screenshot_preview_elevation"
+    android:visibility="gone"
+    android:background="@drawable/screenshot_rounded_corners"
+    android:adjustViewBounds="true"
+    android:contentDescription="@string/screenshot_preview_description"
+    app:layout_constraintBottom_toBottomOf="parent"
+    app:layout_constraintStart_toStartOf="parent"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyguard_media_header.xml b/packages/SystemUI/res/layout/keyguard_media_header.xml
index 20ec10c..a520719 100644
--- a/packages/SystemUI/res/layout/keyguard_media_header.xml
+++ b/packages/SystemUI/res/layout/keyguard_media_header.xml
@@ -45,109 +45,4 @@
         android:layout_height="match_parent"
     />
 
-    <!-- Layout for media controls. -->
-    <LinearLayout
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/keyguard_media_view"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal"
-        android:gravity="center"
-        android:padding="16dp"
-    >
-        <ImageView
-            android:id="@+id/album_art"
-            android:layout_width="@dimen/qs_media_album_size"
-            android:layout_height="@dimen/qs_media_album_size"
-            android:layout_marginRight="16dp"
-            android:layout_weight="0"
-        />
-
-        <!-- Media information -->
-        <LinearLayout
-            android:orientation="vertical"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-        >
-            <LinearLayout
-                android:orientation="horizontal"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:gravity="center"
-            >
-                <com.android.internal.widget.CachingIconView
-                    android:id="@+id/icon"
-                    android:layout_width="16dp"
-                    android:layout_height="16dp"
-                    android:layout_marginEnd="5dp"
-                />
-                <TextView
-                    android:id="@+id/app_name"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:textSize="14sp"
-                    android:singleLine="true"
-                />
-            </LinearLayout>
-
-            <!-- Song name -->
-            <TextView
-                android:id="@+id/header_title"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:singleLine="true"
-                android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
-                android:textSize="18sp"
-                android:paddingBottom="6dp"
-                android:gravity="center"/>
-
-            <!-- Artist name -->
-            <TextView
-                android:id="@+id/header_artist"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:fontFamily="@*android:string/config_bodyFontFamily"
-                android:textSize="14sp"
-                android:singleLine="true"
-            />
-        </LinearLayout>
-
-        <!-- Controls -->
-        <LinearLayout
-            android:id="@+id/media_actions"
-            android:orientation="horizontal"
-            android:layoutDirection="ltr"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:gravity="center"
-            android:layout_gravity="center"
-        >
-            <ImageButton
-                style="@style/MediaPlayer.Button"
-                android:layout_width="48dp"
-                android:layout_height="48dp"
-                android:gravity="center"
-                android:visibility="gone"
-                android:id="@+id/action0"
-            />
-            <ImageButton
-                style="@style/MediaPlayer.Button"
-                android:layout_width="48dp"
-                android:layout_height="48dp"
-                android:gravity="center"
-                android:visibility="gone"
-                android:id="@+id/action1"
-            />
-            <ImageButton
-                style="@style/MediaPlayer.Button"
-                android:layout_width="48dp"
-                android:layout_height="48dp"
-                android:gravity="center"
-                android:visibility="gone"
-                android:id="@+id/action2"
-            />
-        </LinearLayout>
-    </LinearLayout>
-
 </com.android.systemui.statusbar.notification.stack.MediaHeaderView>
diff --git a/packages/SystemUI/res/layout/media_carousel.xml b/packages/SystemUI/res/layout/media_carousel.xml
index 149446c..03e7467 100644
--- a/packages/SystemUI/res/layout/media_carousel.xml
+++ b/packages/SystemUI/res/layout/media_carousel.xml
@@ -16,20 +16,22 @@
   -->
 
 <!-- Carousel for media controls -->
-<HorizontalScrollView
+<com.android.systemui.media.UnboundHorizontalScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:padding="@dimen/qs_media_padding"
     android:scrollbars="none"
-    android:visibility="gone"
+    android:clipChildren="false"
+    android:clipToPadding="false"
     >
     <LinearLayout
         android:id="@+id/media_carousel"
-        android:layout_width="match_parent"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="horizontal"
+        android:clipChildren="false"
+        android:clipToPadding="false"
         >
         <!-- QSMediaPlayers will be added here dynamically -->
     </LinearLayout>
-</HorizontalScrollView>
+</com.android.systemui.media.UnboundHorizontalScrollView>
diff --git a/packages/SystemUI/res/layout/partial_conversation_info.xml b/packages/SystemUI/res/layout/partial_conversation_info.xml
index 2401dfb..a261114 100644
--- a/packages/SystemUI/res/layout/partial_conversation_info.xml
+++ b/packages/SystemUI/res/layout/partial_conversation_info.xml
@@ -144,25 +144,36 @@
         android:clipToPadding="false"
         android:orientation="vertical">
 
-        <LinearLayout
+        <com.android.systemui.statusbar.notification.row.ButtonLinearLayout
+            android:id="@+id/settings_link"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:clipChildren="false"
-            android:clipToPadding="false"
-            android:orientation="horizontal">
-            <ImageView
-                android:layout_height="wrap_content"
-                android:layout_width="wrap_content"
-                android:contentDescription="@null"
-                android:src="@drawable/ic_info"
-                android:tint="?android:attr/textColorPrimary"
-                android:layout_marginEnd="8dp"/>
-            <TextView
-                android:id="@+id/non_configurable_text"
+            android:padding="@dimen/notification_importance_button_padding"
+            android:clickable="true"
+            android:focusable="true"
+            android:background="@drawable/notification_guts_priority_button_bg"
+            android:orientation="vertical">
+
+            <LinearLayout
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                style="@style/TextAppearance.NotificationImportanceChannelGroup" />
-        </LinearLayout>
+                android:clipChildren="false"
+                android:clipToPadding="false"
+                android:orientation="horizontal">
+                <ImageView
+                    android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:contentDescription="@null"
+                    android:src="@drawable/ic_info"
+                    android:tint="?android:attr/textColorPrimary"
+                    android:layout_marginEnd="8dp"/>
+                <TextView
+                    android:id="@+id/non_configurable_text"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    style="@style/TextAppearance.NotificationImportanceChannelGroup" />
+            </LinearLayout>
+        </com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
 
         <RelativeLayout
             android:id="@+id/bottom_buttons"
diff --git a/packages/SystemUI/res/layout/pip_menu_activity.xml b/packages/SystemUI/res/layout/pip_menu_activity.xml
index ee0bd14..179e8fe 100644
--- a/packages/SystemUI/res/layout/pip_menu_activity.xml
+++ b/packages/SystemUI/res/layout/pip_menu_activity.xml
@@ -81,4 +81,13 @@
         android:src="@drawable/ic_close_white"
         android:background="?android:selectableItemBackgroundBorderless" />
 
+    <!--TODO (b/156917828): Add content description for a11y purposes?-->
+    <ImageButton
+        android:id="@+id/resize_handle"
+        android:layout_width="@dimen/pip_action_size"
+        android:layout_height="@dimen/pip_action_size"
+        android:layout_gravity="top|start"
+        android:padding="@dimen/pip_action_padding"
+        android:src="@drawable/pip_resize_handle"
+        android:background="?android:selectableItemBackgroundBorderless" />
 </FrameLayout>
diff --git a/packages/SystemUI/res/layout/qqs_media_panel.xml b/packages/SystemUI/res/layout/qqs_media_panel.xml
deleted file mode 100644
index 2e86732..0000000
--- a/packages/SystemUI/res/layout/qqs_media_panel.xml
+++ /dev/null
@@ -1,90 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2019 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
-  -->
-
-<!-- Layout for QQS media controls -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/qqs_media_controls"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical"
-    android:gravity="center"
-    android:paddingTop="16dp"
-    android:paddingLeft="16dp"
-    android:paddingRight="16dp"
-    android:paddingBottom="12dp"
-    android:background="@drawable/qs_media_background"
-    >
-    <!-- Top line: icon + song name -->
-    <LinearLayout
-        android:orientation="horizontal"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:clipChildren="false"
-        android:gravity="center"
-        android:layout_marginBottom="12dp"
-        >
-        <com.android.internal.widget.CachingIconView
-            android:id="@+id/icon"
-            android:layout_width="14dp"
-            android:layout_height="14dp"
-            android:layout_marginEnd="5dp"
-        />
-        <TextView
-            android:id="@+id/header_title"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
-            android:singleLine="true"
-        />
-    </LinearLayout>
-
-    <!-- Bottom section: controls -->
-    <LinearLayout
-        android:id="@+id/media_actions"
-        android:orientation="horizontal"
-        android:layoutDirection="ltr"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:gravity="center"
-        >
-        <ImageButton
-            style="@style/MediaPlayer.Button"
-            android:layout_width="48dp"
-            android:layout_height="48dp"
-            android:gravity="center"
-            android:visibility="gone"
-            android:id="@+id/action0"
-        />
-        <ImageButton
-            style="@style/MediaPlayer.Button"
-            android:layout_width="48dp"
-            android:layout_height="48dp"
-            android:gravity="center"
-            android:visibility="gone"
-            android:id="@+id/action1"
-        />
-        <ImageButton
-            style="@style/MediaPlayer.Button"
-            android:layout_width="48dp"
-            android:layout_height="48dp"
-            android:gravity="center"
-            android:visibility="gone"
-            android:id="@+id/action2"
-        />
-    </LinearLayout>
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index 0c9ce39..ebfd0a0 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -23,7 +23,6 @@
     android:layout_height="@dimen/qs_footer_height"
     android:layout_marginStart="@dimen/qs_footer_margin"
     android:layout_marginEnd="@dimen/qs_footer_margin"
-    android:elevation="4dp"
     android:background="@android:color/transparent"
     android:baselineAligned="false"
     android:clickable="false"
@@ -128,13 +127,4 @@
             </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
         </com.android.keyguard.AlphaOptimizedLinearLayout>
     </LinearLayout>
-    <View
-        android:id="@+id/qs_drag_handle_view"
-        android:layout_width="48dp"
-        android:layout_height="4dp"
-        android:layout_marginTop="8dp"
-        android:layout_marginBottom="8dp"
-        android:layout_gravity="center_horizontal|bottom"
-        android:background="@drawable/qs_footer_drag_handle" />
-
 </com.android.systemui.qs.QSFooterImpl>
diff --git a/packages/SystemUI/res/layout/qs_media_panel.xml b/packages/SystemUI/res/layout/qs_media_panel.xml
index d633ff4..bf06242 100644
--- a/packages/SystemUI/res/layout/qs_media_panel.xml
+++ b/packages/SystemUI/res/layout/qs_media_panel.xml
@@ -16,236 +16,184 @@
   -->
 
 <!-- Layout for media controls inside QSPanel carousel -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/qs_media_controls"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical"
+    android:layout_height="wrap_content"
+    android:clipChildren="false"
+    android:clipToPadding="false"
     android:gravity="center_horizontal|fill_vertical"
-    android:paddingTop="@dimen/qs_media_panel_outer_padding"
-    android:paddingBottom="@dimen/qs_media_panel_outer_padding"
-    android:background="@drawable/qs_media_background"
-    >
+    app:layoutDescription="@xml/media_scene">
+
+    <View
+        android:id="@+id/media_background"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:background="@drawable/qs_media_background"
+        app:layout_constraintEnd_toEndOf="@id/view_width"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        />
+
+    <FrameLayout
+        android:id="@+id/notification_media_progress_time"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:forceHasOverlappingRendering="false">
+        <!-- width is set to "match_parent" to avoid extra layout calls -->
+        <TextView
+            android:id="@+id/media_elapsed_time"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentLeft="true"
+            android:fontFamily="@*android:string/config_bodyFontFamily"
+            android:textColor="@color/media_primary_text"
+            android:gravity="left"
+            android:textSize="14sp" />
+
+        <TextView
+            android:id="@+id/media_total_time"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:fontFamily="@*android:string/config_bodyFontFamily"
+            android:textColor="@color/media_primary_text"
+            android:gravity="right"
+            android:textSize="14sp" />
+    </FrameLayout>
+
+    <ImageButton
+        android:id="@+id/action0"
+        style="@style/MediaPlayer.Button"
+        android:layout_width="48dp"
+        android:layout_height="48dp" />
+
+    <ImageButton
+        android:id="@+id/action1"
+        style="@style/MediaPlayer.Button"
+        android:layout_width="48dp"
+        android:layout_height="48dp" />
+
+    <ImageButton
+        android:id="@+id/action2"
+        style="@style/MediaPlayer.Button"
+        android:layout_width="52dp"
+        android:layout_height="52dp" />
+
+    <ImageButton
+        android:id="@+id/action3"
+        style="@style/MediaPlayer.Button"
+        android:layout_width="48dp"
+        android:layout_height="48dp" />
+
+    <ImageButton
+        android:id="@+id/action4"
+        style="@style/MediaPlayer.Button"
+        android:layout_width="48dp"
+        android:layout_height="48dp" />
+
+    <!-- Album Art -->
+    <ImageView
+        android:id="@+id/album_art"
+        android:layout_width="@dimen/qs_media_album_size"
+        android:layout_height="@dimen/qs_media_album_size" />
+
+    <!-- Seamless Output Switcher -->
+    <LinearLayout
+        android:id="@+id/media_seamless"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:background="@*android:drawable/media_seamless_background"
+        android:orientation="horizontal"
+        android:forceHasOverlappingRendering="false"
+        android:paddingLeft="12dp"
+        android:paddingTop="6dp"
+        android:paddingRight="12dp"
+        android:paddingBottom="6dp">
+
+        <ImageView
+            android:id="@+id/media_seamless_image"
+            android:layout_width="@dimen/qs_seamless_icon_size"
+            android:layout_height="@dimen/qs_seamless_icon_size"
+            android:layout_marginRight="8dp"
+            android:tint="@color/media_primary_text"
+            android:src="@*android:drawable/ic_media_seamless" />
+
+        <TextView
+            android:id="@+id/media_seamless_text"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:fontFamily="@*android:string/config_bodyFontFamily"
+            android:singleLine="true"
+            android:text="@*android:string/ext_media_seamless_action"
+            android:textColor="@color/media_primary_text"
+            android:textSize="14sp" />
+    </LinearLayout>
+
+    <!-- Seek Bar -->
+    <SeekBar
+        android:id="@+id/media_progress_bar"
+        style="@android:style/Widget.ProgressBar.Horizontal"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:clickable="true"
+        android:maxHeight="3dp"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp"
+        android:thumbTint="@color/media_primary_text"
+        android:progressTint="@color/media_seekbar_progress"
+        android:progressBackgroundTint="@color/media_disabled"
+        android:splitTrack="false" />
+
+    <!-- App name -->
+    <TextView
+        android:id="@+id/app_name"
+        android:textColor="@color/media_primary_text"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:textSize="14sp" />
+
+    <!-- Song name -->
+    <TextView
+        android:id="@+id/header_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+        android:singleLine="true"
+        android:textColor="@color/media_primary_text"
+        android:textSize="18sp" />
+
+    <!-- Artist name -->
+    <TextView
+        android:id="@+id/header_artist"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:fontFamily="@*android:string/config_bodyFontFamily"
+        android:singleLine="true"
+        android:textColor="@color/media_primary_text"
+        android:textSize="14sp" />
+
+    <com.android.internal.widget.CachingIconView
+        android:id="@+id/icon"
+        android:tint="@color/media_primary_text"
+        android:layout_width="16dp"
+        android:layout_height="16dp" />
 
     <!-- Buttons to remove this view when no longer needed -->
     <include
         layout="@layout/qs_media_panel_options"
-        android:visibility="gone"/>
+        android:visibility="gone"
+        app:layout_constraintEnd_toEndOf="@id/view_width"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
 
-    <LinearLayout
-        android:id="@+id/media_guts"
+    <androidx.constraintlayout.widget.Guideline
+        android:id="@+id/view_width"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
         android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-        <!-- Header section -->
-        <LinearLayout
-            android:orientation="horizontal"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="@dimen/qs_media_panel_outer_padding"
-            android:paddingStart="@dimen/qs_media_panel_outer_padding"
-            android:paddingEnd="16dp"
-        >
-
-            <ImageView
-                android:id="@+id/album_art"
-                android:layout_width="@dimen/qs_media_album_size"
-                android:layout_height="@dimen/qs_media_album_size"
-                android:layout_marginRight="16dp"
-                android:layout_weight="0"
-            />
-
-            <LinearLayout
-                android:orientation="vertical"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-            >
-                <LinearLayout
-                    android:orientation="horizontal"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:gravity="center"
-                >
-                    <com.android.internal.widget.CachingIconView
-                        android:id="@+id/icon"
-                        android:layout_width="16dp"
-                        android:layout_height="16dp"
-                        android:layout_marginEnd="5dp"
-                    />
-                    <TextView
-                        android:id="@+id/app_name"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:textSize="14sp"
-                        android:singleLine="true"
-                    />
-                </LinearLayout>
-
-                <!-- Song name -->
-                <TextView
-                    android:id="@+id/header_title"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:singleLine="true"
-                    android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
-                    android:textSize="18sp"
-                    android:paddingBottom="6dp"
-                    android:gravity="center"/>
-
-                <!-- Artist name -->
-                <TextView
-                    android:id="@+id/header_artist"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:fontFamily="@*android:string/config_bodyFontFamily"
-                    android:textSize="14sp"
-                    android:singleLine="true"
-                />
-            </LinearLayout>
-
-            <!-- Output chip -->
-            <LinearLayout
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:visibility="gone"
-                android:paddingTop="6dp"
-                android:paddingBottom="6dp"
-                android:paddingLeft="12dp"
-                android:paddingRight="12dp"
-                android:gravity="center"
-                android:id="@+id/media_seamless"
-                android:background="@*android:drawable/media_seamless_background"
-                android:layout_weight="1"
-                android:forceHasOverlappingRendering="false"
-            >
-                <ImageView
-                    android:layout_width="@dimen/qs_seamless_icon_size"
-                    android:layout_height="@dimen/qs_seamless_icon_size"
-                    android:src="@*android:drawable/ic_media_seamless"
-                    android:layout_marginRight="8dp"
-                    android:id="@+id/media_seamless_image"
-                />
-                <TextView
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:fontFamily="@*android:string/config_bodyFontFamily"
-                    android:text="@*android:string/ext_media_seamless_action"
-                    android:textSize="14sp"
-                    android:id="@+id/media_seamless_text"
-                    android:singleLine="true"
-                />
-            </LinearLayout>
-        </LinearLayout>
-
-        <!-- Seek Bar -->
-        <SeekBar
-            android:id="@+id/media_progress_bar"
-            style="@android:style/Widget.ProgressBar.Horizontal"
-            android:clickable="true"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:maxHeight="3dp"
-            android:paddingTop="24dp"
-            android:paddingBottom="24dp"
-            android:layout_marginBottom="-24dp"
-            android:layout_marginTop="-24dp"
-            android:splitTrack="false"
-        />
-
-        <FrameLayout
-            android:id="@+id/notification_media_progress_time"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingStart="@dimen/qs_media_panel_outer_padding"
-            android:paddingEnd="@dimen/qs_media_panel_outer_padding"
-            android:layout_marginBottom="10dp"
-            android:layout_gravity="center"
-            >
-            <!-- width is set to "match_parent" to avoid extra layout calls -->
-            <TextView
-                android:id="@+id/media_elapsed_time"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_alignParentLeft="true"
-                android:fontFamily="@*android:string/config_bodyFontFamily"
-                android:textSize="14sp"
-                android:gravity="left"
-            />
-            <TextView
-                android:id="@+id/media_total_time"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:fontFamily="@*android:string/config_bodyFontFamily"
-                android:layout_alignParentRight="true"
-                android:textSize="14sp"
-                android:gravity="right"
-            />
-        </FrameLayout>
-
-        <!-- Controls -->
-        <LinearLayout
-            android:id="@+id/media_actions"
-            android:orientation="horizontal"
-            android:layoutDirection="ltr"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingStart="@dimen/qs_media_panel_outer_padding"
-            android:paddingEnd="@dimen/qs_media_panel_outer_padding"
-            android:gravity="center"
-            >
-            <ImageButton
-                style="@style/MediaPlayer.Button"
-                android:layout_width="48dp"
-                android:layout_height="48dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:gravity="center"
-                android:visibility="gone"
-                android:id="@+id/action0"
-            />
-            <ImageButton
-                style="@style/MediaPlayer.Button"
-                android:layout_width="48dp"
-                android:layout_height="48dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:gravity="center"
-                android:visibility="gone"
-                android:id="@+id/action1"
-            />
-            <ImageButton
-                style="@style/MediaPlayer.Button"
-                android:layout_width="52dp"
-                android:layout_height="52dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:gravity="center"
-                android:visibility="gone"
-                android:id="@+id/action2"
-            />
-            <ImageButton
-                style="@style/MediaPlayer.Button"
-                android:layout_width="48dp"
-                android:layout_height="48dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:gravity="center"
-                android:visibility="gone"
-                android:id="@+id/action3"
-            />
-            <ImageButton
-                style="@style/MediaPlayer.Button"
-                android:layout_width="48dp"
-                android:layout_height="48dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:gravity="center"
-                android:visibility="gone"
-                android:id="@+id/action4"
-            />
-        </LinearLayout>
-    </LinearLayout>
-</LinearLayout>
+        app:layout_constraintGuide_begin="300dp" />
+</androidx.constraintlayout.motion.widget.MotionLayout>
diff --git a/packages/SystemUI/res/layout/qs_media_panel_options.xml b/packages/SystemUI/res/layout/qs_media_panel_options.xml
index 46655e7..e72c0e8 100644
--- a/packages/SystemUI/res/layout/qs_media_panel_options.xml
+++ b/packages/SystemUI/res/layout/qs_media_panel_options.xml
@@ -36,6 +36,7 @@
             android:layout_height="18dp"
             android:id="@+id/remove_icon"
             android:layout_marginEnd="16dp"
+            android:tint="@color/media_primary_text"
             android:src="@drawable/ic_clear"/>
         <TextView
             android:layout_width="wrap_content"
@@ -43,6 +44,7 @@
             android:id="@+id/remove_text"
             android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
             android:singleLine="true"
+            android:textColor="@color/media_primary_text"
             android:text="@string/controls_media_close_session" />
     </LinearLayout>
     <TextView
@@ -54,5 +56,6 @@
         android:layout_gravity="end|bottom"
         android:gravity="bottom"
         android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+        android:textColor="@android:color/white"
         android:text="@string/cancel" />
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 01dfeb2..cdf8426 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -54,20 +54,32 @@
         android:layout_marginTop="@*android:dimen/quick_qs_offset_height"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginBottom="@dimen/qs_footer_height"
         android:elevation="4dp"
         android:background="@android:color/transparent"
         android:focusable="true"
-        android:accessibilityTraversalBefore="@android:id/edit"
-    />
+        android:accessibilityTraversalBefore="@android:id/edit">
+        <include layout="@layout/qs_footer_impl" />
+    </com.android.systemui.qs.QSPanel>
 
     <include layout="@layout/quick_status_bar_expanded_header" />
 
-    <include layout="@layout/qs_footer_impl" />
-
     <include android:id="@+id/qs_detail" layout="@layout/qs_detail" />
 
     <include android:id="@+id/qs_customize" layout="@layout/qs_customize_panel"
         android:visibility="gone" />
 
+    <FrameLayout
+        android:id="@+id/qs_drag_handle_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:elevation="4dp"
+        android:paddingBottom="5dp">
+        <View
+            android:layout_width="46dp"
+            android:layout_height="3dp"
+            android:background="@drawable/qs_footer_drag_handle" />
+    </FrameLayout>
+
+
 </com.android.systemui.qs.QSContainerImpl>
diff --git a/packages/SystemUI/res/layout/qs_tile_detail_text.xml b/packages/SystemUI/res/layout/qs_tile_detail_text.xml
deleted file mode 100644
index bcbf826..0000000
--- a/packages/SystemUI/res/layout/qs_tile_detail_text.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2019 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.
--->
-
-<!-- use 'dp' instead of 'sp' as we do not want the text to increase
-     if the user scales the font size -->
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_gravity="bottom|center_horizontal"
-    android:text="..."
-    android:textSize="16dp"
-    android:fontFamily="@*android:string/config_headlineFontFamily"
-    android:singleLine="true"
-    android:visibility="gone"
-    android:paddingBottom="@dimen/qs_tile_detail_padding"
-    android:clickable="false"
-    android:focusable="false" />
-
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index e99b917..9a7c344 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -20,7 +20,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/header"
     android:layout_width="match_parent"
-    android:layout_height="@*android:dimen/quick_qs_total_height"
+    android:layout_height="wrap_content"
     android:layout_gravity="@integer/notification_panel_layout_gravity"
     android:background="@android:color/transparent"
     android:baselineAligned="false"
@@ -29,6 +29,7 @@
     android:clipToPadding="false"
     android:paddingTop="0dp"
     android:paddingEnd="0dp"
+    android:paddingBottom="10dp"
     android:paddingStart="0dp"
     android:elevation="4dp" >
 
@@ -45,8 +46,6 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_below="@id/quick_qs_status_icons"
-        android:layout_marginStart="@dimen/qs_header_tile_margin_horizontal"
-        android:layout_marginEnd="@dimen/qs_header_tile_margin_horizontal"
         android:accessibilityTraversalAfter="@+id/date_time_group"
         android:accessibilityTraversalBefore="@id/expand_indicator"
         android:clipChildren="false"
@@ -54,15 +53,6 @@
         android:focusable="true"
         android:importantForAccessibility="yes" />
 
-    <com.android.systemui.statusbar.AlphaOptimizedImageView
-        android:id="@+id/qs_detail_header_progress"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentBottom="true"
-        android:alpha="0"
-        android:background="@color/qs_detail_progress_track"
-        android:src="@drawable/indeterminate_anim"/>
-
     <TextView
         android:id="@+id/header_debug_info"
         android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index e341f56..0a7c404 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Maak skermkiekie toe"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Skermkiekievoorskou"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Skermopnemer"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Verwerk tans skermopname"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Deurlopende kennisgewing vir \'n skermopnamesessie"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Begin opname?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Terwyl dit opneem, kan die Android-stelsel enige sensitiewe inligting wat op jou skerm sigbaar is of wat op jou toestel gespeel word, vasvang. Dit sluit wagwoorde, betalinginligting, foto\'s, boodskappe en oudio in."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Vee alles uit"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Bestuur"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Geskiedenis"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Inkomend"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Stil kennisgewings"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Opletkennisgewings"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Gesprekke"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Titelloos"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Tik om hierdie program te herbegin en maak volskerm oop."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Instellings vir <xliff:g id="APP_NAME">%1$s</xliff:g>-borrels"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Oorloop"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Voeg terug op stapel"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Bestuur"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> vanaf <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> van <xliff:g id="APP_NAME">%2$s</xliff:g> en <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> meer af"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> kontroles bygevoeg.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> kontrole bygevoeg.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Verwyder"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"As gunsteling gemerk"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"As gunsteling gemerk; posisie <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"As gunsteling ontmerk"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"gunsteling"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"ontmerk as gunsteling"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Skuif na posisie <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Kontroles"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Kies kontroles om toegang vanaf die aan/af-kieslys te kry"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Hou en sleep om kontroles te herrangskik"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 85e06c3..364a0a8 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ቅጽበታዊ ገጽ እይታን አሰናብት"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"የቅጽበታዊ ገጽ ዕይታ ቅድመ-ዕይታ"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"የማያ መቅጃ"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"የማያ ገጽ ቀረጻን በማሰናዳት ላይ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ለአንድ የማያ ገጽ ቀረጻ ክፍለ-ጊዜ በመካሄድ ያለ ማሳወቂያ"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"መቅረጽ ይጀመር?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"እየቀረጹ ሳለ የAndroid ስርዓት በማያ ገጽዎ ላይ የሚታይ ወይም በመሣሪያዎ ላይ የሚጫወት ማንኛውም ሚስጥራዊነት ያለው መረጃን መያዝ ይችላል። ይህ የይለፍ ቃላትን፣ የክፍያ መረጃን፣ ፎቶዎችን፣ መልዕክቶችን እና ኦዲዮን ያካትታል።"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"ሁሉንም አጽዳ"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"ያቀናብሩ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ታሪክ"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"ገቢ"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"ጸጥ ያሉ ማሳወቂያዎች"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"የማንቂያ ማሳወቂያዎች"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"ውይይቶች"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"ርዕስ የለም"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"ይህን መተግበሪያ እንደገና ለማስጀመር መታ ያድርጉ እና ወደ ሙሉ ማያ ገጽ ይሂዱ።"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"ቅንብሮች ለ <xliff:g id="APP_NAME">%1$s</xliff:g> አረፋዎች"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"ትርፍ ፍሰት"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"ወደ ቁልል መልሰው ያክሉ"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"ያቀናብሩ"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ከ<xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ከ <xliff:g id="APP_NAME">%2$s</xliff:g> እና <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> ተጨማሪ"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> ቁጥጥሮች ታክለዋል።</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> ቁጥጥሮች ታክለዋል።</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"ተወግዷል"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"ተወዳጅ የተደረገ"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ተወዳጅ ተደርጓል፣ አቋም <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ተወዳጅ አልተደረገም"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"ተወዳጅ"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"ተወዳጅ አታድርግ"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"ወደ ቦታ <xliff:g id="NUMBER">%d</xliff:g> ውሰድ"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"መቆጣጠሪያዎች"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"ከኃይል ምናሌ ላይ ለመድረስ መቆጣጠሪያዎችን ይምረጡ"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"መቆጣጠሪያዎችን ዳግም ለማስተካከል ይያዙ እና ይጎትቱ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index e6388e9..67cf15c 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"إغلاق لقطة الشاشة"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"معاينة لقطة الشاشة"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"مسجّل الشاشة"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"جارٍ معالجة تسجيل الشاشة"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"إشعار مستمر لجلسة تسجيل شاشة"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"هل تريد بدء التسجيل؟"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"‏أثناء التسجيل، يمكن أن يسجّل نظام Android أي معلومات حساسة مرئية على شاشتك أو يتم تشغيلها على جهازك. ويشمل ذلك كلمات المرور ومعلومات الدفع والصور والرسائل والمقاطع الصوتية."</string>
@@ -523,8 +522,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"محو الكل"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"إدارة"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"السجلّ"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"الإشعارات الواردة"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"الإشعارات الصامتة"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"إشعارات التنبيه"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"المحادثات"</string>
@@ -724,7 +722,7 @@
     <string name="notification_alert_title" msgid="7629202599338071971">"إشعار مصحوب بتنبيه صوتي"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"فقاعة"</string>
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"يساعدك هذا الإشعار على التركيز بدون صوت أو اهتزاز."</string>
-    <string name="notification_channel_summary_default" msgid="3539949463907902037">"يلفت هذا الإشعار انتباهك باستخدام الصوت والاهتزاز."</string>
+    <string name="notification_channel_summary_default" msgid="3539949463907902037">"يلفت هذا الإشعار انتباهك من خلال صوت أو اهتزاز."</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"يلفت هذا الإشعار انتباهك باستخدام الصوت والاهتزاز. تظهر المحادثات من <xliff:g id="APP_NAME">%1$s</xliff:g> كفقاعات تلقائيًا."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"يلفِت هذا الإشعار انتباهك لهذا المحتوى باستخدام اختصار عائم."</string>
     <string name="notification_channel_summary_priority" msgid="7415770044553264622">"تظهر كفقاعة محادثة في أعلى قسم المحادثات"</string>
@@ -1011,10 +1009,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"بلا عنوان"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"انقر لإعادة تشغيل هذا التطبيق والانتقال إلى وضع ملء الشاشة."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"إعدادات فقاعات المحادثات على <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"القائمة الكاملة"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"إضافة دعم إلى الحزم"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"إدارة"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> من <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> من <xliff:g id="APP_NAME">%2$s</xliff:g> و<xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> أيضًا"</string>
@@ -1055,6 +1051,13 @@
       <item quantity="other">تمت إضافة <xliff:g id="NUMBER_1">%s</xliff:g> عنصر تحكّم.</item>
       <item quantity="one">تمت إضافة عنصر تحكّم واحد (<xliff:g id="NUMBER_0">%s</xliff:g>).</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"تمت الإزالة"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"تمت الإضافة إلى المفضّلة"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"تمت الإضافة إلى المفضّلة، الموضع <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"تمت الإزالة من المفضّلة"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"إضافة إلى المُفضلة"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"إزالة من المفضّلة"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"نقل إلى الموضع <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"عناصر التحكّم"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"اختيار عناصر التحكّم التي تريد الوصول إليها من قائمة التشغيل"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"اضغط مع الاستمرار واسحب لإعادة ترتيب عناصر التحكّم."</string>
@@ -1063,10 +1066,8 @@
     <string name="controls_favorite_load_error" msgid="2533215155804455348">"تعذّر تحميل قائمة كل عناصر التحكّم."</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"غير ذلك"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"إضافة إلى أدوات التحكم بالجهاز"</string>
-    <!-- no translation found for controls_dialog_ok (2770230012857881822) -->
-    <skip />
-    <!-- no translation found for controls_dialog_message (342066938390663844) -->
-    <skip />
+    <string name="controls_dialog_ok" msgid="2770230012857881822">"إضافة"</string>
+    <string name="controls_dialog_message" msgid="342066938390663844">"اقتراح من <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"تم تعديل عناصر التحكّم."</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"يشتمل رقم التعريف الشخصي على أحرف أو رموز."</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"إثبات ملكية <xliff:g id="DEVICE">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index df62189c..edd8a85 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"স্ক্ৰীনশ্বট অগ্ৰাহ্য কৰক"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"স্ক্ৰীনশ্বটৰ পূৰ্বদৰ্শন"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"স্ক্ৰীন ৰেকৰ্ডাৰ"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রীন ৰেকৰ্ডিঙৰ প্ৰক্ৰিয়াকৰণ হৈ আছে"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রীণ ৰেকৰ্ডিং ছেশ্বন চলি থকা সময়ত পোৱা জাননী"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"ৰেকৰ্ড কৰা আৰম্ভ কৰিবনে?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"ৰেকৰ্ড কৰি থাকোঁতে, Android Systemএ আপোনাৰ স্ক্রীনত দৃশ্যমান হোৱা অথবা আপোনাৰ ডিভাইচত প্লে’ হৈ থকা যিকোনো সংবেনদশীল তথ্য কেপচাৰ কৰিব পাৰে। এইটোত পাছৱর্ড, পৰিশোধৰ তথ্য, ফট’, বার্তাসমূহ আৰু অডিঅ’ অন্তর্ভুক্ত হয়।"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"সকলো মচক"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"পৰিচালনা"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ইতিহাস"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"অন্তৰ্গামী"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"নীৰৱ জাননীসমূহ"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"সতৰ্কতামূলক জাননীসমূহ"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"বাৰ্তালাপ"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"কোনো শিৰোনাম নাই"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"এপ্‌টো ৰিষ্টাৰ্ট কৰক আৰু পূৰ্ণ স্ক্ৰীণ ব্যৱহাৰ কৰক।"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ bubblesৰ ছেটিংসমূহ"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"অভাৰফ্ল’"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"ষ্টেকত পুনৰ যোগ দিয়ক"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"পৰিচালনা কৰক"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g>ৰ পৰা <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> আৰু<xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>টাৰ পৰা <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> টা নিয়ন্ত্ৰণ যোগ কৰা হ’ল।</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> টা নিয়ন্ত্ৰণ যোগ কৰা হ’ল।</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"আঁতৰোৱা হ’ল"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"প্ৰিয় হিচাপে চিহ্নিত কৰা হ’ল"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"প্ৰিয় হিচাপে চিহ্নিত কৰা হ’ল, স্থান <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"অপ্ৰিয় হিচাপে চিহ্নিত কৰা হ’ল"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"প্ৰিয়"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"অপ্ৰিয়"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g> নম্বৰ অৱস্থানলৈ স্থানান্তৰিত কৰক"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"নিয়ন্ত্ৰণসমূহ"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"পাৱাৰ মেনুখনৰ পৰা এক্সেছ পাবলৈ নিয়ন্ত্ৰণসমূহ বাছনি কৰক"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"নিয়ন্ত্ৰণসমূহ পুনৰ সজাবলৈ ধৰি ৰাখক আৰু টানি আনি এৰক"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index f09a6d6..68e82a1 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Ekran şəklini ötürün"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekran şəklinə önbaxış"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekran Yazıcısı"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran çəkilişi emal edilir"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekranın video çəkimi ərzində silinməyən bildiriş"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Yazmağa başlanılsın?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Yazarkən Android Sistemi ekranınızda görünən və ya cihazınızda göstərilən istənilən həssas məlumatı qeydə ala bilər. Buraya parollar, ödəniş məlumatı, fotolar, mesajlar və audio daxildir."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Hamısını silin"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"İdarə edin"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Tarixçə"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Gələn"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Səssiz bildirişlər"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Xəbərdarlıq bildirişləri"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Söhbətlər"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Başlıq yoxdur"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Bu tətbiqi sıfırlayaraq tam ekrana keçmək üçün klikləyin."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> yumrucuqları üçün ayarlar"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Kənara çıxma"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Yenidən dəstəyə əlavə edin"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"İdarə edin"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> tətbiqindən <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> tətbiqindən <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> və daha <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> qabarcıq"</string>
@@ -1017,7 +1013,7 @@
     <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Söhbət bölməsinin yuxarısında göstərilir"</string>
     <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Kilid ekranında profil şəkli göstərilir"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Tətbiqlərin üzərində üzən qabarcıq kimi görünəcək"</string>
-    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Narahat Etməyin rejimi bölünsün"</string>
+    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Narahat Etməyin rejimində göstərilsin"</string>
     <string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Anladım"</string>
     <string name="magnification_overlay_title" msgid="6584179429612427958">"Böyütmə Üst-üstə Düşən Pəncərəsi"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"Böyütmə Pəncərəsi"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> nizamlayıcı əlavə edilib.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> nizamlayıcı əlavə edilib.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Silinib"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Sevimlilərə əlavə edilib"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Sevimlilərə əlavə edilib, sıra: <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Sevimlilərdən silinib"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"sevimli"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"sevimlilərdən silin"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g> mövqeyinə keçirin"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Nizamlayıcılar"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Enerji menyusundan daxil olacağınız nizamlayıcıları seçin"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Nizamlayıcıları yenidən tənzimləmək üçün tutub sürüşdürün"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index b9af5e9..bdeca46 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Odbacite snimak ekrana"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pregled snimka ekrana"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Snimač ekrana"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađujemo video snimka ekrana"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Obaveštenje o sesiji snimanja ekrana je aktivno"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Želite da započnete snimanje?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Tokom snimanja Android sistem može da snimi osetljive informacije koje su vidljive na ekranu ili koje se puštaju na uređaju. To obuhvata lozinke, informacije o plaćanju, slike, poruke i zvuk."</string>
@@ -514,8 +513,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Obriši sve"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Upravljajte"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Istorija"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Dolazno"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Nečujna obaveštenja"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Obaveštenja koja privlače pažnju"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Konverzacije"</string>
@@ -996,10 +994,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Dodirnite da biste restartovali aplikaciju i prešli u režim celog ekrana."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Podešavanja za <xliff:g id="APP_NAME">%1$s</xliff:g> oblačiće"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Preklapanje"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Dodaj ponovo u grupu"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Upravljajte"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> iz aplikacije <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> iz aplikacije <xliff:g id="APP_NAME">%2$s</xliff:g> i još <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1019,10 +1015,10 @@
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigacija sistema je ažurirana. Da biste uneli izmene, idite u Podešavanja."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Idite u Podešavanja da biste ažurirali navigaciju sistema"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje pripravnosti"</string>
-    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Prikazuju se u vrhu odeljka za konverzacije"</string>
-    <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Prikazuju sliku profila na zaključanom ekranu"</string>
+    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Prikazuje se u vrhu odeljka za konverzacije"</string>
+    <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Prikazuje sliku profila na zaključanom ekranu"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Prikazuju se plutajući oblačići preko aplikacija"</string>
-    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Ometaju podešavanje Ne uznemiravaj"</string>
+    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Ometa podešavanje Ne uznemiravaj"</string>
     <string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Važi"</string>
     <string name="magnification_overlay_title" msgid="6584179429612427958">"Preklopni prozor za uvećanje"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"Prozor za uvećanje"</string>
@@ -1037,6 +1033,13 @@
       <item quantity="few"><xliff:g id="NUMBER_1">%s</xliff:g> kontrole su dodate.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> kontrola je dodato.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Uklonjeno"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Označeno je kao omiljeno"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Označeno je kao omiljeno, <xliff:g id="NUMBER">%d</xliff:g>. pozicija"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Uklonjeno je iz omiljenih"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"označili kao omiljeno"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"uklonili iz omiljenih"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Premestite na <xliff:g id="NUMBER">%d</xliff:g>. poziciju"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Kontrole"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Odaberite kontrole kojima ćete pristupati iz menija napajanja"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Zadržite i prevucite da biste promenili raspored kontrola"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 0f3f537..ae90a46 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Адхіліць здымак экрана"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Перадпрагляд здымка экрана"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Запіс экрана"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Апрацоўваецца запіс экрана"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Бягучае апавяшчэнне для сеанса запісу экрана"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Пачаць запіс?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Падчас запісу сістэма Android можа збіраць канфідэнцыяльную інфармацыю, якая адлюстроўваецца на экране вашай прылады ці прайграецца на ёй. Гэта могуць быць паролі, плацежная інфармацыя, фота, паведамленні і аўдыяданыя."</string>
@@ -517,8 +516,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Ачысціць усё"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Кіраваць"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Гісторыя"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Уваходныя"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Апавяшчэнні без гуку"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Апавяшчэнні з абвесткамі"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Размовы"</string>
@@ -701,7 +699,7 @@
     <string name="notification_channel_unsilenced" msgid="94878840742161152">"Гэтыя апавяшчэнні будуць паказвацца з гукам"</string>
     <string name="inline_blocking_helper" msgid="2891486013649543452">"Звычайна вы адхіляеце гэтыя апавяшчэнні. \nПаказваць іх?"</string>
     <string name="inline_done_button" msgid="6043094985588909584">"Гатова"</string>
-    <string name="inline_ok_button" msgid="603075490581280343">"Ужыць"</string>
+    <string name="inline_ok_button" msgid="603075490581280343">"Прымяніць"</string>
     <string name="inline_keep_showing" msgid="8736001253507073497">"Працягваць паказваць гэтыя апавяшчэнні?"</string>
     <string name="inline_stop_button" msgid="2453460935438696090">"Спыніць апавяшчэнні"</string>
     <string name="inline_deliver_silently_button" msgid="2714314213321223286">"Дастаўляць бязгучна"</string>
@@ -1001,10 +999,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Без назвы"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Націсніце, каб перазапусціць гэту праграму і перайсці ў поўнаэкранны рэжым."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Налады ўсплывальных апавяшчэнняў у праграме \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Дадатковае меню"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Зноў дадаць у стос"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Кіраваць"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ад праграмы \"<xliff:g id="APP_NAME">%2$s</xliff:g>\""</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ад праграмы \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" і яшчэ <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1025,9 +1021,9 @@
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Перайдзіце ў Налады, каб абнавіць параметры навігацыі ў сістэме"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Рэжым чакання"</string>
     <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Паказваюцца ўверсе раздзела размоў"</string>
-    <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Паказваюць выяву профілю на экране блакіроўкі"</string>
+    <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Паказваюць відарыс профілю на экране блакіроўкі"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Паказваюцца як рухомыя апавяшчэнні паверх праграм"</string>
-    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Не распаўсюджваюцца на рэжым \"Не турбаваць\""</string>
+    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Паказваюцца ў рэжыме \"Не турбаваць\""</string>
     <string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Зразумела"</string>
     <string name="magnification_overlay_title" msgid="6584179429612427958">"Акно-накладка з павелічэннем"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"Акно павелічэння"</string>
@@ -1043,6 +1039,13 @@
       <item quantity="many">Дададзена <xliff:g id="NUMBER_1">%s</xliff:g> элементаў кіравання.</item>
       <item quantity="other">Дададзена <xliff:g id="NUMBER_1">%s</xliff:g> элемента кіравання.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Выдалена"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Дададзена ў абранае"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Дададзена ў абранае, пазіцыя <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Выдалена з абранага"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"у абранае"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"выдаліць з абранага"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Перамясціць у пазіцыю <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Сродкі кіравання"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Выберыце элементы кіравання, да якіх вы хочаце мець доступ з меню сілкавання"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Каб змяніць парадак элементаў кіравання, утрымлівайце і перацягвайце іх"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 50781e1..1416e90 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Отхвърляне на екранната снимка"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Визуализация на екранната снимка"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Запис на екрана"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Записът на екрана се обработва"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущо известие за сесия за записване на екрана"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Да се стартира ли записът?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"По време на записване системата Android може да прихване поверителна информация, която е показана на екрана или възпроизвеждана на устройството ви. Това включва пароли, данни за плащане, снимки, съобщения и аудио."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Изчистване на всички"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Управление"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"История"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Входящи"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Беззвучни известия"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Известия за сигнализиране"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Разговори"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Няма заглавие"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Докоснете, за да рестартирате това приложение в режим на цял екран."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Настройки за балончетата за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Препълване"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Добавяне обратно към стека"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Управление"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> от <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"„<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>“ от<xliff:g id="APP_NAME">%2$s</xliff:g> и още <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">Добавени са <xliff:g id="NUMBER_1">%s</xliff:g> контроли.</item>
       <item quantity="one">Добавена е <xliff:g id="NUMBER_0">%s</xliff:g> контрола.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Премахнато"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Означено като любимо"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Означено като любимо – позиция <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Не е означено като любимо"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"за означаване като любимо"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"за премахване на означаването като любимо"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Преместете на позиция <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Контроли"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Избиране на контроли, които да са достъпни в менюто за захранване"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Задръжте и плъзнете, за да пренаредите контролите"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 50a88f25..74cbfda 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"স্ক্রিনশট বাতিল করুন"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"স্ক্রিনশটের প্রিভিউ"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"স্ক্রিন রেকর্ডার"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রিন রেকর্ডিং প্রসেস হচ্ছে"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রিন রেকর্ডিং সেশন চলার বিজ্ঞপ্তি"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"রেকর্ডিং শুরু করবেন?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"রেকর্ড করার সময়, আপনার স্ক্রিনে দেখানো বা ডিভাইসে চালানো যেকোনও ধরনের সংবেদনশীল তথ্য Android সিস্টেম ক্যাপচার করতে পারে। এর মধ্যে পাসওয়ার্ড, পেমেন্টের তথ্য, ফটো, মেসেজ এবং অডিও সম্পর্কিত তথ্য থাকে।"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"সবকিছু সাফ করুন"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"পরিচালনা করুন"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ইতিহাস"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"ইনকামিং"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"নীরব বিজ্ঞপ্তি"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"বিজ্ঞপ্তি সংক্রান্ত সতর্কতা"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"কথোপকথন"</string>
@@ -969,7 +967,7 @@
     <string name="running_foreground_services_title" msgid="5137313173431186685">"পটভূমিতে অ্যাপ চালু আছে"</string>
     <string name="running_foreground_services_msg" msgid="3009459259222695385">"ব্যাটারি এবং ডেটার ব্যবহারের বিশদ বিবরণের জন্য ট্যাপ করুন"</string>
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"মোবাইল ডেটা বন্ধ করবেন?"</string>
-    <string name="mobile_data_disable_message" msgid="8604966027899770415">"আপনি <xliff:g id="CARRIER">%s</xliff:g>-এর মাধ্যমে ডেটা অথবা ইন্টারনেট অ্যাক্সেস করতে পারবেন না। শুধুমাত্র ওয়াই-ফাইয়ের মাধ্যমেই ইন্টারনেট অ্যাক্সেস করা যাবে।"</string>
+    <string name="mobile_data_disable_message" msgid="8604966027899770415">"আপনি \'<xliff:g id="CARRIER">%s</xliff:g>\'-এর মাধ্যমে ডেটা অথবা ইন্টারনেট অ্যাক্সেস করতে পারবেন না। শুধুমাত্র ওয়াই-ফাইয়ের মাধ্যমেই ইন্টারনেট অ্যাক্সেস করা যাবে।"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"আপনার পরিষেবা প্রদানকারী"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"একটি অ্যাপ কোনও অনুমোদনের অনুরোধকে ঢেকে দিচ্ছে, তাই সেটিংস থেকে আপনার প্রতিক্রিয়া যাচাই করা যাচ্ছে না।"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> অ্যাপটিকে <xliff:g id="APP_2">%2$s</xliff:g> এর অংশ দেখানোর অনুমতি দেবেন?"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"কোনও শীর্ষক নেই"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"এই অ্যাপ রিস্টার্ট করতে ট্যাপ করুন ও ফুল-স্ক্রিন ব্যবহার করুন।"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> বাবলের জন্য সেটিংস"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"ওভারফ্লো"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"স্ট্যাকে আবার যোগ করুন"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"ম্যানেজ করা"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> অ্যাপ থেকে <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> অ্যাপ এবং আরও <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>টি থেকে <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g>টি কন্ট্রোল যোগ করা হয়েছে।</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g>টি কন্ট্রোল যোগ করা হয়েছে।</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"সরানো হয়েছে"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"পছন্দসই হিসেবে চিহ্নিত করেছেন"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"পছন্দসই হিসেবে চিহ্নিত করেছেন, অবস্থান <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"পছন্দসই থেকে সরিয়ে দিয়েছেন"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"পছন্দসই"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"পছন্দসই থেকে সরান"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g> অবস্থানে সরান"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"নিয়ন্ত্রণ"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"যেসব কন্ট্রোল অ্যাক্সেস করতে চান সেগুলি পাওয়ার মেনু থেকে বেছে নিন"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"কন্ট্রোলগুলিকে আবার সাজানোর জন্য ধরে রেখে টেনে আনুন"</string>
@@ -1039,10 +1042,8 @@
     <string name="controls_favorite_load_error" msgid="2533215155804455348">"সব কন্ট্রোলের তালিকা লোড করা যায়নি।"</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"অন্য"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"ডিভাইস কন্ট্রোলে যোগ করুন"</string>
-    <!-- no translation found for controls_dialog_ok (2770230012857881822) -->
-    <skip />
-    <!-- no translation found for controls_dialog_message (342066938390663844) -->
-    <skip />
+    <string name="controls_dialog_ok" msgid="2770230012857881822">"যোগ করুন"</string>
+    <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> সাজেস্ট করেছে"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"কন্ট্রোল আপডেট করা হয়েছে"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"পিন-এ অক্ষর বা চিহ্ন রয়েছে"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> যাচাই করুন"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index d334f3c..a062d1a 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -89,10 +89,10 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Odbacite snimak ekrana"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pregled snimka ekrana"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Snimač ekrana"</string>
-    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrada snimanja zaslona"</string>
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađivanje snimka ekrana"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Obavještenje za sesiju snimanja ekrana je u toku"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Započeti snimanje?"</string>
-    <string name="screenrecord_description" msgid="1123231719680353736">"Prilikom snimanja, Android sistem može snimiti sve osjetljive informacije koje su vidljive na vašem ekranu ili koje reproducirate na uređaju. To uključuje lozinke, informacije za plaćanje, fotografije, poruke i zvuk."</string>
+    <string name="screenrecord_description" msgid="1123231719680353736">"Prilikom snimanja, sistem Android može snimiti sve osjetljive informacije koje su vidljive na vašem ekranu ili koje reproducirate na uređaju. To uključuje lozinke, informacije za plaćanje, fotografije, poruke i zvuk."</string>
     <string name="screenrecord_audio_label" msgid="6183558856175159629">"Snimi zvučni zapis"</string>
     <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Zvuk uređaja"</string>
     <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Zvuk s vašeg uređaja, naprimjer muzika, pozivi i melodije zvona"</string>
@@ -589,7 +589,7 @@
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"Postavke zvuka"</string>
     <string name="accessibility_volume_expand" msgid="7653070939304433603">"Proširi"</string>
     <string name="accessibility_volume_collapse" msgid="2746845391013829996">"Suzi"</string>
-    <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatski titluj medije"</string>
+    <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatski titlovi za medije"</string>
     <string name="accessibility_volume_close_odi_captions_tip" msgid="8924753283621160480">"Savjet u titlu"</string>
     <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Preklapanje titlova"</string>
     <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"omogući"</string>
@@ -707,20 +707,20 @@
     <string name="inline_minimize_button" msgid="1474436209299333445">"Minimiziraj"</string>
     <string name="inline_silent_button_silent" msgid="525243786649275816">"Nečujno"</string>
     <string name="inline_silent_button_stay_silent" msgid="2129254868305468743">"Ostani u nečujnom načinu rada"</string>
-    <string name="inline_silent_button_alert" msgid="5705343216858250354">"Upozorenja"</string>
+    <string name="inline_silent_button_alert" msgid="5705343216858250354">"Zvučni"</string>
     <string name="inline_silent_button_keep_alerting" msgid="6577845442184724992">"Nastavi upozoravati"</string>
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Isključi obavještenja"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Nastaviti prikazivanje obavještenja iz ove aplikacije?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Nečujno"</string>
-    <string name="notification_alert_title" msgid="7629202599338071971">"Upozorenja"</string>
+    <string name="notification_alert_title" msgid="7629202599338071971">"Zvučni"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Oblačić"</string>
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"Pomaže vam da se koncentrirate bez zvuka ili vibracije."</string>
-    <string name="notification_channel_summary_default" msgid="3539949463907902037">"Privlači vašu pažnju pomoću zvuka ili vibracije."</string>
+    <string name="notification_channel_summary_default" msgid="3539949463907902037">"Privlači vam pažnju pomoću zvuka ili vibracije."</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"Privlači vašu pažnju pomoću zvuka ili vibracije. Razgovori iz oblačića u aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> kao zadana opcija."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Privlači vašu pažnju pomoću plutajuće prečice do ovog sadržaja."</string>
     <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Prikazuje se na vrhu odjeljka za razgovor u vidu oblačića."</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Postavke"</string>
-    <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
+    <string name="notification_priority_title" msgid="2079708866333537093">"Prioritetni"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> ne podržava postavke za određeni razgovor"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"Nema nedavnih oblačića"</string>
     <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Nedavni i odbačeni oblačići će se pojaviti ovdje"</string>
@@ -749,7 +749,7 @@
     <string name="notification_conversation_favorite" msgid="1905240206975921907">"Važan razgovor"</string>
     <string name="notification_conversation_unfavorite" msgid="181383708304763807">"Nije važan razgovor"</string>
     <string name="notification_conversation_mute" msgid="268951550222925548">"Bez zvuka"</string>
-    <string name="notification_conversation_unmute" msgid="2692255619510896710">"Upozorenja"</string>
+    <string name="notification_conversation_unmute" msgid="2692255619510896710">"Zvučni"</string>
     <string name="notification_conversation_bubble" msgid="2242180995373949022">"Prikaži oblačić"</string>
     <string name="notification_conversation_unbubble" msgid="6908427185031099868">"Ukloni oblačiće"</string>
     <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Dodaj na početni ekran"</string>
@@ -974,7 +974,7 @@
     <string name="running_foreground_services_title" msgid="5137313173431186685">"Aplikacije koje rade u pozadini"</string>
     <string name="running_foreground_services_msg" msgid="3009459259222695385">"Dodirnite za detalje o potrošnji baterije i prijenosa podataka"</string>
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Isključiti prijenos podataka na mobilnoj mreži?"</string>
-    <string name="mobile_data_disable_message" msgid="8604966027899770415">"Nećete imati pristup podacima ili internetu putem mobilnog operatera <xliff:g id="CARRIER">%s</xliff:g>. Internet će biti dostupan samo putem WiFi mreže."</string>
+    <string name="mobile_data_disable_message" msgid="8604966027899770415">"Nećete imati pristup podacima ni internetu putem mobilnog operatera <xliff:g id="CARRIER">%s</xliff:g>. Internet će biti dostupan samo putem WiFi mreže."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"vaš operater"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Postavke ne mogu potvrditi vaš odgovor jer aplikacija zaklanja zahtjev za odobrenje."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Dozvoliti aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> prikazivanje isječaka aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
@@ -996,8 +996,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Dodirnite da ponovo pokrenete ovu aplikaciju i aktivirate prikaz preko cijelog ekrana."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Postavke za oblačiće aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Dodatno"</string>
-    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Dodajte natrag u nizove"</string>
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Preklapanje"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Dodaj nazad u grupu"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Upravljaj"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> od aplikacije <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"Obavještenje <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> aplikacije <xliff:g id="APP_NAME">%2$s</xliff:g> i još <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1017,7 +1017,7 @@
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Navigiranje sistemom je ažurirano. Da izvršite promjene, idite u Postavke."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Idite u Postavke da ažurirate navigiranje sistemom"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje mirovanja"</string>
-    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Prikazuje se iznad odjeljka za razgovor"</string>
+    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Prikazuje se na vrhu odjeljka za razgovor"</string>
     <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Prikazuje sliku profila na zaključanom ekranu"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Izgleda kao plutajući oblačić iznad aplikacija"</string>
     <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Prekida način rada Ne ometaj"</string>
@@ -1035,6 +1035,13 @@
       <item quantity="few">Dodane su <xliff:g id="NUMBER_1">%s</xliff:g> kontrole.</item>
       <item quantity="other">Dodano je <xliff:g id="NUMBER_1">%s</xliff:g> kontrola.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Uklonjeno"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Dodano u omiljeno"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Dodano u omiljeno, pozicija <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Uklonjeno iz omiljenog"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"dodate u omiljeno"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"uklonite iz omiljenog"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Premjesti na poziciju <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Kontrole"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Izaberite kontrole za pristup iz menija napajanja"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Držite i prevucite da preuredite kontrole"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index ed3bb8d..12b8230 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Ignora la captura de pantalla"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Previsualització de la captura de pantalla"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Gravació de pantalla"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processant gravació de pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificació en curs d\'una sessió de gravació de la pantalla"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Vols iniciar la gravació?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Quan graves contingut, el sistema Android pot capturar qualsevol informació sensible que es mostri a la pantalla o que es reprodueixi al dispositiu. Això inclou les contrasenyes, la informació de pagament, les fotos, els missatges i l\'àudio."</string>
@@ -511,9 +510,8 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Esborra-ho tot"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gestiona"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
-    <string name="notification_section_header_gentle" msgid="3044910806569985386">"Notificacions silencioses"</string>
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Entrants"</string>
+    <string name="notification_section_header_gentle" msgid="3044910806569985386">"Notificacions silenciades"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Notificacions d\'alerta"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Converses"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Esborra totes les notificacions silencioses"</string>
@@ -702,7 +700,7 @@
     <string name="inline_block_button" msgid="479892866568378793">"Bloqueja"</string>
     <string name="inline_keep_button" msgid="299631874103662170">"Continua rebent"</string>
     <string name="inline_minimize_button" msgid="1474436209299333445">"Minimitza"</string>
-    <string name="inline_silent_button_silent" msgid="525243786649275816">"Silencioses"</string>
+    <string name="inline_silent_button_silent" msgid="525243786649275816">"Silenci"</string>
     <string name="inline_silent_button_stay_silent" msgid="2129254868305468743">"Continua silenciant"</string>
     <string name="inline_silent_button_alert" msgid="5705343216858250354">"Alertes"</string>
     <string name="inline_silent_button_keep_alerting" msgid="6577845442184724992">"Continua avisant-me"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sense títol"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Toca per reiniciar l\'aplicació i passar a pantalla completa."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Configuració de les bombolles: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Menú addicional"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Torna a afegir a la pila"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Gestiona"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de: <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> (<xliff:g id="APP_NAME">%2$s</xliff:g>) i <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> més"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">S\'han afegit <xliff:g id="NUMBER_1">%s</xliff:g> controls.</item>
       <item quantity="one">S\'ha afegit <xliff:g id="NUMBER_0">%s</xliff:g> control.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Suprimit"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Afegit als preferits"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Afegit als preferits, posició <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Suprimit dels preferits"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"afegir als preferits"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"suprimir dels preferits"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Mou a la posició <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Controls"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Selecciona els controls per accedir-hi des del menú d\'engegada"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Mantén premut i arrossega per reorganitzar els controls"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 73378dd..1d4d7c4 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Zavřít snímek obrazovky"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Náhled snímku obrazovky"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Rekordér obrazovky"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Záznam obrazovky se zpracovává"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Trvalé oznámení o relaci nahrávání"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Spustit nahrávání?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Při nahrávání může systém Android zaznamenávat citlivé údaje, které jsou viditelné na obrazovce nebo které jsou přehrávány na zařízení. Týká se to hesel, údajů o platbě, fotek, zpráv a zvuků."</string>
@@ -402,7 +401,7 @@
     <string name="quick_settings_tethering_label" msgid="5257299852322475780">"Sdílené připojení"</string>
     <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Hotspot"</string>
     <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Zapínání…"</string>
-    <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Spořič dat je zapnutý"</string>
+    <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Spořič dat zapnut"</string>
     <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
       <item quantity="few">%d zařízení</item>
       <item quantity="many">%d zařízení</item>
@@ -517,8 +516,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Smazat vše"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Spravovat"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historie"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Příchozí"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Tichá oznámení"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Oznámení s upozorněním"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Konverzace"</string>
@@ -1001,10 +999,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Bez názvu"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Klepnutím aplikaci restartujete a přejdete na režim celé obrazovky"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Nastavení bublin aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Rozbalovací nabídka"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Přidat zpět do sady"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Spravovat"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"Oznámení <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> z aplikace <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> z aplikace <xliff:g id="APP_NAME">%2$s</xliff:g> a dalších (<xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>)"</string>
@@ -1043,6 +1039,13 @@
       <item quantity="other">Bylo přidáno <xliff:g id="NUMBER_1">%s</xliff:g> ovládacích prvků.</item>
       <item quantity="one">Byl přidán <xliff:g id="NUMBER_0">%s</xliff:g> ovládací prvek.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Odstraněno"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Přidáno do oblíbených"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Přidáno do oblíbených na pozici <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Odebráno z oblíbených"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"přidáte do oblíbených"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"odeberete z oblíbených"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Přesunout na pozici <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Ovládací prvky"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Vyberte ovládací prvky, které budou zobrazeny v nabídce vypínače"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Ovládací prvky můžete uspořádat podržením a přetažením"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 88b74de..580aa7e 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Luk screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Forhåndsvisning af screenshot"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Skærmoptagelse"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skærmoptagelse"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Konstant notifikation om skærmoptagelse"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Vil du starte optagelse?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Når du optager, kan Android-systemet registrere følsomme oplysninger, der er synlige på din skærm, eller som afspilles på din enhed. Dette inkluderer adgangskoder, betalingsoplysninger, fotos, meddelelser og lyd."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Ryd alle"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Administrer"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historik"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Indgående"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Lydløse notifikationer"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Notifikationer med vibration eller lyd"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Samtaler"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Ingen titel"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Tryk for at genstarte denne app, og gå til fuld skærm."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Indstillinger for <xliff:g id="APP_NAME">%1$s</xliff:g>-bobler"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Overløb"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Føj til stak igen"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Administrer"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> fra <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> fra <xliff:g id="APP_NAME">%2$s</xliff:g> og <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> andre"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> styringselement er tilføjet.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> styringselementer er tilføjet.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Fjernet"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Angivet som favorit"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Angivet som favorit. Position <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Fjernet fra favoritter"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"markér som favorit"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"fjern fra favoritter"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Flyt til position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Betjeningselementer"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Vælg, hvilke indstillinger der skal være i menuen for afbryderknappen"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Flyt rundt på styringselementer ved at holde dem nede og trække"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index acfdd47..b2f71a8 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Screenshot schließen"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Screenshotvorschau"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Bildschirmaufzeichnung"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Bildschirmaufzeichnung…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Fortlaufende Benachrichtigung für eine Bildschirmaufzeichnung"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Aufzeichnung starten?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Beim Aufnehmen kann das Android-System vertrauliche Informationen erfassen, die auf deinem Bildschirm angezeigt oder von deinem Gerät wiedergegeben werden. Das können Passwörter, Zahlungsinformationen, Fotos, Nachrichten und Audioinhalte sein."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Alle löschen"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Verwalten"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Verlauf"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Neue Benachrichtigungen"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Lautlose Benachrichtigungen"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Laut gestellte Benachrichtigungen"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Unterhaltungen"</string>
@@ -821,7 +819,7 @@
     <string name="accessibility_long_click_tile" msgid="210472753156768705">"Einstellungen öffnen"</string>
     <string name="accessibility_status_bar_headphones" msgid="1304082414912647414">"Mit Kopfhörer verbunden"</string>
     <string name="accessibility_status_bar_headset" msgid="2699275863720926104">"Mit Headset verbunden"</string>
-    <string name="data_saver" msgid="3484013368530820763">"Datenverbrauch reduzieren"</string>
+    <string name="data_saver" msgid="3484013368530820763">"Datensparmodus"</string>
     <string name="accessibility_data_saver_on" msgid="5394743820189757731">"Datensparmodus aktiviert"</string>
     <string name="accessibility_data_saver_off" msgid="58339669022107171">"Datensparmodus deaktiviert"</string>
     <string name="switch_bar_on" msgid="1770868129120096114">"An"</string>
@@ -854,7 +852,7 @@
     <string name="right_keycode" msgid="2480715509844798438">"Rechter Keycode"</string>
     <string name="left_icon" msgid="5036278531966897006">"Linkes Symbol"</string>
     <string name="right_icon" msgid="1103955040645237425">"Rechtes Symbol"</string>
-    <string name="drag_to_add_tiles" msgid="8933270127508303672">"Zum Hinzufügen von Kacheln Kachel halten und ziehen"</string>
+    <string name="drag_to_add_tiles" msgid="8933270127508303672">"Zum Hinzufügen Kachel halten und ziehen"</string>
     <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Zum Verschieben Kachel halten und ziehen"</string>
     <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Zum Entfernen hierher ziehen"</string>
     <string name="drag_to_remove_disabled" msgid="933046987838658850">"Du brauchst mindestens <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> Kacheln"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Kein Titel"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Tippe, um die App im Vollbildmodus neu zu starten."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Einstellungen für <xliff:g id="APP_NAME">%1$s</xliff:g>-Bubbles"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Mehr anzeigen"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Wieder dem Stapel hinzufügen"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Verwalten"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> von <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> aus <xliff:g id="APP_NAME">%2$s</xliff:g> und <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> weiteren"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> Steuerelemente hinzugefügt.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> Steuerelement hinzugefügt.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Entfernt"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Zu Favoriten hinzugefügt"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Zu Favoriten hinzugefügt, Position <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Aus Favoriten entfernt"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"Zum Hinzufügen zu Favoriten"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"Zum Entfernen aus Favoriten"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Auf Position <xliff:g id="NUMBER">%d</xliff:g> verschieben"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Steuerelemente"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Karten auswählen, auf die man über das Ein-/Aus-Menü zugreifen kann"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Zum Verschieben von Steuerelementen halten und ziehen"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 1a93009..87b65f2 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -1027,6 +1027,13 @@
       <item quantity="other">Προστέθηκαν <xliff:g id="NUMBER_1">%s</xliff:g> στοιχεία ελέγχου.</item>
       <item quantity="one">Προστέθηκε <xliff:g id="NUMBER_0">%s</xliff:g> στοιχείο ελέγχου.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Καταργήθηκε"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Προστέθηκε στα αγαπημένα"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Προστέθηκε στα αγαπημένα, στη θέση <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Αφαιρέθηκε από τα αγαπημένα"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"αγαπημένο"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"μη αγαπημένο"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Μετακίνηση στη θέση <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Στοιχεία ελέγχου"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Επιλέξτε τα στοιχεία ελέγχου στα οποία θα έχετε πρόσβαση από το μενού λειτουργίας."</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Κρατήστε και σύρετε για αναδιάταξη των στοιχείων ελέγχου"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index b2a03d2..d3b51b5 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -1027,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controls added.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> control added.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Removed"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favourited"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favourited, position <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Unfavourited"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"favourite"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"unfavourite"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Move to position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Controls"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Choose controls to access from the power menu"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Hold and drag to rearrange controls"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index db9ed99..90406fa 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -1027,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controls added.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> control added.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Removed"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favourited"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favourited, position <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Unfavourited"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"favourite"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"unfavourite"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Move to position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Controls"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Choose controls to access from the power menu"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Hold and drag to rearrange controls"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index b2a03d2..d3b51b5 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -1027,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controls added.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> control added.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Removed"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favourited"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favourited, position <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Unfavourited"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"favourite"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"unfavourite"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Move to position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Controls"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Choose controls to access from the power menu"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Hold and drag to rearrange controls"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index b2a03d2..d3b51b5 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -1027,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controls added.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> control added.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Removed"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favourited"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favourited, position <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Unfavourited"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"favourite"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"unfavourite"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Move to position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Controls"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Choose controls to access from the power menu"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Hold and drag to rearrange controls"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 2b87b82..b29c5a2 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -1027,6 +1027,13 @@
       <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‏‏‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‎‏‏‎‎‎‎‏‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%s</xliff:g>‎‏‎‎‏‏‏‎ controls added.‎‏‎‎‏‎</item>
       <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‏‏‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‎‏‏‎‎‎‎‏‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%s</xliff:g>‎‏‎‎‏‏‏‎ control added.‎‏‎‎‏‎</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‏‎‏‏‏‏‏‏‏‏‎Removed‎‏‎‎‏‎"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‎‎‏‏‎‎‏‏‎‏‏‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‎Favorited‎‏‎‎‏‎"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‏‏‏‎‏‏‎‏‏‏‎‎‎‏‎‏‎Favorited, position ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‎‏‎‏‏‏‎‏‏‎‎‎‎‏‏‏‎Unfavorited‎‏‎‎‏‎"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‏‎‎‎‎‏‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‎‎‏‏‎‎‏‏‎‏‎favorite‎‏‎‎‏‎"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‏‏‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‏‎‎‏‏‏‎unfavorite‎‏‎‎‏‎"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‏‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‎‎‏‎‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‏‏‏‎‎‎‎‎Move to position ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‏‏‏‎‎‎‎‏‏‏‎‎‎‏‏‎‎‎‏‎‎‏‎‏‏‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‎‏‎‎‏‏‎‎‏‎Controls‎‏‎‎‏‎"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‏‏‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‎‎Choose controls to access from the power menu‎‏‎‎‏‎"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‎‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‏‎Hold &amp; drag to rearrange controls‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 7ef57f8..64c4d6e 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -89,10 +89,9 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Descartar captura de pantalla"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Vista previa de la captura de pantalla"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Grabadora de pantalla"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando grabación pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación constante para una sesión de grabación de pantalla"</string>
-    <string name="screenrecord_start_label" msgid="1750350278888217473">"¿Comenzar grabación?"</string>
+    <string name="screenrecord_start_label" msgid="1750350278888217473">"¿Comenzar a grabar?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Durante la grabación, el sistema de Android puede capturar la información sensible que aparezca en la pantalla o que se reproduzca en el dispositivo. Se incluyen contraseñas, información de pago, fotos, mensajes y audio."</string>
     <string name="screenrecord_audio_label" msgid="6183558856175159629">"Grabar audio"</string>
     <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio del dispositivo"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Borrar todo"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Administrar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Entrante"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Notificaciones silenciosas"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Notificaciones de alerta"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversaciones"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sin título"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Presiona para reiniciar esta app y acceder al modo de pantalla completa."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Configuración para burbujas de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Menú ampliado"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Volver a agregar a la pila"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Administrar"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de <xliff:g id="APP_NAME">%2$s</xliff:g> y <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> más"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">Se agregaron <xliff:g id="NUMBER_1">%s</xliff:g> controles.</item>
       <item quantity="one">Se agregó <xliff:g id="NUMBER_0">%s</xliff:g> control.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Quitados"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Está en favoritos"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Está en favoritos en la posición <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"No está en favoritos"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"agregar a favoritos"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"quitar de favoritos"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Mover a la posición <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Controles"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Elige los controles a los que quieres acceder desde el menú de encendido"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Mantén presionado y arrastra para reorganizar los controles"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 1c59325..0e746b1 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Cerrar captura de pantalla"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Vista previa de captura de pantalla"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Grabación de pantalla"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando grabación de pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación continua de una sesión de grabación de la pantalla"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"¿Empezar a grabar?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Mientras grabas, el sistema Android puede capturar información sensible que se muestre o se reproduzca en tu dispositivo, como contraseñas, datos de pago, fotos, mensajes y audio."</string>
@@ -400,7 +399,7 @@
     <string name="quick_settings_tethering_label" msgid="5257299852322475780">"Compartir conexión"</string>
     <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Zona Wi-Fi"</string>
     <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Activando…"</string>
-    <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Ahorro de datos: sí"</string>
+    <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Ahorro de datos activado"</string>
     <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
       <item quantity="other">%d dispositivos</item>
       <item quantity="one">%d dispositivo</item>
@@ -430,8 +429,8 @@
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"El NFC está desactivado"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"El NFC está activado"</string>
-    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Grabación de la pantalla"</string>
-    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Inicio"</string>
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Grabar pantalla"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Iniciar"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Detener"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Desliza el dedo hacia arriba para cambiar de aplicación"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Borrar todo"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gestionar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Entrantes"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Notificaciones silenciadas"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Notificaciones de alerta"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversaciones"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sin título"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Toca para reiniciar esta aplicación e ir a la pantalla completa."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Ajustes de las burbujas de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Menú adicional"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Volver a añadir a la pila"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Gestionar"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de <xliff:g id="APP_NAME">%2$s</xliff:g> y <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> más"</string>
@@ -1014,10 +1010,10 @@
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Se ha actualizado la navegación del sistema. Para hacer cambios, ve a Ajustes."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Ve a Ajustes para actualizar la navegación del sistema"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"En espera"</string>
-    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Aparecen arriba de la sección de conversaciones"</string>
-    <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Muestran imagen de perfil en pantalla de bloqueo"</string>
+    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Se muestran en la parte superior de la sección de conversaciones"</string>
+    <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Muestran tu imagen de perfil en la pantalla de bloqueo"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Aparecen como burbuja sobre las aplicaciones"</string>
-    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Interrumpen No molestar"</string>
+    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Interrumpen el modo No molestar"</string>
     <string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Entendido"</string>
     <string name="magnification_overlay_title" msgid="6584179429612427958">"Ventana de superposición de ampliación"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"Ventana de ampliación"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">Se han añadido <xliff:g id="NUMBER_1">%s</xliff:g> controles.</item>
       <item quantity="one">Se ha añadido <xliff:g id="NUMBER_0">%s</xliff:g> control.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Quitado"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Añadido a favoritos"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Añadido a favoritos (posición <xliff:g id="NUMBER">%d</xliff:g>)"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Quitado de favoritos"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"añadir a favoritos"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"quitar de favoritos"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Mover a la posición <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Controles"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Elige los controles a los que acceder desde el menú de encendido"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Mantén pulsado y arrastra un control para reubicarlo"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index dce209c0..0b44c0c 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Sule ekraanipilt"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekraanipildi eelvaade"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekraanisalvesti"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekraanisalvestuse töötlemine"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pooleli märguanne ekraanikuva salvestamise seansi puhul"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Kas alustada salvestamist?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Heli salvestamise ajal võib Androidi süsteem jäädvustada tundlikku teavet, mis on ekraanikuval nähtav või mida seadmes esitatakse. See hõlmab paroole, makseteavet, fotosid, sõnumeid ja heli."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Tühjenda kõik"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Haldamine"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Ajalugu"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Sissetulevad"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Hääletud märguanded"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Hoiatusmärguanded"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Vestlused"</string>
@@ -717,7 +715,7 @@
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Hoiab teie tähelepanu hõljuva otseteega selle sisu juurde."</string>
     <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Kuvatakse vestluste jaotise ülaosas mullina."</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Seaded"</string>
-    <string name="notification_priority_title" msgid="2079708866333537093">"Prioriteet"</string>
+    <string name="notification_priority_title" msgid="2079708866333537093">"Prioriteetne"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei toeta vestluspõhiseid seadeid"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"Hiljutisi mulle pole"</string>
     <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Siin kuvatakse hiljutised ja suletud mullid."</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Pealkiri puudub"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Puudutage rakenduse taaskäivitamiseks ja täisekraanrežiimi aktiveerimiseks."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> mullide seaded"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Ületäide"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Lisa tagasi virna"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Halda"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> rakendusest <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> rakenduselt <xliff:g id="APP_NAME">%2$s</xliff:g> ja veel <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1017,7 +1013,7 @@
     <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Kuvatakse vestluste jaotise kohal"</string>
     <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Lukustuskuval kuvatakse profiilipilt"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Kuvatakse rakenduste kohal hõljuva mullina"</string>
-    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Funktsiooni Mitte segada katkestamine"</string>
+    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Funktsioon Mitte segada katkestatakse"</string>
     <string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Selge"</string>
     <string name="magnification_overlay_title" msgid="6584179429612427958">"Suurendamisakna ülekate"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"Suurendamisaken"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">Lisati <xliff:g id="NUMBER_1">%s</xliff:g> juhtnuppu.</item>
       <item quantity="one">Lisati <xliff:g id="NUMBER_0">%s</xliff:g> juhtnupp.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Eemaldatud"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Lisatud lemmikuks"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Lisatud lemmikuks, positsioon <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Eemaldatud lemmikute hulgast"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"lisa lemmikuks"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"eemalda lemmikute hulgast"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Teisalda asendisse <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Juhtnupud"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Valige toitemenüüs saadaolevad juhtelemendid"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Juhtnuppude ümberpaigutamiseks hoidke neid all ja lohistage"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 6172462..a7d1c39 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -65,7 +65,7 @@
     <string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"Gailu honetan saioa hasita daukan erabiltzaileak ezin du aktibatu USB bidezko arazketa. Eginbide hori erabiltzeko, aldatu erabiltzaile nagusira."</string>
     <string name="wifi_debugging_title" msgid="7300007687492186076">"Hari gabeko arazketa onartu nahi duzu sare honetan?"</string>
     <string name="wifi_debugging_message" msgid="5461204211731802995">"Sarearen izena (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWifi-helbidea (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
-    <string name="wifi_debugging_always" msgid="2968383799517975155">"Onartu beti sare honetan"</string>
+    <string name="wifi_debugging_always" msgid="2968383799517975155">"Baimendu beti sare honetan"</string>
     <string name="wifi_debugging_allow" msgid="4573224609684957886">"Baimendu"</string>
     <string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"Ez da onartzen hari gabeko arazketa"</string>
     <string name="wifi_debugging_secondary_user_message" msgid="4492383073970079751">"Gailu honetan saioa hasita daukan erabiltzaileak ezin du aktibatu hari gabeko arazketa. Eginbide hori erabiltzeko, aldatu erabiltzaile nagusira."</string>
@@ -512,7 +512,7 @@
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historia"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Jasotako azkenak"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Soinurik gabeko jakinarazpenak"</string>
-    <string name="notification_section_header_alerting" msgid="3168140660646863240">"Soinua/Dar-dar egiten duten jakinarazpenak"</string>
+    <string name="notification_section_header_alerting" msgid="3168140660646863240">"Jakinarazpen ohartarazleak"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Elkarrizketak"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Garbitu soinurik gabeko jakinarazpen guztiak"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Ez molestatzeko moduak pausatu egin ditu jakinarazpenak"</string>
@@ -852,8 +852,8 @@
     <string name="right_keycode" msgid="2480715509844798438">"Eskuineko teklaren kodea"</string>
     <string name="left_icon" msgid="5036278531966897006">"Ezkerreko ikonoa"</string>
     <string name="right_icon" msgid="1103955040645237425">"Eskuineko ikonoa"</string>
-    <string name="drag_to_add_tiles" msgid="8933270127508303672">"Lauzak gehitzeko, eduki sakatuta eta arrastatu"</string>
-    <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Lauzak antolatzeko, eduki sakatuta eta arrastatu"</string>
+    <string name="drag_to_add_tiles" msgid="8933270127508303672">"Lauzak gehitzeko, eduki itzazu sakatuta, eta arrastatu"</string>
+    <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Lauzak antolatzeko, eduki itzazu sakatuta, eta arrastatu"</string>
     <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Kentzeko, arrastatu hona"</string>
     <string name="drag_to_remove_disabled" msgid="933046987838658850">"<xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> lauza behar dituzu gutxienez"</string>
     <string name="qs_edit" msgid="5583565172803472437">"Editatu"</string>
@@ -990,7 +990,7 @@
     <string name="restart_button_description" msgid="6916116576177456480">"Berrabiarazi aplikazio hau eta ezarri pantaila osoko modua."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioaren ezarpenen burbuilak"</string>
     <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Gainezkatzea"</string>
-    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Gehitu berriro sortan"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Gehitu berriro errenkadan"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Kudeatu"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> (<xliff:g id="APP_NAME">%2$s</xliff:g>)"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> aplikazioaren \"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>\" jakinarazpena, eta beste <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1027,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> kontrol-aukera gehitu dira.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> kontrol-aukera gehitu da.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Kenduta"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Gogokoetan dago"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"<xliff:g id="NUMBER">%d</xliff:g>. gogokoa da"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Ez dago gogokoetan"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"gehitu gogokoetan"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"kendu gogokoetatik"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Eraman <xliff:g id="NUMBER">%d</xliff:g>garren postura"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Kontrolatzeko aukerak"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Aukeratu itzaltzeko menutik atzitu nahi dituzun kontrolatzeko aukerak"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Kontrolatzeko aukerak antolatzeko, eduki itzazu sakatuta, eta arrastatu"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 17e3ad7..75e460f 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"رد کردن نماگرفت"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"پیش‌نمایش نماگرفت"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ضبط‌کننده صفحه‌نمایش"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"درحال پردازش ضبط صفحه‌نمایش"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"اعلان درحال انجام برای جلسه ضبط صفحه‌نمایش"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"ضبط شروع شود؟"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"‏هنگام ضبط، «سیستم Android» می‌تواند هر اطلاعات حساسی را که روی صفحه‌نمایش شما نشان داده می‌شود یا روی دستگاه شما پخش می‌شود ضبط کند. این شامل گذرواژه‌ها، اطلاعات پرداخت، عکس‌ها، پیام‌ها، و صدا می‌شود."</string>
@@ -196,7 +195,7 @@
     <string name="accessibility_data_signal_full" msgid="283507058258113551">"قدرت سیگنال داده کامل است."</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"به <xliff:g id="WIFI">%s</xliff:g> متصل شد."</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"به <xliff:g id="BLUETOOTH">%s</xliff:g> متصل شد."</string>
-    <string name="accessibility_cast_name" msgid="7344437925388773685">"متصل به <xliff:g id="CAST">%s</xliff:g>."</string>
+    <string name="accessibility_cast_name" msgid="7344437925388773685">"به <xliff:g id="CAST">%s</xliff:g> متصل شد."</string>
     <string name="accessibility_no_wimax" msgid="2014864207473859228">"‏WiMAX وجود ندارد."</string>
     <string name="accessibility_wimax_one_bar" msgid="2996915709342221412">"‏WiMAX یک نوار دارد."</string>
     <string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"‏WiMAX دو نوار دارد."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"پاک کردن همه موارد"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"مدیریت"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"سابقه"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"ورودی"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"اعلان‌های بی‌صدا"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"اعلان‌های هشداردهنده"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"مکالمه‌ها"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"بدون عنوان"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"برای بازراه‌اندازی این برنامه و تغییر به حالت تمام‌صفحه، ضربه بزنید."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"تنظیم برای ابزارک‌های اعلان <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"لبریزشده"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"افزودن برگشت به پشته"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"مدیریت"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> از <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> از <xliff:g id="APP_NAME">%2$s</xliff:g> و <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> مورد بیشتر"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> کنترل اضافه شده است.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> کنترل اضافه شده است.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"حذف شد"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"به موارد دلخواه اضافه شد"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"اضافه‌شده به موارد دلخواه، جایگاه <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"حذف‌شده از موارد دلخواه"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"افزودن به موارد دلخواه"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"حذف کردن از موارد دلخواه"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"انتقال به موقعیت <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"کنترل‌ها"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"برای دسترسی از منوی روشن/خاموش، کنترل‌ها را انتخاب کنید"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"برای تغییر دادن ترتیب کنترل‌ها، آن‌ها را نگه دارید و بکشید"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 62779904..d2c6e47 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Hylkää kuvakaappaus"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Kuvakaappauksen esikatselu"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Näytön tallentaja"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Näytön tallennusta käsitellään"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pysyvä ilmoitus näytön tallentamisesta"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Aloitetaanko tallennus?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Tallennuksen aikana Android-järjestelmä voi tallentaa mitä tahansa näytöllä näkyvää tai laitteen toistamaa arkaluontoista tietoa. Näitä tietoja ovat esimerkiksi salasanat, maksutiedot, kuvat, viestit ja äänisisältö."</string>
@@ -430,7 +429,7 @@
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC on poistettu käytöstä"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC on käytössä"</string>
-    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Näytön tallentaminen"</string>
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Tallennus"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Aloita"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Lopeta"</string>
     <string name="media_seamless_remote_device" msgid="177033467332920464">"Laite"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Poista kaikki"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Muuta asetuksia"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historia"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Saapuvat"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Hiljaiset ilmoitukset"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Ääni-ilmoitukset"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Keskustelut"</string>
@@ -715,7 +713,7 @@
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"Kiinnittää huomion äänellä tai värinällä"</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"Kiinnittää huomion äänellä tai värinällä. Näistä keskusteluista (<xliff:g id="APP_NAME">%1$s</xliff:g>) syntyy oletuksena kuplia."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Kelluva sisällön pikakuvake säilyttää huomiosi"</string>
-    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Näkyy keskusteluosion yläosassa kuplana"</string>
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Näkyy keskustelukohdan yläosassa kuplana"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Asetukset"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Tärkeä"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei tue keskustelukohtaisia asetuksia"</string>
@@ -855,7 +853,7 @@
     <string name="left_icon" msgid="5036278531966897006">"Vasen kuvake"</string>
     <string name="right_icon" msgid="1103955040645237425">"Oikea kuvake"</string>
     <string name="drag_to_add_tiles" msgid="8933270127508303672">"Lisää osioita koskettamalla pitkään ja vetämällä"</string>
-    <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Järjestele osioita koskettamalla pitkään ja vetämällä"</string>
+    <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Järjestele koskettamalla pitkään ja vetämällä"</string>
     <string name="drag_to_remove_tiles" msgid="4682194717573850385">"Poista vetämällä tähän."</string>
     <string name="drag_to_remove_disabled" msgid="933046987838658850">"<xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> kiekkoa on vähimmäismäärä"</string>
     <string name="qs_edit" msgid="5583565172803472437">"Muokkaa"</string>
@@ -968,8 +966,8 @@
     <string name="qs_dnd_replace" msgid="7712119051407052689">"Korvaa"</string>
     <string name="running_foreground_services_title" msgid="5137313173431186685">"Sovelluksia käynnissä taustalla"</string>
     <string name="running_foreground_services_msg" msgid="3009459259222695385">"Katso lisätietoja akun ja datan käytöstä napauttamalla"</string>
-    <string name="mobile_data_disable_title" msgid="5366476131671617790">"Poistetaanko mobiilidata käytöstä?"</string>
-    <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g> ei voi enää tarjota sinulle internetyhteyttä. Internetyhteys voidaan muodostaa vain Wi-Fi-verkossa."</string>
+    <string name="mobile_data_disable_title" msgid="5366476131671617790">"Laitetaanko mobiilidata pois päältä?"</string>
+    <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g> ei enää tarjoa pääsyä dataan eikä internetyhteyttä, joka on saatavilla vain Wi-Fin kautta."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"operaattorisi"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Sovellus peittää käyttöoikeuspyynnön, joten Asetukset ei voi vahvistaa valintaasi."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Saako <xliff:g id="APP_0">%1$s</xliff:g> näyttää osia sovelluksesta <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Ei nimeä"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Napauta, niin sovellus käynnistyy uudelleen ja siirtyy koko näytön tilaan."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Kuplien asetukset: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Ylivuoto"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Lisää takaisin pinoon"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Ylläpidä"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g>: <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> (<xliff:g id="APP_NAME">%2$s</xliff:g>) ja <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> muuta"</string>
@@ -1014,7 +1010,7 @@
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Järjestelmän navigointitapa vaihdettu. Voit muuttaa sitä asetuksista."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Vaihda järjestelmän navigointitapaa asetuksista"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Virransäästötila"</string>
-    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Näkyy keskusteluosion yläosassa"</string>
+    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Näkyy keskustelukohdan yläosassa"</string>
     <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Profiilikuva näkyy lukitusnäytöllä"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Näkyy kelluvana kuplana sovellusten päällä"</string>
     <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Keskeyttää Älä häiritse ‑tilan"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> säädintä lisätty</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> säädin lisätty</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Poistettu"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Lisätty suosikkeihin"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Lisätty suosikkeihin sijalle <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Poistettu suosikeista"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"suosikki"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"poista suosikeista"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Siirrä kohtaan <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Säätimet"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Valitse säätimet, joita käytetään virtavalikosta"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Järjestele säätimiä koskettamalla pitkään ja vetämällä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index b34a038..c1a1efb 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -709,7 +709,7 @@
     <string name="notification_silence_title" msgid="8608090968400832335">"Mode silencieux"</string>
     <string name="notification_alert_title" msgid="7629202599338071971">"Alertes"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bulle"</string>
-    <string name="notification_channel_summary_low" msgid="7300447764759926720">"Vous aider à vous concentrer, sans son ni vibration."</string>
+    <string name="notification_channel_summary_low" msgid="7300447764759926720">"Vous aide à vous concentrer, sans son ni vibration."</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"Attire votre attention à l\'aide de sons et de vibrations."</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"Attire votre attention à l\'aide de sons et de vibrations. Conversations des bulles de <xliff:g id="APP_NAME">%1$s</xliff:g> par défaut."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Garde votre attention à l\'aide d\'un raccourci flottant vers ce contenu."</string>
@@ -1010,7 +1010,7 @@
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"La navigation système a été mise à jour. Pour apporter des modifications, accédez au menu Paramètres."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Accédez au menu Paramètres pour mettre à jour la navigation système"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Veille"</string>
-    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Aff. dans le haut de la section des conversations"</string>
+    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Afficher dans le haut de la section des conversations"</string>
     <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Afficher la photo de profil sur l\'écran verrouillé"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Sous forme de bulle flottante, par-dessus les applis"</string>
     <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Interrompre le mode Ne pas déranger"</string>
@@ -1027,6 +1027,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> commande ajoutée.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> commandes ajoutées.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Supprimé"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Ajouté aux favoris"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ajouté aux favoris, en position <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Supprimé des favoris"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"ajouter aux favoris"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"supprimer des favoris"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Déplacer l\'élément à la position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Commandes"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Sélectionnez les commandes auxquelles vous souhaitez accéder à partir du menu de l\'interrupteur"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Maintenez le doigt sur l\'écran, puis glissez-le pour réorganiser les commandes"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7140c5b..6bcea50 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -36,7 +36,7 @@
     <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Activer l\'économiseur de batterie ?"</string>
     <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"À propos de l\'économiseur de batterie"</string>
     <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Activer"</string>
-    <string name="battery_saver_start_action" msgid="4553256017945469937">"Activer l\'économiseur de batterie ?"</string>
+    <string name="battery_saver_start_action" msgid="4553256017945469937">"Activer l\'économiseur de batterie"</string>
     <string name="status_bar_settings_settings_button" msgid="534331565185171556">"Paramètres"</string>
     <string name="status_bar_settings_wifi_button" msgid="7243072479837270946">"Wi-Fi"</string>
     <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rotation automatique de l\'écran"</string>
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Fermer la capture d\'écran"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Aperçu de la capture d\'écran"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Enregistreur d\'écran"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Enregistrement de l\'écran…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement de l\'écran"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Démarrer l\'enregistrement ?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Pendant l\'enregistrement, le système Android peut capturer toute information sensible affichée à l\'écran ou lue sur votre appareil. Ceci inclut les mots de passe, les informations de paiement, les photos, les messages et les contenus audio."</string>
@@ -102,7 +101,7 @@
     <string name="screenrecord_start" msgid="330991441575775004">"Démarrer"</string>
     <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Enregistrement de l\'écran"</string>
     <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Enregistrement de l\'écran et des contenus audio"</string>
-    <string name="screenrecord_taps_label" msgid="1595690528298857649">"Afficher les points de l\'écran touchés"</string>
+    <string name="screenrecord_taps_label" msgid="1595690528298857649">"Afficher les points touchés sur l\'écran"</string>
     <string name="screenrecord_stop_text" msgid="6549288689506057686">"Appuyez ici pour arrêter"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Arrêter"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pause"</string>
@@ -400,7 +399,7 @@
     <string name="quick_settings_tethering_label" msgid="5257299852322475780">"Partage de connexion"</string>
     <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Point d\'accès"</string>
     <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Activation…"</string>
-    <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Économ. données activé"</string>
+    <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Écon. données activé"</string>
     <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
       <item quantity="one">%d appareil</item>
       <item quantity="other">%d appareils</item>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Tout effacer"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gérer"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historique"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Notifications entrantes"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Notifications silencieuses"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Notifications d\'alerte"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversations"</string>
@@ -702,7 +700,7 @@
     <string name="inline_block_button" msgid="479892866568378793">"Bloquer"</string>
     <string name="inline_keep_button" msgid="299631874103662170">"Continuer d\'afficher les notifications"</string>
     <string name="inline_minimize_button" msgid="1474436209299333445">"Réduire"</string>
-    <string name="inline_silent_button_silent" msgid="525243786649275816">"Mode silencieux"</string>
+    <string name="inline_silent_button_silent" msgid="525243786649275816">"Silencieux"</string>
     <string name="inline_silent_button_stay_silent" msgid="2129254868305468743">"Notifications silencieuses"</string>
     <string name="inline_silent_button_alert" msgid="5705343216858250354">"Alertes"</string>
     <string name="inline_silent_button_keep_alerting" msgid="6577845442184724992">"Continuer de m\'avertir"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Appuyez pour redémarrer cette application et activer le mode plein écran."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Paramètres des bulles de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Dépassement"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Ajouter à nouveau l\'élément à la pile"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Gérer"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de l\'application <xliff:g id="APP_NAME">%2$s</xliff:g> et <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> autres"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> controls added.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> commandes ajoutées.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Supprimé"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Ajouté aux favoris"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ajouté aux favoris, en position <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Supprimé des favoris"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"ajouter aux favoris"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"supprimer des favoris"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Déplacer l\'élément à la position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Commandes"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Sélectionnez les commandes auxquelles vous souhaitez accéder depuis le menu de démarrage"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Appuyer et faire glisser pour réorganiser les commandes"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index a86c768..c8eca6a 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -76,7 +76,7 @@
     <string name="learn_more" msgid="4690632085667273811">"Máis información"</string>
     <string name="compat_mode_on" msgid="4963711187149440884">"Ampliar ata ocupar todo"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Estirar ata ocupar todo"</string>
-    <string name="global_action_screenshot" msgid="2760267567509131654">"Crear captura"</string>
+    <string name="global_action_screenshot" msgid="2760267567509131654">"Facer captura"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"enviou unha imaxe"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Gardando captura de pantalla…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Gardando captura de pantalla…"</string>
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Ignora a captura de pantalla"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Vista previa da captura de pantalla"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Gravadora da pantalla"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando gravación pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación en curso sobre unha sesión de gravación de pantalla"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Queres iniciar a gravación?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Durante a gravación, o sistema Android pode captar información confidencial visible na pantalla ou reproducila no dispositivo. Isto inclúe contrasinais, información de pago, fotos, mensaxes e audio."</string>
@@ -382,7 +381,7 @@
     <string name="quick_settings_wifi_on_label" msgid="2489928193654318511">"Wifi activada"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"Non hai redes wifi dispoñibles"</string>
     <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Activando…"</string>
-    <string name="quick_settings_cast_title" msgid="2279220930629235211">"Emisión da pantalla"</string>
+    <string name="quick_settings_cast_title" msgid="2279220930629235211">"Emitir pantalla"</string>
     <string name="quick_settings_casting" msgid="1435880708719268055">"Emitindo"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"Dispositivo sen nome"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2580520859212250265">"Listo para emitir"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Eliminar todas"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Xestionar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Entrantes"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Notificacións silenciadas"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Notificación de alerta"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversas"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sen título"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Toca o botón para reiniciar esta aplicación e abrila en pantalla completa."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Configuración das burbullas de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Mostrar menú adicional"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Engadir de novo á pilla"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Xestionar"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de <xliff:g id="APP_NAME">%2$s</xliff:g> e <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> máis"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">Engadíronse <xliff:g id="NUMBER_1">%s</xliff:g> controis.</item>
       <item quantity="one">Engadiuse <xliff:g id="NUMBER_0">%s</xliff:g> control.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Quitouse"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Está entre os controis favoritos"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Está entre os controis favoritos (posición: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Non está entre os controis favoritos"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"engadir aos controis favoritos"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"quitar dos controis favoritos"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Mover á posición <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Controis"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Escolle os controis para acceder desde o menú de acendido"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Para reorganizar os controis, mantenos premidos e arrástraos"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index e381551..ca3d658 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -32,7 +32,7 @@
     <string name="invalid_charger" msgid="4370074072117767416">"USB મારફતે ચાર્જ કરી શકતા નથી. તમારા ઉપકરણ સાથે આવેલ ચાર્જરનો ઉપયોગ કરો."</string>
     <string name="invalid_charger_title" msgid="938685362320735167">"USB મારફતે ચાર્જ કરી શકતા નથી"</string>
     <string name="invalid_charger_text" msgid="2339310107232691577">"તમારા ઉપકરણ સાથે આવેલ ચાર્જરનો ઉપયોગ કરો"</string>
-    <string name="battery_low_why" msgid="2056750982959359863">"સેટિંગ્સ"</string>
+    <string name="battery_low_why" msgid="2056750982959359863">"સેટિંગ"</string>
     <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"બૅટરી સેવર ચાલુ કરીએ?"</string>
     <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"બૅટરી સેવર વિશે"</string>
     <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"ચાલુ કરો"</string>
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"સ્ક્રીનશૉટ છોડી દો"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"સ્ક્રીનશૉટનો પ્રીવ્યૂ"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"સ્ક્રીન રેકૉર્ડર"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"સ્ક્રીન રેકૉર્ડિંગ ચાલુ છે"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"સ્ક્રીન રેકોર્ડિંગ સત્ર માટે ચાલુ નોટિફિકેશન"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"રેકૉર્ડિંગ શરૂ કરીએ?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"રેકૉર્ડ કરતી વખતે, Android System તમારી સ્ક્રીન પર દેખાતી હોય અથવા તમારા ડિવાઇસ પર ચલાવવામાં આવતી હોય તેવી કોઈપણ સંવેદનશીલ માહિતીને કૅપ્ચર કરી શકે છે. આમાં પાસવર્ડ, ચુકવણીની માહિતી, ફોટા, સંદેશા અને ઑડિયોનો સમાવેશ થાય છે."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"બધુ સાફ કરો"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"મેનેજ કરો"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ઇતિહાસ"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"ઇનકમિંગ"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"સાઇલન્ટ નોટિફિકેશન"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"નોટિફિકેશન બદલી રહ્યાં છીએ"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"વાતચીત"</string>
@@ -805,7 +803,7 @@
     <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"ઍપ્લિકેશનો"</string>
     <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"સહાય"</string>
     <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"બ્રાઉઝર"</string>
-    <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"સંપર્કો"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contacts"</string>
     <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ઇમેઇલ"</string>
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"સંગીત"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"કોઈ શીર્ષક નથી"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"આ ઍપ ફરીથી ચાલુ કરવા માટે ટૅપ કરીને પૂર્ણ સ્ક્રીન કરો."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> બબલ માટેનાં સેટિંગ"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"ઓવરફ્લો"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"સ્ટૅકમાં ફરી ઉમેરો"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"મેનેજ કરો"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> તરફથી <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> અને વધુ <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> તરફથી <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> નિયંત્રણ ઉમેર્યું.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> નિયંત્રણો ઉમેર્યા.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"કાઢી નાખ્યું"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"મનપસંદમાં ઉમેર્યું"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"મનપસંદમાં ઉમેર્યું, સ્થાન <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"મનપસંદમાંથી કાઢી નાખ્યું"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"મનપસંદમાં ઉમેરો"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"મનપસંદમાંથી કાઢી નાખો"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"સ્થાન <xliff:g id="NUMBER">%d</xliff:g> પર ખસેડો"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"નિયંત્રણો"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"પાવર મેનૂમાંથી ઍક્સેસ કરવા માટેના નિયંત્રણોને પસંદ કરો"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"નિયંત્રણોને ફરીથી ગોઠવવા માટે તેમને હોલ્ડ કરીને ખેંચો"</string>
@@ -1039,10 +1042,8 @@
     <string name="controls_favorite_load_error" msgid="2533215155804455348">"બધા નિયંત્રણોની સૂચિ લોડ કરી શકાઈ નથી."</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"અન્ય"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"ડિવાઇસનાં નિયંત્રણોમાં ઉમેરો"</string>
-    <!-- no translation found for controls_dialog_ok (2770230012857881822) -->
-    <skip />
-    <!-- no translation found for controls_dialog_message (342066938390663844) -->
-    <skip />
+    <string name="controls_dialog_ok" msgid="2770230012857881822">"ઉમેરો"</string>
+    <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> દ્વારા સૂચન કરેલા"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"નિયંત્રણ અપડેટ કર્યા"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"પિનમાં અક્ષરો અથવા પ્રતીકોનો સમાવેશ થાય છે"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g>ને ચકાસો"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 3e4beac..a568846 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"स्क्रीनशॉट खारिज करें"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"स्क्रीनशॉट की झलक"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"स्क्रीन रिकॉर्डर"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रीन रिकॉर्डिंग को प्रोसेस किया जा रहा है"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रिकॉर्ड सेशन के लिए जारी सूचना"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"रिकॉर्डिंग शुरू करना चाहते हैं?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"रिकॉर्ड करते समय, Android सिस्टम आपकी स्क्रीन पर दिखने वाली या चलाई जाने वाली संवेदनशील जानकारी को कैप्चर कर सकता है. इसमें पासवर्ड, पैसे चुकाने से जुड़ी जानकारी, फ़ोटो, मैसेज, और ऑडियो शामिल हैं."</string>
@@ -357,7 +356,7 @@
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"ऑडियो"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"हेडसेट"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"इनपुट"</string>
-    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"सुनने में मददगार डिवाइस"</string>
+    <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"कान की मशीन"</string>
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ब्लूटूथ चालू हो रहा है…"</string>
     <string name="quick_settings_brightness_label" msgid="680259653088849563">"स्क्रीन की रोशनी"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"अपने-आप घूमना"</string>
@@ -513,8 +512,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"सभी को हटाएं"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"प्रबंधित करें"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"इतिहास"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"हाल ही में मिली सूचनाएं"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"बिना आवाज़ या वाइब्रेशन वाली सूचनाएं"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"आवाज़ या वाइब्रेशन वाली सूचनाएं"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"बातचीत"</string>
@@ -590,7 +588,7 @@
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"साउंड सेटिंग"</string>
     <string name="accessibility_volume_expand" msgid="7653070939304433603">"विस्तार करें"</string>
     <string name="accessibility_volume_collapse" msgid="2746845391013829996">"छोटा करें"</string>
-    <string name="volume_odi_captions_tip" msgid="8825655463280990941">"ऑडियो-वीडियो पहचानकर अपने-आप कैप्शन बनना"</string>
+    <string name="volume_odi_captions_tip" msgid="8825655463280990941">"ऑडियो-वीडियो से अपने-आप कैप्शन बनना"</string>
     <string name="accessibility_volume_close_odi_captions_tip" msgid="8924753283621160480">"कैप्शन सलाह बंद करें"</string>
     <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"कैप्शन ऊपर लगाएं"</string>
     <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"चालू करें"</string>
@@ -993,10 +991,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"कोई शीर्षक नहीं"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"इस ऐप्लिकेशन को रीस्टार्ट करने और फ़ुल स्क्रीन चालू करने के लिए टैप करें."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> बबल्स की सेटिंग"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"ओवरफ़्लो"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"स्टैक में वापस जोड़ें"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"प्रबंधित करें"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> से <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> और <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> अन्य ऐप्लिकेशन से <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1033,6 +1029,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> कंट्रोल जोड़ा गया.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> कंट्रोल जोड़े गए.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"हटाया गया"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"पसंदीदा बनाया गया"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"पसंदीदा बनाया गया, क्रम संख्या <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"पसंदीदा से हटाया गया"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"पसंदीदा बनाएं"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"पसंदीदा से हटाएं"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"इसे <xliff:g id="NUMBER">%d</xliff:g> नंबर पर ले जाएं"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"कंट्राेल"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"पावर मेन्यू से ऐक्सेस करने के लिए कंट्रोल चुनें"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"कंट्रोल का क्रम फिर से बदलने के लिए उन्हें दबाकर रखें और खींचें"</string>
@@ -1042,7 +1045,7 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"अन्य"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"डिवाइस कंट्रोल में जोड़ें"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"जोड़ें"</string>
-    <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ने सुझाव दिया"</string>
+    <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> से मिला सुझाव"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"कंट्रोल अपडेट किए गए"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"पिन में अक्षर या चिह्न शामिल होते हैं"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> की पुष्टि करें"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 0c0f4de..c914a7f 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -63,7 +63,7 @@
     <string name="usb_debugging_allow" msgid="1722643858015321328">"Dopusti"</string>
     <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Otklanjanje pogrešaka putem USB-a nije dopušteno"</string>
     <string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"Korisnik koji je trenutačno prijavljen na ovaj uređaj ne može uključiti otklanjanje pogrešaka putem USB-a. Da biste upotrebljavali tu značajku, prijeđite na primarnog korisnika."</string>
-    <string name="wifi_debugging_title" msgid="7300007687492186076">"Želite li dopustiti bežično otklanjanje pogrešaka na ovoj mreži?"</string>
+    <string name="wifi_debugging_title" msgid="7300007687492186076">"Dopuštate li bežično otklanjanje pogrešaka na ovoj mreži?"</string>
     <string name="wifi_debugging_message" msgid="5461204211731802995">"Naziv mreže (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nAdresa Wi‑Fija (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
     <string name="wifi_debugging_always" msgid="2968383799517975155">"Uvijek dopusti na ovoj mreži"</string>
     <string name="wifi_debugging_allow" msgid="4573224609684957886">"Dopusti"</string>
@@ -416,7 +416,7 @@
     <string name="quick_settings_cellular_detail_data_used" msgid="6798849610647988987">"<xliff:g id="DATA_USED">%s</xliff:g> iskorišteno"</string>
     <string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Ograničenje od <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Upozorenje <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
-    <string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Radni profil"</string>
+    <string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Poslovni profil"</string>
     <string name="quick_settings_night_display_label" msgid="8180030659141778180">"Noćno svjetlo"</string>
     <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Uključuje se u suton"</string>
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Do izlaska sunca"</string>
@@ -654,7 +654,7 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Prikaži demo način"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
-    <string name="status_bar_work" msgid="5238641949837091056">"Radni profil"</string>
+    <string name="status_bar_work" msgid="5238641949837091056">"Poslovni profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Način rada u zrakoplovu"</string>
     <string name="add_tile" msgid="6239678623873086686">"Dodavanje pločice"</string>
     <string name="broadcast_tile" msgid="5224010633596487481">"Emitiranje pločice"</string>
@@ -664,7 +664,7 @@
     <string name="alarm_template_far" msgid="3561752195856839456">"u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"Brze postavke, <xliff:g id="TITLE">%s</xliff:g>."</string>
     <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"Žarišna točka"</string>
-    <string name="accessibility_managed_profile" msgid="4703836746209377356">"Radni profil"</string>
+    <string name="accessibility_managed_profile" msgid="4703836746209377356">"Poslovni profil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Ugađanje korisničkog sučelja sustava pruža vam dodatne načine za prilagodbu korisničkog sučelja Androida. Te se eksperimentalne značajke mogu promijeniti, prekinuti ili nestati u budućim izdanjima. Nastavite uz oprez."</string>
     <string name="tuner_persistent_warning" msgid="230466285569307806">"Te se eksperimentalne značajke mogu promijeniti, prekinuti ili nestati u budućim izdanjima. Nastavite uz oprez."</string>
@@ -1033,6 +1033,13 @@
       <item quantity="few">Dodane su <xliff:g id="NUMBER_1">%s</xliff:g> kontrole.</item>
       <item quantity="other">Dodano je <xliff:g id="NUMBER_1">%s</xliff:g> kontrola.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Uklonjeno"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Dodano u favorite"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Dodano u favorite, položaj <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Uklonjeno iz favorita"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"dodali u favorite"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"uklonili iz favorita"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Premjestite na položaj <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Kontrole"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Odaberite kontrole kojima želite pristupati iz izbornika napajanja"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Zadržite i povucite da biste promijenili raspored kontrola"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 63f0f3f..de51b24 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Képernyőkép elvetése"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Képernyőkép előnézete"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Képernyőrögzítő"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Képernyőrögzítés feldolgozása"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Folyamatban lévő értesítés képernyőrögzítési munkamenethez"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Elindítja a felvételt?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"A felvétel készítése során az Android rendszer rögzítheti az eszközön lejátszott, illetve a képernyőjén megjelenő bizalmas információkat. Ide tartoznak például a jelszavak, a fizetési információk, a fotók, az üzenetek és az audiotartalmak is."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Az összes törlése"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Kezelés"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Előzmények"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Bejövő"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Néma értesítések"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Figyelemfelkeltő értesítések"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Beszélgetések"</string>
@@ -969,7 +967,7 @@
     <string name="running_foreground_services_title" msgid="5137313173431186685">"A háttérben még futnak alkalmazások"</string>
     <string name="running_foreground_services_msg" msgid="3009459259222695385">"Koppintson az akkumulátor- és adathasználat részleteinek megtekintéséhez"</string>
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Kikapcsolja a mobiladatokat?"</string>
-    <string name="mobile_data_disable_message" msgid="8604966027899770415">"Nem lesz adat-, illetve internet-hozzáférése a(z) <xliff:g id="CARRIER">%s</xliff:g> szolgáltatón keresztül. Az internethez csak Wi-Fi-n keresztül csatlakozhat."</string>
+    <string name="mobile_data_disable_message" msgid="8604966027899770415">"Nem lesz adat-, illetve internet-hozzáférése a <xliff:g id="CARRIER">%s</xliff:g> szolgáltatón keresztül. Az internethez csak Wi-Fi-n keresztül csatlakozhat."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"saját mobilszolgáltató"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Mivel az egyik alkalmazás eltakarja az engedélykérést, a Beállítások alkalmazás nem tudja ellenőrizni az Ön válaszát."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Engedélyezi a(z) <xliff:g id="APP_0">%1$s</xliff:g> alkalmazásnak, hogy részleteket mutasson a(z) <xliff:g id="APP_2">%2$s</xliff:g> alkalmazásból?"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Nincs cím"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Koppintson az alkalmazás újraindításához és a teljes képernyős mód elindításához."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g>-buborékok beállításai"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"További elemeket tartalmazó menü"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Visszaküldés a verembe"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Kezelés"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> a(z) <xliff:g id="APP_NAME">%2$s</xliff:g> alkalmazásból és <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> további"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> vezérlő hozzáadva.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> vezérlő hozzáadva.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Eltávolítva"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Hozzáadva a kedvencekhez"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Hozzáadva a kedvencekhez <xliff:g id="NUMBER">%d</xliff:g>. helyen"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Eltávolítva a kedvencek közül"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"kedvencekhez adás"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"eltávolítás a kedvencek közül"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Áthelyezés a következő pozícióba: <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Vezérlők"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"A bekapcsológomb menüjéből hozzáférhető vezérlők kiválasztása"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Tartsa lenyomva, és húzza a vezérlők átrendezéséhez"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index b7343be..bb0ac29 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Փակել սքրինշոթը"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Սքրինշոթի նախադիտում"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Էկրանի տեսագրիչ"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Էկրանի տեսագրության մշակում"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Էկրանի տեսագրման աշխատաշրջանի ընթացիկ ծանուցում"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Սկսե՞լ տեսագրումը"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Տեսագրման ընթացքում Android-ի համակարգը կարող է գրանցել անձնական տեղեկություններ, որոնք տեսանելի են էկրանին կամ նվագարկվում են ձեր սարքում։ Սա ներառում է այնպիսի տեղեկություններ, ինչպիսիք են, օրինակ, գաղտնաբառերը, վճարային տվյալները, լուսանկարները, հաղորդագրությունները և նվագարկվող աուդիո ֆայլերը։"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Մաքրել բոլորը"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Կառավարել"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Պատմություն"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Մուտքային"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Անձայն ծանուցումներ"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Նախազգուշացնող ծանուցումներ"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Խոսակցություններ"</string>
@@ -715,7 +713,7 @@
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"Ծանուցումները գալիս են ձայնով կամ թրթռոցով։"</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"Ծանուցումները գալիս են ձայնով կամ թրթռոցով։ <xliff:g id="APP_NAME">%1$s</xliff:g>-ի զրույցներն ըստ կանխադրման հայտնվում են ամպիկների տեսքով։"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Լողացող դյուրանցման միջոցով ձեր ուշադրությունն է գրավում բովանդակության նկատմամբ"</string>
-    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Ցուցադրվում է «Խոսակցություններ» բաժնում և հայտնվում է ամպիկի տեսքով։"</string>
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Ցուցադրվում է զրույցների ցանկի վերևում և հայտնվում է ամպիկի տեսքով։"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Կարգավորումներ"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Կարևոր"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը չի աջակցում զրույցի կարգավորումները"</string>
@@ -742,9 +740,9 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Կարգավորել"</string>
     <string name="notification_done" msgid="6215117625922713976">"Պատրաստ է"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Հետարկել"</string>
-    <string name="demote" msgid="6225813324237153980">"Նշել այս ծանուցումը որպես ոչ խոսակցություն"</string>
-    <string name="notification_conversation_favorite" msgid="1905240206975921907">"Կարևոր խոսակցություն"</string>
-    <string name="notification_conversation_unfavorite" msgid="181383708304763807">"Ոչ կարևոր խոսակցություն"</string>
+    <string name="demote" msgid="6225813324237153980">"Նշել այս ծանուցումը որպես ոչ զրույց"</string>
+    <string name="notification_conversation_favorite" msgid="1905240206975921907">"Կարևոր զրույց"</string>
+    <string name="notification_conversation_unfavorite" msgid="181383708304763807">"Ոչ կարևոր զրույց"</string>
     <string name="notification_conversation_mute" msgid="268951550222925548">"Լռեցված"</string>
     <string name="notification_conversation_unmute" msgid="2692255619510896710">"Միացնել ծանուցումների ձայնը"</string>
     <string name="notification_conversation_bubble" msgid="2242180995373949022">"Ցուցադրել ամպիկը"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Անանուն"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Հպեք՝ հավելվածը վերագործարկելու և լիաէկրան ռեժիմին անցնելու համար։"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ի ամպիկների կարգավորումներ"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Լրացուցիչ ընտրացանկ"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Նորից ավելացնել զտիչներում"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Կառավարել"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>՝ <xliff:g id="APP_NAME">%2$s</xliff:g>-ից"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>` <xliff:g id="APP_NAME">%2$s</xliff:g>-ից ու ևս <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> ամպիկ"</string>
@@ -1004,7 +1000,7 @@
     <string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Տեղափոխել ներքև՝ ձախ"</string>
     <string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Տեղափոխել ներքև՝ աջ"</string>
     <string name="bubble_dismiss_text" msgid="7071770411580452911">"Փակել"</string>
-    <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Խոսակցությունը չցուցադրել ամպիկի տեսքով"</string>
+    <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Զրույցը չցուցադրել ամպիկի տեսքով"</string>
     <string name="bubbles_user_education_title" msgid="5547017089271445797">"Զրուցել ամպիկների միջոցով"</string>
     <string name="bubbles_user_education_description" msgid="1160281719576715211">"Նոր խոսակցությունները կհայտնվեն լողացող պատկերակների կամ ամպիկների տեսքով։ Հպեք՝ ամպիկը բացելու համար։ Քաշեք՝ այն տեղափոխելու համար։"</string>
     <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Ամպիկների կարգավորումներ"</string>
@@ -1014,10 +1010,10 @@
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Համակարգի նավիգացիան թարմացվեց: Փոփոխություններ անելու համար անցեք կարգավորումներ:"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Թարմացրեք համակարգի նավիգացիան կարգավորումներում"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Սպասման ռեժիմ"</string>
-    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Ցուցադրվում են «Խոսակցություններ» բաժնի վերևում"</string>
-    <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Ցուցադրում են պրոֆիլի նկարը կողպէկրանին"</string>
+    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Ցուցադրել զրույցների ցանկի վերևում"</string>
+    <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Ցուցադրել պրոֆիլի նկարը կողպէկրանին"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Հայտնվում են որպես լողացող ամպիկ հավելվածների վրայից"</string>
-    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Ընդհատում են «Չանհանգստացնել» ռեժիմը"</string>
+    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Ընդհատել «Չանհանգստացնել» ռեժիմը"</string>
     <string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Եղավ"</string>
     <string name="magnification_overlay_title" msgid="6584179429612427958">"Խոշորացման պատուհանի վրադրում"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"Խոշորացման պատուհան"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="one">Ավելացվեց կառավարման <xliff:g id="NUMBER_1">%s</xliff:g> տարր։</item>
       <item quantity="other">Ավելացվեց կառավարման <xliff:g id="NUMBER_1">%s</xliff:g> տարր։</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Հեռացված է"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Ավելացված է ընտրանիում"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ավելացված է ընտրանիում, դիրքը՝ <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Հեռացված է ընտրանուց"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"ընտրանիում ավելացնելու համար"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"ընտրանուց հեռացնելու համար"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Տեղափոխել դիրք <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Կառավարման տարրեր"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Ընտրեք կառավարման տարրերը՝ դրանք սնուցման ընտրացանկից բացելու համար"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Պահեք և քաշեք՝ կառավարման տարրերը վերադասավորելու համար"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index f3ac8d1..abaa941 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Menutup screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pratinjau screenshot"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Perekam Layar"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Memproses perekaman layar"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifikasi yang sedang berjalan untuk sesi rekaman layar"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Mulai Merekam?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Saat merekam, Sistem Android dapat ikut merekam informasi sensitif yang terlihat di layar atau diputar di perangkat Anda. Informasi ini mencakup sandi, info pembayaran, foto, pesan, dan audio."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Hapus semua"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Kelola"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Histori"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Masuk"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Notifikasi senyap"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Notifikasi aktif"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Percakapan"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Tanpa judul"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Ketuk untuk memulai ulang aplikasi ini dan membuka layar penuh."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Setelan untuk balon <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Tambahan"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Tambahkan kembali ke stack"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Kelola"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> dari <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> dari <xliff:g id="APP_NAME">%2$s</xliff:g> dan <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> lainnya"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> kontrol ditambahkan.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> kontrol ditambahkan.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Dihapus"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Difavoritkan"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Difavoritkan, posisi <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Batal difavoritkan"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"favorit"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"batal favoritkan"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Pindah ke posisi <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Kontrol"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Pilih kontrol yang akan diakses dari menu daya"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Tahan &amp; tarik untuk mengatur ulang kontrol"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index d133ed0..c289e95 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Loka skjámynd"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Forskoðun skjámyndar"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Skjáupptaka"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Vinnur úr skjáupptöku"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Áframhaldandi tilkynning fyrir skjáupptökulotu"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Hefja upptöku?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Á meðan tekið er upp getur Android kerfið fangað viðkvæmar upplýsingar sem sjást á skjánum eða spilast í tækinu. Þar á meðal eru upplýsingar á borð við aðgangsorð, greiðsluupplýsingar, myndir, skilaboð og hljóð."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Hreinsa allt"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Stjórna"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Ferill"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Mótteknar"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Þöglar tilkynningar"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Viðvörunartilkynningar"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Samtöl"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Enginn titill"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Ýttu til að endurræsa forritið og sýna það á öllum skjánum."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Stillingar fyrir blöðrur frá <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Yfirflæði"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Bæta aftur í stafla"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Stjórna"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> frá <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"„<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>“ frá <xliff:g id="APP_NAME">%2$s</xliff:g> og <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> í viðbót"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> stýringu bætt við.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> stýringum bætt við.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Fjarlægt"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Eftirlæti"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Eftirlæti, staða <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Fjarlægt úr eftirlæti"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"setja í eftirlæti"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"fjarlægja úr eftirlæti"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Færa í stöðu <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Stýringar"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Veldu hvaða stýringar birtast í aflrofavalmyndinni"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Haltu og dragðu til að endurraða stýringum"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 2ca52df..35a65dd 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Ignora screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Anteprima screenshot"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Registrazione dello schermo"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Elaboraz. registraz. schermo"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifica costante per una sessione di registrazione dello schermo"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Avviare la registrazione?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Durante la registrazione, il sistema Android può acquisire dati sensibili visibili sullo schermo o riprodotti sul tuo dispositivo, tra cui password, dati di pagamento, foto, messaggi e audio."</string>
@@ -299,8 +298,8 @@
     <string name="accessibility_quick_settings_flashlight_on" msgid="3785616827729850766">"Torcia accesa."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3782375441381402599">"Torcia disattivata."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="4747870681508334200">"Torcia attivata."</string>
-    <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="7548045840282925393">"Inversione colori disattivata."</string>
-    <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="4711141858364404084">"Inversione colori attivata."</string>
+    <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="7548045840282925393">"Inversione dei colori disattivata."</string>
+    <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="4711141858364404084">"Inversione dei colori attivata."</string>
     <string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Hotspot mobile disattivato."</string>
     <string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Hotspot mobile attivato."</string>
     <string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Trasmissione dello schermo interrotta."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Cancella tutto"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gestisci"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Cronologia"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"In arrivo"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Notifiche silenziose"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Notifiche di avviso"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversazioni"</string>
@@ -711,7 +709,7 @@
     <string name="notification_silence_title" msgid="8608090968400832335">"Modalità silenziosa"</string>
     <string name="notification_alert_title" msgid="7629202599338071971">"Avvisi"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Fumetto"</string>
-    <string name="notification_channel_summary_low" msgid="7300447764759926720">"Favorisce la tua concentrazione grazie all\'assenza di suono o vibrazione."</string>
+    <string name="notification_channel_summary_low" msgid="7300447764759926720">"Ti aiuta a non perdere la concentrazione grazie all\'assenza di suono o vibrazione."</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"Richiama la tua attenzione con suono o vibrazione."</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"Richiama la tua attenzione con suono o vibrazione. Conversazioni dalla bolla <xliff:g id="APP_NAME">%1$s</xliff:g> per impostazione predefinita."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantiene la tua attenzione con una scorciatoia mobile a questi contenuti."</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Senza titolo"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Tocca per riavviare l\'app e passare a schermo intero."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Impostazioni per bolle <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Altre"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Aggiungi di nuovo all\'elenco"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Gestisci"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> da <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> da <xliff:g id="APP_NAME">%2$s</xliff:g> e altre <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controlli aggiunti.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> controllo aggiunto.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Rimosso"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Aggiunto ai preferiti"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Preferito, posizione <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Rimosso dai preferiti"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"aggiungere l\'elemento ai preferiti"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"rimuovere l\'elemento dai preferiti"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Sposta nella posizione <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Controlli"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Seleziona i controlli a cui accedere dal menu di accensione"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Tieni premuto e trascina per riordinare i controlli"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 9dfadfb..67a7a93 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"סגירת צילום מסך"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"תצוגה מקדימה של צילום מסך"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"מקליט המסך"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"מתבצע עיבוד של הקלטת מסך"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"התראה מתמשכת לסשן הקלטת מסך"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"להתחיל את ההקלטה?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"‏בזמן ההקלטה, מערכת Android יכולה לתעד מידע רגיש שגלוי במסך או מופעל במכשיר שלך. מידע זה כולל סיסמאות, פרטי תשלום, תמונות, הודעות ואודיו."</string>
@@ -517,8 +516,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"ניקוי הכל"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"ניהול"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"היסטוריה"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"התקבלו"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"התראות שקטות"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"התראות עם צלילים או רטט"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"שיחות"</string>
@@ -1001,10 +999,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"ללא שם"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"צריך להקיש כדי להפעיל מחדש את האפליקציה הזו ולעבור למסך מלא."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"הגדרות בשביל בועות של <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"גלישה"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"הוספה בחזרה לערימה"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"ניהול"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> מהאפליקציה <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> מ-<xliff:g id="APP_NAME">%2$s</xliff:g> ועוד <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1043,6 +1039,13 @@
       <item quantity="other">נוספו <xliff:g id="NUMBER_1">%s</xliff:g> פקדים.</item>
       <item quantity="one">נוסף פקד אחד (<xliff:g id="NUMBER_0">%s</xliff:g>).</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"הוסר"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"סומן כהעדפה"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"סומן כהעדפה, במיקום <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"הוסר מהמועדפים"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"להוסיף למועדפים"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"להוסיף למועדפים"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"העברה למיקום <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"פקדים"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"יש לבחור פקדים לגישה מתפריט ההפעלה"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"יש ללחוץ לחיצה ארוכה ולגרור כדי לארגן מחדש את הפקדים"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 15508ac..59e1b17 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"スクリーンショットを閉じます"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"スクリーンショットのプレビュー"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"スクリーン レコーダー"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"画面の録画を処理しています"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"画面の録画セッション中の通知"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"録画を開始しますか?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"録画中に機密情報が画面に表示されたりデバイスで再生されたりした場合、Android システムでキャプチャされることがあります。これには、パスワード、お支払い情報、写真、メッセージ、音声などが含まれます。"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"すべて消去"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"履歴"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"新着"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"サイレント通知"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"バイブレーションまたは音を伴う通知"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"会話"</string>
@@ -969,7 +967,7 @@
     <string name="running_foreground_services_title" msgid="5137313173431186685">"バックグラウンドで実行中のアプリ"</string>
     <string name="running_foreground_services_msg" msgid="3009459259222695385">"タップして電池やデータの使用量を確認"</string>
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"モバイルデータを OFF にしますか?"</string>
-    <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g> でデータやインターネットにアクセスできなくなります。インターネットには Wi-Fi からのみ接続できます。"</string>
+    <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g>でデータやインターネットにアクセスできなくなります。インターネットには Wi-Fi からのみ接続できます。"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"携帯通信会社"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"アプリが許可リクエストを隠しているため、設定側でユーザーの応答を確認できません。"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"「<xliff:g id="APP_2">%2$s</xliff:g>」のスライスの表示を「<xliff:g id="APP_0">%1$s</xliff:g>」に許可しますか?"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"タイトルなし"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"タップしてこのアプリを再起動すると、全画面表示になります。"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> のバブルの設定"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"オーバーフロー"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"スタックに戻す"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"管理"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>(<xliff:g id="APP_NAME">%2$s</xliff:g>)"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>(<xliff:g id="APP_NAME">%2$s</xliff:g>)、他 <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> 件"</string>
@@ -1031,8 +1027,15 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> 件のコントロールを追加しました。</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> 件のコントロールを追加しました。</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"削除済み"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"お気に入りに追加済み"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"お気に入りに追加済み、位置: <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"お気に入りから削除済み"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"お気に入りに追加"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"お気に入りから削除"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"ポジション <xliff:g id="NUMBER">%d</xliff:g> に移動"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"コントロール"</string>
-    <string name="controls_favorite_subtitle" msgid="6604402232298443956">"電源メニューからアクセスするコントロールを選択する"</string>
+    <string name="controls_favorite_subtitle" msgid="6604402232298443956">"電源ボタン メニューからアクセスするコントロールを選択する"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"コントロールを並べ替えるには長押ししてドラッグします"</string>
     <string name="controls_favorite_removed" msgid="5276978408529217272">"すべてのコントロールを削除しました"</string>
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"変更が保存されていません"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 36580b7..193a513 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -1027,6 +1027,13 @@
       <item quantity="other">დაემატა <xliff:g id="NUMBER_1">%s</xliff:g> მართვის საშუალება.</item>
       <item quantity="one">დაემატა <xliff:g id="NUMBER_0">%s</xliff:g> მართვის საშუალება.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"ამოიშალა"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"რჩეულებშია"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"რჩეულებშია, პოზიციაზე <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"რჩეულებიდან ამოღებულია"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"რჩეული"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"რჩეულებიდან ამოღება"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"გადატანა პოზიციაზე <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"მართვის საშუალებები"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"აირჩიეთ მართვის საშუალებები ელკვების მენიუდან"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"მართვის საშუალებების გადაწყობა შეგიძლიათ მათი ჩავლებით გადატანით"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 4f24828..e0117fe 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Скриншотты жабу"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Скриншотты алдын ала қарау"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Экран жазғыш"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Экран жазғыш бейнесін өңдеу"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды бейнеге жазудың ағымдағы хабарландыруы"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Жазу басталсын ба?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Жазу кезінде Android жүйесі экранда көрсетілетін немесе құрылғыда ойнатылатын құпия ақпаратты пайдалана алады. Ол ақпаратқа құпия сөздер, төлеу ақпараты, фотосуреттер, хабарлар және аудио жатады."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Барлығын тазалау"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Басқару"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Тарих"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Кіріс"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Дыбыссыз хабарландырулар"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Ескертуші хабарландлырулар"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Әңгімелер"</string>
@@ -588,7 +586,7 @@
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"Дыбыс параметрлері"</string>
     <string name="accessibility_volume_expand" msgid="7653070939304433603">"Жаю"</string>
     <string name="accessibility_volume_collapse" msgid="2746845391013829996">"Жию"</string>
-    <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Автоматты субтитр медиасы"</string>
+    <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Автоматты субтитр қосу"</string>
     <string name="accessibility_volume_close_odi_captions_tip" msgid="8924753283621160480">"Субтитрлер кеңесі"</string>
     <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Субтитр қою"</string>
     <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"қосу"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Атауы жоқ"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Бұл қолданбаны қайта қосып, толық экранға өту үшін түртіңіз."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> қалқыма хабарларының параметрлері"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Қосымша мәзір"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Стекке қайта енгізу"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Басқару"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> жіберген хабарландыру: <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасы жіберген <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> және тағы <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> басқару элементі енгізілді.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> басқару элементі енгізілді.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Өшірілді"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Таңдаулыларға қосылды"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Таңдаулыларға қосылды, <xliff:g id="NUMBER">%d</xliff:g>-позиция"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Таңдаулылардан алып тасталды"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"таңдаулылар"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"таңдаулылардан алып тастау"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g> позициясына жылжыту"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Басқару элементтері"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"\"Қуат\" мәзірінен пайдалануға болатын басқару элементтерін таңдаңыз."</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Басқару элементтерінің ретін өзгерту үшін оларды басып тұрып сүйреңіз."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 11b7514c..00b455b 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ច្រានចោល​រូបថត​អេក្រង់"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ការមើល​រូបថត​អេក្រង់​សាកល្បង"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"មុខងារថត​អេក្រង់"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"កំពុង​ដំណើរការ​ការថតអេក្រង់"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ការជូនដំណឹង​ដែល​កំពុង​ដំណើរការ​សម្រាប់​រយៈពេលប្រើ​ការថត​សកម្មភាព​អេក្រង់"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"ចាប់ផ្តើម​ថត​ឬ?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"នៅពេល​កំពុងថត ប្រព័ន្ធ Android អាច​ថត​ព័ត៌មាន​រសើប​ដែលអាច​មើលឃើញ​នៅលើ​អេក្រង់​របស់អ្នក ឬដែល​បានចាក់​នៅលើ​ឧបករណ៍​របស់អ្នក។ ព័ត៌មាននេះ​រួមមាន​ពាក្យសម្ងាត់ ព័ត៌មាន​អំពី​ការបង់ប្រាក់ រូបថត សារ និងសំឡេង។"</string>
@@ -369,7 +368,7 @@
     <string name="quick_settings_location_off_label" msgid="7923929131443915919">"ទីតាំង​បាន​បិទ"</string>
     <string name="quick_settings_media_device_label" msgid="8034019242363789941">"ឧបករណ៍​មេឌៀ"</string>
     <string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
-    <string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"សម្រាប់​តែ​ការ​ហៅ​ពេល​អាសន្ន"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"ការហៅទៅលេខសង្គ្រោះបន្ទាន់​តែប៉ុណ្ណោះ"</string>
     <string name="quick_settings_settings_label" msgid="2214639529565474534">"ការ​កំណត់"</string>
     <string name="quick_settings_time_label" msgid="3352680970557509303">"ពេលវេលា"</string>
     <string name="quick_settings_user_label" msgid="1253515509432672496">"ខ្ញុំ"</string>
@@ -382,7 +381,7 @@
     <string name="quick_settings_wifi_on_label" msgid="2489928193654318511">"Wi-Fi បានបើក"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"គ្មានបណ្តាញ Wi-Fi ទេ"</string>
     <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"កំពុង​បើក..."</string>
-    <string name="quick_settings_cast_title" msgid="2279220930629235211">"ការថតវីដេអូ​នៅលើអេក្រង់"</string>
+    <string name="quick_settings_cast_title" msgid="2279220930629235211">"ការបញ្ចាំងអេក្រង់"</string>
     <string name="quick_settings_casting" msgid="1435880708719268055">"ការ​ចាត់​ថ្នាក់"</string>
     <string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"ឧបករណ៍​​ដែល​មិន​មាន​ឈ្មោះ"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2580520859212250265">"ត្រៀម​រួចរាល់​ដើម្បី​ចាត់​ថ្នាក់"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"សម្អាត​ទាំងអស់"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"គ្រប់គ្រង"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ប្រវត្តិ"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"មក​ដល់"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"ការជូនដំណឹង​ស្ងាត់"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"ការជូនដំណឹង​ញ័រ ឬរោទ៍"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"ការសន្ទនា"</string>
@@ -711,7 +709,7 @@
     <string name="notification_silence_title" msgid="8608090968400832335">"ស្ងាត់"</string>
     <string name="notification_alert_title" msgid="7629202599338071971">"បញ្ចេញ​សំឡេង"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"ពពុះ"</string>
-    <string name="notification_channel_summary_low" msgid="7300447764759926720">"ជួយឱ្យ​អ្នក​ផ្តោតអារម្មណ៍ ដោយមិនឮសំឡេង ឬ​ការញ័រ។"</string>
+    <string name="notification_channel_summary_low" msgid="7300447764759926720">"ជួយឱ្យ​អ្នក​ផ្តោតអារម្មណ៍ ដោយមិនឮសំឡេង ឬ​ញ័រ។"</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"ធ្វើឱ្យ​អ្នក​ចាប់អារម្មណ៍​តាមរយៈ​សំឡេង ឬ​ការញ័រ។"</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"ធ្វើឱ្យ​អ្នក​ចាប់អារម្មណ៍​តាមរយៈ​សំឡេង ឬ​ការញ័រ។ ការសន្ទនា​ពី​ពពុះ <xliff:g id="APP_NAME">%1$s</xliff:g> តាម​លំនាំដើម​។"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ធ្វើឱ្យអ្នក​ចាប់អារម្មណ៍​ដោយប្រើ​ផ្លូវកាត់​អណ្ដែត​សម្រាប់ខ្លឹមសារនេះ។"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"គ្មាន​ចំណងជើង"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"ចុចដើម្បី​ចាប់ផ្ដើម​កម្មវិធី​នេះឡើងវិញ រួចចូលប្រើ​ពេញអេក្រង់។"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"ការកំណត់​សម្រាប់​ពពុះ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"ម៉ឺនុយបន្ថែម"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"បញ្ចូល​ទៅក្នុង​គំនរវិញ"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"គ្រប់គ្រង"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ពី <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ពី <xliff:g id="APP_NAME">%2$s</xliff:g> និង <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> ទៀត"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">បានបញ្ចូល​ការគ្រប់គ្រង <xliff:g id="NUMBER_1">%s</xliff:g>។</item>
       <item quantity="one">បានបញ្ចូល​ការគ្រប់គ្រង <xliff:g id="NUMBER_0">%s</xliff:g>។</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"បានដកចេញ"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"បានដាក់ជា​សំណព្វ"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"បានដាក់ជា​សំណព្វ ទីតាំង​ទី <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"បានដកចេញ​ពី​សំណព្វ"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"ដាក់ជា​សំណព្វ"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"ដកចេញ​ពី​សំណព្វ"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"ផ្លាស់ទី​ទៅតាំងទី <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"ការគ្រប់គ្រង"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"ជ្រើសរើស​ការគ្រប់គ្រង ដើម្បី​ចូលប្រើ​ពីម៉ឺនុយ​ថាមពល"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"ចុច​ឱ្យ​ជាប់ រួចអូស​ដើម្បី​រៀបចំ​ការគ្រប់គ្រង​ឡើងវិញ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index fc0844a..d2554c1 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ವಜಾಗೊಳಿಸಿ"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ಸ್ಕ್ರೀನ್‍ಶಾಟ್‍ನ ಪೂರ್ವವೀಕ್ಷಣೆ"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡರ್"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಆಗುತ್ತಿದೆ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಸೆಶನ್‌ಗಾಗಿ ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಅಧಿಸೂಚನೆ"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"ರೆಕಾರ್ಡಿಂಗ್ ಪ್ರಾರಂಭಿಸಬೇಕೆ?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"ರೆಕಾರ್ಡಿಂಗ್ ಸಮಯದಲ್ಲಿ, ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ಗೋಚರಿಸುವ ಅಥವಾ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲಾದ ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯನ್ನು Android ಸಿಸ್ಟಂ ಕ್ಯಾಪ್ಚರ್ ಮಾಡಬಹುದು. ಇದು ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಪಾವತಿ ಮಾಹಿತಿ, ಫೋಟೋಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ಆಡಿಯೋವನ್ನು ಒಳಗೊಂಡಿದೆ."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿ"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"ನಿರ್ವಹಿಸಿ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ಇತಿಹಾಸ"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"ಒಳಬರುವ"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"ನಿಶ್ಶಬ್ಧ ಅಧಿಸೂಚನೆಗಳು"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"ಎಚ್ಚರಿಸುವ ಅಧಿಸೂಚನೆಗಳು"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"ಸಂಭಾಷಣೆಗಳು"</string>
@@ -985,16 +983,14 @@
     <string name="auto_saver_enabled_text" msgid="7889491183116752719">"ಬ್ಯಾಟರಿ <xliff:g id="PERCENTAGE">%d</xliff:g>%% ಗಿಂತ ಕಡಿಮೆ ಆದಾಗ ಬ್ಯಾಟರಿ ಸೇವರ್‌ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆನ್‌ ಆಗುತ್ತದೆ."</string>
     <string name="open_saver_setting_action" msgid="2111461909782935190">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="auto_saver_okay_action" msgid="7815925750741935386">"ಅರ್ಥವಾಯಿತು"</string>
-    <string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI ಹೀಪ್ ಡಂಪ್ ಮಾಡಿ"</string>
+    <string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
     <string name="sensor_privacy_mode" msgid="4462866919026513692">"ಸೆನ್ಸರ್‌ಗಳು ಆಫ್"</string>
     <string name="device_services" msgid="1549944177856658705">"ಸಾಧನ ಸೇವೆಗಳು"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"ಯಾವುದೇ ಶೀರ್ಷಿಕೆಯಿಲ್ಲ"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"ಈ ಆ್ಯಪ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಲು ಮತ್ತು ಪೂರ್ಣ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ನೋಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಬಬಲ್ಸ್‌ಗಾಗಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"ಓವರ್‌ಫ್ಲೋ"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"ಸ್ಟ್ಯಾಕ್‌ಗೆ ಪುನಃ ಸೇರಿಸಿ"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"ನಿರ್ವಹಿಸಿ"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> ಆ್ಯಪ್‌ನ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> ಮತ್ತು <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> ಹೆಚ್ಚಿನವುಗಳ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಲಾಗಿದೆ.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಲಾಗಿದೆ.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"ಮೆಚ್ಚಲಾಗಿರುವುದು"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ಮೆಚ್ಚಲಾಗಿರುವುದು, ಸ್ಥಾನ <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ಮೆಚ್ಚಿನದಲ್ಲದ್ದು"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"ಮೆಚ್ಚಿನ"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"ಮೆಚ್ಚಿನದಲ್ಲದ್ದು"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"ಸ್ಥಾನ <xliff:g id="NUMBER">%d</xliff:g> ಕ್ಕೆ ಸರಿಸಿ"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"ನಿಯಂತ್ರಣಗಳು"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"ಪವರ್ ಮೆನುವಿನಿಂದ ಪ್ರವೇಶಿಸಲು ನಿಯಂತ್ರಣಗಳನ್ನು ಆರಿಸಿ"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"ನಿಯಂತ್ರಣಗಳನ್ನು ಮರುಹೊಂದಿಸಲು ಹೋಲ್ಡ್ ಮಾಡಿ ಮತ್ತು ಡ್ರ್ಯಾಗ್‌ ಮಾಡಿ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index cca8adb..58433aa 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"스크린샷 닫기"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"스크린샷 미리보기"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"화면 녹화"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"화면 녹화 처리 중"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"화면 녹화 세션에 관한 지속적인 알림"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"녹화를 시작하시겠습니까?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Android 시스템이 녹화 중에 화면에 표시되거나 기기에서 재생되는 민감한 정보를 캡처할 수 있습니다. 여기에는 비밀번호, 결제 정보, 사진, 메시지 및 오디오가 포함됩니다."</string>
@@ -400,7 +399,7 @@
     <string name="quick_settings_tethering_label" msgid="5257299852322475780">"테더링"</string>
     <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"핫스팟"</string>
     <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"켜는 중..."</string>
-    <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"데이터 절약 모드 사용 중"</string>
+    <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"데이터 절약 모드"</string>
     <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
       <item quantity="other">기기 %d대</item>
       <item quantity="one">기기 %d대</item>
@@ -490,7 +489,7 @@
     <string name="user_logout_notification_title" msgid="3644848998053832589">"사용자 로그아웃"</string>
     <string name="user_logout_notification_text" msgid="7441286737342997991">"현재 사용자 로그아웃"</string>
     <string name="user_logout_notification_action" msgid="7974458760719361881">"사용자 로그아웃"</string>
-    <string name="user_add_user_title" msgid="4172327541504825032">"새 사용자를 추가할까요?"</string>
+    <string name="user_add_user_title" msgid="4172327541504825032">"신규 사용자를 추가할까요?"</string>
     <string name="user_add_user_message_short" msgid="2599370307878014791">"추가된 새로운 사용자는 자신의 공간을 설정해야 합니다.\n\n모든 사용자는 다른 사용자들을 위하여 앱을 업데이트할 수 있습니다."</string>
     <string name="user_limit_reached_title" msgid="2429229448830346057">"사용자 제한 도달"</string>
     <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398">
@@ -511,13 +510,12 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"모두 지우기"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"관리"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"기록"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"최근 알림"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"무음 알림"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"소리 알림"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"대화"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"무음 알림 모두 삭제"</string>
-    <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"방해 금지 모드로 일시중지된 알림"</string>
+    <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"방해 금지 모드로 알림이 일시중지됨"</string>
     <string name="media_projection_action_text" msgid="3634906766918186440">"시작하기"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"알림 없음"</string>
     <string name="profile_owned_footer" msgid="2756770645766113964">"프로필이 모니터링될 수 있음"</string>
@@ -969,7 +967,7 @@
     <string name="running_foreground_services_title" msgid="5137313173431186685">"백그라운드에서 실행 중인 앱"</string>
     <string name="running_foreground_services_msg" msgid="3009459259222695385">"탭하여 배터리 및 데이터 사용량 확인"</string>
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"모바일 데이터를 사용 중지하시겠습니까?"</string>
-    <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g>을(를) 통해 데이터 또는 인터넷에 액세스할 수 없습니다. 인터넷은 Wi-Fi를 통해서만 사용할 수 있습니다."</string>
+    <string name="mobile_data_disable_message" msgid="8604966027899770415">"<xliff:g id="CARRIER">%s</xliff:g>을(를) 통해 데이터 또는 인터넷에 액세스할 수 없게 됩니다. 인터넷은 Wi-Fi를 통해서만 사용할 수 있습니다."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"이동통신사"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"앱이 권한 요청을 가리고 있기 때문에 설정에서 내 응답을 확인할 수 없습니다."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g>에서 <xliff:g id="APP_2">%2$s</xliff:g>의 슬라이스를 표시하도록 허용하시겠습니까?"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"제목 없음"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"탭하여 이 앱을 다시 시작하고 전체 화면으로 이동합니다."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> 대화창 설정"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"더보기"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"스택에 다시 추가"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"관리"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g>의 <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> 외 <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>개의 <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1017,7 +1013,7 @@
     <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"대화 섹션의 상단에 표시"</string>
     <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"잠금 화면에서 프로필 사진 표시"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"앱 상단에서 플로팅 대화창으로 표시"</string>
-    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"방해 금지 모드 제외"</string>
+    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"방해 금지 모드 무시"</string>
     <string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"확인"</string>
     <string name="magnification_overlay_title" msgid="6584179429612427958">"확대 오버레이 창"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"확대 창"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">제어 기능 <xliff:g id="NUMBER_1">%s</xliff:g>개가 추가되었습니다.</item>
       <item quantity="one">제어 기능 <xliff:g id="NUMBER_0">%s</xliff:g>개가 추가되었습니다.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"삭제됨"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"즐겨찾기에 추가됨"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"즐겨찾기에 추가됨, 위치 <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"즐겨찾기에서 삭제됨"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"즐겨찾기"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"즐겨찾기에서 삭제"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"다음 위치로 이동: <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"제어"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"전원 메뉴에서 액세스할 컨트롤을 선택합니다."</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"길게 누르고 드래그하여 컨트롤 재정렬"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 15e53cd..88fa0072 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Скриншотту четке кагуу"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Скриншотту алдын ала көрүү"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"экрандан видео жаздырып алуу"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Экрандан жаздырылып алынган видео иштетилүүдө"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды жаздыруу сеансы боюнча учурдагы билдирме"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Жаздырып баштайсызбы?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Жаздыруу учурунда Android тутуму экраныңызда көрүнүп турган жана түзмөктө ойноп жаткан бардык купуя маалыматты жаздырып алат. Буга сырсөздөр, төлөм маалыматы, сүрөттөр, билдирүүлөр жана аудио файлдар кирет."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Баарын тазалап салуу"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Башкаруу"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Таржымал"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Кирүүчү"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Үнсүз билдирмелер"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Эскертүүлөр"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Жазышуулар"</string>
@@ -711,7 +709,7 @@
     <string name="notification_silence_title" msgid="8608090968400832335">"Үнсүз"</string>
     <string name="notification_alert_title" msgid="7629202599338071971">"Шашылыш билдирүү"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Көбүк"</string>
-    <string name="notification_channel_summary_low" msgid="7300447764759926720">"Үн же дирилдөөсүз ой топтоого жардам берет."</string>
+    <string name="notification_channel_summary_low" msgid="7300447764759926720">"Билдирмелер келгенде, үн чыкпайт же дирилдебейт."</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"Билдирүүдөн үн чыгат же дирилдейт."</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"Билдирүүдөн үн чыгат же дирилдейт. <xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосундагы жазышуулар демейки жөндөө боюнча калкып чыкма билдирмелер болуп көрүнөт."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Калкыма ыкчам баскыч менен көңүлүңүздү бул мазмунга буруп турат."</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Аталышы жок"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Бул колдонмону өчүрүп күйгүзүп, толук экранга өтүү үчүн, таптап коюңуз."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> калкып чыкма билдирмелер жөндөөлөрү"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Кошумча меню"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Кайра топтомго кошуу"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Башкаруу"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> колдонмосунан <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> жана дагы <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> колдонмодон <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> көзөмөл кошулду.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> көзөмөл кошулду.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Өчүрүлдү"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Сүйүктүүлөргө кошулду"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Сүйүктүүлөргө <xliff:g id="NUMBER">%d</xliff:g>-позицияга кошулду"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Сүйүктүүлөрдөн чыгарылды"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"сүйүктүүлөргө кошуу"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"сүйүктүүлөрдөн чыгаруу"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g>-позицияга жылдыруу"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Башкаруу элементтери"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Күйгүзүү/өчүрүү баскычынын менюсу үчүн көзөмөлдөрдү тандаңыз"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Башкаруу элементтеринин иретин өзгөртүү үчүн кармап туруп, сүйрөңүз"</string>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index 5a8c5dc..d118d89 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -40,4 +40,6 @@
     <!-- Padding between status bar and bubbles when displayed in expanded state, smaller
          value in landscape since we have limited vertical space-->
     <dimen name="bubble_padding_top">4dp</dimen>
+
+    <dimen name="controls_activity_view_top_offset">25dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 0c403db2..305d678 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4811759950673118541">"ສ່ວນຕິດຕໍ່ຜູ່ໃຊ້ຂອງລະບົບ"</string>
+    <string name="app_label" msgid="4811759950673118541">"ສ່ວນຕິດຕໍ່ຜູ້ໃຊ້ຂອງລະບົບ"</string>
     <string name="status_bar_clear_all_button" msgid="2491321682873657397">"ລຶບ"</string>
     <string name="status_bar_no_notifications_title" msgid="7812479124981107507">"ບໍ່ມີການແຈ້ງເຕືອນ"</string>
     <string name="status_bar_ongoing_events_title" msgid="3986169317496615446">"ດຳເນີນຢູ່"</string>
@@ -715,7 +715,7 @@
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ເອົາໃຈໃສ່ທາງລັດແບບລອຍໄປຫາເນື້ອຫານີ້."</string>
     <string name="notification_channel_summary_priority" msgid="7415770044553264622">"ສະແດງຢູ່ເທິງສຸດຂອງພາກສ່ວນການສົນທະນາ ແລະ ສະແດງເປັນຟອງ."</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ຕັ້ງຄ່າ"</string>
-    <string name="notification_priority_title" msgid="2079708866333537093">"ຄວາມສຳຄັນ"</string>
+    <string name="notification_priority_title" msgid="2079708866333537093">"ສຳຄັນ"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ່ຮອງຮັບການຕັ້ງຄ່າສະເພາະຂອງການສົນທະນາ"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"ບໍ່ມີຟອງຫຼ້າສຸດ"</string>
     <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"ຟອງຫຼ້າສຸດ ແລະ ຟອງທີ່ປິດໄປຈະປາກົດຢູ່ບ່ອນນີ້"</string>
@@ -1027,6 +1027,13 @@
       <item quantity="other">ເພີ່ມ <xliff:g id="NUMBER_1">%s</xliff:g> ການຄວບຄຸມແລ້ວ.</item>
       <item quantity="one">ເພີ່ມ <xliff:g id="NUMBER_0">%s</xliff:g> ການຄວບຄຸມແລ້ວ.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"ລຶບອອກແລ້ວ"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"ເພີ່ມລາຍການທີ່ມັກແລ້ວ"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ເພີ່ມລາຍການທີ່ມັກແລ້ວ, ຕຳແໜ່ງ <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ຍົກເລີກລາຍການທີ່ມັກແລ້ວ"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"ເພີ່ມລາຍການທີ່ມັກ"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"ຍົກເລີກລາຍການທີ່ມັກ"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"ຍ້າຍໄປຕຳແໜ່ງ <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"ການຄວບຄຸມ"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"ເລືອກການຄວບຄຸມເພື່ອເຂົ້າເຖິງຈາກເມນູເປີດປິດ"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"ກົດຄ້າງໄວ້ເພື່ອຈັດຮຽງການຄວບຄຸມຄືນໃໝ່"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 95570bc..7c31473 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Praleisti ekrano kopiją"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekrano kopijos peržiūra"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekrano vaizdo įrašytuvas"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Apdorojam. ekrano vaizdo įraš."</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Šiuo metu rodomas ekrano įrašymo sesijos pranešimas"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Pradėti įrašymą?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Įrašant „Android“ sistema gali fiksuoti bet kokią neskelbtiną informaciją, rodomą ekrane ar leidžiamą įrenginyje. Tai apima slaptažodžius, išsamią mokėjimo informaciją, nuotraukas, pranešimus ir garso įrašus."</string>
@@ -517,8 +516,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Viską išvalyti"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Tvarkyti"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Istorija"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Gaunami"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Tylieji pranešimai"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Įspėjamieji pranešimai"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Pokalbiai"</string>
@@ -1001,10 +999,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Nėra pavadinimo"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Palieskite, kad paleistumėte iš naujo šią programą arba įjungtumėte viso ekrano režimą."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ burbulų nustatymai"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Perpildymas"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Pridėti atgal į krūvą"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Tvarkyti"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"„<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>“ iš „<xliff:g id="APP_NAME">%2$s</xliff:g>“"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"„<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>“ iš „<xliff:g id="APP_NAME">%2$s</xliff:g>“ ir dar <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1043,6 +1039,13 @@
       <item quantity="many">Pridėta <xliff:g id="NUMBER_1">%s</xliff:g> valdiklio.</item>
       <item quantity="other">Pridėta <xliff:g id="NUMBER_1">%s</xliff:g> valdiklių.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Pašalinta"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Įtraukta į mėgstamiausius"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Įtraukta į mėgstamiausius, padėtis: <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Pašalinta iš mėgstamiausių"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"įtraukti į mėgstamiausius"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"pašalinti iš mėgstamiausių"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Perkelti į <xliff:g id="NUMBER">%d</xliff:g> padėtį"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Valdikliai"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Pasirinkite valdiklius, kuriuos norite pasiekti įjungimo meniu"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Norėdami pertvarkyti valdiklius, vilkite laikydami nuspaudę"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 3a01e0e..211e363 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Nerādīt ekrānuzņēmumu"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekrānuzņēmuma priekšskatījums"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekrāna ierakstītājs"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekrāna ieraksta apstrāde"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Aktīvs paziņojums par ekrāna ierakstīšanas sesiju"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Vai sākt ierakstīšanu?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Ierakstīšanas laikā Android sistēmā var tikt tverta jebkura sensitīvā informācija, kas ir redzama jūsu ekrānā vai tiek atskaņota jūsu ierīcē. Šī informācija ir paroles, maksājumu informācija, fotoattēli, ziņojumi un audio."</string>
@@ -514,8 +513,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Dzēst visu"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Pārvaldīt"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Vēsture"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Ienākošie"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Klusie paziņojumi"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Paziņojumi ar skaņu vai vibrāciju"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Sarunas"</string>
@@ -996,10 +994,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Nav nosaukuma"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Pieskarieties, lai restartētu šo lietotni un pārietu pilnekrāna režīmā."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> burbuļu iestatījumi"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Pārpilde"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Pievienot atpakaļ kopai"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Pārvaldīt"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> no: <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> no lietotnes “<xliff:g id="APP_NAME">%2$s</xliff:g>” un vēl <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1037,6 +1033,13 @@
       <item quantity="one">Pievienota <xliff:g id="NUMBER_1">%s</xliff:g> vadīkla.</item>
       <item quantity="other">Pievienotas <xliff:g id="NUMBER_1">%s</xliff:g> vadīklas.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Noņemta"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Pievienota izlasei"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Pievienota izlasei, <xliff:g id="NUMBER">%d</xliff:g>. pozīcija"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Noņemta no izlases"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"pievienotu izlasei"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"noņemtu no izlases"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Pārvietot uz <xliff:g id="NUMBER">%d</xliff:g>. pozīciju"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Vadīklas"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Izvēlieties vadīklas, kurām piekļūt no barošanas izvēlnes"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Lai pārkārtotu vadīklas, turiet un velciet tās"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 7aab7f6..45e37d6 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Отфрлете ја сликата од екранот"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Преглед на слика од екранот"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Снимач на екран"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Се обработува снимка од екран"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Тековно известување за сесија за снимање на екранот"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Да се започне со снимање?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"При снимањето, системот Android може да ги сними сите чувствителни податоци што се видливи на вашиот екран или пуштени на уредот. Ова вклучува лозинки, податоци за плаќање, фотографии, пораки и аудио."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Избриши сѐ"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Управувајте"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Историја"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Дојдовни"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Тивки известувања"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Известувања за предупредување"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Разговори"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Без наслов"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Допрете за да ја рестартирате апликацијава и да ја отворите на цел екран."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Поставки за балончињата за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Прелевање"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Додајте назад во stack"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Управување"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> од <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> од <xliff:g id="APP_NAME">%2$s</xliff:g> и уште <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="one">Додадена е <xliff:g id="NUMBER_1">%s</xliff:g> контрола.</item>
       <item quantity="other">Додадени се <xliff:g id="NUMBER_1">%s</xliff:g> контроли.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Отстранета"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Омилена"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Омилена, позиција <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Неомилена"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"означите како омилена"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"означите како неомилена"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Преместете на позиција <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Контроли"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Изберете ги контролите до кои ќе пристапувате од менито за вклучување"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Задржете и влечете за да ги преуредите контролите"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 466d6d4..63aa40e 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"സ്ക്രീൻഷോട്ട് ഡിസ്‌മിസ് ചെയ്യുക"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"സ്‌ക്രീൻഷോട്ട് പ്രിവ്യു"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"സ്ക്രീൻ റെക്കോർഡർ"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"സ്ക്രീൻ റെക്കോർഡിംഗ് പ്രോസസുചെയ്യുന്നു"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ഒരു സ്ക്രീൻ റെക്കോർഡിംഗ് സെഷനായി നിലവിലുള്ള അറിയിപ്പ്"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"റെക്കോർഡിംഗ് ആരംഭിക്കണോ?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"റെക്കോർഡ് ചെയ്യുമ്പോൾ, നിങ്ങളുടെ സ്‌ക്രീനിൽ ദൃശ്യമാകുന്നതോ ഉപകരണത്തിൽ പ്ലേ ചെയ്യുന്നതോ ആയ ഏത് തന്ത്രപ്രധാന വിവരങ്ങളും Android സിസ്റ്റത്തിന് പകർത്താനാവും. പാസ്‍വേഡുകൾ, പേയ്‌മെന്റ് വിവരം, ഫോട്ടോകൾ, സന്ദേശങ്ങൾ, ഓഡിയോ എന്നിവ ഇതിൽ ഉൾപ്പെടുന്നു."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"എല്ലാം മായ്‌ക്കുക"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"മാനേജ് ചെയ്യുക"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ചരിത്രം"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"ഇൻകമിംഗ്"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"നിശബ്‌ദ അറിയിപ്പുകൾ"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"മുന്നറിയിപ്പ് നൽകുന്ന അറിയിപ്പുകൾ"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"സംഭാഷണങ്ങൾ"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"പേരില്ല"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"ഈ ആപ്പ് റീസ്‌റ്റാർട്ട് ചെയ്യാനും പൂർണ്ണ സ്‌ക്രീനാവാനും ടാപ്പ് ചെയ്യുക."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> ബബിളുകളുടെ ക്രമീകരണം"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"ഓവർഫ്ലോ"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"അടുക്കുകളിലേക്ക് തിരിച്ച് ചേർക്കുക"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"മാനേജ് ചെയ്യുക"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g>-ൽ നിന്നുള്ള <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> എന്നതിൽ നിന്നുള്ള <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> കൂടുതലും"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> നിയന്ത്രണങ്ങൾ ചേർത്തു.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> നിയന്ത്രണം ചേർത്തു.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"നീക്കം ചെയ്‌തു"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"പ്രിയപ്പെട്ടതാക്കി"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"പ്രിയപ്പെട്ടതാക്കി, സ്ഥാനം <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"പ്രിയപ്പെട്ടതല്ലാതാക്കി"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"പ്രിയപ്പെട്ടതാക്കുക"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"പ്രിയപ്പെട്ടതല്ലാതാക്കുക"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g>-ാം സ്ഥാനത്തേയ്ക്ക് നീക്കുക"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"നിയന്ത്രണങ്ങൾ"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"പവർ മെനുവിൽ നിന്ന് ആക്സസ് ചെയ്യേണ്ട നിയന്ത്രണങ്ങൾ തിരഞ്ഞെടുക്കുക"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"നിയന്ത്രണങ്ങൾ പുനഃക്രമീകരിക്കാൻ പിടിച്ച് വലിച്ചിടുക"</string>
@@ -1039,10 +1042,8 @@
     <string name="controls_favorite_load_error" msgid="2533215155804455348">"എല്ലാ നിയന്ത്രണങ്ങളുടെയും ലിസ്റ്റ് ലോഡ് ചെയ്യാനായില്ല."</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"മറ്റുള്ളവ"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"ഉപകരണ നിയന്ത്രണങ്ങളിലേക്ക് ചേർക്കുക"</string>
-    <!-- no translation found for controls_dialog_ok (2770230012857881822) -->
-    <skip />
-    <!-- no translation found for controls_dialog_message (342066938390663844) -->
-    <skip />
+    <string name="controls_dialog_ok" msgid="2770230012857881822">"ചേർക്കുക"</string>
+    <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> നിർദ്ദേശിച്ചത്"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"നിയന്ത്രണങ്ങൾ അപ്ഡേറ്റ് ചെയ്തു"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"പിന്നിൽ അക്ഷരങ്ങളോ ചിഹ്നങ്ങളോ അടങ്ങിയിരിക്കുന്നു"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> പരിശോധിച്ചുറപ്പിക്കുക"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index dcff600..a007553 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -45,7 +45,7 @@
     <string name="status_bar_settings_notifications" msgid="5285316949980621438">"Мэдэгдэл"</string>
     <string name="bluetooth_tethered" msgid="4171071193052799041">"Блютүүтыг модем болгож байна"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="2972273031043777851">"Оруулах аргыг тохируулах"</string>
-    <string name="status_bar_use_physical_keyboard" msgid="4849251850931213371">"Бодит гар"</string>
+    <string name="status_bar_use_physical_keyboard" msgid="4849251850931213371">"Биет гар"</string>
     <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g>-г <xliff:g id="USB_DEVICE">%2$s</xliff:g>-д хандахыг зөвшөөрөх үү?"</string>
     <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g>-д <xliff:g id="USB_DEVICE">%2$s</xliff:g>-д хандахыг зөвшөөрөх үү?\nЭнэ аппад бичих зөвшөөрөл олгогдоогүй ч USB төхөөрөмжөөр дамжуулан аудио бичиж чадсан."</string>
     <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g>-г <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>-д хандахыг зөвшөөрөх үү?"</string>
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Дэлгэцийн агшныг хаах"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Дэлгэцийн агшныг урьдчилан үзэх"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Дэлгэцийн үйлдэл бичигч"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Дэлгэц бичлэг боловсруулж байна"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Дэлгэц бичих горимын үргэлжилж буй мэдэгдэл"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Бичлэгийг эхлүүлэх үү?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Бичих үед Андройд систем нь таны дэлгэц дээр харагдах эсвэл төхөөрөмж дээрээ тоглуулсан аливаа эмзэг мэдээллийг авах боломжтой. Үүнд нууц үг, төлбөрийн мэдээлэл, зураг, зурвас болон аудио багтана."</string>
@@ -299,8 +298,8 @@
     <string name="accessibility_quick_settings_flashlight_on" msgid="3785616827729850766">"Флаш гэрэл ассан."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3782375441381402599">"Флаш гэрлийг унтраасан."</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="4747870681508334200">"Флаш гэрлийг асаасан."</string>
-    <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="7548045840282925393">"Өнгө урвуулагчийг унтраасан."</string>
-    <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="4711141858364404084">"Өнгө урвуулагчийг асаасан."</string>
+    <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="7548045840282925393">"Өнгө хувиргалтыг унтраасан."</string>
+    <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="4711141858364404084">"Өнгө хувиргалтыг асаасан."</string>
     <string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"Мобайл хотспотыг унтраасан."</string>
     <string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"Мобайл хотспотыг асаасан."</string>
     <string name="accessibility_casting_turned_off" msgid="1387906158563374962">"Дэлгэц дамжуулалт зогссон."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Бүгдийг арилгах"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Удирдах"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Түүх"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Ирж буй"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Чимээгүй мэдэгдэл"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Сэрэмжлүүлэх мэдэгдэл"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Харилцан яриа"</string>
@@ -695,7 +693,7 @@
     <string name="notification_channel_unsilenced" msgid="94878840742161152">"Эдгээр мэдэгдлийг танд мэдэгдэнэ"</string>
     <string name="inline_blocking_helper" msgid="2891486013649543452">"Та эдгээр мэдэгдлийг ихэвчлэн хаадаг. \nЭдгээрийг харуулсан хэвээр байх уу?"</string>
     <string name="inline_done_button" msgid="6043094985588909584">"Болсон"</string>
-    <string name="inline_ok_button" msgid="603075490581280343">"Хаах"</string>
+    <string name="inline_ok_button" msgid="603075490581280343">"Ашиглах"</string>
     <string name="inline_keep_showing" msgid="8736001253507073497">"Эдгээр мэдэгдлийг харуулсан хэвээр байх уу?"</string>
     <string name="inline_stop_button" msgid="2453460935438696090">"Мэдэгдлийг зогсоох"</string>
     <string name="inline_deliver_silently_button" msgid="2714314213321223286">"Дуугүй хүргэх"</string>
@@ -712,7 +710,7 @@
     <string name="notification_alert_title" msgid="7629202599338071971">"Дуутай"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Бөмбөлөг"</string>
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"Дуу эсвэл чичиргээгүйгээр танд төвлөрөхөд тусална."</string>
-    <string name="notification_channel_summary_default" msgid="3539949463907902037">"Дуу эсвэл чичиргээгүйгээр таны анхаарлыг татна."</string>
+    <string name="notification_channel_summary_default" msgid="3539949463907902037">"Дуу эсвэл чичиргээгээр таны анхаарлыг татна."</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"Дуу эсвэл чичиргээгээр таны анхаарлыг татна. <xliff:g id="APP_NAME">%1$s</xliff:g>-н харилцан яриаг өгөгдмөл тохиргоогоор бөмбөлөг болгоно."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Энэ контентын хөвөн гарч ирэх товчлолтойгоор таны анхаарлыг татдаг."</string>
     <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Харилцан ярианы хэсгийн дээд талд, бөмбөлөг хэлбэрээр харагдана."</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Гарчиггүй"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Энэ аппыг дахин эхлүүлж, бүтэн дэлгэцэд орохын тулд товшино уу."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g>-н бөмбөлгүүдийн тохиргоо"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Халих"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Өрөлтөд буцааж нэмэх"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Удирдах"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g>-н <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g>-н <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> болон бусад <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> хяналтыг нэмлээ.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> хяналтыг нэмлээ.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Хассан"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Дуртай гэж тэмдэглэсэн"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"<xliff:g id="NUMBER">%d</xliff:g>-р байршилд дуртай гэж тэмдэглэсэн"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Дургүй гэж тэмдэглэсэн"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"дуртай гэж тэмдэглэх"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"дургүй гэж тэмдэглэх"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g>-р байрлал руу зөөх"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Хяналт"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Тэжээлийн цэсээс хандах хяналтуудыг сонгоно уу"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Хяналтуудыг дахин засварлахын тулд дараад чирнэ үү"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 5497d70..5cf0ebb 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -22,7 +22,7 @@
     <string name="app_label" msgid="4811759950673118541">"सिस्टम UI"</string>
     <string name="status_bar_clear_all_button" msgid="2491321682873657397">"साफ करा"</string>
     <string name="status_bar_no_notifications_title" msgid="7812479124981107507">"सूचना नाहीत"</string>
-    <string name="status_bar_ongoing_events_title" msgid="3986169317496615446">"सुरु असलेले"</string>
+    <string name="status_bar_ongoing_events_title" msgid="3986169317496615446">"सुरू असलेले"</string>
     <string name="status_bar_latest_events_title" msgid="202755896454005436">"सूचना"</string>
     <string name="battery_low_title" msgid="6891106956328275225">"बॅटरी लवकर संपू शकते"</string>
     <string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> शिल्लक"</string>
@@ -35,7 +35,7 @@
     <string name="battery_low_why" msgid="2056750982959359863">"सेटिंग्ज"</string>
     <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"बॅटरी सेव्हर सुरू करायचा का?"</string>
     <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"बॅटरी सेव्हर बाबत"</string>
-    <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"चालू करा"</string>
+    <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"सुरू करा"</string>
     <string name="battery_saver_start_action" msgid="4553256017945469937">"बॅटरी सेव्हर सुरू करा"</string>
     <string name="status_bar_settings_settings_button" msgid="534331565185171556">"सेटिंग्ज"</string>
     <string name="status_bar_settings_wifi_button" msgid="7243072479837270946">"वाय-फाय"</string>
@@ -62,7 +62,7 @@
     <string name="usb_debugging_always" msgid="4003121804294739548">"या संगणकावरून नेहमी अनुमती द्या"</string>
     <string name="usb_debugging_allow" msgid="1722643858015321328">"अनुमती द्या"</string>
     <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"USB डीबग करण्‍यास अनुमती नाही"</string>
-    <string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"सध्‍या या डीव्हाइसमध्‍ये साइन इन केलेला वापरकर्ता USB डीबग करणे चालू करू शकत नाही. हे वैशिष्‍ट्य वापरण्‍यासाठी, प्राथमिक वापरकर्त्‍यावर स्विच करा."</string>
+    <string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"सध्‍या या डीव्हाइसमध्‍ये साइन इन केलेला वापरकर्ता USB डीबग करणे सुरू करू शकत नाही. हे वैशिष्‍ट्य वापरण्‍यासाठी, प्राथमिक वापरकर्त्‍यावर स्विच करा."</string>
     <string name="wifi_debugging_title" msgid="7300007687492186076">"या नेटवर्कवर वायरलेस डीबगिंग करण्याला अनुमती द्यायची का?"</string>
     <string name="wifi_debugging_message" msgid="5461204211731802995">"नेटवर्कचे नाव (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nवाय-फाय ॲड्रेस (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
     <string name="wifi_debugging_always" msgid="2968383799517975155">"या नेटवर्कवर नेहमी अनुमती द्या"</string>
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"स्क्रीनशॉट डिसमिस करा"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"स्क्रीनशॉटचे पूर्वावलोकन"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"स्क्रीन रेकॉर्डर"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रीन रेकॉर्डिंग प्रोसेस सुरू"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रेकॉर्ड सत्रासाठी सुरू असलेली सूचना"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"रेकॉर्डिंग सुरू करायचे आहे का?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"रेकॉर्डिंग करताना, Android सिस्टम तुमच्या स्क्रीनवर दिसणारी किंवा तुमच्या डिव्हाइसवर प्ले केलेली कोणतीही संवेदनशील माहिती कॅप्चर करू शकते. यात पासवर्ड, पेमेंट माहिती, फोटो, मेसेज आणि ऑडिओचा समावेश आहे."</string>
@@ -211,7 +210,7 @@
     <string name="accessibility_two_bars" msgid="1335676987274417121">"दोन बार."</string>
     <string name="accessibility_three_bars" msgid="819417766606501295">"तीन बार."</string>
     <string name="accessibility_signal_full" msgid="5920148525598637311">"सिग्नल पूर्ण."</string>
-    <string name="accessibility_desc_on" msgid="2899626845061427845">"चालू."</string>
+    <string name="accessibility_desc_on" msgid="2899626845061427845">"सुरू."</string>
     <string name="accessibility_desc_off" msgid="8055389500285421408">"बंद."</string>
     <string name="accessibility_desc_connected" msgid="3082590384032624233">"कनेक्‍ट केले."</string>
     <string name="accessibility_desc_connecting" msgid="8011433412112903614">"कनेक्ट करत आहे."</string>
@@ -236,7 +235,7 @@
     <string name="cell_data_off" msgid="4886198950247099526">"बंद"</string>
     <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ब्लूटूथ टेदरिंग."</string>
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"विमान मोड."</string>
-    <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN चालू."</string>
+    <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN सुरू."</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"सिम कार्ड नाही."</string>
     <string name="carrier_network_change_mode" msgid="5174141476991149918">"वाहक नेटवर्क बदलत आहे"</string>
     <string name="accessibility_battery_details" msgid="6184390274150865789">"बॅटरी तपशील उघडा"</string>
@@ -267,13 +266,13 @@
     <string name="accessibility_desc_close" msgid="8293708213442107755">"बंद करा"</string>
     <string name="accessibility_quick_settings_wifi" msgid="167707325133803052">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string>
     <string name="accessibility_quick_settings_wifi_changed_off" msgid="2230487165558877262">"Wifi बंद झाले."</string>
-    <string name="accessibility_quick_settings_wifi_changed_on" msgid="1490362586009027611">"Wifi चालू झाले."</string>
+    <string name="accessibility_quick_settings_wifi_changed_on" msgid="1490362586009027611">"Wifi सुरू झाले."</string>
     <string name="accessibility_quick_settings_mobile" msgid="1817825313718492906">"मोबाईल <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
     <string name="accessibility_quick_settings_battery" msgid="533594896310663853">"बॅटरी <xliff:g id="STATE">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_airplane_off" msgid="1275658769368793228">"विमान मोड बंद."</string>
-    <string name="accessibility_quick_settings_airplane_on" msgid="8106176561295294255">"विमान मोड चालू."</string>
+    <string name="accessibility_quick_settings_airplane_on" msgid="8106176561295294255">"विमान मोड सुरू."</string>
     <string name="accessibility_quick_settings_airplane_changed_off" msgid="8880183481476943754">"विमान मोड बंद केला."</string>
-    <string name="accessibility_quick_settings_airplane_changed_on" msgid="6327378061894076288">"विमान मोड चालू केला."</string>
+    <string name="accessibility_quick_settings_airplane_changed_on" msgid="6327378061894076288">"विमान मोड सुरू केला."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"संपूर्ण शांतता"</string>
     <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3375848309132140014">"फक्‍त अलार्म"</string>
     <string name="accessibility_quick_settings_dnd" msgid="2415967452264206047">"व्यत्यय आणू नका."</string>
@@ -281,35 +280,35 @@
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="186315911607486129">"व्यत्यय आणू नका सुरू केले आहे."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="8250942386687551283">"ब्लूटूथ."</string>
     <string name="accessibility_quick_settings_bluetooth_off" msgid="3795983516942423240">"ब्लूटूथ बंद."</string>
-    <string name="accessibility_quick_settings_bluetooth_on" msgid="3819082137684078013">"ब्लूटूथ चालू."</string>
+    <string name="accessibility_quick_settings_bluetooth_on" msgid="3819082137684078013">"ब्लूटूथ सुरू."</string>
     <string name="accessibility_quick_settings_bluetooth_connecting" msgid="7362294657419149294">"ब्लूटूथ कनेक्ट करत आहे."</string>
     <string name="accessibility_quick_settings_bluetooth_connected" msgid="5237625393869747261">"ब्लूटूथ कनेक्‍ट केले."</string>
     <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="3344226652293797283">"ब्लूटूथ बंद केले."</string>
-    <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="1263282011749437549">"ब्लूटूथ चालू केले."</string>
+    <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_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_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>
     <string name="accessibility_quick_settings_less_time" msgid="9110364286464977870">"कमी वेळ."</string>
     <string name="accessibility_quick_settings_flashlight_off" msgid="7606563260714825190">"फ्लॅशलाइट बंद."</string>
     <string name="accessibility_quick_settings_flashlight_unavailable" msgid="7458591827288347635">"फ्लॅशलाइट अनुपलब्ध आहे."</string>
-    <string name="accessibility_quick_settings_flashlight_on" msgid="3785616827729850766">"फ्लॅशलाइट चालू."</string>
+    <string name="accessibility_quick_settings_flashlight_on" msgid="3785616827729850766">"फ्लॅशलाइट सुरू."</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3782375441381402599">"फ्लॅशलाइट बंद केला."</string>
-    <string name="accessibility_quick_settings_flashlight_changed_on" msgid="4747870681508334200">"फ्लॅशलाइट चालू केला."</string>
+    <string name="accessibility_quick_settings_flashlight_changed_on" msgid="4747870681508334200">"फ्लॅशलाइट सुरू केला."</string>
     <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="7548045840282925393">"रंग उत्क्रमण बंद केले."</string>
-    <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="4711141858364404084">"रंग उत्क्रमण चालू केले."</string>
+    <string name="accessibility_quick_settings_color_inversion_changed_on" msgid="4711141858364404084">"रंग उत्क्रमण सुरू केले."</string>
     <string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"मोबाईल हॉटस्पॉट बंद केला."</string>
-    <string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"मोबाईल हॉटस्पॉट चालू केला."</string>
+    <string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"मोबाईल हॉटस्पॉट सुरू केला."</string>
     <string name="accessibility_casting_turned_off" msgid="1387906158563374962">"स्क्रीन कास्ट करणे थांबले."</string>
     <string name="accessibility_quick_settings_work_mode_off" msgid="562749867895549696">"कार्य मोड बंद."</string>
-    <string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"कार्य मोड चालू."</string>
+    <string name="accessibility_quick_settings_work_mode_on" msgid="2779253456042059110">"कार्य मोड सुरू."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="6256690740556798683">"कार्य मोड बंद केला."</string>
-    <string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"कार्य मोड चालू केला."</string>
+    <string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"कार्य मोड सुरू केला."</string>
     <string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"डेटा सर्व्हर बंद केला."</string>
-    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"डेटा सर्व्हर चालू केला."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="6370606590802623078">"डेटा सर्व्हर सुरू केला."</string>
     <string name="accessibility_quick_settings_sensor_privacy_changed_off" msgid="7608378211873807353">"सेन्सर गोपनीयता बंद केली आहे."</string>
     <string name="accessibility_quick_settings_sensor_privacy_changed_on" msgid="4267393685085328801">"सेन्सर गोपनीयता सुरू केली आहे."</string>
     <string name="accessibility_brightness" msgid="5391187016177823721">"डिस्प्ले चमक"</string>
@@ -319,7 +318,7 @@
     <string name="data_usage_disabled_dialog_mobile_title" msgid="2286843518689837719">"मोबाइल डेटा थांबवला आहे"</string>
     <string name="data_usage_disabled_dialog_title" msgid="9131615296036724838">"डेटास विराम दिला आहे"</string>
     <string name="data_usage_disabled_dialog" msgid="7933201635215099780">"तुम्ही सेट केलेली डेटा मर्यादा संपली. आता तुमचे मोबाइल डेटा वापरणे बंद आहे.\n\nतुम्ही ते पुन्हा सुरू केल्यास, डेटा वापरासाठी शुल्क लागू होईल."</string>
-    <string name="data_usage_disabled_dialog_enable" msgid="2796648546086408937">"पुन्हा सुरु करा"</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="accessibility_location_active" msgid="2845747916764660369">"स्थान विनंत्या सक्रिय"</string>
@@ -379,7 +378,7 @@
     <string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"कनेक्ट केले नाही"</string>
     <string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"नेटवर्क नाही"</string>
     <string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"वाय-फाय बंद"</string>
-    <string name="quick_settings_wifi_on_label" msgid="2489928193654318511">"वाय-फाय चालू"</string>
+    <string name="quick_settings_wifi_on_label" msgid="2489928193654318511">"वाय-फाय सुरू"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"वाय-फाय नेटवर्क उपलब्‍ध नाहीत"</string>
     <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"सुरू करत आहे…"</string>
     <string name="quick_settings_cast_title" msgid="2279220930629235211">"स्क्रीन कास्ट करा"</string>
@@ -417,9 +416,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावणी"</string>
     <string name="quick_settings_work_mode_label" msgid="2754212289804324685">"कार्य प्रोफाइल"</string>
     <string name="quick_settings_night_display_label" msgid="8180030659141778180">"रात्रीचा प्रकाश"</string>
-    <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"संध्याकाळी चालू असते"</string>
+    <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"संध्याकाळी सुरू असते"</string>
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"सूर्योदयापर्यंत"</string>
-    <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> वाजता चालू"</string>
+    <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g> वाजता सुरू"</string>
     <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> पर्यंत"</string>
     <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"गडद थीम"</string>
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"बॅटरी सेव्‍हर"</string>
@@ -481,9 +480,9 @@
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"या सत्रातील सर्व अ‍ॅप्स आणि डेटा हटवला जाईल."</string>
     <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"काढा"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"अतिथी, तुमचे पुन्‍हा स्‍वागत आहे!"</string>
-    <string name="guest_wipe_session_message" msgid="3393823610257065457">"तुम्ही तुमचे सत्र सुरु ठेवू इच्छिता?"</string>
+    <string name="guest_wipe_session_message" msgid="3393823610257065457">"तुम्ही तुमचे सत्र सुरू ठेवू इच्छिता?"</string>
     <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"येथून सुरू करा"</string>
-    <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"होय, सुरु ठेवा"</string>
+    <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"होय, सुरू ठेवा"</string>
     <string name="guest_notification_title" msgid="4434456703930764167">"अतिथी वापरकर्ता"</string>
     <string name="guest_notification_text" msgid="4202692942089571351">"अ‍ॅप्स आणि डेटा हटविण्‍यासाठी, अतिथी वापरकर्ता काढा"</string>
     <string name="guest_notification_remove_action" msgid="4153019027696868099">"अतिथी काढा"</string>
@@ -511,10 +510,9 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"सर्व साफ करा"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"व्यवस्थापित करा"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"इतिहास"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"आलेल्या"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"सायलंट सूचना"</string>
-    <string name="notification_section_header_alerting" msgid="3168140660646863240">"लक्ष वेधून घेणाऱ्या सूचना"</string>
+    <string name="notification_section_header_alerting" msgid="3168140660646863240">"इशारा देणाऱ्या सूचना"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"संभाषणे"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"सर्व सायलंट सूचना साफ करा"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"व्यत्यय आणून नकाद्वारे सूचना थांबवल्या"</string>
@@ -552,7 +550,7 @@
     <string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"आपल्या संस्थेने या डिव्हाइसवर प्रमाणपत्र अधिकार इंस्टॉल केला आहे. आपल्या सुरक्षित नेटवर्क रहदारीचे परीक्षण केले जाऊ शकते किंवा ती सुधारली जाऊ शकते."</string>
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"आपल्या संस्थेने आपल्या कार्य प्रोफाइलवर प्रमाणपत्र अधिकार इंस्टॉल केला आहे. आपल्या सुरक्षित नेटवर्क रहदारीचे परीक्षण केले जाऊ शकते किंवा ती सुधारली जाऊ शकते."</string>
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"या डिव्हाइसवर प्रमाणपत्र अधिकार इंस्टॉल केला आहे. आपल्या सुरक्षित नेटवर्क रहदारीचे परीक्षण केले जाऊ शकते किंवा ती सुधारली जाऊ शकते."</string>
-    <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"आपल्या प्रशासकाने नेटवर्क लॉगिंग चालू केले आहे, जे आपल्या डिव्हाइसवरील रहदारीचे परीक्षण करते."</string>
+    <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"आपल्या प्रशासकाने नेटवर्क लॉगिंग सुरू केले आहे, जे आपल्या डिव्हाइसवरील रहदारीचे परीक्षण करते."</string>
     <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"तुम्‍ही <xliff:g id="VPN_APP">%1$s</xliff:g> शी कनेक्‍ट केले आहे, जे ईमेल, अ‍ॅप्स आणि वेबसाइटसहित आपल्‍या नेटवर्क क्रिया मॉनिटर करू शकते."</string>
     <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"तुम्‍ही <xliff:g id="VPN_APP_0">%1$s</xliff:g> आणि <xliff:g id="VPN_APP_1">%2$s</xliff:g> शी कनेक्‍ट केले आहे, जे ईमेल, अ‍ॅप्स आणि वेबसाइटसहित आपल्‍या नेटवर्क क्रिया मॉनिटर करू शकते."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"तुमचे कार्य प्रोफाइल <xliff:g id="VPN_APP">%1$s</xliff:g> शी कनेक्‍ट केले आहे, जे ईमेल, अ‍ॅप्स आणि वेबसाइटसह आपल्‍या नेटवर्क क्रियाकलापाचे परीक्षण करू शकते."</string>
@@ -567,7 +565,7 @@
     <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"VPN सेटिंग्ज उघडा"</string>
     <string name="monitoring_description_ca_cert_settings_separator" msgid="7107390013344435439">" "</string>
     <string name="monitoring_description_ca_cert_settings" msgid="8329781950135541003">"विश्वासू क्रेडेंशियल उघडा"</string>
-    <string name="monitoring_description_network_logging" msgid="577305979174002252">"आपल्या प्रशासकाने नेटवर्क लॉगिंग चालू केले आहे, जे आपल्या डिव्हाइसवरील रहदारीचे निरीक्षण करते.\n\nअधिक माहितीसाठी आपल्या प्रशासकाशी संपर्क साधा."</string>
+    <string name="monitoring_description_network_logging" msgid="577305979174002252">"आपल्या प्रशासकाने नेटवर्क लॉगिंग सुरू केले आहे, जे आपल्या डिव्हाइसवरील रहदारीचे निरीक्षण करते.\n\nअधिक माहितीसाठी आपल्या प्रशासकाशी संपर्क साधा."</string>
     <string name="monitoring_description_vpn" msgid="1685428000684586870">"तुम्ही VPN कनेक्शन सेट करण्यासाठी अ‍ॅपला परवानगी दिली.\n\nहा अ‍ॅप ईमेल, अ‍ॅप्स आणि वेबसाइटसह, तुमच्या डिव्हाइस आणि नेटवर्क ॲक्टिव्हिटीचे परीक्षण करू शकतो."</string>
     <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"तुमचे कार्य प्रोफाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> द्वारे व्यवस्थापित केले जाते.\n\nतुमचा प्रशासक ईमेल, अ‍ॅप्स आणि वेबसाइटसह आपल्या नेटवर्क ॲक्टिव्हिटीचे निरीक्षण करण्यास सक्षम आहे.\n\nअधिक माहितीसाठी आपल्या प्रशासकाशी संपर्क साधा.\n\nतुम्ही VPN शी देखील कनेक्ट आहात, जे आपल्या नेटवर्क ॲक्टिव्हिटीचे निरीक्षण करू शकते."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
@@ -608,7 +606,7 @@
     <string name="screen_pinning_start" msgid="5695091877402422575">"स्क्रीन पिन केला"</string>
     <string name="screen_pinning_exit" msgid="5114993350662745840">"स्क्रीन अनपिन केला"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="463533331480997595">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> लपवायचे?"</string>
-    <string name="quick_settings_reset_confirmation_message" msgid="2320586180785674186">"तुम्ही सेटिंग्जमध्ये ते पुढील वेळी चालू कराल तेव्हा ते पुन्हा दिसेल."</string>
+    <string name="quick_settings_reset_confirmation_message" msgid="2320586180785674186">"तुम्ही सेटिंग्जमध्ये ते पुढील वेळी सुरू कराल तेव्हा ते पुन्हा दिसेल."</string>
     <string name="quick_settings_reset_confirmation_button" msgid="3341477479055016776">"लपवा"</string>
     <string name="stream_voice_call" msgid="7468348170702375660">"कॉल करा"</string>
     <string name="stream_system" msgid="7663148785370565134">"सिस्टम"</string>
@@ -638,7 +636,7 @@
     <string name="output_title" msgid="3938776561655668350">"मीडिया आउटपुट"</string>
     <string name="output_calls_title" msgid="7085583034267889109">"फोन कॉल आउटपुट"</string>
     <string name="output_none_found" msgid="5488087293120982770">"कोणतीही डिव्हाइस सापडली नाहीत"</string>
-    <string name="output_none_found_service_off" msgid="935667567681386368">"कोणतीही डिव्हाइस सापडली नाहीत. <xliff:g id="SERVICE">%1$s</xliff:g> चालू करून पाहा"</string>
+    <string name="output_none_found_service_off" msgid="935667567681386368">"कोणतीही डिव्हाइस सापडली नाहीत. <xliff:g id="SERVICE">%1$s</xliff:g> सुरू करून पाहा"</string>
     <string name="output_service_bt" msgid="4315362133973911687">"ब्लूटूथ"</string>
     <string name="output_service_wifi" msgid="9003667810868222134">"वाय-फाय"</string>
     <string name="output_service_bt_wifi" msgid="7186882540475524124">"ब्लूटूथ आणि वाय-फाय"</string>
@@ -665,7 +663,7 @@
     <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>
-    <string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनर आपल्‍याला Android वापरकर्ता इंटरफेस ट्विक आणि कस्टमाइझ करण्‍याचे अनेक प्रकार देते. ही प्रयोगात्मक वैशिष्‍ट्ये बदलू शकतात, खंडित होऊ शकतात किंवा भविष्‍यातील रिलीज मध्‍ये कदाचित दिसणार नाहीत. सावधगिरी बाळगून पुढे सुरु ठेवा."</string>
+    <string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनर आपल्‍याला Android वापरकर्ता इंटरफेस ट्विक आणि कस्टमाइझ करण्‍याचे अनेक प्रकार देते. ही प्रयोगात्मक वैशिष्‍ट्ये बदलू शकतात, खंडित होऊ शकतात किंवा भविष्‍यातील रिलीज मध्‍ये कदाचित दिसणार नाहीत. सावधगिरी बाळगून पुढे सुरू ठेवा."</string>
     <string name="tuner_persistent_warning" msgid="230466285569307806">"ही प्रयोगात्मक वैशिष्‍ट्ये बदलू शकतात, खंडित होऊ शकतात किंवा भविष्‍यातील रिलीज मध्‍ये कदाचित दिसणार नाहीत."</string>
     <string name="got_it" msgid="477119182261892069">"समजले"</string>
     <string name="tuner_toast" msgid="3812684836514766951">"अभिनंदन! सिस्टम UI ट्युनर सेटिंग्जमध्‍ये जोडले गेले आहे"</string>
@@ -678,14 +676,14 @@
     <string name="show_brightness" msgid="6700267491672470007">"द्रुत सेटिंग्जमध्‍ये चमक दर्शवा"</string>
     <string name="experimental" msgid="3549865454812314826">"प्रायोगिक"</string>
     <string name="enable_bluetooth_title" msgid="866883307336662596">"ब्लूटूथ सुरू करायचे?"</string>
-    <string name="enable_bluetooth_message" msgid="6740938333772779717">"तुमचा कीबोर्ड तुमच्या टॅबलेटसह कनेक्ट करण्यासाठी, तुम्ही प्रथम ब्लूटूथ चालू करणे आवश्यक आहे."</string>
-    <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"चालू करा"</string>
+    <string name="enable_bluetooth_message" msgid="6740938333772779717">"तुमचा कीबोर्ड तुमच्या टॅबलेटसह कनेक्ट करण्यासाठी, तुम्ही प्रथम ब्लूटूथ सुरू करणे आवश्यक आहे."</string>
+    <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"सुरू करा"</string>
     <string name="show_silently" msgid="5629369640872236299">"सूचना शांतपणे दर्शवा"</string>
     <string name="block" msgid="188483833983476566">"सर्व सूचना ब्लॉक करा"</string>
     <string name="do_not_silence" msgid="4982217934250511227">"शांत करू नका"</string>
     <string name="do_not_silence_block" msgid="4361847809775811849">"शांत किंवा अवरोधित करू नका"</string>
     <string name="tuner_full_importance_settings" msgid="1388025816553459059">"पॉवर सूचना नियंत्रणे"</string>
-    <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"चालू"</string>
+    <string name="tuner_full_importance_settings_on" msgid="917981436602311547">"सुरू"</string>
     <string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"बंद"</string>
     <string name="power_notification_controls_description" msgid="1334963837572708952">"पॉवर सूचना नियंत्रणांच्या साहाय्याने तुम्ही अ‍ॅप सूचनांसाठी 0 ते 5 असे महत्त्व स्तर सेट करू शकता. \n\n"<b>"स्तर 5"</b>" \n- सूचना सूचीच्या शीर्षस्थानी दाखवा \n- फुल स्क्रीन व्यत्ययास अनुमती द्या \n- नेहमी डोकावून पहा \n\n"<b>"स्तर 4"</b>\n" - फुल स्क्रीन व्यत्ययास प्रतिबंधित करा \n- नेहमी डोकावून पहा \n\n"<b>"स्तर 3"</b>" \n- फुल स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n\n"<b>"स्तर 2"</b>" \n- फुल स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n- कधीही ध्वनी किंवा व्हायब्रेट करू नका \n\n"<b>"स्तर 1"</b>\n"- फुल स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n- कधीही ध्वनी किंवा व्हायब्रेट करू नका \n- लॉक स्क्रीन आणि स्टेटस बार मधून लपवा \n- सूचना सूचीच्या तळाशी दर्शवा \n\n"<b>"स्तर 0"</b>" \n- अ‍ॅपमधील सर्व सूचना ब्लॉक करा"</string>
     <string name="notification_header_default_channel" msgid="225454696914642444">"सूचना"</string>
@@ -921,7 +919,7 @@
     <string name="pip_skip_to_prev" msgid="3742589641443049237">"डावलून मागे जा"</string>
     <string name="thermal_shutdown_title" msgid="2702966892682930264">"तापल्‍यामुळे फोन बंद झाला"</string>
     <string name="thermal_shutdown_message" msgid="7432744214105003895">"तुमचा फोन आता व्‍यवस्थित सुरू आहे"</string>
-    <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"तुमचा फोन खूप तापलाय, म्हणून तो थंड होण्यासाठी बंद झाला आहे. तुमचा फोन आता व्‍यवस्थित सुरू आहे.\n\nतुम्ही असे केल्यास तुमचा फोन खूप तापेल:\n	•संसाधन केंद्रित अ‍ॅप वापरणे (गेमिंग, व्हिडिओ किंवा नेव्हिगेशन अ‍ॅप यासारखे)\n	•मोठ्या फायली डाउनलोड किंवा अपलोड करणे\n	•उच्च तापमानामध्ये तुमचा फोन वापरणे"</string>
+    <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"तुमचा फोन खूप तापलाय, म्हणून तो थंड होण्यासाठी बंद झाला आहे. तुमचा फोन आता व्‍यवस्थित सुरू आहे.\n\nतुम्ही असे केल्यास तुमचा फोन खूप तापेल:\n	•संसाधन केंद्रित अ‍ॅप वापरणे (गेमिंग, व्हिडिओ किंवा नेव्हिगेशन अ‍ॅप यासारखे)\n	•मोठ्या फाइल डाउनलोड किंवा अपलोड करणे\n	•उच्च तापमानामध्ये तुमचा फोन वापरणे"</string>
     <string name="high_temp_title" msgid="2218333576838496100">"फोन ऊष्ण होत आहे"</string>
     <string name="high_temp_notif_message" msgid="163928048626045592">"फोन थंड होत असताना काही वैशिष्‍ट्ये मर्यादित असतात"</string>
     <string name="high_temp_dialog_message" msgid="3793606072661253968">"तुमचा फोन स्वयंचलितपणे थंड होईल. तुम्ही अद्यापही तुमचा फोन वापरू शकता परंतु तो कदाचित धीमेपणे कार्य करेल.\n\nतुमचा फोन एकदा थंड झाला की, तो सामान्यपणे कार्य करेल."</string>
@@ -960,9 +958,9 @@
     <string name="wifi_is_off" msgid="5389597396308001471">"वाय-फाय बंद आहे"</string>
     <string name="bt_is_off" msgid="7436344904889461591">"ब्लूटूथ बंद आहे"</string>
     <string name="dnd_is_off" msgid="3185706903793094463">"व्यत्यय आणू नका बंद आहे"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="3535469468310002616">"व्यत्यय आणू नका एका <xliff:g id="ID_1">%s</xliff:g> स्वयंचलित नियमाने चालू केले."</string>
-    <string name="qs_dnd_prompt_app" msgid="4027984447935396820">"व्यत्यय आणू नका (<xliff:g id="ID_1">%s</xliff:g>) ॲपने चालू केले."</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="1841469944118486580">"व्यत्यय आणू नका एका स्वयंचलित नियमाने किंवा ॲपने चालू केले."</string>
+    <string name="qs_dnd_prompt_auto_rule" msgid="3535469468310002616">"व्यत्यय आणू नका एका <xliff:g id="ID_1">%s</xliff:g> स्वयंचलित नियमाने सुरू केले."</string>
+    <string name="qs_dnd_prompt_app" msgid="4027984447935396820">"व्यत्यय आणू नका (<xliff:g id="ID_1">%s</xliff:g>) ॲपने सुरू केले."</string>
+    <string name="qs_dnd_prompt_auto_rule_app" msgid="1841469944118486580">"व्यत्यय आणू नका एका स्वयंचलित नियमाने किंवा ॲपने सुरू केले."</string>
     <string name="qs_dnd_until" msgid="7844269319043747955">"<xliff:g id="ID_1">%s</xliff:g> पर्यंत"</string>
     <string name="qs_dnd_keep" msgid="3829697305432866434">"ठेवा"</string>
     <string name="qs_dnd_replace" msgid="7712119051407052689">"पुनर्स्थित करा"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"शीर्षक नाही"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"हे अ‍ॅप रीस्टार्ट करण्यासाठी आणि फुल स्क्रीन करण्यासाठी टॅप करा."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> बबलसाठी सेटिंग्ज"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"ओव्हरफ्लो"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"स्टॅकमध्ये परत जोडा"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"व्यवस्थापित करा"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> कडून <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> आणि आणखी <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> कडून <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> नियंत्रणे जोडली.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> नियंत्रण जोडले.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"काढून टाकले"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"आवडले"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"आवडले, स्थान <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"नावडले"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"आवडते"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"नावडते"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g> स्थानावर हलवा"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"नियंत्रणे"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"पॉवर मेनूमधून अ‍ॅक्सेस करण्यासाठी नियंत्रणे निवडा"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"नियंत्रणांची पुनर्रचना करण्यासाठी धरून ठेवा आणि ड्रॅग करा"</string>
@@ -1039,10 +1042,8 @@
     <string name="controls_favorite_load_error" msgid="2533215155804455348">"सर्व नियंत्रणांची सूची लोड करता आली नाही."</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"इतर"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"डिव्हाइस नियंत्रणांमध्ये जोडा"</string>
-    <!-- no translation found for controls_dialog_ok (2770230012857881822) -->
-    <skip />
-    <!-- no translation found for controls_dialog_message (342066938390663844) -->
-    <skip />
+    <string name="controls_dialog_ok" msgid="2770230012857881822">"जोडा"</string>
+    <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ने सुचवले आहे"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"नियंत्रणे अपडेट केली आहेत"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"पिनमध्ये अक्षरांचा किंवा चिन्हांचा समावेश असतो"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> ची पडताळणी करा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index e394480..44bd1a6 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Ketepikan tangkapan skrin"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pratonton tangkapan skrin"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Perakam Skrin"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Memproses rakaman skrin"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pemberitahuan breterusan untuk sesi rakaman skrin"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Mula Merakam?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Semasa merakam, Sistem Android dapat menangkap mana-mana maklumat sensitif yang kelihatan pada skrin anda atau yang dimainkan pada peranti anda. Ini termasuklah kata laluan, maklumat pembayaran, foto, mesej dan audio."</string>
@@ -390,7 +389,7 @@
     <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi-Fi tidak disambungkan"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Kecerahan"</string>
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="2325362583903258677">"AUTO"</string>
-    <string name="quick_settings_inversion_label" msgid="5078769633069667698">"Terbalikkan warna"</string>
+    <string name="quick_settings_inversion_label" msgid="5078769633069667698">"Songsangkan warna"</string>
     <string name="quick_settings_color_space_label" msgid="537528291083575559">"Mod pembetulan warna"</string>
     <string name="quick_settings_more_settings" msgid="2878235926753776694">"Lagi tetapan"</string>
     <string name="quick_settings_done" msgid="2163641301648855793">"Selesai"</string>
@@ -511,10 +510,9 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Kosongkan semua"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Urus"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Sejarah"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Masuk"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Pemberitahuan senyap"</string>
-    <string name="notification_section_header_alerting" msgid="3168140660646863240">"Pemberitahuan memaklumi"</string>
+    <string name="notification_section_header_alerting" msgid="3168140660646863240">"Pemberitahuan makluman"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Perbualan"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Kosongkan semua pemberitahuan senyap"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Pemberitahuan dijeda oleh Jangan Ganggu"</string>
@@ -588,7 +586,7 @@
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"Tetapan bunyi"</string>
     <string name="accessibility_volume_expand" msgid="7653070939304433603">"Kembangkan"</string>
     <string name="accessibility_volume_collapse" msgid="2746845391013829996">"Runtuhkan"</string>
-    <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Kapsyen media automatik"</string>
+    <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Sari kata media automatik"</string>
     <string name="accessibility_volume_close_odi_captions_tip" msgid="8924753283621160480">"Petua sari kata"</string>
     <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Tindanan kapsyen"</string>
     <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"dayakan"</string>
@@ -704,12 +702,12 @@
     <string name="inline_minimize_button" msgid="1474436209299333445">"Minimumkan"</string>
     <string name="inline_silent_button_silent" msgid="525243786649275816">"Senyap"</string>
     <string name="inline_silent_button_stay_silent" msgid="2129254868305468743">"Kekal senyap"</string>
-    <string name="inline_silent_button_alert" msgid="5705343216858250354">"Memaklumi"</string>
+    <string name="inline_silent_button_alert" msgid="5705343216858250354">"Pemakluman"</string>
     <string name="inline_silent_button_keep_alerting" msgid="6577845442184724992">"Teruskan memberikan makluman"</string>
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Matikan pemberitahuan"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Terus tunjukkan pemberitahuan daripada apl ini?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Senyap"</string>
-    <string name="notification_alert_title" msgid="7629202599338071971">"Memaklumi"</string>
+    <string name="notification_alert_title" msgid="7629202599338071971">"Pemakluman"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Gelembung"</string>
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"Membantu anda fokus tanpa bunyi atau getaran."</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"Menarik perhatian anda dengan bunyi atau getaran."</string>
@@ -746,7 +744,7 @@
     <string name="notification_conversation_favorite" msgid="1905240206975921907">"Perbualan penting"</string>
     <string name="notification_conversation_unfavorite" msgid="181383708304763807">"Bukan perbualan penting"</string>
     <string name="notification_conversation_mute" msgid="268951550222925548">"Disenyapkan"</string>
-    <string name="notification_conversation_unmute" msgid="2692255619510896710">"Memaklumi"</string>
+    <string name="notification_conversation_unmute" msgid="2692255619510896710">"Pemakluman"</string>
     <string name="notification_conversation_bubble" msgid="2242180995373949022">"Tunjukkan gelembung"</string>
     <string name="notification_conversation_unbubble" msgid="6908427185031099868">"Alih keluar gelembung"</string>
     <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Tambahkan pada skrin utama"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Tiada tajuk"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Ketik untuk memulakan semula apl ini dan menggunakan skrin penuh."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Tetapan untuk gelembung <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Limpahan"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Tambah kembali pada tindanan"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Urus"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> daripada <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> daripada <xliff:g id="APP_NAME">%2$s</xliff:g> dan <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> lagi"</string>
@@ -1017,7 +1013,7 @@
     <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Tunjukkan di atas bahagian perbualan"</string>
     <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Tunjukkan gambar profil pada skrin kunci"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Dipaparkan sebagai gelembung terapung di atas apl"</string>
-    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Ganggu Ciri Jangan Ganggu"</string>
+    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Ganggu ciri Jangan Ganggu"</string>
     <string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"OK"</string>
     <string name="magnification_overlay_title" msgid="6584179429612427958">"Tetingkap Tindanan Pembesaran"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"Tetingkap Pembesaran"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> kawalan ditambah.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> kawalan ditambah.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Dialih keluar"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Digemari"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Digemari, kedudukan <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Dinyahgemari"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"gemari"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"nyahgemari"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Alih ke kedudukan <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Kawalan"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Pilih kawalan untuk diakses daripada menu kuasa"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Tahan &amp; seret untuk mengatur semula kawalan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 8a0a615..02eae37 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ဖန်သားပြင်ဓာတ်ပုံ ပယ်ရန်"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ဖန်သားပြင်ဓာတ်ပုံ အစမ်းကြည့်ရှုခြင်း"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ဖန်သားပြင် ရိုက်ကူးမှု"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ဖန်သားပြင်ရိုက်ကူးနေသည်"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ဖန်သားပြင် ရိုက်ကူးသည့် စက်ရှင်အတွက် ဆက်တိုက်လာနေသော အကြောင်းကြားချက်"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"စတင် ရိုက်ကူးမလား။"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"ရိုက်ကူးနေစဉ်အတွင်း Android စနစ်သည် သင့်မျက်နှာပြင်ပေါ်တွင် မြင်နိုင်သော သို့မဟုတ် သင့်စက်ပစ္စည်းတွင် ဖွင့်ထားသော အရေးကြီးသည့် အချက်အလက်မှန်သမျှကို ရိုက်ကူးနိုင်သည်။ ၎င်းတွင် စကားဝှက်များ၊ ငွေပေးချေမှု အချက်အလက်၊ ဓာတ်ပုံများ၊ မက်ဆေ့ဂျ်များနှင့် အသံများ ပါဝင်သည်။"</string>
@@ -511,10 +510,9 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"အားလုံး ဖယ်ရှားရန်"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"စီမံရန်"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"မှတ်တမ်း"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
-    <string name="notification_section_header_gentle" msgid="3044910806569985386">"အကြောင်းကြားချက်များကို အသံတိတ်ခြင်း"</string>
-    <string name="notification_section_header_alerting" msgid="3168140660646863240">"အကြောင်းကြားချက်များကို သတိပေးခြင်း"</string>
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"အဝင်"</string>
+    <string name="notification_section_header_gentle" msgid="3044910806569985386">"အသံမပြုသည့် အကြောင်းကြားချက်များ"</string>
+    <string name="notification_section_header_alerting" msgid="3168140660646863240">"သတိပေးသည့် အကြောင်းကြားချက်များ"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"စကားဝိုင်းများ"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"အသံတိတ် အကြောင်းကြားချက်များအားလုံးကို ရှင်းလင်းရန်"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"အကြောင်းကြားချက်များကို \'မနှောင့်ယှက်ရ\' က ခေတ္တရပ်ထားသည်"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"ခေါင်းစဉ် မရှိပါ"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"ဤအက်ပ်ကို ပြန်စတင်ပြီး မျက်နှာပြင်အပြည့်လုပ်ရန် တို့ပါ။"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> ပူဖောင်းကွက်အတွက် ဆက်တင်များ"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"အပိုများပြရန်"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"ပူဖေါင်းတန်းသို့ ပြန်ထည့်ရန်"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"စီမံရန်"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> မှ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> နှင့် နောက်ထပ် <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> ခုမှ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1014,7 +1010,7 @@
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"စနစ်လမ်းညွှန်ခြင်း အပ်ဒိတ်လုပ်ပြီးပါပြီ။ အပြောင်းအလဲများ ပြုလုပ်ရန် \'ဆက်တင်များ\' သို့သွားပါ။"</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"စနစ်လမ်းညွှန်ခြင်း အပ်ဒိတ်လုပ်ရန် \'ဆက်တင်များ\' သို့သွားပါ"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"အသင့်အနေအထား"</string>
-    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"စကားဝိုင်းအပိုင်း၏ ထိပ်တွင်ပြရန်"</string>
+    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"စကားဝိုင်းကဏ္ဍ၏ အပေါ်ဘက်တွင်ပြရန်"</string>
     <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"လော့ခ်မျက်နှာပြင်တွင် ပရိုဖိုင်ပုံကို ပြရန်"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"အက်ပ်အပေါ်တွင် မျောနေသောပူ‌ဖောင်းကွက်အဖြစ် ပေါ်မည်"</string>
     <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"\'မနှောင့်ယှက်ရ\' ကို ကြားဖြတ်ခြင်း"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">ခလုတ် <xliff:g id="NUMBER_1">%s</xliff:g> ခု ထည့်လိုက်သည်။</item>
       <item quantity="one">ခလုတ် <xliff:g id="NUMBER_0">%s</xliff:g> ခု ထည့်လိုက်သည်။</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"ဖယ်ရှားထားသည်"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"အကြိုက်ဆုံးတွင် ထည့်ထားသည်"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"အကြိုက်ဆုံးတွင် ထည့်ထားသည်၊ အဆင့် <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"အကြိုက်ဆုံးမှ ဖယ်ရှားထားသည်"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"အကြိုက်ဆုံးတွင် ထည့်ရန်"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"အကြိုက်ဆုံးမှ ဖယ်ရှားရန်"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"အနေအထား <xliff:g id="NUMBER">%d</xliff:g> သို့ ရွှေ့ရန်"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"ထိန်းချုပ်မှုများ"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"ဖွင့်ပိတ်မီနူးမှ သုံးရန် ထိန်းချုပ်မှုများ ရွေးပါ"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"ထိန်းချုပ်မှုများ ပြန်စီစဉ်ရန် ဖိပြီးဆွဲပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 2c57ed2..e935425 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Avvis skjermdumpen"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Forhåndsvisning av skjermdump"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Skjermopptaker"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skjermopptaket"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Vedvarende varsel for et skjermopptak"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Vil du starte opptaket?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Under opptak kan Android-systemet registrere all sensitiv informasjon som er synlig på skjermen eller spilles av på enheten. Dette inkluderer passord, betalingsinformasjon, bilder, meldinger og lyd."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Fjern alt"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Administrer"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Logg"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Innkommende"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Lydløse varsler"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Varsler med varsling"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Samtaler"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Ingen tittel"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Trykk for å starte denne appen på nytt og vise den i fullskjerm."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Innstillinger for <xliff:g id="APP_NAME">%1$s</xliff:g>-bobler"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Overflyt"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Legg tilbake i stabelen"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Administrer"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> fra <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> fra <xliff:g id="APP_NAME">%2$s</xliff:g> og <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> flere"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> kontroller er lagt til.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> kontroll er lagt til.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Fjernet"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favoritt"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favoritt, posisjon <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Fjernet som favoritt"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"merke som favoritt"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"fjerne som favoritt"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Flytt til posisjon <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Kontroller"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Velg kontroller som er tilgjengelige fra av/på-menyen"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Hold og dra for å flytte kontroller"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 8d0adc0..a4b271b 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"स्क्रिनसट हटाउनुहोस्"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"स्क्रिनसटको पूर्वावलोकन"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"स्क्रिन रेकर्डर"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रिन रेकर्डिङको प्रक्रिया अघि बढाइँदै"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"कुनै स्क्रिन रेकर्ड गर्ने सत्रका लागि चलिरहेको सूचना"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"रेकर्ड गर्न थाल्ने हो?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"रेकर्ड गर्दा, Android प्रणालीले तपाईंको स्क्रिनमा देखिने वा तपाईंको यन्त्रमा प्ले गरिने सबै संवेदनशील जानकारी रेकर्ड गर्न सक्छ। यो जानकारीमा पासवर्ड, भुक्तानीसम्बन्धी जानकारी, फोटो, सन्देश र अडियो समावेश हुन्छ।"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"सबै हटाउनुहोस्"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"व्यवस्थित गर्नुहोस्"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"इतिहास"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"हालसालै प्राप्त भएका सूचनाहरू"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"मौन सूचनाहरू"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"कम्पन वा आवाजसहितका सूचनाहरू"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"वार्तालापहरू"</string>
@@ -971,7 +969,7 @@
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"मोबाइल डेटा निष्क्रिय पार्ने हो?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"तपाईं <xliff:g id="CARRIER">%s</xliff:g> मार्फत डेटा वा इन्टरनेट प्रयोग गर्न सक्नुहुने छैन। Wi-Fi मार्फत मात्र इन्टरनेट उपलब्ध हुने छ।"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"तपाईंको सेवा प्रदायक"</string>
-    <string name="touch_filtered_warning" msgid="8119511393338714836">"कुनै अनुप्रयोगको कारणले अनुमतिसम्बन्धी अनुरोध बुझ्न गाह्रो भइरहेकोले सेटिङहरूले तपाईंको प्रतिक्रिया प्रमाणित गर्न सक्दैनन्।"</string>
+    <string name="touch_filtered_warning" msgid="8119511393338714836">"कुनै एपको कारणले अनुमतिसम्बन्धी अनुरोध बुझ्न गाह्रो भइरहेकोले सेटिङहरूले तपाईंको प्रतिक्रिया प्रमाणित गर्न सक्दैनन्।"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> लाई <xliff:g id="APP_2">%2$s</xliff:g> का स्लाइसहरू देखाउन अनुमति दिने हो?"</string>
     <string name="slice_permission_text_1" msgid="6675965177075443714">"- यसले <xliff:g id="APP">%1$s</xliff:g> बाट जानकारी पढ्न सक्छ"</string>
     <string name="slice_permission_text_2" msgid="6758906940360746983">"- यसले <xliff:g id="APP">%1$s</xliff:g> भित्र कारबाही गर्न सक्छ"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"शीर्षक छैन"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"यो एप पुनः सुरु गर्न ट्याप गर्नुहोस् र फुल स्क्रिन मोडमा जानुहोस्।"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> का बबलसम्बन्धी सेटिङहरू"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"ओभरफ्लो देखाउनुहोस्"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"स्ट्याकमा फेरि थप्नुहोस्"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"व्यवस्थापन गर्नुहोस्"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> को <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> का <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> र थप <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> वटा नियन्त्र थपियो।</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> नियन्त्र थपियो</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"हटाइएको"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"मनपराइएको"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"मन पराइएका कुराहरूको <xliff:g id="NUMBER">%d</xliff:g> औँ स्थानमा"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"मन पर्ने कुराहरूको सूचीमा नराखिएको"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"मन पर्ने कुराहरूको सूचीमा राख्नुहोस्"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"मन पर्ने कुराहरूको सूचीमा नराख्नुहोस्"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g>ले निर्देश गर्ने ठाउँमा सार्नुहोस्"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"नियन्त्रणहरू"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"पावर मेनुबाट प्रयोग गर्न चाहेका नियन्त्रण सुविधाहरू छान्नुहोस्"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"नियन्त्रणहरूको क्रम मिलाउन तिनलाई थिचेर ड्र्याग गर्नुहोस्"</string>
@@ -1039,10 +1042,8 @@
     <string name="controls_favorite_load_error" msgid="2533215155804455348">"सबै नियन्त्रणहरूको सूची लोड गर्न सकिएन।"</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"अन्य"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"यन्त्र नियन्त्रण गर्ने विजेटहरूको सूचीमा थप्नुहोस्"</string>
-    <!-- no translation found for controls_dialog_ok (2770230012857881822) -->
-    <skip />
-    <!-- no translation found for controls_dialog_message (342066938390663844) -->
-    <skip />
+    <string name="controls_dialog_ok" msgid="2770230012857881822">"थप्नुहोस्"</string>
+    <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ले सिफारिस गरेको"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"नियन्त्रण सुविधाहरू अद्यावधिक गरिए"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN मा अक्षर वा चिन्हहरू समाविष्ट हुन्छन्"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> पुष्टि गर्नुहोस्"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 419fa3e..94c72ff 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -1027,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> bedieningselementen toegevoegd.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> bedieningselement toegevoegd.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Verwijderd"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Gemarkeerd als favoriet"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Gemarkeerd als favoriet, positie <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Verwijderd als favoriet"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"als favoriet markeren"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"als favoriet verwijderen"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Verplaatsen naar positie <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Bedieningselementen"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Kies bedieningselementen die je vanaf het aan/uit-menu wilt kunnen gebruiken"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Houd vast en sleep om de bedieningselementen opnieuw in te delen"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 13798af..604e93f 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ସ୍କ୍ରିନସଟ୍ ଖାରଜ କରନ୍ତୁ"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ସ୍କ୍ରିନସଟର ପ୍ରିଭ୍ୟୁ"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ସ୍କ୍ରିନ୍ ରେକର୍ଡର୍"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ସ୍କ୍ରିନ ରେକର୍ଡିଂର ପ୍ରକ୍ରିୟାକରଣ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ଏକ ସ୍କ୍ରି‍ନ୍‍ ରେକର୍ଡ୍‍ ସେସନ୍‍ ପାଇଁ ଚାଲୁଥିବା ବିଜ୍ଞପ୍ତି"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"ରେକର୍ଡିଂ ଆରମ୍ଭ କରିବେ?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"ରେକର୍ଡିଂ ସମୟରେ, Android ସିଷ୍ଟମ୍ ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା ବା ଆପଣଙ୍କ ଡିଭାଇସରେ ଚାଲୁଥିବା ଯେ କୌଣସି ସମ୍ବେଦନଶୀଳ ସୂଚନାକୁ କ୍ୟାପଚର୍ କରିପାରିବ। ଏଥିରେ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ସୂଚନା, ଫଟୋ, ମେସେଜ ଏବଂ ଅଡିଓ ଅନ୍ତର୍ଭୁକ୍ତ।"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"ସମସ୍ତ ଖାଲି କରନ୍ତୁ"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"ପରିଚାଳନା କରନ୍ତୁ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ଇତିହାସ"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"ଇନକମିଂ"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"ନୀରବ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"ଆଲର୍ଟ କରିବା ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ"</string>
@@ -977,7 +975,7 @@
     <string name="slice_permission_text_2" msgid="6758906940360746983">"- ଏହା <xliff:g id="APP">%1$s</xliff:g> ଭିତରେ କାମ କରିପାରିବ"</string>
     <string name="slice_permission_checkbox" msgid="4242888137592298523">"ଯେକୌଣସି ଆପ୍‌ରେ ସ୍ଲାଇସ୍‌କୁ ଦେଖାଇବା ପାଇଁ <xliff:g id="APP">%1$s</xliff:g>କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
     <string name="slice_permission_allow" msgid="6340449521277951123">"ଅନୁମତି ଦିଅନ୍ତୁ"</string>
-    <string name="slice_permission_deny" msgid="6870256451658176895">"ଅସ୍ଵୀକାର କରନ୍ତୁ"</string>
+    <string name="slice_permission_deny" msgid="6870256451658176895">"ଅଗ୍ରାହ୍ୟ କରନ୍ତୁ"</string>
     <string name="auto_saver_title" msgid="6873691178754086596">"ବ୍ୟାଟେରୀ ସେଭର୍‌ ଅନ୍‌ ହେବାର ସମୟ ସେଟ୍‌ କରିବାକୁ ଟାପ୍‌ କରନ୍ତୁ"</string>
     <string name="auto_saver_text" msgid="3214960308353838764">"ବ୍ୟାଟେରୀ ସରିବାକୁ ଥିବା ସମୟରେ ଚାଲୁ କରନ୍ତୁ"</string>
     <string name="no_auto_saver_action" msgid="7467924389609773835">"ନାହିଁ, ଥାଉ"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"କୌଣସି ଶୀର୍ଷକ ନାହିଁ"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"ଏହି ଆପ୍‌କୁ ରିଷ୍ଟାର୍ଟ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ ଏବଂ ଫୁଲ୍‌ସ୍କ୍ରିନ୍‌କୁ ଯାଆନ୍ତୁ।"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବବଲ୍‌ଗୁଡ଼ିକ ପାଇଁ ସେଟିଂସ୍"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"ଓଭରଫ୍ଲୋ"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"ଷ୍ଟାକରେ ପୁଣି ଯୋଗ କରନ୍ତୁ"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"ପରିଚାଳନା କରନ୍ତୁ"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g>ରୁ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> ଏବଂ ଅଧିକ <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>ଟିରୁ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1017,7 +1013,7 @@
     <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"ବାର୍ତ୍ତାଳାପ ବିଭାଗର ଶୀର୍ଷରେ ଦେଖାନ୍ତୁ"</string>
     <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"ଲକ୍ ସ୍କ୍ରିନରେ ପ୍ରୋଫାଇଲ୍ ଛବି ଦେଖାନ୍ତୁ"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"ଆପଗୁଡ଼ିକ ଉପରେ ଫ୍ଲୋଟିଂ ବବଲ୍ ପରି ଦେଖାଯିବ"</string>
-    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"\'ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\' ମୋଡରେ ବାଧା ଉପୁଯାଇପାରିବ"</string>
+    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"\'ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\' ମୋଡରେ ବାଧା"</string>
     <string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"ବୁଝିଗଲି"</string>
     <string name="magnification_overlay_title" msgid="6584179429612427958">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ଓଭର୍‌ଲେ ୱିଣ୍ଡୋ"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ୱିଣ୍ଡୋ"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g>ଟି ନିୟନ୍ତ୍ରଣ ଯୋଗ କରାଯାଇଛି।</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g>ଟି ନିୟନ୍ତ୍ରଣ ଯୋଗ କରାଯାଇଛି।</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"କାଢ଼ି ଦିଆଯାଇଛି"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"ପସନ୍ଦ କରାଯାଇଛି"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ପସନ୍ଦ କରାଯାଇଛି, ସ୍ଥିତି <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ନାପସନ୍ଦ କରାଯାଇଛି"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"ପସନ୍ଦ କରନ୍ତୁ"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"ନାପସନ୍ଦ କରନ୍ତୁ"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g> ସ୍ଥିତିକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"ପାୱାର ମେନୁରୁ ଆକ୍ସେସ୍ କରିବାକୁ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ବାଛନ୍ତୁ"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ପୁଣି ସଜାଇବାକୁ ସେଗୁଡ଼ିକୁ ଧରି ଟାଣନ୍ତୁ"</string>
@@ -1039,10 +1042,8 @@
     <string name="controls_favorite_load_error" msgid="2533215155804455348">"ସବୁ ନିୟନ୍ତ୍ରଣର ତାଲିକା ଲୋଡ୍ କରିପାରିଲା ନାହିଁ।"</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ଅନ୍ୟ"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"ଡିଭାଇସ୍ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକରେ ଯୋଗ କରନ୍ତୁ"</string>
-    <!-- no translation found for controls_dialog_ok (2770230012857881822) -->
-    <skip />
-    <!-- no translation found for controls_dialog_message (342066938390663844) -->
-    <skip />
+    <string name="controls_dialog_ok" msgid="2770230012857881822">"ଯୋଗ କରନ୍ତୁ"</string>
+    <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ଦ୍ଵାରା ପ୍ରସ୍ତାବିତ"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଅପଡେଟ୍ କରାଯାଇଛି"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PINରେ ଅକ୍ଷର କିମ୍ୱା ସଙ୍କେତଗୁଡ଼ିକ ଥାଏ"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> ଯାଞ୍ଚ କରନ୍ତୁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 0981f3c..c5a9b35 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਖਾਰਜ ਕਰੋ"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਪੂਰਵ-ਝਲਕ"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਰ"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਜਾਰੀ ਹੈ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ਕਿਸੇ ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ ਸੈਸ਼ਨ ਲਈ ਚੱਲ ਰਹੀ ਸੂਚਨਾ"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"ਕੀ ਰਿਕਾਰਡਿੰਗ ਸ਼ੁਰੂ ਕਰਨੀ ਹੈ?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"ਰਿਕਾਰਡਿੰਗ ਕਰਨ ਵੇਲੇ, Android ਸਿਸਟਮ ਕੋਈ ਵੀ ਅਜਿਹੀ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਕੈਪਚਰ ਕਰ ਸਕਦਾ ਹੈ ਜੋ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਣਯੋਗ ਹੈ ਜਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਜਾਂਦੀ ਹੈ। ਇਸ ਵਿੱਚ ਪਾਸਵਰਡ, ਭੁਗਤਾਨ ਵੇਰਵੇ, ਫ਼ੋਟੋਆਂ, ਸੁਨੇਹੇ ਅਤੇ ਆਡੀਓ ਸ਼ਾਮਲ ਹਨ।"</string>
@@ -358,7 +357,7 @@
     <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"ਸੁਣਨ ਦੇ ਸਾਧਨ"</string>
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ਚਾਲੂ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
     <string name="quick_settings_brightness_label" msgid="680259653088849563">"ਚਮਕ"</string>
-    <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"ਸਵੈ-ਘੁੰਮਾਓ"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"ਸਵੈ-ਘੁਮਾਓ"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"ਸਕ੍ਰੀਨ ਨੂੰ ਆਪਣੇ ਆਪ ਘੁੰਮਾਓ"</string>
     <string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"<xliff:g id="ID_1">%s</xliff:g> ਮੋਡ"</string>
     <string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"ਰੋਟੇਸ਼ਨ  ਲਾਕ  ਕੀਤੀ"</string>
@@ -369,7 +368,7 @@
     <string name="quick_settings_location_off_label" msgid="7923929131443915919">"ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਬੰਦ"</string>
     <string name="quick_settings_media_device_label" msgid="8034019242363789941">"ਮੀਡੀਆ ਡੀਵਾਈਸ"</string>
     <string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
-    <string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"ਕੇਵਲ ਐਮਰਜੈਂਸੀ ਕਾਲਾਂ"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"ਸਿਰਫ਼ ਸੰਕਟਕਾਲੀਨ ਕਾਲਾਂ"</string>
     <string name="quick_settings_settings_label" msgid="2214639529565474534">"ਸੈਟਿੰਗਾਂ"</string>
     <string name="quick_settings_time_label" msgid="3352680970557509303">"ਸਮਾਂ"</string>
     <string name="quick_settings_user_label" msgid="1253515509432672496">"ਮੈਂ"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"ਸਭ ਕਲੀਅਰ ਕਰੋ"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ਇਤਿਹਾਸ"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"ਇਨਕਮਿੰਗ"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"ਸ਼ਾਂਤ ਸੂਚਨਾਵਾਂ"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"ਸੁਚੇਤ ਕਰਨ ਵਾਲੀਆਂ ਸੂਚਨਾਵਾਂ"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"ਗੱਲਾਂਬਾਤਾਂ"</string>
@@ -854,7 +852,7 @@
     <string name="right_keycode" msgid="2480715509844798438">"ਸੱਜਾ ਕੀ-ਕੋਡ"</string>
     <string name="left_icon" msgid="5036278531966897006">"ਖੱਬਾ ਪ੍ਰਤੀਕ"</string>
     <string name="right_icon" msgid="1103955040645237425">"ਸੱਜਾ ਪ੍ਰਤੀਕ"</string>
-    <string name="drag_to_add_tiles" msgid="8933270127508303672">"ਟਾਇਲਾਂ ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਫੜ੍ਹ ਕੇ ਰੱਖੋ ਅਤੇ ਘਸੀਟੋ"</string>
+    <string name="drag_to_add_tiles" msgid="8933270127508303672">"ਟਾਇਲਾਂ ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਫੜ੍ਹ ਕੇ ਘਸੀਟੋ"</string>
     <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"ਟਾਇਲਾਂ ਨੂੰ ਮੁੜ-ਵਿਵਸਥਿਤ ਕਰਨ ਲਈ ਫੜ੍ਹ ਕੇ ਘਸੀਟੋ"</string>
     <string name="drag_to_remove_tiles" msgid="4682194717573850385">"ਹਟਾਉਣ ਲਈ ਇੱਥੇ ਘਸੀਟੋ"</string>
     <string name="drag_to_remove_disabled" msgid="933046987838658850">"ਤੁਹਾਨੂੰ ਘੱਟੋ-ਘੱਟ <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> ਟਾਇਲਾਂ ਦੀ ਲੋੜ ਪਵੇਗੀ"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"ਕੋਈ ਸਿਰਲੇਖ ਨਹੀਂ"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"ਇਸ ਐਪ ਨੂੰ ਮੁੜ-ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ ਅਤੇ ਪੂਰੀ-ਸਕ੍ਰੀਨ ਮੋਡ \'ਤੇ ਜਾਓ।"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਬਬਲ ਲਈ ਸੈਟਿੰਗਾਂ"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"ਓਵਰਫ਼ਲੋ"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"ਸਟੈਕ ਵਿੱਚ ਵਾਪਸ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> ਤੋਂ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> ਅਤੇ <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> ਹੋਰਾਂ ਤੋਂ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ।</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕੀਤੇ ਗਏ।</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"ਹਟਾਇਆ ਗਿਆ"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"ਮਨਪਸੰਦ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ਮਨਪਸੰਦ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ, ਸਥਾਨ <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ਮਨਪਸੰਦ ਵਿੱਚੋਂ ਹਟਾਇਆ ਗਿਆ"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"ਮਨਪਸੰਦ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"ਮਨਪਸੰਦ ਵਿੱਚੋਂ ਹਟਾਓ"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g> ਸਥਾਨ \'ਤੇ ਲਿਜਾਓ"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"ਕੰਟਰੋਲ"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"ਪਹੁੰਚ ਕਰਨ ਲਈ ਪਾਵਰ ਮੀਨੂ ਤੋਂ ਕੰਟਰੋਲ ਚੁਣੋ"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"ਕੰਟਰੋਲਾਂ ਨੂੰ ਮੁੜ-ਵਿਵਸਥਿਤ ਕਰਨ ਲਈ ਫੜ੍ਹ ਕੇ ਘਸੀਟੋ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index e510b0e..350bdd9 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Zamknij zrzut ekranu"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Podgląd zrzutu ekranu"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Nagrywanie ekranu"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Przetwarzam nagrywanie ekranu"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Stałe powiadomienie o sesji rejestrowania zawartości ekranu"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Rozpocząć nagrywanie?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Podczas nagrywania system Android może rejestrować wszelkie informacje poufne wyświetlane na ekranie lub odtwarzane na urządzeniu. Dotyczy to m.in. haseł, szczegółów płatności, zdjęć, wiadomości i odtwarzanych dźwięków."</string>
@@ -419,7 +418,7 @@
     <string name="quick_settings_cellular_detail_data_used" msgid="6798849610647988987">"Wykorzyst.: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
     <string name="quick_settings_cellular_detail_data_limit" msgid="1791389609409211628">"Limit <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_cellular_detail_data_warning" msgid="7957253810481086455">"Ostrzeżenie: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
-    <string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Profil do pracy"</string>
+    <string name="quick_settings_work_mode_label" msgid="2754212289804324685">"Profil służbowy"</string>
     <string name="quick_settings_night_display_label" msgid="8180030659141778180">"Podświetlenie nocne"</string>
     <string name="quick_settings_night_secondary_label_on_at_sunset" msgid="3358706312129866626">"Włącz o zachodzie"</string>
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"Do wschodu słońca"</string>
@@ -517,8 +516,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Usuń wszystkie"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Zarządzaj"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historia"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Przychodzące"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Ciche powiadomienia"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Alerty"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Rozmowy"</string>
@@ -659,7 +657,7 @@
     <string name="show_demo_mode" msgid="3677956462273059726">"Pokaż tryb demonstracyjny"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string>
-    <string name="status_bar_work" msgid="5238641949837091056">"Profil do pracy"</string>
+    <string name="status_bar_work" msgid="5238641949837091056">"Profil służbowy"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Tryb samolotowy"</string>
     <string name="add_tile" msgid="6239678623873086686">"Dodaj nazwę"</string>
     <string name="broadcast_tile" msgid="5224010633596487481">"Rozgłaszana nazwa"</string>
@@ -669,7 +667,7 @@
     <string name="alarm_template_far" msgid="3561752195856839456">"w: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_detail" msgid="544463655956179791">"Szybkie ustawienia, <xliff:g id="TITLE">%s</xliff:g>."</string>
     <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"Hotspot"</string>
-    <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil do pracy"</string>
+    <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil służbowy"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Dobra zabawa, ale nie dla każdego"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Kalibrator System UI udostępnia dodatkowe sposoby dostrajania i dostosowywania interfejsu Androida. Te eksperymentalne funkcje mogą się zmienić, popsuć lub zniknąć w przyszłych wersjach. Zachowaj ostrożność."</string>
     <string name="tuner_persistent_warning" msgid="230466285569307806">"Te eksperymentalne funkcje mogą się zmienić, popsuć lub zniknąć w przyszłych wersjach. Zachowaj ostrożność."</string>
@@ -1001,10 +999,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Bez tytułu"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Kliknij, by uruchomić tę aplikację ponownie i przejść w tryb pełnoekranowy."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Ustawienia dymków aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Przepełnienie"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Dodaj ponownie do stosu"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Zarządzaj"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> z aplikacji <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> z aplikacji <xliff:g id="APP_NAME">%2$s</xliff:g> i jeszcze <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1043,6 +1039,13 @@
       <item quantity="other">Dodano <xliff:g id="NUMBER_1">%s</xliff:g> elementu sterującego</item>
       <item quantity="one">Dodano <xliff:g id="NUMBER_0">%s</xliff:g> element sterujący</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Usunięto"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Dodano do ulubionych"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Dodano do ulubionych, pozycja <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Usunięto z ulubionych"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"dodać do ulubionych"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"usunąć z ulubionych"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Przenieś w położenie <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Elementy sterujące"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Wybierz elementy sterujące dostępne w menu zasilania"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Przytrzymaj i przeciągnij, aby przestawić elementy sterujące"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index d63d623..af6d755 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -706,7 +706,7 @@
     <string name="inline_silent_button_keep_alerting" msgid="6577845442184724992">"Continuar alertando"</string>
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desativar notificações"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Continuar mostrando notificações desse app?"</string>
-    <string name="notification_silence_title" msgid="8608090968400832335">"Silenciosa"</string>
+    <string name="notification_silence_title" msgid="8608090968400832335">"Silencioso"</string>
     <string name="notification_alert_title" msgid="7629202599338071971">"Alertar"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bolha"</string>
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"Ajuda você a manter o foco sem som ou vibração."</string>
@@ -1027,6 +1027,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> controle adicionado.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controles adicionados.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado como favorito"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionado como favorito (posição <xliff:g id="NUMBER">%d</xliff:g>)"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Removido dos favoritos"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"adicionar aos favoritos"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"remover dos favoritos"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Mover para a posição <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Controles"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Escolha os controles para acessar pelo menu do botão liga/desliga"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Mantenha a tela pressionada e arraste para reorganizar os controles"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 2b34ac3..17853c4 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -709,11 +709,11 @@
     <string name="notification_silence_title" msgid="8608090968400832335">"Silencioso"</string>
     <string name="notification_alert_title" msgid="7629202599338071971">"Alertar"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Balão"</string>
-    <string name="notification_channel_summary_low" msgid="7300447764759926720">"Ajuda-o a focar-se sem som ou vibração."</string>
-    <string name="notification_channel_summary_default" msgid="3539949463907902037">"Chama a sua atenção com som ou vibração."</string>
+    <string name="notification_channel_summary_low" msgid="7300447764759926720">"Ajuda-o a concentrar-se sem som ou vibração"</string>
+    <string name="notification_channel_summary_default" msgid="3539949463907902037">"Chama a sua atenção com som ou vibração"</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"Chama a sua atenção com som ou vibração. As conversas da app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem como um balão por predefinição."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantém a sua atenção com um atalho flutuante para este conteúdo."</string>
-    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Aparece na parte superior da secção de conversas e surge como um balão."</string>
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Aparece na parte superior da secção de conversas e surge como um balão"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Definições"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> não suporta definições específicas de conversas."</string>
@@ -1027,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controlos adicionados.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> controlo adicionado.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado aos favoritos"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionados aos favoritos, posição <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Removido dos favoritos"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"adicionar aos favoritos"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"remover dos favoritos"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Mover para a posição <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Controlos"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Escolha os controlos a que pretende aceder a partir do menu ligar/desligar."</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Toque sem soltar e arraste para reorganizar os controlos."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index d63d623..af6d755 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -706,7 +706,7 @@
     <string name="inline_silent_button_keep_alerting" msgid="6577845442184724992">"Continuar alertando"</string>
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desativar notificações"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Continuar mostrando notificações desse app?"</string>
-    <string name="notification_silence_title" msgid="8608090968400832335">"Silenciosa"</string>
+    <string name="notification_silence_title" msgid="8608090968400832335">"Silencioso"</string>
     <string name="notification_alert_title" msgid="7629202599338071971">"Alertar"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bolha"</string>
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"Ajuda você a manter o foco sem som ou vibração."</string>
@@ -1027,6 +1027,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> controle adicionado.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controles adicionados.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado como favorito"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionado como favorito (posição <xliff:g id="NUMBER">%d</xliff:g>)"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Removido dos favoritos"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"adicionar aos favoritos"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"remover dos favoritos"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Mover para a posição <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Controles"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Escolha os controles para acessar pelo menu do botão liga/desliga"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Mantenha a tela pressionada e arraste para reorganizar os controles"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 8388b48..2491221 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Închideți captura de ecran"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Previzualizare a capturii de ecran"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Recorder pentru ecran"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Se procesează înregistrarea"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificare în curs pentru o sesiune de înregistrare a ecranului"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Începeți înregistrarea?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"În timpul înregistrării, sistemul Android poate captura informațiile sensibile vizibile pe ecran sau redate pe dispozitiv. Aici sunt incluse parole, informații de plată, fotografii, mesaje și conținut audio."</string>
@@ -514,8 +513,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Ștergeți toate notificările"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gestionați"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Istoric"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Primite"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Notificări silențioase"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Notificări de alertare"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversații"</string>
@@ -996,10 +994,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Fără titlu"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Atingeți ca să reporniți aplicația și să treceți în modul ecran complet."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Setări pentru baloanele <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Suplimentar"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Adăugați înapoi în stivă"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Gestionați"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de la <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> de la <xliff:g id="APP_NAME">%2$s</xliff:g> și încă <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1037,6 +1033,13 @@
       <item quantity="other">S-au adăugat <xliff:g id="NUMBER_1">%s</xliff:g> de comenzi.</item>
       <item quantity="one">S-a adăugat <xliff:g id="NUMBER_0">%s</xliff:g> comandă.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Eliminată"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Marcată ca preferată"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Marcată ca preferată, poziția <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"S-a anulat marcarea ca preferată"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"marcați ca preferată"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"anulați marcarea ca preferată"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Mutați pe poziția <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Comenzi"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Alegeți comenzile de accesat din meniul de alimentare"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Țineți apăsat și trageți pentru a rearanja comenzile"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 2832d89..b752fc4 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -88,9 +88,8 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Не удалось сделать скриншот: нет разрешения от приложения или организации."</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Закрыть скриншот"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Предварительный просмотр скриншота"</string>
-    <string name="screenrecord_name" msgid="2596401223859996572">"Создание скриншотов"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_name" msgid="2596401223859996572">"Запись видео с экрана"</string>
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обработка записи с экрана…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущее уведомление для записи видео с экрана"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Начать запись?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Во время записи система Android может получить доступ к конфиденциальной информации, которая видна на экране или воспроизводится на устройстве, в том числе к паролям, сведениям о платежах, фотографиям, сообщениям и аудиозаписям."</string>
@@ -101,7 +100,7 @@
     <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Звук с устройства и микрофон"</string>
     <string name="screenrecord_start" msgid="330991441575775004">"Начать"</string>
     <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Идет запись видео с экрана."</string>
-    <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Идет запись видео с экрана и звука."</string>
+    <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Идет запись видео с экрана и звука"</string>
     <string name="screenrecord_taps_label" msgid="1595690528298857649">"Показывать прикосновения к экрану"</string>
     <string name="screenrecord_stop_text" msgid="6549288689506057686">"Нажмите, чтобы остановить"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Остановить"</string>
@@ -517,8 +516,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Очистить все"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Настроить"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"История"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Входящие"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Беззвучные уведомления"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Оповещения"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Разговоры"</string>
@@ -721,7 +719,7 @@
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"Уведомления приходят со звуком или вибрацией"</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"Уведомления приходят со звуком или вибрацией. Разговоры из приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" по умолчанию появляются в виде всплывающего чата."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Привлекает ваше внимание к контенту с помощью плавающего ярлыка"</string>
-    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Появляется в верхней части списка разговоров и в виде всплывающего чата."</string>
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Появляется в верхней части списка разговоров и в виде всплывающего чата"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Настройки"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" не поддерживает настройки разговора."</string>
@@ -1001,10 +999,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Без названия"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Нажмите, чтобы перезапустить приложение и перейти в полноэкранный режим."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Настройки всплывающих чатов от приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Дополнительное меню"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Добавить обратно в стек"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Настроить"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> из приложения \"<xliff:g id="APP_NAME">%2$s</xliff:g>\""</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> от приложения \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" и ещё <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1043,6 +1039,13 @@
       <item quantity="many">Добавлено <xliff:g id="NUMBER_1">%s</xliff:g> элементов управления.</item>
       <item quantity="other">Добавлено <xliff:g id="NUMBER_1">%s</xliff:g> элемента управления.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Удалено"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Добавлено в избранное"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Добавлено в избранное на позицию <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Не добавлено в избранное"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"добавить в избранное"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"удалить из избранного"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Переместить на позицию <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Элементы управления"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Выберите элементы управления, которые будут доступны в меню кнопки питания."</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Чтобы изменить порядок элементов управления, перетащите их"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index fb87a0b..7c4a13a 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"තිර රුව ඉවත ලන්න"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"තිර රූ පෙර දසුන"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"තිර රෙකෝඩරය"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"තිර පටිගත කිරීම සකසමින්"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"තිර පටිගත කිරීමේ සැසියක් සඳහා කෙරෙන දැනුම් දීම"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"පටිගත කිරීම ආරම්භ කරන්නද?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"පටිගත කරන අතරතුර, Android පද්ධතියට ඔබේ තිරයේ පෙනෙන හෝ ඔබේ උපාංගයේ වාදනය කරන ඕනෑම සංවේදී තොරතුරක් ග්‍රහණය කර ගැනීමට හැකිය. මෙයට මුරපද, ගෙවීම් තොරතුරු, ඡායාරූප, පණිවිඩ සහ ඕඩියෝ ඇතුළත් වේ."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"සියල්ල හිස් කරන්න"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"කළමනාකරණය කරන්න"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ඉතිහාසය"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"එන"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"නිහඬ දැනුම්දීම්"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"ඇඟවීමේ දැනුම් දීම්"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"සංවාද"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"මාතෘකාවක් නැත"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"මෙම යෙදුම යළි ඇරඹීමට සහ පූර්ණ තිරයට යාමට තට්ටු කරන්න"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> බුබුළු සඳහා සැකසීම්"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"පිටාර යාම"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"අට්ටිය වෙත ආපසු එක් කරන්න"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"කළමනා කරන්න"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> වෙතින් <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> වෙතින් <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> සහ තවත් <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> ක්"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="one">පාලන <xliff:g id="NUMBER_1">%s</xliff:g>ක් එක් කරන ලදී.</item>
       <item quantity="other">පාලන <xliff:g id="NUMBER_1">%s</xliff:g>ක් එක් කරන ලදී.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"ඉවත් කළා"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"ප්‍රියතම කළා"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ප්‍රියතම කළා, තත්ත්ව <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ප්‍රියතම වෙතින් ඉවත් කළා"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"ප්‍රියතම කරන්න"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"ප්‍රියතම වෙතින් ඉවත් කරන්න"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"ස්ථාන <xliff:g id="NUMBER">%d</xliff:g> වෙත ගෙන යන්න"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"පාලන"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"බල මෙනුවෙන් ප්‍රවේශ වීමට පාලන තෝරා ගන්න"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"පාලන නැවත පිළියෙළ කිරීමට අල්ලාගෙන සිට අදින්න"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index c835809..015da68 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Zavrieť snímku obrazovky"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ukážka snímky obrazovky"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Rekordér obrazovky"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Spracúva sa záznam obrazovky"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Zobrazuje sa upozornenie týkajúce sa relácie záznamu obrazovky"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Chcete spustiť nahrávanie?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Počas nahrávania zaznamená systém Android všetky citlivé údaje, ktoré sa zobrazia na obrazovke alebo prehrajú v zariadení. Zahrnuje to heslá, platobné údaje, fotky, správy a zvuky."</string>
@@ -517,8 +516,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Vymazať všetko"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Spravovať"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"História"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Prichádzajúce"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Tiché upozornenia"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Varovné upozornenia"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Konverzácie"</string>
@@ -594,7 +592,7 @@
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"Nastavenia zvuku"</string>
     <string name="accessibility_volume_expand" msgid="7653070939304433603">"Rozbaliť"</string>
     <string name="accessibility_volume_collapse" msgid="2746845391013829996">"Zbaliť"</string>
-    <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automaticky pridávať titulky k médiám"</string>
+    <string name="volume_odi_captions_tip" msgid="8825655463280990941">"Automatické titulkovanie médií"</string>
     <string name="accessibility_volume_close_odi_captions_tip" msgid="8924753283621160480">"Zavrieť tip pre titulky"</string>
     <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Prekrytie titulkov"</string>
     <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"povoliť"</string>
@@ -1001,10 +999,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Bez názvu"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Klepnutím reštartujete túto aplikáciu a prejdete do režimu celej obrazovky."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Nastavenia bublín aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Rozšírená ponuka"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Pridať späť do zásobníka"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Spravovať"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> z aplikácie <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> z aplikácie <xliff:g id="APP_NAME">%2$s</xliff:g> a ďalšie (<xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>)"</string>
@@ -1032,9 +1028,9 @@
     <string name="magnification_overlay_title" msgid="6584179429612427958">"Okno prekrytia priblíženia"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"Okno priblíženia"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"Ovládacie prvky okna priblíženia"</string>
-    <string name="quick_controls_title" msgid="6839108006171302273">"Ovládanie zariadenia"</string>
+    <string name="quick_controls_title" msgid="6839108006171302273">"Ovládanie zariadení"</string>
     <string name="quick_controls_subtitle" msgid="1667408093326318053">"Pridajte ovládacie prvky pre svoje pripojené zariadenia"</string>
-    <string name="quick_controls_setup_title" msgid="8901436655997849822">"Nastavenie ovládania zariadenia"</string>
+    <string name="quick_controls_setup_title" msgid="8901436655997849822">"Nastavenie ovládania zariadení"</string>
     <string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"Pridržaním vypínača získate prístup k ovládacím prvkom"</string>
     <string name="controls_providers_title" msgid="6879775889857085056">"Výberom aplikácie pridajte ovládacie prvky"</string>
     <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
@@ -1043,6 +1039,13 @@
       <item quantity="other">Bolo pridaných <xliff:g id="NUMBER_1">%s</xliff:g> ovládacích prvkov.</item>
       <item quantity="one">Bol pridaný <xliff:g id="NUMBER_0">%s</xliff:g> ovládací prvok.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Odstránené"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Pridané medzi obľúbené"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Pridané medzi obľúbené, pozícia <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Odstránené z obľúbených"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"pridáte medzi obľúbené"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"odstránite z obľúbených"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Presunúť na pozíciu <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Ovládacie prvky"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Vyberte si ovládacie prvky, ku ktorým chcete mať prístup v ponuke vypínača"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Ovládacie prvky môžete usporiadať pridržaním a presunutím"</string>
@@ -1050,7 +1053,7 @@
     <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"Zmeny neboli uložené"</string>
     <string name="controls_favorite_load_error" msgid="2533215155804455348">"Zoznam všetkých ovl. prvkov sa nepodarilo načítať."</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Iné"</string>
-    <string name="controls_dialog_title" msgid="2343565267424406202">"Pridanie do ovládania zariadenia"</string>
+    <string name="controls_dialog_title" msgid="2343565267424406202">"Pridanie do ovládania zariadení"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Pridať"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Navrhuje <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Ovládanie bolo aktualizované"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 038b3b6..0cf7e7c 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -391,7 +391,7 @@
     <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Povezava Wi-Fi ni vzpostavljena"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Svetlost"</string>
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="2325362583903258677">"SAMODEJNO"</string>
-    <string name="quick_settings_inversion_label" msgid="5078769633069667698">"Obrni barve"</string>
+    <string name="quick_settings_inversion_label" msgid="5078769633069667698">"Inverzija barv"</string>
     <string name="quick_settings_color_space_label" msgid="537528291083575559">"Način popravljanja barv"</string>
     <string name="quick_settings_more_settings" msgid="2878235926753776694">"Več nastavitev"</string>
     <string name="quick_settings_done" msgid="2163641301648855793">"Končano"</string>
@@ -977,7 +977,7 @@
     <string name="running_foreground_services_title" msgid="5137313173431186685">"Aplikacije, ki se izvajajo v ozadju"</string>
     <string name="running_foreground_services_msg" msgid="3009459259222695385">"Dotaknite se za prikaz podrobnosti porabe baterije in prenosa podatkov"</string>
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Želite izklopiti prenos podatkov v mobilnih omrežjih?"</string>
-    <string name="mobile_data_disable_message" msgid="8604966027899770415">"Prek operaterja <xliff:g id="CARRIER">%s</xliff:g> ne boste imeli dostopa do podatkovne povezave ali interneta. Internet bo na voljo samo prek povezave Wi-Fi."</string>
+    <string name="mobile_data_disable_message" msgid="8604966027899770415">"Prek operaterja »<xliff:g id="CARRIER">%s</xliff:g>« ne boste imeli dostopa do podatkovne povezave ali interneta. Internet bo na voljo samo prek povezave Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"svojega operaterja"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Ker aplikacija zakriva zahtevo za dovoljenje, z nastavitvami ni mogoče preveriti vašega odziva."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Želite dovoliti, da aplikacija <xliff:g id="APP_0">%1$s</xliff:g> prikaže izreze aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
@@ -1039,6 +1039,13 @@
       <item quantity="few"><xliff:g id="NUMBER_1">%s</xliff:g> kontrolniki dodani.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> kontrolnikov dodanih.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Odstranjeno"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Dodano med priljubljene"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Dodano med priljubljene, položaj <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Odstranjeno iz priljubljenih"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"dodajanje med priljubljene"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"odstranitev iz priljubljenih"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Premakni na položaj <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Kontrolniki"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Izberite kontrolnike, do katerih želite imeti dostop prek menija za vklop/izklop"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Držite in povlecite, da prerazporedite kontrolnike"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index f7e2bf2..f8da01c 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Hiq pamjen e ekranit"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pamja paraprake e imazhit"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Regjistruesi i ekranit"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Regjistrimi i ekranit po përpunohet"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Njoftim i vazhdueshëm për një seancë regjistrimi të ekranit"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Të nis regjistrimi?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Gjatë regjistrimit, sistemi Android mund të regjistrojë çdo informacion delikat që është i dukshëm në ekranin tënd ose që luhet në pajisje. Kjo përfshin fjalëkalimet, informacionin e pagesave, fotografitë, mesazhet dhe audion."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Pastroji të gjitha"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Menaxho"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historiku"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Hyrëse"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Njoftimet në heshtje"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Njoftimet sinjalizuese"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Bisedat"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Pa titull"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Trokit për ta rinisur këtë aplikacion dhe për të kaluar në ekranin e plotë."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Cilësimet për flluskat e <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Tejkalo"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Shto përsëri te stiva"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Menaxho"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> nga <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> nga <xliff:g id="APP_NAME">%2$s</xliff:g> dhe <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> të tjera"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">U shtuan <xliff:g id="NUMBER_1">%s</xliff:g> kontrolle.</item>
       <item quantity="one">U shtua <xliff:g id="NUMBER_0">%s</xliff:g> kontroll.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"E hequr"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"E shtuar te të preferuarat"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"E shtuar te të preferuarat, pozicioni <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"E hequr nga të preferuarat"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"ta shënosh si të preferuar"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"ta heqësh nga të preferuarat"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Zhvendose te pozicioni <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Kontrollet"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Zgjidh kontrollet për të pasur qasje nga menyja e energjisë"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Mbaje të shtypur dhe zvarrit për të risistemuar kontrollet"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index d61b36c..4a72d9d 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Одбаците снимак екрана"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Преглед снимка екрана"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Снимач екрана"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обрађујемо видео снимка екрана"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Обавештење о сесији снимања екрана је активно"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Желите да започнете снимање?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Током снимања Android систем може да сними осетљиве информације које су видљиве на екрану или које се пуштају на уређају. То обухвата лозинке, информације о плаћању, слике, поруке и звук."</string>
@@ -514,8 +513,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Обриши све"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Управљајте"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Историја"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Долазно"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Нечујна обавештења"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Обавештења која привлаче пажњу"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Конверзације"</string>
@@ -996,10 +994,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Без наслова"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Додирните да бисте рестартовали апликацију и прешли у режим целог екрана."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Подешавања за <xliff:g id="APP_NAME">%1$s</xliff:g> облачиће"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Преклапање"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Додај поново у групу"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Управљајте"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> из апликације <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> из апликације <xliff:g id="APP_NAME">%2$s</xliff:g> и још <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1019,10 +1015,10 @@
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Навигација система је ажурирана. Да бисте унели измене, идите у Подешавања."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Идите у Подешавања да бисте ажурирали навигацију система"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Стање приправности"</string>
-    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Приказују се у врху одељка за конверзације"</string>
-    <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Приказују слику профила на закључаном екрану"</string>
+    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Приказује се у врху одељка за конверзације"</string>
+    <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Приказује слику профила на закључаном екрану"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Приказују се плутајући облачићи преко апликација"</string>
-    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Ометају подешавање Не узнемиравај"</string>
+    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Омета подешавање Не узнемиравај"</string>
     <string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Важи"</string>
     <string name="magnification_overlay_title" msgid="6584179429612427958">"Преклопни прозор за увећање"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"Прозор за увећање"</string>
@@ -1037,6 +1033,13 @@
       <item quantity="few"><xliff:g id="NUMBER_1">%s</xliff:g> контроле су додате.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> контрола је додато.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Уклоњено"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Означено је као омиљено"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Означено је као омиљено, <xliff:g id="NUMBER">%d</xliff:g>. позиција"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Уклоњено је из омиљених"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"означили као омиљено"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"уклонили из омиљених"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Преместите на <xliff:g id="NUMBER">%d</xliff:g>. позицију"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Контроле"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Одаберите контроле којима ћете приступати из менија напајања"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Задржите и превуците да бисте променили распоред контрола"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index a2ef8b6..dd76429 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Stäng skärmdump"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Förhandsgranskning av skärmdump"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Skärminspelare"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandlar skärminspelning"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Avisering om att skärminspelning pågår"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Vill du starta inspelningen?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"När du spelar in kan Android-systemet registrera alla känsliga uppgifter som visas på skärmen eller spelas upp på enheten. Detta omfattar lösenord, betalningsuppgifter, foton, meddelanden och ljud."</string>
@@ -400,7 +399,7 @@
     <string name="quick_settings_tethering_label" msgid="5257299852322475780">"Internetdelning"</string>
     <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Surfzon"</string>
     <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Aktiverar …"</string>
-    <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Databesparing är på"</string>
+    <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Databesparing på"</string>
     <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
       <item quantity="other">%d enheter</item>
       <item quantity="one">%d enhet</item>
@@ -511,10 +510,9 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Rensa alla"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Hantera"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historik"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Inkommande"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Ljudlösa aviseringar"</string>
-    <string name="notification_section_header_alerting" msgid="3168140660646863240">"Aviseringar med vibration eller ljud"</string>
+    <string name="notification_section_header_alerting" msgid="3168140660646863240">"Aviseringar med vibrationer eller ljud"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Konversationer"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Rensa alla ljudlösa aviseringar"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Aviseringar har pausats via Stör ej"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Ingen titel"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Tryck för att starta om appen i helskärmsläge."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Inställningar för <xliff:g id="APP_NAME">%1$s</xliff:g>-bubblor"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Fler menyalternativ"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Lägg tillbaka på stack"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Hantera"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> från <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> från <xliff:g id="APP_NAME">%2$s</xliff:g> och <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> fler"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> kontroller har lagts till.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> kontroll har lagts till.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Har tagits bort"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Har lagts till som favorit"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Har lagts till som favorit, plats <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Har tagits bort från favoriter"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"lägga till som favorit"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"ta bort från favoriter"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Flytta till position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Kontroller"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Välj snabbkontroller som ska visas i strömbrytarmenyn"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Ändra ordning på kontrollerna genom att trycka och dra"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index cc9d9b2..652c6b3 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -89,11 +89,10 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Ondoa picha ya skrini"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Onyesho la kukagua picha ya skrini"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Kinasa Skrini"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Inachakata rekodi ya skrini"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Arifa inayoendelea ya kipindi cha kurekodi skrini"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Ungependa kuanza kurekodi?"</string>
-    <string name="screenrecord_description" msgid="1123231719680353736">"Inaporekodi, Mfumo wa Android unaweza kurekodi maelezo yoyote nyeti yanayoonekana kwenye skrini au yanayochezwa kwenye kifaa chako. Hii ni pamoja na manenosiri, maelezo ya malipo, picha, ujumbe na sauti."</string>
+    <string name="screenrecord_description" msgid="1123231719680353736">"Wakati wa kurekodi, Mfumo wa Android unaweza kusana maelezo yoyote nyeti yanayoonekana kwenye skrini au yanayochezwa kwenye kifaa chako. Hii ni pamoja na manenosiri, maelezo ya malipo, picha, ujumbe na sauti."</string>
     <string name="screenrecord_audio_label" msgid="6183558856175159629">"Rekodi sauti"</string>
     <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Sauti ya kifaa"</string>
     <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sauti kutoka kwenye kifaa chako, kama vile muziki, simu na milio ya simu"</string>
@@ -511,10 +510,9 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Futa zote"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Dhibiti"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historia"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Simu inayoingia"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Arifa zisizo na sauti"</string>
-    <string name="notification_section_header_alerting" msgid="3168140660646863240">"Arifa za ilani"</string>
+    <string name="notification_section_header_alerting" msgid="3168140660646863240">"Arifa za kuarifu"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Mazungumzo"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Futa arifa zote zisizo na sauti"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Kipengele cha Usinisumbue kimesitisha arifa"</string>
@@ -712,7 +710,7 @@
     <string name="notification_alert_title" msgid="7629202599338071971">"Kutoa arifa"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Kiputo"</string>
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"Hukusaidia kuwa makini bila sauti au mtetemo."</string>
-    <string name="notification_channel_summary_default" msgid="3539949463907902037">"Hupata umakinifu wako kwa sauti na mtetemo."</string>
+    <string name="notification_channel_summary_default" msgid="3539949463907902037">"Hupata umakinifu wako kwa sauti au mtetemo."</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"Hupata umakinifu wako kwa sauti au mtetemo. Mazungumzo kutoka kiputo cha <xliff:g id="APP_NAME">%1$s</xliff:g> kwa chaguomsingi."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Huweka umakinifu wako kwenye maudhui haya kwa kutumia njia ya mkato ya kuelea."</string>
     <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Huonyeshwa sehemu ya juu ya mazungumzo na huonekana kama kiputo."</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Wimbo hauna jina"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Gusa ili uzime na uwashe upya programu hii kisha nenda kwenye skrini nzima."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Mipangilio ya viputo vya <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Vipengee vya ziada"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Rejesha kwenye rafu"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Dhibiti"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> kutoka kwa <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> kutoka kwa <xliff:g id="APP_NAME">%2$s</xliff:g> na nyingine<xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">Umeweka vidhibiti <xliff:g id="NUMBER_1">%s</xliff:g>.</item>
       <item quantity="one">Umeweka kidhibiti <xliff:g id="NUMBER_0">%s</xliff:g>.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Kimeondolewa"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Kimewekwa kwenye vipendwa"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Kimewekwa kwenye vipendwa, nafasi ya <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Kimeondolewa kwenye vipendwa"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"weka kwenye vipendwa"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"ondoa kwenye vipendwa"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Sogeza kwenye nafasi ya <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Vidhibiti"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Chagua vidhibiti vya kufikia ukitumia menyu ya kuwasha/kuzima"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Shikilia na uburute ili upange upya vidhibiti"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index fc19d6e..6010be6 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ஸ்கிரீன்ஷாட்டை நிராகரி"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ஸ்கிரீன்ஷாட்டின் மாதிரிக்காட்சி"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"ஸ்கிரீன் ரெக்கார்டர்"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ஸ்க்ரீன் ரெக்கார்டிங் செயலாக்கப்படுகிறது"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"திரை ரெக்கார்டிங் அமர்விற்கான தொடர் அறிவிப்பு"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"ரெக்கார்டிங்கைத் தொடங்கவா?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"ரெக்கார்டு செய்யும்போது, உங்கள் திரையில் தோன்றக்கூடிய அல்லது சாதனத்தில் பிளே ஆகக்கூடிய ஏதேனும் அதிமுக்கியத் தகவலை Android சிஸ்டம் படமெடுக்க முடியும். கடவுச்சொற்கள், பேமெண்ட் தகவல், படங்கள், மெசேஜ்கள், ஆடியோ ஆகியவை இதில் அடங்கும்."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"எல்லாவற்றையும் அழி"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"அறிவிப்புகளை நிர்வகி"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"வரலாறு"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"உள்வருவது"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"ஒலியில்லாத அறிவிப்புகள்"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"விழிப்பூட்டல் அறிவிப்புகள்"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"உரையாடல்கள்"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"தலைப்பு இல்லை"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"தட்டுவதன் மூலம் இந்த ஆப்ஸை மீண்டும் தொடங்கலாம், முழுத்திரையில் பார்க்கலாம்."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> குமிழ்களுக்கான அமைப்புகள்"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"ஓவர்ஃப்லோ"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"மீண்டும் ஸ்டேக்கில் சேர்க்கவும்"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"நிர்வகி"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> இலிருந்து <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> மற்றும் மேலும் <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> ஆப்ஸிலிருந்து வந்துள்ள அறிவிப்பு: <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> கட்டுப்பாடுகள் சேர்க்கப்பட்டன.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> கட்டுப்பாடு சேர்க்கப்பட்டது.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"அகற்றப்பட்டது"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"பிடித்தவற்றில் சேர்க்கப்பட்டது"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"பிடித்தவற்றில் சேர்க்கப்பட்டது, நிலை <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"பிடித்தவற்றிலிருந்து நீக்கப்பட்டது"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"பிடித்தவற்றில் சேர்க்க இருமுறை தட்டவும்"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"பிடித்தவற்றிலிருந்து நீக்க இருமுறை தட்டவும்"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g>ம் நிலைக்கு நகர்த்து"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"கட்டுப்பாடுகள்"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"பவர் மெனுவில் இருந்து அணுகுவதற்கான கட்டுப்பாடுகளைத் தேர்ந்தெடுக்கலாம்"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"கட்டுப்பாடுகளை மறுவரிசைப்படுத்த அவற்றைப் பிடித்து இழுக்கவும்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index a2b3dec..3c2ada7 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -63,8 +63,8 @@
     <string name="usb_debugging_allow" msgid="1722643858015321328">"అనుమతించు"</string>
     <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"USB డీబగ్గింగ్‌కి అనుమతి లేదు"</string>
     <string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"ఈ పరికరానికి ప్రస్తుతం సైన్ ఇన్ చేసిన వినియోగదారు USB డీబగ్గింగ్ ఆన్ చేయలేరు. ఈ ఫీచర్ ఉపయోగించడానికి, ప్రాథమిక వినియోగదారుకి మారాలి."</string>
-    <string name="wifi_debugging_title" msgid="7300007687492186076">"ఈ నెట్‌వర్క్ పై వైర్‌లెస్ డీబగ్గింగ్‌ను అనుమతిస్తారా?"</string>
-    <string name="wifi_debugging_message" msgid="5461204211731802995">"నెట్‌వర్క్ పేరు (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi చిరునామా (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
+    <string name="wifi_debugging_title" msgid="7300007687492186076">"ఈ నెట్‌వర్క్ ద్వారా వైర్‌లెస్ డీబగ్గింగ్‌ను అనుమతించాలా?"</string>
+    <string name="wifi_debugging_message" msgid="5461204211731802995">"నెట్‌వర్క్ పేరు (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi అడ్రస్ (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
     <string name="wifi_debugging_always" msgid="2968383799517975155">"ఈ నెట్‌వర్క్ నుండి ఎల్లప్పుడూ అనుమతించు"</string>
     <string name="wifi_debugging_allow" msgid="4573224609684957886">"అనుమతించు"</string>
     <string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"వైర్‌లెస్ డీబగ్గింగ్‌కి అనుమతి లేదు"</string>
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"స్క్రీన్‌షాట్‌ను మూసివేస్తుంది"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"స్క్రీన్‌షాట్ ప్రివ్యూ"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"స్క్రీన్ రికార్డర్"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"స్క్రీన్ రికార్డింగ్ అవుతోంది"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"స్క్రీన్ రికార్డ్ సెషన్ కోసం ఆన్‌గోయింగ్ నోటిఫికేషన్"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"రికార్డింగ్‌ను ప్రారంభించాలా?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"రికార్డ్ చేస్తున్నప్పుడు, Android సిస్టమ్ మీ స్క్రీన్‌పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన ఏ సున్నితమైన సమాచారాన్నైనా క్యాప్చర్ చేయగలదు. ఈ సమాచారంలో, పాస్‌వర్డ్‌లు, చెల్లింపు వివరాలు, ఫోటోలు, మెసేజ్‌లు, ఆడియో ఉంటాయి."</string>
@@ -99,7 +98,7 @@
     <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"మీ పరికరం నుండి వచ్చే సంగీతం, కాల్‌లు, రింగ్‌టోన్‌ల వంటి ధ్వనులు"</string>
     <string name="screenrecord_mic_label" msgid="2111264835791332350">"మైక్రోఫోన్"</string>
     <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"పరికరం ఆడియో, మైక్రోఫోన్"</string>
-    <string name="screenrecord_start" msgid="330991441575775004">"ప్రారంభం"</string>
+    <string name="screenrecord_start" msgid="330991441575775004">"ప్రారంభించు"</string>
     <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"స్క్రీన్ రికార్డింగ్ చేయబడుతోంది"</string>
     <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"స్క్రీన్, ఆడియో రికార్డింగ్ చేయబడుతున్నాయి"</string>
     <string name="screenrecord_taps_label" msgid="1595690528298857649">"స్క్రీన్‌పై తాకే స్థానాలను చూపు"</string>
@@ -366,10 +365,10 @@
     <string name="quick_settings_rotation_locked_landscape_label" msgid="2000295772687238645">"ల్యాండ్‌స్కేప్"</string>
     <string name="quick_settings_ime_label" msgid="3351174938144332051">"ఇన్‌పుట్ పద్ధతి"</string>
     <string name="quick_settings_location_label" msgid="2621868789013389163">"లొకేషన్"</string>
-    <string name="quick_settings_location_off_label" msgid="7923929131443915919">"స్థానం ఆఫ్‌లో ఉంది"</string>
+    <string name="quick_settings_location_off_label" msgid="7923929131443915919">"లొకేష‌న్ ఆఫ్‌లో ఉంది"</string>
     <string name="quick_settings_media_device_label" msgid="8034019242363789941">"ప్రసార మాధ్యమ పరికరం"</string>
     <string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
-    <string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"అత్యవసర కాల్‌లు మాత్రమే"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"ఎమర్జెన్సీ కాల్స్ మాత్రమే"</string>
     <string name="quick_settings_settings_label" msgid="2214639529565474534">"సెట్టింగ్‌లు"</string>
     <string name="quick_settings_time_label" msgid="3352680970557509303">"సమయం"</string>
     <string name="quick_settings_user_label" msgid="1253515509432672496">"నేను"</string>
@@ -390,7 +389,7 @@
     <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"Wi‑Fi కనెక్ట్ కాలేదు"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ప్రకాశం"</string>
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="2325362583903258677">"ఆటోమేటిక్"</string>
-    <string name="quick_settings_inversion_label" msgid="5078769633069667698">"రంగుల‌ను అటుఇటు మార్చు"</string>
+    <string name="quick_settings_inversion_label" msgid="5078769633069667698">"కలర్ మార్పిడి"</string>
     <string name="quick_settings_color_space_label" msgid="537528291083575559">"రంగు సవరణ మోడ్"</string>
     <string name="quick_settings_more_settings" msgid="2878235926753776694">"మరిన్ని సెట్టింగ్‌లు"</string>
     <string name="quick_settings_done" msgid="2163641301648855793">"పూర్తయింది"</string>
@@ -421,7 +420,7 @@
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4063448287758262485">"సూర్యోదయం వరకు"</string>
     <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g>కి"</string>
     <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> వరకు"</string>
-    <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ముదురు రంగు థీమ్"</string>
+    <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ముదురు రంగు రూపం"</string>
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"బ్యాటరీ సేవర్"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"సూర్యాస్తమయానికి"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"సూర్యోదయం వరకు"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"అన్నీ క్లియర్ చేయండి"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"నిర్వహించండి"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"చరిత్ర"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"ఇన్‌కమింగ్"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"నిశ్శబ్ద నోటిఫికేషన్‌లు"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"అలర్ట్ చేసే నోటిఫికేషన్‌లు"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"సంభాషణలు"</string>
@@ -858,7 +856,7 @@
     <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"టైల్‌ల క్రమం మార్చడానికి వాటిని పట్టుకుని, లాగండి"</string>
     <string name="drag_to_remove_tiles" msgid="4682194717573850385">"తీసివేయడానికి ఇక్కడికి లాగండి"</string>
     <string name="drag_to_remove_disabled" msgid="933046987838658850">"మీ వద్ద కనీసం <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> టైల్‌లు ఉండాలి"</string>
-    <string name="qs_edit" msgid="5583565172803472437">"సవరించు"</string>
+    <string name="qs_edit" msgid="5583565172803472437">"ఎడిట్ చేయండి"</string>
     <string name="tuner_time" msgid="2450785840990529997">"సమయం"</string>
   <string-array name="clock_options">
     <item msgid="3986445361435142273">"గంటలు, నిమిషాలు మరియు సెకన్లను చూపు"</item>
@@ -969,7 +967,7 @@
     <string name="running_foreground_services_title" msgid="5137313173431186685">"నేపథ్యంలో అమలు అవుతున్న ఆప్‌లు"</string>
     <string name="running_foreground_services_msg" msgid="3009459259222695385">"బ్యాటరీ మరియు డేటా వినియోగ వివరాల కోసం నొక్కండి"</string>
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"మొబైల్ డేటాను ఆఫ్ చేయాలా?"</string>
-    <string name="mobile_data_disable_message" msgid="8604966027899770415">"మీకు <xliff:g id="CARRIER">%s</xliff:g> ద్వారా డేటా లేదా ఇంటర్నెట్‌కు యాక్సెస్ ఉండదు. Wi-Fi ద్వారా మాత్రమే ఇంటర్నెట్ అందుబాటులో ఉంటుంది."</string>
+    <string name="mobile_data_disable_message" msgid="8604966027899770415">"\"<xliff:g id="CARRIER">%s</xliff:g>\" ద్వారా మీకు డేటా లేదా ఇంటర్నెట్‌కు యాక్సెస్ ఉండదు. Wi-Fi ద్వారా మాత్రమే ఇంటర్నెట్ అందుబాటులో ఉంటుంది."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"మీ క్యారియర్"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"అనుమతి అభ్యర్థనకు ఒక యాప్ అడ్డు తగులుతున్నందున సెట్టింగ్‌లు మీ ప్రతిస్పందనను ధృవీకరించలేకపోయాయి."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_2">%2$s</xliff:g> స్లైస్‌లను చూపించడానికి <xliff:g id="APP_0">%1$s</xliff:g>ని అనుమతించండి?"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"శీర్షిక లేదు"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"ఈ యాప్‌ను పునఃప్రారంభించేలా నొక్కి, ఆపై పూర్తి స్క్రీన్‌‍లోకి వెళ్లండి."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> బబుల్స్ సెట్టింగ్‌లు"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"ఓవర్‌ఫ్లో"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"స్ట్యాక్‌కు తిరిగి జోడించండి"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"నిర్వహించండి"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> నుండి <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> నుండి <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> మరియు మరో <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> కంట్రోల్‌లు యాడ్ అయ్యాయి.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> కంట్రోల్ యాడ్ అయింది.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"తీసివేయబడింది"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"ఇష్టమైనదిగా గుర్తు పెట్టబడింది"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"<xliff:g id="NUMBER">%d</xliff:g>వ స్థానంలో ఇష్టమైనదిగా గుర్తు పెట్టబడింది"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ఇష్టమైనదిగా పెట్టిన గుర్తు తీసివేయబడింది"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"ఇష్టమైనదిగా గుర్తు పెట్టు"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"ఇష్టమైనదిగా పెట్టిన గుర్తును తీసివేయి"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g> పొజిషన్‌కు తరలించండి"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"నియంత్రణలు"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"పవర్ మెనూ నుండి యాక్సెస్ చేయడానికి నియంత్రణలను ఎంచుకోండి"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"నియంత్రణల క్రమం మార్చడానికి పట్టుకుని&amp;amp, లాగండి"</string>
diff --git a/packages/SystemUI/res/values-te/strings_tv.xml b/packages/SystemUI/res/values-te/strings_tv.xml
index ded2f50..df8b06d 100644
--- a/packages/SystemUI/res/values-te/strings_tv.xml
+++ b/packages/SystemUI/res/values-te/strings_tv.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="notification_channel_tv_pip" msgid="844249465483874817">"చిత్రంలో చిత్రం"</string>
+    <string name="notification_channel_tv_pip" msgid="844249465483874817">"పిక్చర్-ఇన్-పిక్చర్"</string>
     <string name="pip_notification_unknown_title" msgid="4413256731340767259">"(శీర్షిక లేని ప్రోగ్రామ్)"</string>
     <string name="pip_close" msgid="5775212044472849930">"PIPని మూసివేయి"</string>
     <string name="pip_fullscreen" msgid="3877997489869475181">"పూర్తి స్క్రీన్"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 8d9d151..3ee8638 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -38,7 +38,7 @@
     <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"เปิด"</string>
     <string name="battery_saver_start_action" msgid="4553256017945469937">"เปิดโหมดประหยัดแบตเตอรี่"</string>
     <string name="status_bar_settings_settings_button" msgid="534331565185171556">"การตั้งค่า"</string>
-    <string name="status_bar_settings_wifi_button" msgid="7243072479837270946">"WiFi"</string>
+    <string name="status_bar_settings_wifi_button" msgid="7243072479837270946">"Wi-Fi"</string>
     <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"หมุนหน้าจออัตโนมัติ"</string>
     <string name="status_bar_settings_mute_label" msgid="914392730086057522">"ปิดเสียง"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="2151934479226017725">"อัตโนมัติ"</string>
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ปิดภาพหน้าจอ"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ตัวอย่างภาพหน้าจอ"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"โปรแกรมอัดหน้าจอ"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"กำลังประมวลผลการอัดหน้าจอ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"การแจ้งเตือนต่อเนื่องสำหรับเซสชันการบันทึกหน้าจอ"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"เริ่มบันทึกเลยไหม"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"ขณะบันทึก ระบบ Android จะบันทึกข้อมูลที่ละเอียดอ่อนที่ปรากฏบนหน้าจอหรือเล่นในอุปกรณ์ได้ ซึ่งรวมถึงรหัสผ่าน ข้อมูลการชำระเงิน รูปภาพ ข้อความ และเสียง"</string>
@@ -375,7 +374,7 @@
     <string name="quick_settings_user_label" msgid="1253515509432672496">"ฉัน"</string>
     <string name="quick_settings_user_title" msgid="8673045967216204537">"ผู้ใช้"</string>
     <string name="quick_settings_user_new_user" msgid="3347905871336069666">"ผู้ใช้ใหม่"</string>
-    <string name="quick_settings_wifi_label" msgid="2879507532983487244">"WiFi"</string>
+    <string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
     <string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"ไม่ได้เชื่อมต่อ"</string>
     <string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ไม่มีเครือข่าย"</string>
     <string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"ปิด WiFi"</string>
@@ -390,7 +389,7 @@
     <string name="quick_settings_cast_no_wifi" msgid="6980194769795014875">"ไม่ได้เชื่อมต่อ Wi-Fi"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ความสว่าง"</string>
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="2325362583903258677">"อัตโนมัติ"</string>
-    <string name="quick_settings_inversion_label" msgid="5078769633069667698">"สลับสี"</string>
+    <string name="quick_settings_inversion_label" msgid="5078769633069667698">"กลับสี"</string>
     <string name="quick_settings_color_space_label" msgid="537528291083575559">"โหมดการแก้ไขสี"</string>
     <string name="quick_settings_more_settings" msgid="2878235926753776694">"การตั้งค่าเพิ่มเติม"</string>
     <string name="quick_settings_done" msgid="2163641301648855793">"เสร็จสิ้น"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"ล้างทั้งหมด"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"จัดการ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ประวัติ"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"เข้ามาใหม่"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"การแจ้งเตือนแบบไม่มีเสียง"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"มีการแจ้งเตือน"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"การสนทนา"</string>
@@ -712,8 +710,8 @@
     <string name="notification_alert_title" msgid="7629202599338071971">"แจ้งเตือน"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"บับเบิล"</string>
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"ช่วยรักษาสมาธิของคุณด้วยการไม่ส่งเสียงหรือสั่น"</string>
-    <string name="notification_channel_summary_default" msgid="3539949463907902037">"ดึงความสนใจของคุณด้วยเสียงและการสั่น"</string>
-    <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"ดึงความสนใจของคุณด้วยเสียงและการสั่น การสนทนาจาก <xliff:g id="APP_NAME">%1$s</xliff:g> จะแสดงเป็นบับเบิลโดยค่าเริ่มต้น"</string>
+    <string name="notification_channel_summary_default" msgid="3539949463907902037">"ดึงความสนใจของคุณด้วยเสียงหรือการสั่น"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"ดึงความสนใจของคุณด้วยเสียงหรือการสั่น การสนทนาจาก <xliff:g id="APP_NAME">%1$s</xliff:g> จะแสดงเป็นบับเบิลโดยค่าเริ่มต้น"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ดึงดูดความสนใจของคุณไว้เสมอด้วยทางลัดแบบลอยที่มายังเนื้อหานี้"</string>
     <string name="notification_channel_summary_priority" msgid="7415770044553264622">"แสดงที่ด้านบนของส่วนการสนทนาและปรากฏเป็นบับเบิล"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"การตั้งค่า"</string>
@@ -969,7 +967,7 @@
     <string name="running_foreground_services_title" msgid="5137313173431186685">"แอปที่กำลังทำงานในเบื้องหลัง"</string>
     <string name="running_foreground_services_msg" msgid="3009459259222695385">"แตะเพื่อดูรายละเอียดเกี่ยวกับแบตเตอรี่และปริมาณการใช้อินเทอร์เน็ต"</string>
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"ปิดอินเทอร์เน็ตมือถือไหม"</string>
-    <string name="mobile_data_disable_message" msgid="8604966027899770415">"คุณจะใช้เน็ตมือถือหรืออินเทอร์เน็ตผ่าน <xliff:g id="CARRIER">%s</xliff:g> ไม่ได้ แต่จะใช้ผ่าน Wi-Fi ได้เท่านั้น"</string>
+    <string name="mobile_data_disable_message" msgid="8604966027899770415">"คุณจะใช้เน็ตมือถือหรืออินเทอร์เน็ตผ่าน \"<xliff:g id="CARRIER">%s</xliff:g>\" ไม่ได้ แต่จะใช้ผ่าน Wi-Fi ได้เท่านั้น"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"ผู้ให้บริการของคุณ"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"เนื่องจากแอปหนึ่งได้บดบังคำขอสิทธิ์ ระบบจึงไม่สามารถยืนยันคำตอบของคุณสำหรับการตั้งค่าได้"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"อนุญาตให้ <xliff:g id="APP_0">%1$s</xliff:g> แสดงส่วนต่างๆ ของ <xliff:g id="APP_2">%2$s</xliff:g>"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"ไม่มีชื่อ"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"แตะเพื่อรีสตาร์ทแอปนี้และแสดงแบบเต็มหน้าจอ"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"การตั้งค่าบับเบิล <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"รายการเพิ่มเติม"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"เพิ่มกลับไปที่สแต็ก"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"จัดการ"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> จาก <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> จาก <xliff:g id="APP_NAME">%2$s</xliff:g> และอีก <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> รายการ"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">เพิ่มตัวควบคุม <xliff:g id="NUMBER_1">%s</xliff:g> ตัวแล้ว</item>
       <item quantity="one">เพิ่มตัวควบคุม <xliff:g id="NUMBER_0">%s</xliff:g> ตัวแล้ว</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"นำออกแล้ว"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"ตั้งเป็นรายการโปรดแล้ว"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ตั้งเป็นรายการโปรดแล้ว โดยอยู่ลำดับที่ <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"นำออกจากรายการโปรดแล้ว"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"ตั้งเป็นรายการโปรด"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"นำออกจากรายการโปรด"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"ย้ายไปที่ตำแหน่ง <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"การควบคุม"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"เลือกตัวควบคุมที่ต้องการให้เข้าถึงได้จากเมนูเปิด/ปิด"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"กดตัวควบคุมค้างไว้แล้วลากเพื่อจัดเรียงใหม่"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index cfb8d54..2b26931 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"I-dismiss ang screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Preview ng screenshot"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Recorder ng Screen"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Pinoproseso screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Kasalukuyang notification para sa session ng pag-record ng screen"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Simulang Mag-record?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Habang nagre-record, puwedeng ma-capture ng Android System ang anumang sensitibong impormasyong nakikita sa iyong screen o nagpe-play sa device mo. Kasama dito ang mga password, impormasyon sa pagbabayad, mga larawan, mensahe, at audio."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"I-clear lahat"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Pamahalaan"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"History"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Papasok"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Mga silent na notification"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Mga nag-aalertong notification"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Mga Pag-uusap"</string>
@@ -715,7 +713,7 @@
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"Kinukuha ang iyong atensyon sa pamamagitan ng tunog o pag-vibrate."</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"Kinukuha ang iyong atensyon sa pamamagitan ng tunog o pag-vibrate. Mga pag-uusap mula sa <xliff:g id="APP_NAME">%1$s</xliff:g> bubble bilang default."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Pinapanatili ang iyong atensyon sa pamamagitan ng lumulutang na shortcut sa content na ito."</string>
-    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Lumalabas sa itaas ng seksyon ng pag-uusap at nagpapakita bilang bubble."</string>
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Makikita sa itaas ng seksyon ng pag-uusap at lalabas bilang bubble"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Mga Setting"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priyoridad"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"Hindi sinusuportahan ng <xliff:g id="APP_NAME">%1$s</xliff:g> ang mga setting na partikular sa pag-uusap"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Walang pamagat"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"I-tap para i-restart ang app na ito at mag-full screen."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Mga setting para sa mga bubble ng <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Overflow"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Idagdag ulit sa stack"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Pamahalaan"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> mula sa <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> mula sa <xliff:g id="APP_NAME">%2$s</xliff:g> at <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> pa"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> kontrol ang naidagdag.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> na kontrol ang naidagdag.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Inalis"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Ginawang paborito"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ginawang paborito, posisyon <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Inalis sa paborito"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"gawing paborito"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"alisin sa paborito"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Ilipat sa posisyong <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Mga Kontrol"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Pumili ng mga kontrol na maa-access mula sa power menu"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"I-hold at i-drag para baguhin ang pagkakaayos ng mga kontrol"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 3b6ad40..7e35a77 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Ekran görüntüsünü kapat"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekran görüntüsü önizlemesi"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekran Kaydedicisi"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran kaydı işleniyor"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekran kaydı oturumu için devam eden bildirim"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Kayıt Başlatılsın mı?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Kayıt sırasında Android Sistemi, ekranınızda görünen veya cihazınızda oynatılan hassas bilgileri yakalayabilir. Buna şifreler, ödeme bilgileri, fotoğraflar, mesajlar ve sesler dahildir."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Tümünü temizle"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Yönet"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Geçmiş"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Gelen"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Sessiz bildirimler"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Uyaran bildirimler"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Görüşmeler"</string>
@@ -954,7 +952,7 @@
     <string name="instant_apps_message_with_help" msgid="1816952263531203932">"Uygulama yüklenmeden açıldı. Daha fazla bilgi için dokunun."</string>
     <string name="app_info" msgid="5153758994129963243">"Uygulama bilgisi"</string>
     <string name="go_to_web" msgid="636673528981366511">"Tarayıcıya git"</string>
-    <string name="mobile_data" msgid="4564407557775397216">"Mobil veriler"</string>
+    <string name="mobile_data" msgid="4564407557775397216">"Mobil veri"</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="MOBILE_DATA_TYPE">%2$s</xliff:g>, <xliff:g id="CARRIER_NAME">%1$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="5389597396308001471">"Kablosuz bağlantı kapalı"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Başlıksız"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Bu uygulamayı yeniden başlatmak ve tam ekrana geçmek için dokunun."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> baloncukları için ayarlar"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Taşma"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Yığına geri ekle"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Yönet"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> uygulamasından <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> uygulamasından <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ve diğer <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> kontrol eklendi.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> kontrol eklendi.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Kaldırıldı"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favoriler listesine eklendi"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favorilere eklendi, konum: <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Favorilerden kaldırıldı"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"favorilere ekleyin"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"favorilerden kaldırın"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g>. konuma taşı"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Kontroller"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Güç menüsünden erişmek için denetimleri seçin"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Kontrolleri yeniden düzenlemek için basılı tutup sürükleyin"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 11aba0b..97157a4 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -88,9 +88,8 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Додаток або адміністратор вашої організації не дозволяють робити знімки екрана"</string>
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Закрити знімок екрана"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Перегляд знімка екрана"</string>
-    <string name="screenrecord_name" msgid="2596401223859996572">"Створення знімків екрана"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_name" msgid="2596401223859996572">"Відеозапис екрана"</string>
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обробка записування екрана"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Сповіщення про сеанс запису екрана"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Почати запис?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Під час запису система Android може фіксувати будь-яку конфіденційну інформацію, яка з\'являється на екрані або відтворюється на пристрої, зокрема паролі, платіжну інформацію, фотографії, повідомлення та звуки."</string>
@@ -517,8 +516,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Очистити все"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Керувати"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Історія"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Нові"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Беззвучні сповіщення"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Сповіщення зі звуком чи вібрацією"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Розмови"</string>
@@ -1001,10 +999,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Без назви"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Натисніть, щоб перезапустити додаток і перейти в повноекранний режим."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Налаштування спливаючих чатів від додатка <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Додаткове меню"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Додати в список"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Налаштувати"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"Cповіщення \"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>\" від додатка <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"Сповіщення \"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>\" від додатка <xliff:g id="APP_NAME">%2$s</xliff:g> (і ще <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g>)"</string>
@@ -1043,6 +1039,13 @@
       <item quantity="many">Додано <xliff:g id="NUMBER_1">%s</xliff:g> елементів керування.</item>
       <item quantity="other">Додано <xliff:g id="NUMBER_1">%s</xliff:g> елемента керування.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Вилучено"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Додано у вибране"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Додано у вибране, позиція <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Видалено з вибраного"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"додати у вибране"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"видалити з вибраного"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Перемістити на позицію <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Елементи керування"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Виберіть, які елементи керування будуть у меню \"Живлення\""</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Щоб змінити порядок елементів керування, перетягуйте їх"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index cacfb3e..3263d6d 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"اسکرین شاٹ برخاست کریں"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"اسکرین شاٹ کا پیش منظر"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"سکرین ریکارڈر"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"سکرین ریکارڈنگ پروسیس ہورہی ہے"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"اسکرین ریکارڈ سیشن کیلئے جاری اطلاع"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"ریکارڈنگ شروع کریں؟"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"‏ریکارڈ کرنے کے دوران، Android سسٹم آپ کی اسکرین پر نظر آنے والی یا آپ کے آلہ پر چلنے والی کسی بھی حساس معلومات کو کیپچر کر سکتا ہے۔ اس میں پاس ورڈز، ادائیگی کی معلومات، تصاویر، پیغامات اور آڈیو شامل ہیں۔"</string>
@@ -101,7 +100,7 @@
     <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"آلہ کا آڈیو اور مائیکروفون"</string>
     <string name="screenrecord_start" msgid="330991441575775004">"شروع کریں"</string>
     <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"ریکارڈنگ اسکرین"</string>
-    <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"ریکارڈنگ اسکرین اور آڈیو"</string>
+    <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"اسکرین اور آڈیو کی ریکارڈنگ ہو رہی ہے"</string>
     <string name="screenrecord_taps_label" msgid="1595690528298857649">"اسکرین پر کئے گئے ٹچز دکھائیں"</string>
     <string name="screenrecord_stop_text" msgid="6549288689506057686">"روکنے کے لیے تھپتھپائیں"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"روکیں"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"سبھی کو صاف کریں"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"نظم کریں"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"سرگزشت"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"اِن کمنگ"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"اطلاعات خاموش کریں"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"متنبہ کرنے کی اطلاعات"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"گفتگوئیں"</string>
@@ -588,7 +586,7 @@
     <string name="accessibility_volume_settings" msgid="1458961116951564784">"صوتی ترتیبات"</string>
     <string name="accessibility_volume_expand" msgid="7653070939304433603">"پھیلائیں"</string>
     <string name="accessibility_volume_collapse" msgid="2746845391013829996">"سکیڑیں"</string>
-    <string name="volume_odi_captions_tip" msgid="8825655463280990941">"خودکار طور پر کیپشن میڈیا"</string>
+    <string name="volume_odi_captions_tip" msgid="8825655463280990941">"خودکار طور پر میڈیا پر کیپشن لگائیں"</string>
     <string name="accessibility_volume_close_odi_captions_tip" msgid="8924753283621160480">"کیپشنز کی تجویز بند کریں"</string>
     <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"کیپشنز کا اوورلے"</string>
     <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"فعال کریں"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"کوئی عنوان نہیں ہے"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"یہ ایپ دوبارہ شروع کرنے کے لیے تھپتھپائیں اور پوری اسکرین پر جائیں۔"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> بلبلوں کے لیے ترتیبات"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"اوورفلو"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"انبار میں واپس شامل کریں"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"نظم کریں"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g> کی جانب سے <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> اور <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> مزید سے <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1017,7 +1013,7 @@
     <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"گفتگو کے سیکشن میں سب سے اوپر دکھائیں"</string>
     <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"مقفل سکرین پر پروفائل کی تصویر دکھائیں"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"ایپس کے سب سے اوپر فلوٹنگ بلبلہ کے طور پر ظاہر ہوں"</string>
-    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"مداخلت کریں ڈسٹرب نہ کریں"</string>
+    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"ڈسٹرب نہ کریں میں مداخلت کریں"</string>
     <string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"سمجھ آ گئی"</string>
     <string name="magnification_overlay_title" msgid="6584179429612427958">"میگنیفیکیشن اوورلے ونڈو"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"میگنیفکیشن ونڈو"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> کنٹرولز شامل کر دیے گئے۔</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> کنٹرول شامل کر دیا گیا۔</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"ہٹا دیا گیا"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"پسند کردہ"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"پسند کردہ، پوزیشن <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ناپسند کردہ"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"پسندیدہ بنائیں"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"پسندیدگی ختم کریں"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"پوزیشن <xliff:g id="NUMBER">%d</xliff:g> میں منتقل کریں"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"کنٹرولز"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"پاور مینو سے رسائی حاصل کرنے کے لیے کنٹرولز کو منتخب کریں"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"کنٹرولز کو دوبارہ ترتیب دینے کے ليے پکڑیں اور گھسیٹیں"</string>
@@ -1039,10 +1042,8 @@
     <string name="controls_favorite_load_error" msgid="2533215155804455348">"تمام کنٹرولز کی فہرست لوڈ نہیں کی جا سکی۔"</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"دیگر"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"آلہ کے کنٹرولز میں شامل کریں"</string>
-    <!-- no translation found for controls_dialog_ok (2770230012857881822) -->
-    <skip />
-    <!-- no translation found for controls_dialog_message (342066938390663844) -->
-    <skip />
+    <string name="controls_dialog_ok" msgid="2770230012857881822">"شامل کریں"</string>
+    <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> کی طرف سے تجویز کردہ"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"کنٹرولز اپ ڈیٹ کیے گئے"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"‏PIN میں حروف یا علامات شامل ہیں"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"<xliff:g id="DEVICE">%s</xliff:g> کی تصدیق کریں"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 9ec17d7..7befe46 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Skrinshotni yopish"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Skrinshotga razm solish"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekrandan yozib olish"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran yozib olinmoqda"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekrandan yozib olish seansi uchun joriy bildirishnoma"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Yozib olish boshlansinmi?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Yozib olishda Android tizimi ekraningizda koʻringan yoki qurilmangizda ijro etilgan maxfiy axborotni ham yozib olishi mumkin. Bunga parollar, toʻlovga oid axborot, suratlar, xabarlar va audio kiradi."</string>
@@ -511,10 +510,9 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Hammasini tozalash"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Boshqarish"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Tarix"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Kiruvchi"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Sokin bildirishnomalar"</string>
-    <string name="notification_section_header_alerting" msgid="3168140660646863240">"Bildirishnomalarning yuborilishi"</string>
+    <string name="notification_section_header_alerting" msgid="3168140660646863240">"Ogohlantirishlar"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Suhbatlar"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Barcha sokin bildirishnomalarni tozalash"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Bezovta qilinmasin rejimida bildirishnomalar pauza qilingan"</string>
@@ -704,20 +702,20 @@
     <string name="inline_minimize_button" msgid="1474436209299333445">"Kichraytirish"</string>
     <string name="inline_silent_button_silent" msgid="525243786649275816">"Tovushsiz"</string>
     <string name="inline_silent_button_stay_silent" msgid="2129254868305468743">"Ovozsiz qolsin"</string>
-    <string name="inline_silent_button_alert" msgid="5705343216858250354">"Bildirishnoma yuborish"</string>
+    <string name="inline_silent_button_alert" msgid="5705343216858250354">"Ogohlantirish"</string>
     <string name="inline_silent_button_keep_alerting" msgid="6577845442184724992">"Signal berishda davom etilsin"</string>
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Bildirishnoma kelmasin"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Bu ilovadan keladigan bildirishnomalar chiqaversinmi?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Tovushsiz"</string>
-    <string name="notification_alert_title" msgid="7629202599338071971">"Bildirishnoma yuborish"</string>
+    <string name="notification_alert_title" msgid="7629202599338071971">"Ogohlantirish"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Pufaklar"</string>
     <string name="notification_channel_summary_low" msgid="7300447764759926720">"Bildirishnomalar tovush va tebranishsiz keladi."</string>
     <string name="notification_channel_summary_default" msgid="3539949463907902037">"Bildirishnomalar tovush va tebranish bilan keladi."</string>
     <string name="notification_channel_summary_default_with_bubbles" msgid="6298026344552480458">"Bildirishnomalar tovush va tebranish bilan keladi. <xliff:g id="APP_NAME">%1$s</xliff:g> suhbatlari standart holatda bulutcha shaklida chiqadi."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Bu kontentni ochuvchi erkin yorliq diqqatingizda boʻladi."</string>
-    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Suhbatlar boʻlimining yuqori qismida bulutcha shaklida chiqadi."</string>
+    <string name="notification_channel_summary_priority" msgid="7415770044553264622">"Suhbatlar ruknining tepasida bulutcha shaklida chiqadi."</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Sozlamalar"</string>
-    <string name="notification_priority_title" msgid="2079708866333537093">"Muhimligi"</string>
+    <string name="notification_priority_title" msgid="2079708866333537093">"Muhim"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasida suhbat sozlamalari ishlamaydi"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"Avvalgi bulutchalar topilmadi"</string>
     <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Bu yerda oxirgi va yopilgan bulutcha shaklidagi bildirishnomalar chiqadi"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Nomsiz"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Bu ilovani qaytadan ishga tushirish va butun ekranga ochish uchun bosing."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g> bulutchalari uchun sozlamalar"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Kengaytirilgan"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Yana toʻplamga kiritish"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Boshqarish"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g> ilovasidan <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> va yana <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> ta bildirishnoma"</string>
@@ -1014,10 +1010,10 @@
     <string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Tizim navigatsiyasi yangilandi. Buni Sozlamalar orqali oʻzgartirishingiz mumkin."</string>
     <string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Tizim navigatsiyasini yangilash uchun Sozlamalarni oching"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Kutib turing"</string>
-    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Suhbatlar qismining tepasida koʻrsatish"</string>
-    <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Ekran qulfida profil rasmini koʻrsatish"</string>
+    <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Suhbatlar ruknining tepasida chiqarish"</string>
+    <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Ekran qulfida profil rasmini chiqarish"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Ilovalar ustida bulutchali xabar sifatida chiqadi"</string>
-    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"“Bezovta qilinmasin” rejimida koʻrsatish"</string>
+    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Bezovta qilinmasin rejimida chiqarish"</string>
     <string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"OK"</string>
     <string name="magnification_overlay_title" msgid="6584179429612427958">"Kattalashtirish oynasining ustidan ochilishi"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"Kattalashtirish oynasi"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> ta nazorat kiritilgan.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> ta nazorat kiritilgan.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Olib tashlandi"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Saralanganlarga kiritilgan"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Saralanganlarga kiritilgan, <xliff:g id="NUMBER">%d</xliff:g>-joy"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Saralanganlardan olib tashlangan"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"saralanganlarga kiritish"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"saralanganlardan olib tashlash"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"<xliff:g id="NUMBER">%d</xliff:g>-joyga olish"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Boshqaruv elementlari"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Quvvat tugmasi menyusida chiqadigan boshqaruv elementlarini tanlang"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Boshqaruv elementlarini qayta tartiblash uchun ushlab torting"</string>
@@ -1040,7 +1043,7 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Boshqa"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Qurilma boshqaruv elementlariga kiritish"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Kiritish"</string>
-    <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> tomonidan taklif etilgan"</string>
+    <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> taklif etgan"</string>
     <string name="controls_dialog_confirmation" msgid="586517302736263447">"Boshqaruv elementlari yangilandi"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN kod harflar va belgilardan iborat boʻladi"</string>
     <string name="controls_pin_verify" msgid="3452778292918877662">"Tekshirish: <xliff:g id="DEVICE">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 73101b2..3f333f0 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Đóng ảnh chụp màn hình"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Xem trước ảnh chụp màn hình"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Trình ghi màn hình"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Đang xử lý video ghi màn hình"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Thông báo đang diễn ra về phiên ghi màn hình"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Bắt đầu ghi?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Trong khi ghi, Hệ thống Android có thể ghi lại mọi thông tin nhạy cảm hiển thị trên màn hình hoặc phát trên thiết bị của bạn. Những thông tin này bao gồm mật khẩu, thông tin thanh toán, ảnh, thông báo và âm thanh."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Xóa tất cả"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Quản lý"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Lịch sử"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Hiển thị gần đây"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Thông báo im lặng"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Thông báo cảnh báo"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Cuộc trò chuyện"</string>
@@ -969,7 +967,7 @@
     <string name="running_foreground_services_title" msgid="5137313173431186685">"Ứng dụng đang chạy trong nền"</string>
     <string name="running_foreground_services_msg" msgid="3009459259222695385">"Nhấn để biết chi tiết về mức sử dụng dữ liệu và pin"</string>
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"Tắt dữ liệu di động?"</string>
-    <string name="mobile_data_disable_message" msgid="8604966027899770415">"Bạn sẽ không có quyền sử dụng dữ liệu hoặc truy cập Internet thông qua <xliff:g id="CARRIER">%s</xliff:g>. Bạn chỉ có thể truy cập Internet thông qua Wi-Fi."</string>
+    <string name="mobile_data_disable_message" msgid="8604966027899770415">"Bạn sẽ không có quyền sử dụng dữ liệu hoặc truy cập Internet thông qua chế độ <xliff:g id="CARRIER">%s</xliff:g>. Bạn chỉ có thể truy cập Internet thông qua Wi-Fi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"nhà mạng của bạn"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"Vì ứng dụng đang che khuất yêu cầu cấp quyền nên Cài đặt không thể xác minh câu trả lời của bạn."</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"Cho phép <xliff:g id="APP_0">%1$s</xliff:g> hiển thị các lát của <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Không có tiêu đề"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Nhấn để khởi động lại ứng dụng này và xem ở chế độ toàn màn hình."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Tùy chọn cài đặt cho bong bóng trò chuyện <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Trình đơn mục bổ sung"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Thêm lại vào ngăn xếp"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Quản lý"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> của <xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> từ <xliff:g id="APP_NAME">%2$s</xliff:g> và <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> bong bóng khác"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">Đã thêm <xliff:g id="NUMBER_1">%s</xliff:g> tùy chọn điều khiển.</item>
       <item quantity="one">Đã thêm <xliff:g id="NUMBER_0">%s</xliff:g> tùy chọn điều khiển.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Đã xóa"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Được yêu thích"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Được yêu thích, vị trí số <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Không được yêu thích"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"đánh dấu là yêu thích"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"bỏ yêu thích"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Di chuyển tới vị trí số <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Các tùy chọn điều khiển"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Chọn các tùy chọn điều khiển để truy cập từ trình đơn nguồn"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Giữ và kéo để sắp xếp lại các tùy chọn điều khiển"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 8ea00ae..ed4885c 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -63,7 +63,7 @@
     <string name="usb_debugging_allow" msgid="1722643858015321328">"允许"</string>
     <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"不允许使用 USB 调试功能"</string>
     <string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"目前已登录此设备的用户无法开启 USB 调试功能。要使用此功能,请切换为主要用户的帐号。"</string>
-    <string name="wifi_debugging_title" msgid="7300007687492186076">"要在此网络上允许无线调试吗?"</string>
+    <string name="wifi_debugging_title" msgid="7300007687492186076">"要允许在此网络上进行无线调试吗?"</string>
     <string name="wifi_debugging_message" msgid="5461204211731802995">"网络名称 (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWLAN 地址 (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
     <string name="wifi_debugging_always" msgid="2968383799517975155">"在此网络上始终允许"</string>
     <string name="wifi_debugging_allow" msgid="4573224609684957886">"允许"</string>
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"关闭屏幕截图"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"屏幕截图预览"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"屏幕录制器"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在处理屏幕录制视频"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"持续显示屏幕录制会话通知"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"要开始录制吗?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"在录制内容时,Android 系统可以捕捉到您屏幕上显示或设备中播放的敏感信息,其中包括密码、付款信息、照片、消息和音频。"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"全部清除"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"历史记录"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"收到的通知"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"无声通知"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"提醒通知"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"对话"</string>
@@ -717,7 +715,7 @@
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"通过可链接到这项内容的浮动快捷方式吸引您的注意。"</string>
     <string name="notification_channel_summary_priority" msgid="7415770044553264622">"以对话泡形式显示在对话部分顶部。"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"设置"</string>
-    <string name="notification_priority_title" msgid="2079708866333537093">"优先级"</string>
+    <string name="notification_priority_title" msgid="2079708866333537093">"优先"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g>不支持对话专用设置"</string>
     <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"最近没有对话泡"</string>
     <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"此处会显示最近的对话泡和已关闭的对话泡"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"无标题"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"点按即可重启此应用并进入全屏模式。"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"<xliff:g id="APP_NAME">%1$s</xliff:g>对话泡的设置"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"菜单"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"重新加入叠放"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"管理"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g>:<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"<xliff:g id="APP_NAME">%2$s</xliff:g>和另外 <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> 个应用:<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1017,7 +1013,7 @@
     <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"显示在对话部分顶部"</string>
     <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"在锁定屏幕上显示个人资料照片"</string>
     <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"以悬浮对话泡的形式显示在应用之上"</string>
-    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"中断“勿扰”模式"</string>
+    <string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"中断勿扰模式"</string>
     <string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"知道了"</string>
     <string name="magnification_overlay_title" msgid="6584179429612427958">"放大叠加窗口"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"放大窗口"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">已添加 <xliff:g id="NUMBER_1">%s</xliff:g> 个控件。</item>
       <item quantity="one">已添加 <xliff:g id="NUMBER_0">%s</xliff:g> 个控件。</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"已移除"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"已收藏"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"已收藏,位置:<xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"已取消收藏"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"收藏"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"取消收藏"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"移至位置 <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"控件"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"选择要从电源菜单访问的控件"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"按住并拖动即可重新排列控件"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 751767a..66ef1ae 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -65,7 +65,7 @@
     <string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"目前登入此裝置的使用者無法啟用 USB 偵錯功能。如要使用此功能,請切換至主要使用者。"</string>
     <string name="wifi_debugging_title" msgid="7300007687492186076">"要在此網絡上允許無線偵錯功能嗎?"</string>
     <string name="wifi_debugging_message" msgid="5461204211731802995">"網絡名稱 (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWi‑Fi 地址 (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
-    <string name="wifi_debugging_always" msgid="2968383799517975155">"在此網絡上永遠允許"</string>
+    <string name="wifi_debugging_always" msgid="2968383799517975155">"一律允許在此網絡上執行"</string>
     <string name="wifi_debugging_allow" msgid="4573224609684957886">"允許"</string>
     <string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"不允許無線偵錯功能"</string>
     <string name="wifi_debugging_secondary_user_message" msgid="4492383073970079751">"目前登入此裝置的使用者無法啟用無線偵錯功能。如要使用此功能,請切換至主要使用者。"</string>
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"關閉螢幕截圖"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"螢幕截圖預覽"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"螢幕畫面錄影工具"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在處理螢幕錄影內容"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示錄影畫面工作階段通知"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"要開始錄影嗎?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"錄影時,Android 系統可擷取螢幕上顯示或裝置播放的任何敏感資料,包括密碼、付款資料、相片、訊息和音訊。"</string>
@@ -101,7 +100,7 @@
     <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"裝置音訊和麥克風"</string>
     <string name="screenrecord_start" msgid="330991441575775004">"開始"</string>
     <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"正在錄影螢幕畫面"</string>
-    <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"錄影螢幕畫面和音訊"</string>
+    <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"正在錄製螢幕畫面和音訊"</string>
     <string name="screenrecord_taps_label" msgid="1595690528298857649">"顯示輕觸螢幕的位置"</string>
     <string name="screenrecord_stop_text" msgid="6549288689506057686">"輕按即可停止"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"停止"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"全部清除"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"記錄"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"收到的通知"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"靜音通知"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"提醒通知"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"對話"</string>
@@ -969,7 +967,7 @@
     <string name="running_foreground_services_title" msgid="5137313173431186685">"正在背景中執行的應用程式"</string>
     <string name="running_foreground_services_msg" msgid="3009459259222695385">"輕按即可查看電池和數據用量詳情"</string>
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"要關閉流動數據嗎?"</string>
-    <string name="mobile_data_disable_message" msgid="8604966027899770415">"您將無法透過「<xliff:g id="CARRIER">%s</xliff:g>」使用流動數據或互聯網,只可透過 Wi-Fi 才能連接互聯網。"</string>
+    <string name="mobile_data_disable_message" msgid="8604966027899770415">"您無法透過「<xliff:g id="CARRIER">%s</xliff:g>」使用流動數據或互聯網。如要使用互聯網,您必須連接 Wi-Fi。"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"您的流動網絡供應商"</string>
     <string name="touch_filtered_warning" msgid="8119511393338714836">"由於某個應用程式已阻擋權限要求畫面,因此「設定」應用程式無法驗證您的回應。"</string>
     <string name="slice_permission_title" msgid="3262615140094151017">"要允許「<xliff:g id="APP_0">%1$s</xliff:g>」顯示「<xliff:g id="APP_2">%2$s</xliff:g>」的快訊嗎?"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"無標題"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"輕按即可重新開啟此應用程式並放大至全螢幕。"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」小視窗設定"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"顯示更多"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"加回堆疊"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"管理"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"來自「<xliff:g id="APP_NAME">%2$s</xliff:g>」的 <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"來自「<xliff:g id="APP_NAME">%2$s</xliff:g>」及另外 <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> 個應用程式的<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">已新增 <xliff:g id="NUMBER_1">%s</xliff:g> 個控制項。</item>
       <item quantity="one">已新增 <xliff:g id="NUMBER_0">%s</xliff:g> 個控制項。</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"已移除"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"已加入收藏"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"已加入至收藏位置 <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"已取消收藏"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"加入收藏"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"取消收藏"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"移至位置 <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"控制項"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"從電源選單選擇要存取的控制項"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"按住並拖曳便可重新排列控制項"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 6f825de..6480f19 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"關閉螢幕截圖"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"螢幕截圖預覽"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"螢幕錄影器"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"處理螢幕錄影內容"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示螢幕畫面錄製工作階段通知"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"要開始錄製嗎?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"錄製螢幕畫面時,Android 系統可擷取螢幕上顯示或裝置播放的任何機密資訊,包括密碼、付款資訊、相片、訊息和音訊。"</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"全部清除"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"記錄"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"收到的通知"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"靜音通知"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"快訊通知"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"對話"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"無標題"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"輕觸即可重新啟動這個應用程式並進入全螢幕模式。"</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」對話框的設定"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"溢位"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"重新加入堆疊"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"管理"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"<xliff:g id="APP_NAME">%2$s</xliff:g>:<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"「<xliff:g id="APP_NAME">%2$s</xliff:g>」和其他 <xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> 個應用程式:<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="other">已新增 <xliff:g id="NUMBER_1">%s</xliff:g> 個控制項。</item>
       <item quantity="one">已新增 <xliff:g id="NUMBER_0">%s</xliff:g> 個控制項。</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"已移除"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"已加入收藏"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"已加入收藏,位置 <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"從收藏中移除"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"加入收藏"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"從收藏中移除"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"移到位置 <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"控制項"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"選擇要從電源選單存取的控制項"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"按住並拖曳即可重新排列控制項"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index a02cfa2..28251f2 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -89,8 +89,7 @@
     <string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Cashisa isithombe-skrini"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ukubuka kuqala isithombe-skrini"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Irekhoda yesikrini"</string>
-    <!-- no translation found for screenrecord_background_processing_label (7244617554884238898) -->
-    <skip />
+    <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Icubungula okokuqopha iskrini"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Isaziso esiqhubekayo seseshini yokurekhoda isikrini"</string>
     <string name="screenrecord_start_label" msgid="1750350278888217473">"Qala ukurekhoda?"</string>
     <string name="screenrecord_description" msgid="1123231719680353736">"Ngenkathi irekhoda, Isistimu ye-Android ingathatha noma iluphi ulwazi olubucayi olubonakal kusikrini sakho noma oludlalwa kudivayisi yakho. Lokhu kufaka phakathi amaphasiwedi, ulwazi lokukhokha, izithombe, imilayezo, nomsindo."</string>
@@ -511,8 +510,7 @@
     <string name="clear_all_notifications_text" msgid="348312370303046130">"Sula konke"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"Phatha"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Umlando"</string>
-    <!-- no translation found for notification_section_header_incoming (5295312809341711367) -->
-    <skip />
+    <string name="notification_section_header_incoming" msgid="5295312809341711367">"Okungenayo"</string>
     <string name="notification_section_header_gentle" msgid="3044910806569985386">"Thulisa izaziso"</string>
     <string name="notification_section_header_alerting" msgid="3168140660646863240">"Izaziso zokuxwayisa"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Izingxoxo"</string>
@@ -991,10 +989,8 @@
     <string name="music_controls_no_title" msgid="4166497066552290938">"Asikho isihloko"</string>
     <string name="restart_button_description" msgid="6916116576177456480">"Thepha ukuze uqale kabusha lolu hlelo lokusebenza uphinde uye kusikrini esigcwele."</string>
     <string name="bubbles_settings_button_description" msgid="7324245408859877545">"Izilungiselelo zamabhamuza e-<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for bubble_overflow_button_content_description (5523744621434300510) -->
-    <skip />
-    <!-- no translation found for bubble_accessibility_action_add_back (6217995665917123890) -->
-    <skip />
+    <string name="bubble_overflow_button_content_description" msgid="5523744621434300510">"Ukuphuphuma"</string>
+    <string name="bubble_accessibility_action_add_back" msgid="6217995665917123890">"Engeza emuva kusitaki"</string>
     <string name="manage_bubbles_text" msgid="6856830436329494850">"Phatha"</string>
     <string name="bubble_content_description_single" msgid="5175160674436546329">"I-<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> kusuka ku-<xliff:g id="APP_NAME">%2$s</xliff:g>"</string>
     <string name="bubble_content_description_stack" msgid="7907610717462651870">"I-<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> kusukela ku-<xliff:g id="APP_NAME">%2$s</xliff:g> nokungu-<xliff:g id="BUBBLE_COUNT">%3$d</xliff:g> ngaphezulu"</string>
@@ -1031,6 +1027,13 @@
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> ukulawulwa okwengeziwe.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> ukulawulwa okwengeziwe.</item>
     </plurals>
+    <string name="controls_removed" msgid="3731789252222856959">"Isusiwe"</string>
+    <string name="accessibility_control_favorite" msgid="8694362691985545985">"Kwenziwe intandokazi"</string>
+    <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Kwenziwe intandokazi, isimo esiyi-<xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Akwenziwanga intandokazi"</string>
+    <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"intandokazi"</string>
+    <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"susa ubuntandokazi"</string>
+    <string name="accessibility_control_move" msgid="8980344493796647792">"Hambisa ukuze ubeke ku-<xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="controls_favorite_default_title" msgid="967742178688938137">"Izilawuli"</string>
     <string name="controls_favorite_subtitle" msgid="6604402232298443956">"Khetha izilawuli ukuze ufinyelele kusuka kumenyu yamandla"</string>
     <string name="controls_favorite_rearrange" msgid="5616952398043063519">"Bamba futhi uhudule ukuze uphinde ulungise izilawuli"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index b677600..837627c 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -239,9 +239,14 @@
 
     <color name="magnification_border_color">#FF9900</color>
 
+    <!-- media -->
+    <color name="media_primary_text">@android:color/white</color>
+    <color name="media_seekbar_progress">#c0ffffff</color>
+    <color name="media_disabled">#80ffffff</color>
+
     <!-- controls -->
-    <color name="control_primary_text">@color/GM2_grey_100</color>
-    <color name="control_secondary_text">@color/GM2_grey_500</color>
+    <color name="control_primary_text">#E6FFFFFF</color>
+    <color name="control_secondary_text">#99FFFFFF</color>
     <color name="control_default_foreground">@color/GM2_grey_500</color>
     <color name="control_default_background">@color/GM2_grey_900</color>
     <color name="control_list_popup_background">@*android:color/background_floating_material_dark</color>
@@ -257,4 +262,6 @@
 
     <!-- Docked misalignment message -->
     <color name="misalignment_text_color">#F28B82</color>
+
+    <color name="screenrecord_status_color">#E94235</color>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 99e347e..1481bff 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -314,13 +314,14 @@
     <dimen name="screenshot_dismiss_button_margin">8dp</dimen>
     <dimen name="screenshot_action_container_offset_y">32dp</dimen>
     <dimen name="screenshot_action_container_corner_radius">10dp</dimen>
-    <dimen name="screenshot_action_container_padding_vertical">10dp</dimen>
+    <dimen name="screenshot_action_container_padding_vertical">6dp</dimen>
     <dimen name="screenshot_action_container_margin_horizontal">8dp</dimen>
     <dimen name="screenshot_action_container_padding_left">96dp</dimen>
     <dimen name="screenshot_action_container_padding_right">8dp</dimen>
     <!-- Radius of the chip background on global screenshot actions -->
     <dimen name="screenshot_button_corner_radius">20dp</dimen>
     <dimen name="screenshot_action_chip_margin_right">8dp</dimen>
+    <dimen name="screenshot_action_chip_margin_vertical">10dp</dimen>
     <dimen name="screenshot_action_chip_padding_vertical">7dp</dimen>
     <dimen name="screenshot_action_chip_icon_size">18dp</dimen>
     <dimen name="screenshot_action_chip_padding_start">8dp</dimen>
@@ -498,10 +499,10 @@
     <dimen name="qs_quick_tile_padding">12dp</dimen>
     <dimen name="qs_header_gear_translation">16dp</dimen>
     <dimen name="qs_header_tile_margin_horizontal">4dp</dimen>
+    <dimen name="qs_header_tile_margin_bottom">18dp</dimen>
     <dimen name="qs_page_indicator_width">16dp</dimen>
     <dimen name="qs_page_indicator_height">8dp</dimen>
     <dimen name="qs_tile_icon_size">24dp</dimen>
-    <dimen name="qs_tile_detail_padding">3dp</dimen>
     <dimen name="qs_tile_text_size">12sp</dimen>
     <dimen name="qs_tile_divider_height">1dp</dimen>
     <dimen name="qs_panel_padding">16dp</dimen>
@@ -1027,6 +1028,9 @@
     <!-- Amount to shift the layout when exiting/entering for controls activities -->
     <dimen name="global_actions_controls_y_translation">20dp</dimen>
 
+    <!-- Shift quick access wallet down in Global Actions when Controls are unavailable -->
+    <dimen name="global_actions_wallet_top_margin">40dp</dimen>
+
     <!-- The maximum offset in either direction that elements are moved horizontally to prevent
          burn-in on AOD. -->
     <dimen name="burn_in_prevention_offset_x">8dp</dimen>
@@ -1043,6 +1047,10 @@
     <dimen name="bottom_padding">48dp</dimen>
     <dimen name="edge_margin">8dp</dimen>
 
+    <!-- The absolute side margins of quick settings -->
+    <dimen name="quick_settings_side_margins">16dp</dimen>
+    <dimen name="quick_settings_expanded_bottom_margin">16dp</dimen>
+    <dimen name="quick_settings_media_extra_bottom_margin">4dp</dimen>
     <dimen name="rounded_corner_content_padding">0dp</dimen>
     <dimen name="nav_content_padding">0dp</dimen>
     <dimen name="nav_quick_scrub_track_edge_padding">24dp</dimen>
@@ -1230,12 +1238,12 @@
 
     <!-- Size of media cards in the QSPanel carousel -->
     <dimen name="qs_media_width">350dp</dimen>
-    <dimen name="qs_media_padding">8dp</dimen>
+    <dimen name="qs_media_padding">16dp</dimen>
     <dimen name="qs_media_panel_outer_padding">16dp</dimen>
-    <dimen name="qs_media_corner_radius">10dp</dimen>
-    <dimen name="qs_media_album_size">72dp</dimen>
+    <dimen name="qs_media_album_size">52dp</dimen>
     <dimen name="qs_seamless_icon_size">20dp</dimen>
     <dimen name="qqs_media_spacing">8dp</dimen>
+    <dimen name="qqs_horizonal_tile_padding_bottom">8dp</dimen>
 
     <dimen name="magnification_border_size">5dp</dimen>
     <dimen name="magnification_frame_move_short">5dp</dimen>
@@ -1276,6 +1284,10 @@
     <dimen name="control_status_padding">3dp</dimen>
     <fraction name="controls_toggle_bg_intensity">5%</fraction>
     <fraction name="controls_dimmed_alpha">40%</fraction>
+    <dimen name="controls_setup_top_margin">16dp</dimen>
+    <dimen name="controls_setup_title">22sp</dimen>
+    <dimen name="controls_setup_subtitle">14sp</dimen>
+    <dimen name="controls_setup_vertical_padding">52dp</dimen>
 
     <!-- Home Controls activity view detail panel-->
     <dimen name="controls_activity_view_top_offset">100dp</dimen>
@@ -1318,7 +1330,10 @@
     <dimen name="screenrecord_dialog_padding">18dp</dimen>
     <dimen name="screenrecord_logo_size">24dp</dimen>
     <dimen name="screenrecord_status_text_size">14sp</dimen>
-    <dimen name="screenrecord_status_icon_radius">5dp</dimen>
+    <dimen name="screenrecord_status_icon_radius">7dp</dimen>
+    <dimen name="screenrecord_status_icon_width">21dp</dimen>
+    <dimen name="screenrecord_status_icon_height">17.5dp</dimen>
+    <dimen name="screenrecord_status_icon_bg_radius">8dp</dimen>
 
     <dimen name="kg_user_switcher_text_size">16sp</dimen>
 
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 8156e8d..09918e7 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -70,6 +70,26 @@
     <item type="id" name="panel_alpha_animator_end_tag"/>
     <item type="id" name="cross_fade_layer_type_changed_tag"/>
 
+    <item type="id" name="absolute_x_animator_tag"/>
+    <item type="id" name="absolute_x_animator_start_tag"/>
+    <item type="id" name="absolute_x_animator_end_tag"/>
+    <item type="id" name="absolute_x_current_value"/>
+
+    <item type="id" name="absolute_y_animator_tag"/>
+    <item type="id" name="absolute_y_animator_start_tag"/>
+    <item type="id" name="absolute_y_animator_end_tag"/>
+    <item type="id" name="absolute_y_current_value"/>
+
+    <item type="id" name="view_height_animator_tag"/>
+    <item type="id" name="view_height_animator_start_tag"/>
+    <item type="id" name="view_height_animator_end_tag"/>
+    <item type="id" name="view_height_current_value"/>
+
+    <item type="id" name="view_width_animator_tag"/>
+    <item type="id" name="view_width_animator_start_tag"/>
+    <item type="id" name="view_width_animator_end_tag"/>
+    <item type="id" name="view_width_current_value"/>
+
     <!-- Whether the icon is from a notification for which targetSdk < L -->
     <item type="id" name="icon_is_pre_L"/>
 
@@ -149,5 +169,8 @@
     <item type="id" name="screen_recording_options" />
     <item type="id" name="screen_recording_dialog_source_text" />
     <item type="id" name="screen_recording_dialog_source_description" />
+
+    <item type="id" name="accessibility_action_controls_move_before" />
+    <item type="id" name="accessibility_action_controls_move_after" />
 </resources>
 
diff --git a/packages/SystemUI/res/values/integers.xml b/packages/SystemUI/res/values/integers.xml
index f35f351..b1e91c8 100644
--- a/packages/SystemUI/res/values/integers.xml
+++ b/packages/SystemUI/res/values/integers.xml
@@ -33,11 +33,6 @@
     <!-- Maximum number of bubbles we allow in overflow before we dismiss the oldest one. -->
     <integer name="bubbles_max_overflow">16</integer>
 
-    <!-- Ratio of "left" end of status bar that will swipe to QQS. -->
-    <integer name="qqs_split_fraction">3</integer>
-    <!-- Ratio of "right" end of status bar that will swipe to QS. -->
-    <integer name="qs_split_fraction">2</integer>
-
     <integer name="magnification_default_scale">2</integer>
 
     <!-- The position of the volume dialog on the screen.
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ec29622..e1df81a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -212,6 +212,13 @@
     <!-- Power menu item for taking a screenshot [CHAR LIMIT=20]-->
     <string name="global_action_screenshot">Screenshot</string>
 
+    <!-- Text shown when viewing global actions while phone is locked and additional controls are hidden [CHAR LIMIT=NONE] -->
+    <string name="global_action_lock_message" product="default">Unlock your phone for more options</string>
+    <!-- Text shown when viewing global actions while phone is locked and additional controls are hidden [CHAR LIMIT=NONE] -->
+    <string name="global_action_lock_message" product="tablet">Unlock your tablet for more options</string>
+    <!-- Text shown when viewing global actions while phone is locked and additional controls are hidden [CHAR LIMIT=NONE] -->
+    <string name="global_action_lock_message" product="device">Unlock your device for more options</string>
+
     <!-- text to show in place of RemoteInput images when they cannot be shown.
          [CHAR LIMIT=50] -->
     <string name="remote_input_image_insertion_text">sent an image</string>
@@ -790,6 +797,9 @@
     <!-- Accessibility text describing sensors off active. [CHAR LIMIT=NONE] -->
     <string name="accessibility_sensors_off_active">Sensors off active</string>
 
+    <!-- Accessibility text describing that media is playing. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_media_active">Media is active</string>
+
     <!-- Content description of the clear button in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_clear_all">Clear all notifications.</string>
 
@@ -2698,6 +2708,22 @@
         <item quantity="other"><xliff:g id="number" example="3">%s</xliff:g> controls added.</item>
     </plurals>
 
+    <!-- Removed control in management screen [CHAR LIMIT=20] -->
+    <string name="controls_removed">Removed</string>
+
+    <!-- a11y state description for a control that is currently favorited [CHAR LIMIT=NONE] -->
+    <string name="accessibility_control_favorite">Favorited</string>
+    <!-- a11y state description for a control that is currently favorited with its position [CHAR LIMIT=NONE] -->
+    <string name="accessibility_control_favorite_position">Favorited, position <xliff:g id="number" example="1">%d</xliff:g></string>
+    <!-- a11y state description for a control that is currently not favorited [CHAR LIMIT=NONE] -->
+    <string name="accessibility_control_not_favorite">Unfavorited</string>
+    <!-- a11y action to favorite a control. It will read as "Double-tap to favorite" in screen readers [CHAR LIMIT=NONE] -->
+    <string name="accessibility_control_change_favorite">favorite</string>
+    <!-- a11y action to unfavorite a control. It will read as "Double-tap to unfavorite" in screen readers [CHAR LIMIT=NONE] -->
+    <string name="accessibility_control_change_unfavorite">unfavorite</string>
+    <!-- a11y action to move a control to the position specified by the parameter [CHAR LIMIT=NONE] -->
+    <string name="accessibility_control_move">Move to position <xliff:g id="number" example="1">%d</xliff:g></string>
+
     <!-- Controls management controls screen default title [CHAR LIMIT=30] -->
     <string name="controls_favorite_default_title">Controls</string>
     <!-- Controls management controls screen subtitle [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index f0edd63..52ace2b 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -622,6 +622,8 @@
 
     <style name="MediaPlayer.Button" parent="@android:style/Widget.Material.Button.Borderless.Small">
         <item name="android:background">@null</item>
+        <item name="android:tint">@android:color/white</item>
+        <item name="android:stateListAnimator">@anim/media_button_state_list_animator</item>
     </style>
 
     <!-- Used to style charging animation AVD animation -->
@@ -756,6 +758,7 @@
         <!-- used to override dark/light theming -->
         <item name="*android:colorBackgroundFloating">@color/GM2_grey_800</item>
         <item name="*android:colorPopupBackground">@color/GM2_grey_800</item>
+        <item name="*android:dialogCornerRadius">8dp</item>
     </style>
 
     <style name="TextAppearance.ControlSetup">
@@ -765,11 +768,11 @@
     </style>
 
     <style name="TextAppearance.ControlSetup.Title">
-        <item name="android:textSize">25sp</item>
+        <item name="android:textSize">@dimen/controls_setup_title</item>
     </style>
 
     <style name="TextAppearance.ControlSetup.Subtitle">
-        <item name="android:textSize">16sp</item>
+        <item name="android:textSize">@dimen/controls_setup_subtitle</item>
     </style>
 
     <!-- The attributes used for title (textAppearanceLarge) and message (textAppearanceMedium)
diff --git a/packages/SystemUI/res/xml/media_scene.xml b/packages/SystemUI/res/xml/media_scene.xml
new file mode 100644
index 0000000..f61b2b0
--- /dev/null
+++ b/packages/SystemUI/res/xml/media_scene.xml
@@ -0,0 +1,447 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+<MotionScene
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <Transition
+        app:constraintSetStart="@id/collapsed"
+        app:constraintSetEnd="@id/expanded"
+        app:duration="1000" >
+        <KeyFrameSet >
+            <KeyPosition
+                app:motionTarget="@+id/action0"
+                app:keyPositionType="pathRelative"
+                app:framePosition="70"
+                app:sizePercent="0.9" />
+            <KeyPosition
+                app:motionTarget="@+id/action1"
+                app:keyPositionType="pathRelative"
+                app:framePosition="70"
+                app:sizePercent="0.9" />
+            <KeyPosition
+                app:motionTarget="@+id/action2"
+                app:keyPositionType="pathRelative"
+                app:framePosition="70"
+                app:sizePercent="0.9" />
+            <KeyPosition
+                app:motionTarget="@+id/action3"
+                app:keyPositionType="pathRelative"
+                app:framePosition="70"
+                app:sizePercent="0.9" />
+            <KeyPosition
+                app:motionTarget="@+id/action4"
+                app:keyPositionType="pathRelative"
+                app:framePosition="70"
+                app:sizePercent="0.9" />
+            <KeyPosition
+                app:motionTarget="@+id/media_progress_bar"
+                app:keyPositionType="pathRelative"
+                app:framePosition="70"
+                app:sizePercent="0.9" />
+            <KeyAttribute
+                app:motionTarget="@id/media_progress_bar"
+                app:framePosition="0"
+                android:alpha="0.0" />
+            <KeyAttribute
+                app:motionTarget="@+id/media_progress_bar"
+                app:framePosition="70"
+                android:alpha="0.0"/>
+            <KeyPosition
+                app:motionTarget="@+id/notification_media_progress_time"
+                app:keyPositionType="pathRelative"
+                app:framePosition="70"
+                app:sizePercent="0.9" />
+            <KeyAttribute
+                app:motionTarget="@id/notification_media_progress_time"
+                app:framePosition="0"
+                android:alpha="0.0" />
+            <KeyAttribute
+                app:motionTarget="@+id/notification_media_progress_time"
+                app:framePosition="70"
+                android:alpha="0.0"/>
+            <KeyAttribute
+                app:motionTarget="@id/action0"
+                app:framePosition="0"
+                android:alpha="0.0" />
+            <KeyAttribute
+                app:motionTarget="@+id/action0"
+                app:framePosition="70"
+                android:alpha="0.0"/>
+            <KeyAttribute
+                app:motionTarget="@id/action1"
+                app:framePosition="0"
+                android:alpha="0.0" />
+            <KeyAttribute
+                app:motionTarget="@+id/action1"
+                app:framePosition="70"
+                android:alpha="0.0"/>
+            <KeyAttribute
+                app:motionTarget="@id/action2"
+                app:framePosition="0"
+                android:alpha="0.0" />
+            <KeyAttribute
+                app:motionTarget="@+id/action2"
+                app:framePosition="70"
+                android:alpha="0.0"/>
+            <KeyAttribute
+                app:motionTarget="@id/action3"
+                app:framePosition="0"
+                android:alpha="0.0" />
+            <KeyAttribute
+                app:motionTarget="@+id/action3"
+                app:framePosition="70"
+                android:alpha="0.0"/>
+            <KeyAttribute
+                app:motionTarget="@id/action4"
+                app:framePosition="0"
+                android:alpha="0.0" />
+            <KeyAttribute
+                app:motionTarget="@+id/action4"
+                app:framePosition="70"
+                android:alpha="0.0"/>
+        </KeyFrameSet>
+    </Transition>
+
+    <ConstraintSet android:id="@+id/expanded">
+        <Constraint
+            android:id="@+id/icon"
+            android:layout_width="16dp"
+            android:layout_height="16dp"
+            android:layout_marginStart="18dp"
+            android:layout_marginTop="22dp"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            />
+
+        <Constraint
+            android:id="@+id/app_name"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="10dp"
+            android:layout_marginStart="10dp"
+            android:layout_marginTop="20dp"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintStart_toEndOf="@id/icon"
+            app:layout_constraintEnd_toStartOf="@id/media_seamless"
+            app:layout_constraintHorizontal_bias="0"
+            />
+
+        <Constraint
+            android:id="@+id/media_seamless"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:layout_constraintEnd_toEndOf="@id/view_width"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintWidth_min="60dp"
+            android:layout_marginTop="@dimen/qs_media_panel_outer_padding"
+            android:layout_marginEnd="@dimen/qs_media_panel_outer_padding"
+            />
+
+        <Constraint
+            android:id="@+id/album_art"
+            android:layout_width="@dimen/qs_media_album_size"
+            android:layout_height="@dimen/qs_media_album_size"
+            android:layout_marginTop="14dp"
+            android:layout_marginStart="@dimen/qs_media_panel_outer_padding"
+            app:layout_constraintTop_toBottomOf="@+id/app_name"
+            app:layout_constraintStart_toStartOf="parent"
+            />
+
+        <!-- Song name -->
+        <Constraint
+            android:id="@+id/header_title"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="@dimen/qs_media_panel_outer_padding"
+            android:layout_marginTop="17dp"
+            android:layout_marginStart="16dp"
+            app:layout_constraintTop_toBottomOf="@+id/app_name"
+            app:layout_constraintStart_toEndOf="@id/album_art"
+            app:layout_constraintEnd_toEndOf="@id/view_width"
+            app:layout_constraintHorizontal_bias="0"/>
+
+        <!-- Artist name -->
+        <Constraint
+            android:id="@+id/header_artist"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="@dimen/qs_media_panel_outer_padding"
+            android:layout_marginTop="3dp"
+            app:layout_constraintTop_toBottomOf="@id/header_title"
+            app:layout_constraintStart_toStartOf="@id/header_title"
+            app:layout_constraintEnd_toEndOf="@id/view_width"
+            app:layout_constraintHorizontal_bias="0"/>
+
+        <!-- Seek Bar -->
+        <Constraint
+            android:id="@+id/media_progress_bar"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="3dp"
+            app:layout_constraintTop_toBottomOf="@id/header_artist"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="@id/view_width"
+            />
+
+        <Constraint
+            android:id="@+id/notification_media_progress_time"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="38dp"
+            android:layout_marginEnd="@dimen/qs_media_panel_outer_padding"
+            android:layout_marginStart="@dimen/qs_media_panel_outer_padding"
+            app:layout_constraintTop_toBottomOf="@id/header_artist"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="@id/view_width"
+            />
+
+        <Constraint
+            android:id="@+id/action0"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:layout_marginTop="5dp"
+            android:layout_marginStart="4dp"
+            android:layout_marginEnd="4dp"
+            android:layout_marginBottom="@dimen/qs_media_panel_outer_padding"
+            app:layout_constraintHorizontal_chainStyle="packed"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintRight_toLeftOf="@id/action1"
+            app:layout_constraintTop_toBottomOf="@id/notification_media_progress_time"
+            app:layout_constraintBottom_toBottomOf="parent">
+        </Constraint>
+
+        <Constraint
+            android:id="@+id/action1"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:layout_marginStart="4dp"
+            android:layout_marginEnd="4dp"
+            android:layout_marginBottom="@dimen/qs_media_panel_outer_padding"
+            app:layout_constraintLeft_toRightOf="@id/action0"
+            app:layout_constraintRight_toLeftOf="@id/action2"
+            app:layout_constraintTop_toTopOf="@id/action0"
+            app:layout_constraintBottom_toBottomOf="parent">
+        </Constraint>
+
+        <Constraint
+            android:id="@+id/action2"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:layout_marginStart="4dp"
+            android:layout_marginEnd="4dp"
+            android:layout_marginBottom="@dimen/qs_media_panel_outer_padding"
+            app:layout_constraintLeft_toRightOf="@id/action1"
+            app:layout_constraintRight_toLeftOf="@id/action3"
+            app:layout_constraintTop_toTopOf="@id/action0"
+            app:layout_constraintBottom_toBottomOf="parent">
+        </Constraint>
+
+        <Constraint
+            android:id="@+id/action3"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:layout_marginStart="4dp"
+            android:layout_marginEnd="4dp"
+            app:layout_constraintLeft_toRightOf="@id/action2"
+            app:layout_constraintRight_toLeftOf="@id/action4"
+            app:layout_constraintTop_toTopOf="@id/action0"
+            android:layout_marginBottom="@dimen/qs_media_panel_outer_padding"
+            app:layout_constraintBottom_toBottomOf="parent">
+        </Constraint>
+
+        <Constraint
+            android:id="@+id/action4"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:layout_marginStart="4dp"
+            android:layout_marginEnd="4dp"
+            android:layout_marginBottom="@dimen/qs_media_panel_outer_padding"
+            app:layout_constraintLeft_toRightOf="@id/action3"
+            app:layout_constraintRight_toRightOf="@id/view_width"
+            app:layout_constraintTop_toTopOf="@id/action0"
+            app:layout_constraintBottom_toBottomOf="parent">
+        </Constraint>
+    </ConstraintSet>
+
+    <ConstraintSet android:id="@+id/collapsed">
+        <Constraint
+            android:id="@+id/icon"
+            android:layout_width="16dp"
+            android:layout_height="16dp"
+            android:layout_marginStart="18dp"
+            android:layout_marginTop="22dp"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            />
+
+        <Constraint
+            android:id="@+id/app_name"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="10dp"
+            android:layout_marginStart="10dp"
+            android:layout_marginTop="20dp"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintStart_toEndOf="@id/icon"
+            app:layout_constraintEnd_toStartOf="@id/media_seamless"
+            app:layout_constraintHorizontal_bias="0"
+            />
+
+        <Constraint
+            android:id="@+id/media_seamless"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:layout_constraintEnd_toEndOf="@id/view_width"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintWidth_min="60dp"
+            android:layout_marginTop="@dimen/qs_media_panel_outer_padding"
+            android:layout_marginEnd="@dimen/qs_media_panel_outer_padding"
+            />
+
+        <Constraint
+            android:id="@+id/album_art"
+            android:layout_width="@dimen/qs_media_album_size"
+            android:layout_height="@dimen/qs_media_album_size"
+            android:layout_marginTop="16dp"
+            android:layout_marginStart="@dimen/qs_media_panel_outer_padding"
+            android:layout_marginBottom="24dp"
+            app:layout_constraintTop_toBottomOf="@id/icon"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            />
+
+        <!-- Song name -->
+        <Constraint
+            android:id="@+id/header_title"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="17dp"
+            android:layout_marginStart="16dp"
+            app:layout_constraintTop_toBottomOf="@id/app_name"
+            app:layout_constraintBottom_toTopOf="@id/header_artist"
+            app:layout_constraintStart_toEndOf="@id/album_art"
+            app:layout_constraintEnd_toStartOf="@id/action0"
+            app:layout_constraintHorizontal_bias="0"/>
+
+        <!-- Artist name -->
+        <Constraint
+            android:id="@+id/header_artist"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="3dp"
+            android:layout_marginBottom="24dp"
+            app:layout_constraintTop_toBottomOf="@id/header_title"
+            app:layout_constraintStart_toStartOf="@id/header_title"
+            app:layout_constraintEnd_toStartOf="@id/action0"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintHorizontal_bias="0"/>
+
+        <!-- Seek Bar -->
+        <Constraint
+            android:id="@+id/media_progress_bar"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:alpha="0.0"
+            app:layout_constraintTop_toBottomOf="@id/album_art"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="@id/view_width"
+            android:visibility="gone"
+            />
+
+        <Constraint
+            android:id="@+id/notification_media_progress_time"
+            android:alpha="0.0"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="35dp"
+            android:layout_marginEnd="@dimen/qs_media_panel_outer_padding"
+            android:layout_marginStart="@dimen/qs_media_panel_outer_padding"
+            app:layout_constraintTop_toBottomOf="@id/album_art"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="@id/view_width"
+            android:visibility="gone"
+            />
+
+        <Constraint
+            android:id="@+id/action0"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:layout_marginStart="4dp"
+            android:layout_marginTop="16dp"
+            android:visibility="gone"
+            app:layout_constraintHorizontal_chainStyle="packed"
+            app:layout_constraintTop_toBottomOf="@id/app_name"
+            app:layout_constraintLeft_toRightOf="@id/header_title"
+            app:layout_constraintRight_toLeftOf="@id/action1"
+            >
+        </Constraint>
+
+        <Constraint
+            android:id="@+id/action1"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:layout_marginStart="4dp"
+            android:layout_marginEnd="4dp"
+            android:layout_marginTop="18dp"
+            app:layout_constraintTop_toBottomOf="@id/app_name"
+            app:layout_constraintLeft_toRightOf="@id/action0"
+            app:layout_constraintRight_toLeftOf="@id/action2"
+            >
+        </Constraint>
+
+        <Constraint
+            android:id="@+id/action2"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:layout_marginStart="4dp"
+            android:layout_marginEnd="4dp"
+            android:layout_marginTop="18dp"
+            app:layout_constraintTop_toBottomOf="@id/app_name"
+            app:layout_constraintLeft_toRightOf="@id/action1"
+            app:layout_constraintRight_toLeftOf="@id/action3"
+            >
+        </Constraint>
+
+        <Constraint
+            android:id="@+id/action3"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:layout_marginStart="4dp"
+            android:layout_marginEnd="4dp"
+            android:layout_marginTop="18dp"
+            app:layout_constraintTop_toBottomOf="@id/app_name"
+            app:layout_constraintLeft_toRightOf="@id/action2"
+            app:layout_constraintRight_toLeftOf="@id/action4"
+            >
+        </Constraint>
+
+        <Constraint
+            android:id="@+id/action4"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:layout_marginStart="4dp"
+            android:layout_marginEnd="4dp"
+            android:visibility="gone"
+            android:layout_marginTop="18dp"
+            app:layout_constraintTop_toBottomOf="@id/app_name"
+            app:layout_constraintLeft_toRightOf="@id/action3"
+            app:layout_constraintRight_toRightOf="@id/view_width"
+            >
+        </Constraint>
+    </ConstraintSet>
+</MotionScene>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index 0350f2d..114472b 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -16,6 +16,7 @@
 
 package com.android.systemui.shared.recents;
 
+import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Bundle;
 import android.view.MotionEvent;
@@ -69,4 +70,9 @@
      * Sent when some system ui state changes.
      */
     void onSystemUiStateChanged(int stateFlags) = 16;
+
+    /**
+     * Sent when the split screen is resized
+     */
+    void onSplitScreenSecondaryBoundsChanged(in Rect bounds, in Rect insets) = 17;
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 806678f..cffc10f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -51,6 +51,7 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
@@ -78,6 +79,9 @@
     public static final String CLOSE_SYSTEM_WINDOWS_REASON_RECENTS = "recentapps";
     public static final String CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY = "homekey";
 
+    // Should match the value in AssistManager
+    private static final String INVOCATION_TIME_MS_KEY = "invocation_time_ms";
+
     private final PackageManager mPackageManager;
     private final BackgroundExecutor mBackgroundExecutor;
     private final TaskStackChangeListeners mTaskStackChangeListeners;
@@ -511,6 +515,8 @@
         if (service == null) {
             return false;
         }
+        args.putLong(INVOCATION_TIME_MS_KEY, SystemClock.elapsedRealtime());
+
         try {
             return service.showSessionFromSession(token, args, flags);
         } catch (RemoteException e) {
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 1369350..5a78c90 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
@@ -86,6 +86,8 @@
     // enabled (since it's used to navigate back within the bubbled app, or to collapse the bubble
     // stack.
     public static final int SYSUI_STATE_BUBBLES_EXPANDED = 1 << 14;
+    // The global actions dialog is showing
+    public static final int SYSUI_STATE_GLOBAL_ACTIONS_SHOWING = 1 << 15;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({SYSUI_STATE_SCREEN_PINNING,
@@ -102,7 +104,8 @@
             SYSUI_STATE_SEARCH_DISABLED,
             SYSUI_STATE_TRACING_ENABLED,
             SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED,
-            SYSUI_STATE_BUBBLES_EXPANDED
+            SYSUI_STATE_BUBBLES_EXPANDED,
+            SYSUI_STATE_GLOBAL_ACTIONS_SHOWING
     })
     public @interface SystemUiStateFlags {}
 
@@ -119,6 +122,7 @@
         str.add((flags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED) != 0
                 ? "keygrd_occluded" : "");
         str.add((flags & SYSUI_STATE_BOUNCER_SHOWING) != 0 ? "bouncer_visible" : "");
+        str.add((flags & SYSUI_STATE_GLOBAL_ACTIONS_SHOWING) != 0 ? "global_actions" : "");
         str.add((flags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0 ? "a11y_click" : "");
         str.add((flags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0 ? "a11y_long_click" : "");
         str.add((flags & SYSUI_STATE_TRACING_ENABLED) != 0 ? "tracing" : "");
@@ -192,8 +196,9 @@
      * disabled.
      */
     public static boolean isBackGestureDisabled(int sysuiStateFlags) {
-        // Always allow when the bouncer is showing (even on top of the keyguard)
-        if ((sysuiStateFlags & SYSUI_STATE_BOUNCER_SHOWING) != 0) {
+        // Always allow when the bouncer/global actions is showing (even on top of the keyguard)
+        if ((sysuiStateFlags & SYSUI_STATE_BOUNCER_SHOWING) != 0
+                || (sysuiStateFlags & SYSUI_STATE_GLOBAL_ACTIONS_SHOWING) != 0) {
             return false;
         }
         // Disable when in immersive, or the notifications are interactive
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestReceiver.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestReceiver.java
index 8bd7c79..30156a0 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestReceiver.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestReceiver.java
@@ -58,7 +58,7 @@
      */
     public void onReceive(Context context, Bundle bundle, View view, Size viewSize) {
         if (mSurfaceControlViewHost != null) {
-            mSurfaceControlViewHost.die();
+            mSurfaceControlViewHost.release();
         }
 
         SurfaceControl surfaceControl = SurfaceViewRequestUtils.getSurfaceControl(bundle);
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 0106609..b1e1434 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -19,8 +19,6 @@
 import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
 import static android.telephony.PhoneStateListener.LISTEN_NONE;
 
-import static com.android.systemui.DejankUtils.whitelistIpcs;
-
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -47,6 +45,7 @@
 
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.inject.Inject;
 
@@ -61,9 +60,11 @@
 
     private final boolean mIsEmergencyCallCapable;
     private final Handler mMainHandler;
+    private final Handler mBgHandler;
     private boolean mTelephonyCapable;
     private boolean mShowMissingSim;
     private boolean mShowAirplaneMode;
+    private final AtomicBoolean mNetworkSupported = new AtomicBoolean();
     @VisibleForTesting
     protected KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private WifiManager mWifiManager;
@@ -78,12 +79,14 @@
             new WakefulnessLifecycle.Observer() {
                 @Override
                 public void onFinishedWakingUp() {
-                    if (mCarrierTextCallback != null) mCarrierTextCallback.finishedWakingUp();
+                    final CarrierTextCallback callback = mCarrierTextCallback;
+                    if (callback != null) callback.finishedWakingUp();
                 }
 
                 @Override
                 public void onStartedGoingToSleep() {
-                    if (mCarrierTextCallback != null) mCarrierTextCallback.startedGoingToSleep();
+                    final CarrierTextCallback callback = mCarrierTextCallback;
+                    if (callback != null) callback.startedGoingToSleep();
                 }
             };
 
@@ -131,7 +134,7 @@
         @Override
         public void onActiveDataSubscriptionIdChanged(int subId) {
             mActiveMobileDataSubscription = subId;
-            if (mKeyguardUpdateMonitor != null) {
+            if (mNetworkSupported.get() && mCarrierTextCallback != null) {
                 updateCarrierText();
             }
         }
@@ -173,6 +176,17 @@
         mSimSlotsNumber = getTelephonyManager().getSupportedModemCount();
         mSimErrorState = new boolean[mSimSlotsNumber];
         mMainHandler = Dependency.get(Dependency.MAIN_HANDLER);
+        mBgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
+        mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
+        mBgHandler.post(() -> {
+            boolean supported = ConnectivityManager.from(mContext).isNetworkSupported(
+                    ConnectivityManager.TYPE_MOBILE);
+            if (supported && mNetworkSupported.compareAndSet(false, supported)) {
+                // This will set/remove the listeners appropriately. Note that it will never double
+                // add the listeners.
+                handleSetListening(mCarrierTextCallback);
+            }
+        });
     }
 
     private TelephonyManager getTelephonyManager() {
@@ -221,48 +235,51 @@
     }
 
     /**
-     * Sets the listening status of this controller. If the callback is null, it is set to
-     * not listening
+     * This may be called internally after retrieving the correct value of {@code mNetworkSupported}
+     * (assumed false to start). In that case, the following happens:
+     * <ul>
+     *     <li> If there was a registered callback, and the network is supported, it will register
+     *          listeners.
+     *     <li> If there was not a registered callback, it will try to remove unregistered listeners
+     *          which is a no-op
+     * </ul>
      *
-     * @param callback Callback to provide text updates
+     * This call will always be processed in a background thread.
      */
-    public void setListening(CarrierTextCallback callback) {
+    private void handleSetListening(CarrierTextCallback callback) {
         TelephonyManager telephonyManager = getTelephonyManager();
         if (callback != null) {
             mCarrierTextCallback = callback;
-            // TODO(b/140034799)
-            if (whitelistIpcs(() -> ConnectivityManager.from(mContext).isNetworkSupported(
-                    ConnectivityManager.TYPE_MOBILE))) {
-                mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
+            if (mNetworkSupported.get()) {
                 // Keyguard update monitor expects callbacks from main thread
-                mMainHandler.post(() -> {
-                    if (mKeyguardUpdateMonitor != null) {
-                        mKeyguardUpdateMonitor.registerCallback(mCallback);
-                    }
-                });
+                mMainHandler.post(() -> mKeyguardUpdateMonitor.registerCallback(mCallback));
                 mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
                 telephonyManager.listen(mPhoneStateListener,
                         LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
             } else {
                 // Don't listen and clear out the text when the device isn't a phone.
-                mKeyguardUpdateMonitor = null;
-                callback.updateCarrierInfo(new CarrierTextCallbackInfo("", null, false, null));
+                mMainHandler.post(() -> callback.updateCarrierInfo(
+                        new CarrierTextCallbackInfo("", null, false, null)
+                ));
             }
         } else {
             mCarrierTextCallback = null;
-            if (mKeyguardUpdateMonitor != null) {
-                // Keyguard update monitor expects callbacks from main thread
-                mMainHandler.post(() -> {
-                    if (mKeyguardUpdateMonitor != null) {
-                        mKeyguardUpdateMonitor.removeCallback(mCallback);
-                    }
-                });
-                mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
-            }
+            mMainHandler.post(() -> mKeyguardUpdateMonitor.removeCallback(mCallback));
+            mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
             telephonyManager.listen(mPhoneStateListener, LISTEN_NONE);
         }
     }
 
+    /**
+     * Sets the listening status of this controller. If the callback is null, it is set to
+     * not listening.
+     *
+     * @param callback Callback to provide text updates
+     */
+    public void setListening(CarrierTextCallback callback) {
+        mBgHandler.post(() -> handleSetListening(callback));
+    }
+
     protected List<SubscriptionInfo> getSubscriptionInfo() {
         return mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(false);
     }
@@ -500,7 +517,7 @@
      */
     private CarrierTextController.StatusMode getStatusForIccState(int simState) {
         final boolean missingAndNotProvisioned =
-                !Dependency.get(KeyguardUpdateMonitor.class).isDeviceProvisioned()
+                !mKeyguardUpdateMonitor.isDeviceProvisioned()
                         && (simState == TelephonyManager.SIM_STATE_ABSENT
                         || simState == TelephonyManager.SIM_STATE_PERM_DISABLED);
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMedia.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardMedia.kt
deleted file mode 100644
index 487c295..0000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardMedia.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard
-
-import android.graphics.drawable.Drawable
-
-import java.util.List
-
-/** State for lock screen media controls. */
-data class KeyguardMedia(
-    val foregroundColor: Int,
-    val backgroundColor: Int,
-    val app: String?,
-    val appIcon: Drawable?,
-    val artist: String?,
-    val song: String?,
-    val artwork: Drawable?,
-    val actionIcons: List<Drawable>
-)
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMediaPlayer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMediaPlayer.java
deleted file mode 100644
index af5196f..0000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardMediaPlayer.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard;
-
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Bitmap;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
-import android.media.MediaMetadata;
-import android.media.session.MediaController;
-import android.media.session.MediaSession;
-import android.util.Log;
-import android.view.View;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import androidx.core.graphics.drawable.RoundedBitmapDrawable;
-import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
-import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MutableLiveData;
-import androidx.lifecycle.Observer;
-import androidx.palette.graphics.Palette;
-
-import com.android.internal.util.ContrastColorUtil;
-import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.media.MediaControllerFactory;
-import com.android.systemui.statusbar.notification.MediaNotificationProcessor;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.stack.MediaHeaderView;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executor;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/**
- * Media controls to display on the lockscreen
- *
- * TODO: Should extend MediaControlPanel to avoid code duplication.
- * Unfortunately, it isn't currently possible because the ActivatableNotificationView background is
- * different.
- */
-@Singleton
-public class KeyguardMediaPlayer {
-
-    private static final String TAG = "KeyguardMediaPlayer";
-    // Buttons that can be displayed on lock screen media controls.
-    private static final int[] ACTION_IDS = {R.id.action0, R.id.action1, R.id.action2};
-
-    private final Context mContext;
-    private final Executor mBackgroundExecutor;
-    private final KeyguardMediaViewModel mViewModel;
-    private KeyguardMediaObserver mObserver;
-
-    @Inject
-    public KeyguardMediaPlayer(Context context, MediaControllerFactory factory,
-            @Background Executor backgroundExecutor) {
-        mContext = context;
-        mBackgroundExecutor = backgroundExecutor;
-        mViewModel = new KeyguardMediaViewModel(context, factory);
-    }
-
-    /** Binds media controls to a view hierarchy. */
-    public void bindView(View v) {
-        if (mObserver != null) {
-            throw new IllegalStateException("cannot bind views, already bound");
-        }
-        mViewModel.loadDimens();
-        mObserver = new KeyguardMediaObserver(v);
-        // Control buttons
-        for (int i = 0; i < ACTION_IDS.length; i++) {
-            ImageButton button = v.findViewById(ACTION_IDS[i]);
-            if (button == null) {
-                continue;
-            }
-            final int index = i;
-            button.setOnClickListener(unused -> mViewModel.onActionClick(index));
-        }
-        mViewModel.getKeyguardMedia().observeForever(mObserver);
-    }
-
-    /** Unbinds media controls. */
-    public void unbindView() {
-        if (mObserver == null) {
-            throw new IllegalStateException("cannot unbind views, nothing bound");
-        }
-        mViewModel.getKeyguardMedia().removeObserver(mObserver);
-        mObserver = null;
-    }
-
-    /** Clear the media controls because there isn't an active session. */
-    public void clearControls() {
-        mBackgroundExecutor.execute(mViewModel::clearControls);
-    }
-
-    /**
-     * Update the media player
-     *
-     * TODO: consider registering a MediaLister instead of exposing this update method.
-     *
-     * @param entry Media notification that will be used to update the player
-     * @param appIcon Icon for the app playing the media
-     * @param mediaMetadata Media metadata that will be used to update the player
-     */
-    public void updateControls(NotificationEntry entry, Icon appIcon,
-            MediaMetadata mediaMetadata) {
-        if (mObserver == null) {
-            throw new IllegalStateException("cannot update controls, views not bound");
-        }
-        if (mediaMetadata == null) {
-            Log.d(TAG, "media metadata was null, closing media controls");
-            // Note that clearControls() executes on the same background executor, so there
-            // shouldn't be an issue with an outdated update running after clear. However, if stale
-            // controls are observed then consider removing any enqueued updates.
-            clearControls();
-            return;
-        }
-        mBackgroundExecutor.execute(() -> mViewModel.updateControls(entry, appIcon, mediaMetadata));
-    }
-
-    /** ViewModel for KeyguardMediaControls. */
-    private static final class KeyguardMediaViewModel {
-
-        private final Context mContext;
-        private final MediaControllerFactory mMediaControllerFactory;
-        private final MutableLiveData<KeyguardMedia> mMedia = new MutableLiveData<>();
-        private final Object mActionsLock = new Object();
-        private List<PendingIntent> mActions;
-        private float mAlbumArtRadius;
-        private int mAlbumArtSize;
-
-        KeyguardMediaViewModel(Context context, MediaControllerFactory factory) {
-            mContext = context;
-            mMediaControllerFactory = factory;
-            loadDimens();
-        }
-
-        /** Close the media player because there isn't an active session. */
-        public void clearControls() {
-            synchronized (mActionsLock) {
-                mActions = null;
-            }
-            mMedia.postValue(null);
-        }
-
-        /** Update the media player with information about the active session. */
-        public void updateControls(NotificationEntry entry, Icon appIcon,
-                MediaMetadata mediaMetadata) {
-
-            // Check the playback state of the media controller. If it is null, then the session was
-            // probably destroyed. Don't update in this case.
-            final MediaSession.Token token = entry.getSbn().getNotification().extras
-                    .getParcelable(Notification.EXTRA_MEDIA_SESSION);
-            final MediaController controller = token != null
-                    ? mMediaControllerFactory.create(token) : null;
-            if (controller != null && controller.getPlaybackState() == null) {
-                clearControls();
-                return;
-            }
-
-            // Foreground and Background colors computed from album art
-            Notification notif = entry.getSbn().getNotification();
-            int fgColor = notif.color;
-            int bgColor = entry.getRow() == null ? -1 : entry.getRow().getCurrentBackgroundTint();
-            Bitmap artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
-            if (artworkBitmap == null) {
-                artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
-            }
-            if (artworkBitmap != null) {
-                // If we have art, get colors from that
-                Palette p = MediaNotificationProcessor.generateArtworkPaletteBuilder(artworkBitmap)
-                        .generate();
-                Palette.Swatch swatch = MediaNotificationProcessor.findBackgroundSwatch(p);
-                bgColor = swatch.getRgb();
-                fgColor = MediaNotificationProcessor.selectForegroundColor(bgColor, p);
-            }
-            // Make sure colors will be legible
-            boolean isDark = !ContrastColorUtil.isColorLight(bgColor);
-            fgColor = ContrastColorUtil.resolveContrastColor(mContext, fgColor, bgColor,
-                    isDark);
-            fgColor = ContrastColorUtil.ensureTextContrast(fgColor, bgColor, isDark);
-
-            // Album art
-            RoundedBitmapDrawable artwork = null;
-            if (artworkBitmap != null) {
-                Bitmap original = artworkBitmap.copy(Bitmap.Config.ARGB_8888, true);
-                Bitmap scaled = Bitmap.createScaledBitmap(original, mAlbumArtSize, mAlbumArtSize,
-                        false);
-                artwork = RoundedBitmapDrawableFactory.create(mContext.getResources(), scaled);
-                artwork.setCornerRadius(mAlbumArtRadius);
-            }
-
-            // App name
-            Notification.Builder builder = Notification.Builder.recoverBuilder(mContext, notif);
-            String app = builder.loadHeaderAppName();
-
-            // App Icon
-            Drawable appIconDrawable = appIcon.loadDrawable(mContext);
-
-            // Song name
-            String song = mediaMetadata.getString(MediaMetadata.METADATA_KEY_TITLE);
-
-            // Artist name
-            String artist = mediaMetadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
-
-            // Control buttons
-            List<Drawable> actionIcons = new ArrayList<>();
-            final List<PendingIntent> intents = new ArrayList<>();
-            Notification.Action[] actions = notif.actions;
-            final int[] actionsToShow = notif.extras.getIntArray(
-                    Notification.EXTRA_COMPACT_ACTIONS);
-
-            Context packageContext = entry.getSbn().getPackageContext(mContext);
-            for (int i = 0; i < ACTION_IDS.length; i++) {
-                if (actionsToShow != null && actions != null && i < actionsToShow.length
-                        && actionsToShow[i] < actions.length) {
-                    final int idx = actionsToShow[i];
-                    actionIcons.add(actions[idx].getIcon().loadDrawable(packageContext));
-                    intents.add(actions[idx].actionIntent);
-                } else {
-                    actionIcons.add(null);
-                    intents.add(null);
-                }
-            }
-            synchronized (mActionsLock) {
-                mActions = intents;
-            }
-
-            KeyguardMedia data = new KeyguardMedia(fgColor, bgColor, app, appIconDrawable, artist,
-                    song, artwork, actionIcons);
-            mMedia.postValue(data);
-        }
-
-        /** Gets state for the lock screen media controls. */
-        public LiveData<KeyguardMedia> getKeyguardMedia() {
-            return mMedia;
-        }
-
-        /**
-         * Handle user clicks on media control buttons (actions).
-         *
-         * @param index position of the button that was clicked.
-         */
-        public void onActionClick(int index) {
-            PendingIntent intent = null;
-            // This might block the ui thread to wait for the lock. Currently, however, the
-            // lock is held by the bg thread to assign a member, which should be fast. An
-            // alternative could be to add the intents to the state and let the observer set
-            // the onClick listeners.
-            synchronized (mActionsLock) {
-                if (mActions != null && index < mActions.size()) {
-                    intent = mActions.get(index);
-                }
-            }
-            if (intent != null) {
-                try {
-                    intent.send();
-                } catch (PendingIntent.CanceledException e) {
-                    Log.d(TAG, "failed to send action intent", e);
-                }
-            }
-        }
-
-        void loadDimens() {
-            mAlbumArtRadius = mContext.getResources().getDimension(R.dimen.qs_media_corner_radius);
-            mAlbumArtSize = (int) mContext.getResources().getDimension(
-                    R.dimen.qs_media_album_size);
-        }
-    }
-
-    /** Observer for state changes of lock screen media controls. */
-    private static final class KeyguardMediaObserver implements Observer<KeyguardMedia> {
-
-        private final View mRootView;
-        private final MediaHeaderView mMediaHeaderView;
-        private final ImageView mAlbumView;
-        private final ImageView mAppIconView;
-        private final TextView mAppNameView;
-        private final TextView mTitleView;
-        private final TextView mArtistView;
-        private final List<ImageButton> mButtonViews = new ArrayList<>();
-
-        KeyguardMediaObserver(View v) {
-            mRootView = v;
-            mMediaHeaderView = v instanceof MediaHeaderView ? (MediaHeaderView) v : null;
-            mAlbumView = v.findViewById(R.id.album_art);
-            mAppIconView = v.findViewById(R.id.icon);
-            mAppNameView = v.findViewById(R.id.app_name);
-            mTitleView = v.findViewById(R.id.header_title);
-            mArtistView = v.findViewById(R.id.header_artist);
-            for (int i = 0; i < ACTION_IDS.length; i++) {
-                mButtonViews.add(v.findViewById(ACTION_IDS[i]));
-            }
-        }
-
-        /** Updates lock screen media player views when state changes. */
-        @Override
-        public void onChanged(KeyguardMedia data) {
-            if (data == null) {
-                mRootView.setVisibility(View.GONE);
-                return;
-            }
-            mRootView.setVisibility(View.VISIBLE);
-
-            // Background color
-            if (mMediaHeaderView != null) {
-                mMediaHeaderView.setBackgroundColor(data.getBackgroundColor());
-            }
-
-            // Album art
-            if (mAlbumView != null) {
-                mAlbumView.setImageDrawable(data.getArtwork());
-                mAlbumView.setVisibility(data.getArtwork() == null ? View.GONE : View.VISIBLE);
-            }
-
-            // App icon
-            if (mAppIconView != null) {
-                Drawable iconDrawable = data.getAppIcon();
-                iconDrawable.setTint(data.getForegroundColor());
-                mAppIconView.setImageDrawable(iconDrawable);
-            }
-
-            // App name
-            if (mAppNameView != null) {
-                String appNameString = data.getApp();
-                mAppNameView.setText(appNameString);
-                mAppNameView.setTextColor(data.getForegroundColor());
-            }
-
-            // Song name
-            if (mTitleView != null) {
-                mTitleView.setText(data.getSong());
-                mTitleView.setTextColor(data.getForegroundColor());
-            }
-
-            // Artist name
-            if (mArtistView != null) {
-                mArtistView.setText(data.getArtist());
-                mArtistView.setTextColor(data.getForegroundColor());
-            }
-
-            // Control buttons
-            for (int i = 0; i < ACTION_IDS.length; i++) {
-                ImageButton button = mButtonViews.get(i);
-                if (button == null) {
-                    continue;
-                }
-                Drawable icon = data.getActionIcons().get(i);
-                if (icon == null) {
-                    button.setVisibility(View.GONE);
-                    button.setImageDrawable(null);
-                } else {
-                    button.setVisibility(View.VISIBLE);
-                    button.setImageDrawable(icon);
-                    button.setImageTintList(ColorStateList.valueOf(data.getForegroundColor()));
-                }
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f771cc6..0db713e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -33,6 +33,7 @@
 
 import android.annotation.AnyThread;
 import android.annotation.MainThread;
+import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.AlarmManager;
@@ -247,8 +248,7 @@
     // Battery status
     private BatteryStatus mBatteryStatus;
 
-    @VisibleForTesting
-    protected StrongAuthTracker mStrongAuthTracker;
+    private StrongAuthTracker mStrongAuthTracker;
 
     private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
             mCallbacks = Lists.newArrayList();
@@ -1512,6 +1512,16 @@
         mUserTrustIsUsuallyManaged.delete(userId);
     }
 
+    @VisibleForTesting
+    protected void setStrongAuthTracker(@NonNull StrongAuthTracker tracker) {
+        if (mStrongAuthTracker != null) {
+            mLockPatternUtils.unregisterStrongAuthTracker(mStrongAuthTracker);
+        }
+
+        mStrongAuthTracker = tracker;
+        mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
+    }
+
     private void registerRingerTracker() {
         mRingerModeTracker.getRingerMode().observeForever(mRingerModeObserver);
     }
@@ -1525,7 +1535,8 @@
             DumpManager dumpManager,
             RingerModeTracker ringerModeTracker,
             @Background Executor backgroundExecutor,
-            StatusBarStateController statusBarStateController) {
+            StatusBarStateController statusBarStateController,
+            LockPatternUtils lockPatternUtils) {
         mContext = context;
         mSubscriptionManager = SubscriptionManager.from(context);
         mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
@@ -1534,6 +1545,7 @@
         mBroadcastDispatcher = broadcastDispatcher;
         mRingerModeTracker = ringerModeTracker;
         mStatusBarStateController = statusBarStateController;
+        mLockPatternUtils = lockPatternUtils;
         dumpManager.registerDumpable(getClass().getName(), this);
 
         mHandler = new Handler(mainLooper) {
@@ -1702,8 +1714,8 @@
 
         mTrustManager = context.getSystemService(TrustManager.class);
         mTrustManager.registerTrustListener(this);
-        mLockPatternUtils = new LockPatternUtils(context);
-        mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
+
+        setStrongAuthTracker(mStrongAuthTracker);
 
         mDreamManager = IDreamManager.Stub.asInterface(
                 ServiceManager.getService(DreamService.DREAM_SERVICE));
@@ -2847,6 +2859,9 @@
         mBroadcastDispatcher.unregisterReceiver(mBroadcastAllReceiver);
         mRingerModeTracker.getRingerMode().removeObserver(mRingerModeObserver);
 
+        mLockPatternUtils.unregisterStrongAuthTracker(mStrongAuthTracker);
+        mTrustManager.unregisterTrustListener(this);
+
         mHandler.removeCallbacksAndMessages(null);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
index e17d4e6..77abffc 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
@@ -23,10 +23,13 @@
 import android.util.ArraySet;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.statusbar.NotificationInteractionTracker;
 import com.android.systemui.statusbar.NotificationLifetimeExtender;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.util.time.SystemClock;
 
+import javax.inject.Inject;
+
 /**
  * Extends the lifetime of foreground notification services such that they show for at least
  * five seconds
@@ -41,9 +44,14 @@
     private ArraySet<NotificationEntry> mManagedEntries = new ArraySet<>();
     private Handler mHandler = new Handler(Looper.getMainLooper());
     private final SystemClock mSystemClock;
+    private final NotificationInteractionTracker mInteractionTracker;
 
-    public ForegroundServiceLifetimeExtender(SystemClock systemClock) {
+    @Inject
+    public ForegroundServiceLifetimeExtender(
+            NotificationInteractionTracker interactionTracker,
+            SystemClock systemClock) {
         mSystemClock = systemClock;
+        mInteractionTracker = interactionTracker;
     }
 
     @Override
@@ -58,8 +66,9 @@
             return false;
         }
 
-        long currentTime = mSystemClock.uptimeMillis();
-        return currentTime - entry.getCreationTime() < MIN_FGS_TIME_MS;
+        boolean hasInteracted = mInteractionTracker.hasUserInteractedWith(entry.getKey());
+        long aliveTime = mSystemClock.uptimeMillis() - entry.getCreationTime();
+        return aliveTime < MIN_FGS_TIME_MS && !hasInteracted;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
index ef1f4e0..650b9a7 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
@@ -51,6 +51,7 @@
             ForegroundServiceController foregroundServiceController,
             NotificationEntryManager notificationEntryManager,
             NotifPipeline notifPipeline,
+            ForegroundServiceLifetimeExtender fgsLifetimeExtender,
             SystemClock systemClock) {
         mContext = context;
         mForegroundServiceController = foregroundServiceController;
@@ -78,8 +79,7 @@
                 removeNotification(entry.getSbn());
             }
         });
-        mEntryManager.addNotificationLifetimeExtender(
-                new ForegroundServiceLifetimeExtender(systemClock));
+        mEntryManager.addNotificationLifetimeExtender(fgsLifetimeExtender);
 
         notifPipeline.addCollectionListener(new NotifCollectionListener() {
             @Override
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index d008088..f1cb667 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -28,7 +28,7 @@
 
 import com.android.internal.os.BinderInternal;
 import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.dump.DumpManager;
+import com.android.systemui.dump.DumpHandler;
 import com.android.systemui.dump.SystemUIAuxiliaryDumpService;
 
 import java.io.FileDescriptor;
@@ -39,15 +39,15 @@
 public class SystemUIService extends Service {
 
     private final Handler mMainHandler;
-    private final DumpManager mDumpManager;
+    private final DumpHandler mDumpHandler;
 
     @Inject
     public SystemUIService(
             @Main Handler mainHandler,
-            DumpManager dumpManager) {
+            DumpHandler dumpHandler) {
         super();
         mMainHandler = mainHandler;
-        mDumpManager = dumpManager;
+        mDumpHandler = dumpHandler;
     }
 
     @Override
@@ -94,10 +94,10 @@
         String[] massagedArgs = args;
         if (args.length == 0) {
             massagedArgs = new String[] {
-                    DumpManager.PRIORITY_ARG,
-                    DumpManager.PRIORITY_ARG_CRITICAL};
+                    DumpHandler.PRIORITY_ARG,
+                    DumpHandler.PRIORITY_ARG_CRITICAL};
         }
 
-        mDumpManager.dump(fd, pw, massagedArgs);
+        mDumpHandler.dump(fd, pw, massagedArgs);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index b727563..0135e4c 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -128,6 +128,8 @@
     public static final int SYSTEM_ACTION_ID_ACCESSIBILITY_SHORTCUT =
             AccessibilityService.GLOBAL_ACTION_ACCESSIBILITY_SHORTCUT; // 13
 
+    private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
+
     private Recents mRecents;
     private StatusBar mStatusBar;
     private SystemActionsBroadcastReceiver mReceiver;
@@ -147,7 +149,11 @@
 
     @Override
     public void start() {
-        mContext.registerReceiverForAllUsers(mReceiver, mReceiver.createIntentFilter(), null, null);
+        mContext.registerReceiverForAllUsers(
+                mReceiver,
+                mReceiver.createIntentFilter(),
+                PERMISSION_SELF,
+                null);
         registerActions();
     }
 
@@ -397,6 +403,7 @@
                 case INTENT_ACTION_ACCESSIBILITY_BUTTON_CHOOSER:
                 case INTENT_ACTION_ACCESSIBILITY_SHORTCUT: {
                     Intent intent = new Intent(intentAction);
+                    intent.setPackage(context.getPackageName());
                     return PendingIntent.getBroadcast(context, 0, intent, 0);
                 }
                 default:
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
index 8cd89dd..525e989 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.SystemClock;
+import android.provider.Settings;
 import android.util.Log;
 import android.view.accessibility.AccessibilityManager;
 
@@ -61,6 +62,7 @@
 
     private static final long DEFAULT_SHOWN_FREQUENCY_THRESHOLD_MS = 0;
     private static final long DEFAULT_SHOW_AND_GO_DURATION_MS = TimeUnit.SECONDS.toMillis(3);
+    private static final String SETTINGS_SECURE_USER_SETUP_COMPLETE = "user_setup_complete";
 
     /**
      * This is the default behavior that will be used once the system is up. It will be set once the
@@ -203,6 +205,10 @@
     }
 
     private boolean handlesUnblocked(boolean ignoreThreshold) {
+        if (!isUserSetupComplete()) {
+            return false;
+        }
+
         long timeSinceHidden = SystemClock.elapsedRealtime() - mHandlesLastHiddenAt;
         boolean notThrottled = ignoreThreshold || timeSinceHidden >= getShownFrequencyThreshold();
         ComponentName assistantComponent =
@@ -284,6 +290,11 @@
         mShowAndGoEndsAt = 0;
     }
 
+    private boolean isUserSetupComplete() {
+        return Settings.Secure.getInt(
+                mContext.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1;
+    }
+
     @VisibleForTesting
     void setInGesturalModeForTest(boolean inGesturalMode) {
         mInGesturalMode = inGesturalMode;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 9d1dfa7..1dd6409 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -34,7 +34,6 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.WindowInsets.Type;
 import android.view.WindowManager;
 import android.view.animation.Interpolator;
 import android.widget.FrameLayout;
@@ -635,7 +634,6 @@
         lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         lp.setTitle("BiometricPrompt");
         lp.token = windowToken;
-        lp.setFitInsetsTypes(lp.getFitInsetsTypes() & ~Type.statusBars());
         return lp;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 0dbee66..f1b401e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -102,6 +102,13 @@
         return user.getIdentifier() + "|" + entry.getSbn().getPackageName();
     }
 
+    // TODO: Decouple Bubble from NotificationEntry and transform ShortcutInfo into Bubble
+    Bubble(ShortcutInfo shortcutInfo) {
+        mShortcutInfo = shortcutInfo;
+        mKey = shortcutInfo.getId();
+        mGroupId = shortcutInfo.getId();
+    }
+
     /** Used in tests when no UI is required. */
     @VisibleForTesting(visibility = PRIVATE)
     Bubble(NotificationEntry e,
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index ca0cd77..2587369 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -175,7 +175,7 @@
     private INotificationManager mINotificationManager;
 
     // Callback that updates BubbleOverflowActivity on data change.
-    @Nullable private BubbleData.Listener mOverflowListener = null;
+    @Nullable private Runnable mOverflowCallback = null;
 
     private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
     private IStatusBarService mBarService;
@@ -185,9 +185,10 @@
     // Used to post to main UI thread
     private Handler mHandler = new Handler();
 
-    /** LayoutParams used to add the BubbleStackView to the window maanger. */
+    /** LayoutParams used to add the BubbleStackView to the window manager. */
     private WindowManager.LayoutParams mWmLayoutParams;
-
+    /** Whether or not the BubbleStackView has been added to the WindowManager. */
+    private boolean mAddedToWindowManager = false;
 
     // Used for determining view rect for touch interaction
     private Rect mTempRect = new Rect();
@@ -198,6 +199,11 @@
     /** Last known orientation, used to detect orientation changes in {@link #onConfigChanged}. */
     private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
 
+    /**
+     * Last known screen density, used to detect display size changes in {@link #onConfigChanged}.
+     */
+    private int mDensityDpi = Configuration.DENSITY_DPI_UNDEFINED;
+
     private boolean mInflateSynchronously;
 
     // TODO (b/145659174): allow for multiple callbacks to support the "shadow" new notif pipeline
@@ -280,31 +286,6 @@
         }
     }
 
-    public BubbleController(Context context,
-            NotificationShadeWindowController notificationShadeWindowController,
-            StatusBarStateController statusBarStateController,
-            ShadeController shadeController,
-            BubbleData data,
-            ConfigurationController configurationController,
-            NotificationInterruptStateProvider interruptionStateProvider,
-            ZenModeController zenModeController,
-            NotificationLockscreenUserManager notifUserManager,
-            NotificationGroupManager groupManager,
-            NotificationEntryManager entryManager,
-            NotifPipeline notifPipeline,
-            FeatureFlags featureFlags,
-            DumpManager dumpManager,
-            FloatingContentCoordinator floatingContentCoordinator,
-            BubbleDataRepository dataRepository,
-            SysUiState sysUiState,
-            INotificationManager notificationManager) {
-        this(context, notificationShadeWindowController, statusBarStateController, shadeController,
-                data, null /* synchronizer */, configurationController, interruptionStateProvider,
-                zenModeController, notifUserManager, groupManager, entryManager,
-                notifPipeline, featureFlags, dumpManager, floatingContentCoordinator,
-                dataRepository, sysUiState, notificationManager);
-    }
-
     /**
      * Injected constructor. See {@link BubbleModule}.
      */
@@ -326,7 +307,8 @@
             FloatingContentCoordinator floatingContentCoordinator,
             BubbleDataRepository dataRepository,
             SysUiState sysUiState,
-            INotificationManager notificationManager) {
+            INotificationManager notificationManager,
+            WindowManager windowManager) {
         dumpManager.registerDumpable(TAG, this);
         mContext = context;
         mShadeController = shadeController;
@@ -395,7 +377,7 @@
         }
         mSurfaceSynchronizer = synchronizer;
 
-        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+        mWindowManager = windowManager;
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
 
@@ -595,8 +577,8 @@
         mInflateSynchronously = inflateSynchronously;
     }
 
-    void setOverflowListener(BubbleData.Listener listener) {
-        mOverflowListener = listener;
+    void setOverflowCallback(Runnable updateOverflow) {
+        mOverflowCallback = updateOverflow;
     }
 
     /**
@@ -614,9 +596,8 @@
         if (mStackView == null) {
             mStackView = new BubbleStackView(
                     mContext, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator,
-                    mSysUiState, mNotificationShadeWindowController);
+                    mSysUiState, mNotificationShadeWindowController, this::onAllBubblesAnimatedOut);
             mStackView.addView(mBubbleScrim);
-            addToWindowManager();
             if (mExpandListener != null) {
                 mStackView.setExpandListener(mExpandListener);
             }
@@ -624,10 +605,17 @@
             mStackView.setUnbubbleConversationCallback(notificationEntry ->
                     onUserChangedBubble(notificationEntry, false /* shouldBubble */));
         }
+
+        addToWindowManagerMaybe();
     }
 
-    /** Adds the BubbleStackView to the WindowManager. */
-    private void addToWindowManager() {
+    /** Adds the BubbleStackView to the WindowManager if it's not already there. */
+    private void addToWindowManagerMaybe() {
+        // If the stack is null, or already added, don't add it.
+        if (mStackView == null || mAddedToWindowManager) {
+            return;
+        }
+
         mWmLayoutParams = new WindowManager.LayoutParams(
                 // Fill the screen so we can use translation animations to position the bubble
                 // stack. We'll use touchable regions to ignore touches that are not on the bubbles
@@ -648,9 +636,37 @@
         mWmLayoutParams.packageName = mContext.getPackageName();
         mWmLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 
-        mWindowManager.addView(mStackView, mWmLayoutParams);
+        try {
+            mAddedToWindowManager = true;
+            mWindowManager.addView(mStackView, mWmLayoutParams);
+        } catch (IllegalStateException e) {
+            // This means the stack has already been added. This shouldn't happen, since we keep
+            // track of that, but just in case, update the previously added view's layout params.
+            e.printStackTrace();
+            updateWmFlags();
+        }
     }
 
+    /** Removes the BubbleStackView from the WindowManager if it's there. */
+    private void removeFromWindowManagerMaybe() {
+        if (!mAddedToWindowManager) {
+            return;
+        }
+
+        try {
+            mAddedToWindowManager = false;
+            mWindowManager.removeView(mStackView);
+        } catch (IllegalArgumentException e) {
+            // This means the stack has already been removed - it shouldn't happen, but ignore if it
+            // does, since we wanted it removed anyway.
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Updates the BubbleStackView's WindowManager.LayoutParams, and updates the WindowManager with
+     * the new params if the stack has been added.
+     */
     private void updateWmFlags() {
         if (isStackExpanded()) {
             // If we're expanded, we want to be focusable so that the ActivityView can receive focus
@@ -662,7 +678,25 @@
             mWmLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
         }
 
-        mWindowManager.updateViewLayout(mStackView, mWmLayoutParams);
+        if (mStackView != null && mAddedToWindowManager) {
+            try {
+                mWindowManager.updateViewLayout(mStackView, mWmLayoutParams);
+            } catch (IllegalArgumentException e) {
+                // If the stack is somehow not there, ignore the attempt to update it.
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * Called by the BubbleStackView and whenever all bubbles have animated out, and none have been
+     * added in the meantime.
+     */
+    private void onAllBubblesAnimatedOut() {
+        if (mStackView != null) {
+            mStackView.setVisibility(INVISIBLE);
+            removeFromWindowManagerMaybe();
+        }
     }
 
     /**
@@ -729,9 +763,16 @@
 
     @Override
     public void onConfigChanged(Configuration newConfig) {
-        if (mStackView != null && newConfig != null && newConfig.orientation != mOrientation) {
-            mOrientation = newConfig.orientation;
-            mStackView.onOrientationChanged(newConfig.orientation);
+        if (mStackView != null && newConfig != null) {
+            if (newConfig.orientation != mOrientation) {
+                mOrientation = newConfig.orientation;
+                mStackView.onOrientationChanged(newConfig.orientation);
+            }
+            if (newConfig.densityDpi != mDensityDpi) {
+                mDensityDpi = newConfig.densityDpi;
+                mBubbleIconFactory = new BubbleIconFactory(mContext);
+                mStackView.onDisplaySizeChanged();
+            }
         }
     }
 
@@ -845,10 +886,9 @@
     }
 
     void updateBubble(NotificationEntry notif, boolean suppressFlyout, boolean showInShade) {
-        if (mStackView == null) {
-            // Lazy init stack view when a bubble is created
-            ensureStackViewCreated();
-        }
+        // Lazy init stack view when a bubble is created
+        ensureStackViewCreated();
+
         // If this is an interruptive notif, mark that it's interrupted
         if (notif.getImportance() >= NotificationManager.IMPORTANCE_HIGH) {
             notif.setInterruption();
@@ -894,6 +934,7 @@
         // Update the state in NotificationManagerService
         try {
             int flags = Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
+            flags |= Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE;
             mBarService.onNotificationBubbleChanged(entry.getKey(), shouldBubble, flags);
         } catch (RemoteException e) {
         }
@@ -1010,8 +1051,8 @@
         @Override
         public void applyUpdate(BubbleData.Update update) {
             // Update bubbles in overflow.
-            if (mOverflowListener != null) {
-                mOverflowListener.applyUpdate(update);
+            if (mOverflowCallback != null) {
+                mOverflowCallback.run();
             }
 
             // Collapsing? Do this first before remaining steps.
@@ -1039,8 +1080,7 @@
                     if (!mBubbleData.hasOverflowBubbleWithKey(bubble.getKey())
                         && (!bubble.showInShade()
                             || reason == DISMISS_NOTIF_CANCEL
-                            || reason == DISMISS_GROUP_CANCELLED
-                            || reason == DISMISS_OVERFLOW_MAX_REACHED)) {
+                            || reason == DISMISS_GROUP_CANCELLED)) {
                         // The bubble is now gone & the notification is hidden from the shade, so
                         // time to actually remove it
                         for (NotifCallback cb : mCallbacks) {
@@ -1111,6 +1151,9 @@
                     Log.d(TAG, BubbleDebugConfig.formatBubblesString(mStackView.getBubblesOnScreen(),
                             mStackView.getExpandedBubble()));
                 }
+                Log.d(TAG, "\n[BubbleData] overflow:");
+                Log.d(TAG, BubbleDebugConfig.formatBubblesString(mBubbleData.getOverflowBubbles(),
+                        null) + "\n");
             }
         }
     };
@@ -1205,11 +1248,15 @@
         if (mStackView == null) {
             return;
         }
-        if (mStatusBarStateListener.getCurrentState() == SHADE && hasBubbles()) {
-            // Bubbles only appear in unlocked shade
-            mStackView.setVisibility(hasBubbles() ? VISIBLE : INVISIBLE);
-        } else if (mStackView != null) {
+
+        if (mStatusBarStateListener.getCurrentState() != SHADE) {
+            // Bubbles don't appear over the locked shade.
             mStackView.setVisibility(INVISIBLE);
+        } else if (hasBubbles()) {
+            // If we're unlocked, show the stack if we have bubbles. If we don't have bubbles, the
+            // stack will be set to INVISIBLE in onAllBubblesAnimatedOut after the bubbles animate
+            // out.
+            mStackView.setVisibility(VISIBLE);
         }
 
         mStackView.updateContentDescription();
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index f2b1c03..65d5beb 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -74,8 +74,6 @@
         @Nullable Bubble selectedBubble;
         @Nullable Bubble addedBubble;
         @Nullable Bubble updatedBubble;
-        @Nullable Bubble addedOverflowBubble;
-        @Nullable Bubble removedOverflowBubble;
         // Pair with Bubble and @DismissReason Integer
         final List<Pair<Bubble, Integer>> removedBubbles = new ArrayList<>();
 
@@ -94,12 +92,10 @@
                     || addedBubble != null
                     || updatedBubble != null
                     || !removedBubbles.isEmpty()
-                    || addedOverflowBubble != null
-                    || removedOverflowBubble != null
                     || orderChanged;
         }
 
-        void bubbleRemoved(Bubble bubbleToRemove, @DismissReason int reason) {
+        void bubbleRemoved(Bubble bubbleToRemove, @DismissReason  int reason) {
             removedBubbles.add(new Pair<>(bubbleToRemove, reason));
         }
     }
@@ -237,7 +233,6 @@
 
     private void moveOverflowBubbleToPending(Bubble b) {
         mOverflowBubbles.remove(b);
-        mStateChange.removedOverflowBubble = b;
         mPendingBubbles.add(b);
     }
 
@@ -445,9 +440,8 @@
                 if (DEBUG_BUBBLE_DATA) {
                     Log.d(TAG, "Cancel overflow bubble: " + b);
                 }
-                mOverflowBubbles.remove(b);
                 mStateChange.bubbleRemoved(b, reason);
-                mStateChange.removedOverflowBubble = b;
+                mOverflowBubbles.remove(b);
             }
             return;
         }
@@ -489,7 +483,6 @@
             Log.d(TAG, "Overflowing: " + bubble);
         }
         mOverflowBubbles.add(0, bubble);
-        mStateChange.addedOverflowBubble = bubble;
         bubble.stopInflation();
         if (mOverflowBubbles.size() == mMaxOverflowBubbles + 1) {
             // Remove oldest bubble.
@@ -497,9 +490,8 @@
             if (DEBUG_BUBBLE_DATA) {
                 Log.d(TAG, "Overflow full. Remove: " + oldest);
             }
-            mOverflowBubbles.remove(oldest);
-            mStateChange.removedOverflowBubble = oldest;
             mStateChange.bubbleRemoved(oldest, BubbleController.DISMISS_OVERFLOW_MAX_REACHED);
+            mOverflowBubbles.remove(oldest);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
index b9825e1..ba93f41 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
@@ -15,24 +15,32 @@
  */
 package com.android.systemui.bubbles
 
+import android.annotation.SuppressLint
 import android.annotation.UserIdInt
+import android.content.pm.LauncherApps
+import android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC
+import android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER
+import android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_CACHED
+import android.os.UserHandle
 import android.util.Log
+import com.android.systemui.bubbles.storage.BubbleEntity
 import com.android.systemui.bubbles.storage.BubblePersistentRepository
 import com.android.systemui.bubbles.storage.BubbleVolatileRepository
-import com.android.systemui.bubbles.storage.BubbleXmlEntity
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.cancelAndJoin
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.yield
+
 import javax.inject.Inject
 import javax.inject.Singleton
 
 @Singleton
 internal class BubbleDataRepository @Inject constructor(
     private val volatileRepository: BubbleVolatileRepository,
-    private val persistentRepository: BubblePersistentRepository
+    private val persistentRepository: BubblePersistentRepository,
+    private val launcherApps: LauncherApps
 ) {
 
     private val ioScope = CoroutineScope(Dispatchers.IO)
@@ -64,10 +72,10 @@
         if (entities.isNotEmpty()) persistToDisk()
     }
 
-    private fun transform(userId: Int, bubbles: List<Bubble>): List<BubbleXmlEntity> {
+    private fun transform(userId: Int, bubbles: List<Bubble>): List<BubbleEntity> {
         return bubbles.mapNotNull { b ->
             val shortcutId = b.shortcutInfo?.id ?: return@mapNotNull null
-            BubbleXmlEntity(userId, b.packageName, shortcutId)
+            BubbleEntity(userId, b.packageName, shortcutId)
         }
     }
 
@@ -100,15 +108,60 @@
     /**
      * Load bubbles from disk.
      */
+    // TODO: call this method from BubbleController and update UI
+    @SuppressLint("WrongConstant")
     fun loadBubbles(cb: (List<Bubble>) -> Unit) = ioScope.launch {
-        val bubbleXmlEntities = persistentRepository.readFromDisk()
-        volatileRepository.addBubbles(bubbleXmlEntities)
-        uiScope.launch {
-            // TODO: transform bubbleXmlEntities into bubbles
-            // cb(bubbles)
-        }
+        /**
+         * Load BubbleEntity from disk.
+         * e.g.
+         * [
+         *     BubbleEntity(0, "com.example.messenger", "id-2"),
+         *     BubbleEntity(10, "com.example.chat", "my-id1")
+         *     BubbleEntity(0, "com.example.messenger", "id-1")
+         * ]
+         */
+        val entities = persistentRepository.readFromDisk()
+        volatileRepository.addBubbles(entities)
+        /**
+         * Extract userId/packageName from these entities.
+         * e.g.
+         * [
+         *     ShortcutKey(0, "com.example.messenger"), ShortcutKey(0, "com.example.chat")
+         * ]
+         */
+        val shortcutKeys = entities.map { ShortcutKey(it.userId, it.packageName) }.toSet()
+        /**
+         * Retrieve shortcuts with given userId/packageName combination, then construct a mapping
+         * between BubbleEntity and ShortcutInfo.
+         * e.g.
+         * {
+         *     BubbleEntity(0, "com.example.messenger", "id-0") ->
+         *         ShortcutInfo(userId=0, pkg="com.example.messenger", id="id-0"),
+         *     BubbleEntity(0, "com.example.messenger", "id-2") ->
+         *         ShortcutInfo(userId=0, pkg="com.example.messenger", id="id-2"),
+         *     BubbleEntity(10, "com.example.chat", "id-1") ->
+         *         ShortcutInfo(userId=10, pkg="com.example.chat", id="id-1"),
+         *     BubbleEntity(10, "com.example.chat", "id-3") ->
+         *         ShortcutInfo(userId=10, pkg="com.example.chat", id="id-3")
+         * }
+         */
+        val shortcutMap = shortcutKeys.flatMap { key ->
+            launcherApps.getShortcuts(
+                    LauncherApps.ShortcutQuery()
+                            .setPackage(key.pkg)
+                            .setQueryFlags(SHORTCUT_QUERY_FLAG), UserHandle.of(key.userId))
+                    ?.map { BubbleEntity(key.userId, key.pkg, it.id) to it } ?: emptyList()
+        }.toMap()
+        // For each entity loaded from xml, find the corresponding ShortcutInfo then convert them
+        // into Bubble.
+        val bubbles = entities.mapNotNull { entity -> shortcutMap[entity]?.let { Bubble(it) } }
+        uiScope.launch { cb(bubbles) }
     }
+
+    private data class ShortcutKey(val userId: Int, val pkg: String)
 }
 
 private const val TAG = "BubbleDataRepository"
 private const val DEBUG = false
+private const val SHORTCUT_QUERY_FLAG =
+        FLAG_MATCH_DYNAMIC or FLAG_MATCH_PINNED_BY_ANY_LAUNCHER or FLAG_MATCH_CACHED
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index baf92dc..7697400 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -250,6 +250,7 @@
 
         mPointerDrawable = new ShapeDrawable(TriangleShape.create(
                 mPointerWidth, mPointerHeight, true /* pointUp */));
+        mPointerDrawable.setTint(Color.WHITE);
         mPointerView.setBackground(mPointerDrawable);
         mPointerView.setVisibility(INVISIBLE);
 
@@ -311,14 +312,10 @@
 
     void applyThemeAttrs() {
         final TypedArray ta = mContext.obtainStyledAttributes(
-                new int[] {
-                        android.R.attr.colorBackgroundFloating,
-                        android.R.attr.dialogCornerRadius});
-        int bgColor = ta.getColor(0, Color.WHITE);
-        float cornerRadius = ta.getDimensionPixelSize(1, 0);
+                new int[] {android.R.attr.dialogCornerRadius});
+        float cornerRadius = ta.getDimensionPixelSize(0, 0);
         ta.recycle();
 
-        mPointerDrawable.setTint(bgColor);
         if (mActivityView != null && ScreenDecorationsUtils.supportsRoundedCornersOnWindows(
                 mContext.getResources())) {
             mActivityView.setCornerRadius(cornerRadius);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java
index e96bef3..f4eb580 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java
@@ -58,12 +58,13 @@
     public BubbleOverflow(Context context) {
         mContext = context;
         mInflater = LayoutInflater.from(context);
-        mBitmapSize = mContext.getResources().getDimensionPixelSize(R.dimen.bubble_bitmap_size);
-        mIconBitmapSize = mContext.getResources().getDimensionPixelSize(
-                R.dimen.bubble_overflow_icon_bitmap_size);
     }
 
     void setUpOverflow(ViewGroup parentViewGroup, BubbleStackView stackView) {
+        mBitmapSize = mContext.getResources().getDimensionPixelSize(R.dimen.bubble_bitmap_size);
+        mIconBitmapSize = mContext.getResources().getDimensionPixelSize(
+                R.dimen.bubble_overflow_icon_bitmap_size);
+
         mExpandedView = (BubbleExpandedView) mInflater.inflate(
                 R.layout.bubble_expanded_view, parentViewGroup /* root */,
                 false /* attachToRoot */);
@@ -74,6 +75,7 @@
     }
 
     void updateIcon(Context context, ViewGroup parentViewGroup) {
+        mContext = context;
         mInflater = LayoutInflater.from(context);
         mOverflowBtn = (BadgedImageView) mInflater.inflate(R.layout.bubble_overflow_button,
                 parentViewGroup /* root */,
@@ -87,7 +89,7 @@
         ta.recycle();
 
         TypedValue typedValue = new TypedValue();
-        context.getTheme().resolveAttribute(android.R.attr.colorAccent, typedValue, true);
+        mContext.getTheme().resolveAttribute(android.R.attr.colorAccent, typedValue, true);
         int colorAccent = mContext.getColor(typedValue.resourceId);
         mOverflowBtn.getDrawable().setTint(colorAccent);
         mDotColor = colorAccent;
@@ -97,7 +99,7 @@
                 mBitmapSize - mIconBitmapSize /* inset */);
         AdaptiveIconDrawable adaptiveIconDrawable = new AdaptiveIconDrawable(bg, fg);
 
-        BubbleIconFactory iconFactory = new BubbleIconFactory(context);
+        BubbleIconFactory iconFactory = new BubbleIconFactory(mContext);
         mIcon = iconFactory.createBadgedIconBitmap(adaptiveIconDrawable,
                 null /* user */,
                 true /* shrinkNonAdaptiveIcons */).icon;
@@ -106,7 +108,7 @@
                 null /* outBounds */, null /* path */, null /* outMaskShape */);
         float radius = DEFAULT_PATH_SIZE / 2f;
         mPath = PathParser.createPathFromPathData(
-                context.getResources().getString(com.android.internal.R.string.config_icon_mask));
+                mContext.getResources().getString(com.android.internal.R.string.config_icon_mask));
         Matrix matrix = new Matrix();
         matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
                 radius /* pivot y */);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
index c2ca9fa..08ec789 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
@@ -41,6 +41,7 @@
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
+import com.android.internal.util.ContrastColorUtil;
 import com.android.systemui.R;
 
 import java.util.ArrayList;
@@ -108,12 +109,11 @@
         mAdapter = new BubbleOverflowAdapter(getApplicationContext(), mOverflowBubbles,
                 mBubbleController::promoteBubbleFromOverflow, viewWidth, viewHeight);
         mRecyclerView.setAdapter(mAdapter);
-
-        mOverflowBubbles.addAll(mBubbleController.getOverflowBubbles());
-        mAdapter.notifyDataSetChanged();
-        setEmptyStateVisibility();
-
-        mBubbleController.setOverflowListener(mDataListener);
+        onDataChanged(mBubbleController.getOverflowBubbles());
+        mBubbleController.setOverflowCallback(() -> {
+            onDataChanged(mBubbleController.getOverflowBubbles());
+        });
+        onThemeChanged();
     }
 
     /**
@@ -140,14 +140,6 @@
         }
     }
 
-    void setEmptyStateVisibility() {
-        if (mOverflowBubbles.isEmpty()) {
-            mEmptyState.setVisibility(View.VISIBLE);
-        } else {
-            mEmptyState.setVisibility(View.GONE);
-        }
-    }
-
     void setBackgroundColor() {
         final TypedArray ta = getApplicationContext().obtainStyledAttributes(
                 new int[]{android.R.attr.colorBackgroundFloating});
@@ -156,40 +148,22 @@
         findViewById(android.R.id.content).setBackgroundColor(bgColor);
     }
 
-    private final BubbleData.Listener mDataListener = new BubbleData.Listener() {
+    void onDataChanged(List<Bubble> bubbles) {
+        mOverflowBubbles.clear();
+        mOverflowBubbles.addAll(bubbles);
+        mAdapter.notifyDataSetChanged();
 
-        @Override
-        public void applyUpdate(BubbleData.Update update) {
-
-            Bubble toRemove = update.removedOverflowBubble;
-            if (toRemove != null) {
-                if (DEBUG_OVERFLOW) {
-                    Log.d(TAG, "remove: " + toRemove);
-                }
-                toRemove.cleanupViews();
-                int i = mOverflowBubbles.indexOf(toRemove);
-                mOverflowBubbles.remove(toRemove);
-                mAdapter.notifyItemRemoved(i);
-            }
-
-            Bubble toAdd = update.addedOverflowBubble;
-            if (toAdd != null) {
-                if (DEBUG_OVERFLOW) {
-                    Log.d(TAG, "add: " + toAdd);
-                }
-                mOverflowBubbles.add(0, toAdd);
-                mAdapter.notifyItemInserted(0);
-            }
-
-            setEmptyStateVisibility();
-
-            if (DEBUG_OVERFLOW) {
-                Log.d(TAG, BubbleDebugConfig.formatBubblesString(
-                        mBubbleController.getOverflowBubbles(),
-                        null));
-            }
+        if (mOverflowBubbles.isEmpty()) {
+            mEmptyState.setVisibility(View.VISIBLE);
+        } else {
+            mEmptyState.setVisibility(View.GONE);
         }
-    };
+
+        if (DEBUG_OVERFLOW) {
+            Log.d(TAG, "Updated overflow bubbles:\n" + BubbleDebugConfig.formatBubblesString(
+                    mOverflowBubbles, /*selected*/ null));
+        }
+    }
 
     @Override
     public void onStart() {
@@ -241,6 +215,8 @@
     @Override
     public BubbleOverflowAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
             int viewType) {
+
+        // Set layout for overflow bubble view.
         LinearLayout overflowView = (LinearLayout) LayoutInflater.from(parent.getContext())
                 .inflate(R.layout.bubble_overflow_view, parent, false);
         LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
@@ -249,6 +225,18 @@
         params.width = mWidth;
         params.height = mHeight;
         overflowView.setLayoutParams(params);
+
+        // Ensure name has enough contrast.
+        final TypedArray ta = mContext.obtainStyledAttributes(
+                new int[]{android.R.attr.colorBackgroundFloating, android.R.attr.textColorPrimary});
+        final int bgColor = ta.getColor(0, Color.WHITE);
+        int textColor = ta.getColor(1, Color.BLACK);
+        textColor = ContrastColorUtil.ensureTextContrast(textColor, bgColor, true);
+        ta.recycle();
+
+        TextView viewName = overflowView.findViewById(R.id.bubble_view_name);
+        viewName.setTextColor(textColor);
+
         return new ViewHolder(overflowView);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 2cb097f..ec45f93 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -362,6 +362,10 @@
             new MagnetizedObject.MagnetListener() {
                 @Override
                 public void onStuckToTarget(@NonNull MagnetizedObject.MagneticTarget target) {
+                    if (mExpandedAnimationController.getDraggedOutBubble() == null) {
+                        return;
+                    }
+
                     animateDesaturateAndDarken(
                             mExpandedAnimationController.getDraggedOutBubble(), true);
                 }
@@ -369,6 +373,10 @@
                 @Override
                 public void onUnstuckFromTarget(@NonNull MagnetizedObject.MagneticTarget target,
                         float velX, float velY, boolean wasFlungOut) {
+                    if (mExpandedAnimationController.getDraggedOutBubble() == null) {
+                        return;
+                    }
+
                     animateDesaturateAndDarken(
                             mExpandedAnimationController.getDraggedOutBubble(), false);
 
@@ -383,6 +391,10 @@
 
                 @Override
                 public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target) {
+                    if (mExpandedAnimationController.getDraggedOutBubble() == null) {
+                        return;
+                    }
+
                     mExpandedAnimationController.dismissDraggedOutBubble(
                             mExpandedAnimationController.getDraggedOutBubble() /* bubble */,
                             mDismissTargetContainer.getHeight() /* translationYBy */,
@@ -445,6 +457,10 @@
             final boolean clickedBubbleIsCurrentlyExpandedBubble =
                     clickedBubble.getKey().equals(mExpandedBubble.getKey());
 
+            if (isExpanded()) {
+                mExpandedAnimationController.onGestureFinished();
+            }
+
             if (isExpanded() && !clickedBubbleIsCurrentlyExpandedBubble) {
                 if (clickedBubble != mBubbleData.getSelectedBubble()) {
                     // Select the clicked bubble.
@@ -464,7 +480,6 @@
                     mBubbleData.setExpanded(!mBubbleData.isExpanded());
                 }
             }
-            mExpandedAnimationController.onGestureFinished();
         }
     };
 
@@ -653,7 +668,8 @@
             @Nullable SurfaceSynchronizer synchronizer,
             FloatingContentCoordinator floatingContentCoordinator,
             SysUiState sysUiState,
-            NotificationShadeWindowController notificationShadeWindowController) {
+            NotificationShadeWindowController notificationShadeWindowController,
+            Runnable allBubblesAnimatedOutAction) {
         super(context);
 
         mBubbleData = data;
@@ -688,11 +704,18 @@
         mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
         int elevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
 
+        final Runnable onBubbleAnimatedOut = () -> {
+            if (getBubbleCount() == 0) {
+                allBubblesAnimatedOutAction.run();
+            }
+        };
+
         mStackAnimationController = new StackAnimationController(
-                floatingContentCoordinator, this::getBubbleCount);
+                floatingContentCoordinator, this::getBubbleCount, onBubbleAnimatedOut);
 
         mExpandedAnimationController = new ExpandedAnimationController(
-                mDisplaySize, mExpandedViewPadding, res.getConfiguration().orientation);
+                mDisplaySize, mExpandedViewPadding, res.getConfiguration().orientation,
+                onBubbleAnimatedOut);
         mSurfaceSynchronizer = synchronizer != null ? synchronizer : DEFAULT_SURFACE_SYNCHRONIZER;
 
         setUpUserEducation();
@@ -787,8 +810,8 @@
 
         mOrientationChangedListener =
                 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
-                    mExpandedAnimationController.updateOrientation(mOrientation, mDisplaySize);
-                    mStackAnimationController.updateOrientation(mOrientation);
+                    mExpandedAnimationController.updateResources(mOrientation, mDisplaySize);
+                    mStackAnimationController.updateResources(mOrientation);
 
                     // Reposition & adjust the height for new orientation
                     if (mIsExpanded) {
@@ -868,7 +891,7 @@
                 }
             }
 
-            return false;
+            return true;
         });
     }
 
@@ -1004,7 +1027,7 @@
             mBubbleOverflow.setUpOverflow(mBubbleContainer, this);
         } else {
             mBubbleContainer.removeView(mBubbleOverflow.getBtn());
-            mBubbleOverflow.updateIcon(mContext, this);
+            mBubbleOverflow.updateIcon(mContext,this);
             overflowBtnIndex = mBubbleContainer.getChildCount();
         }
         mBubbleContainer.addView(mBubbleOverflow.getBtn(), overflowBtnIndex,
@@ -1051,10 +1074,33 @@
         mShowingManage = false;
     }
 
+    /** Respond to the display size change by recalculating view size and location. */
+    public void onDisplaySizeChanged() {
+        setUpOverflow();
+
+        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
+        wm.getDefaultDisplay().getRealSize(mDisplaySize);
+        Resources res = getContext().getResources();
+        mStatusBarHeight = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.status_bar_height);
+        mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
+        mBubbleSize = getResources().getDimensionPixelSize(R.dimen.individual_bubble_size);
+        for (Bubble b : mBubbleData.getBubbles()) {
+            if (b.getIconView() == null) {
+                Log.d(TAG, "Display size changed. Icon null: " + b);
+                continue;
+            }
+            b.getIconView().setLayoutParams(new LayoutParams(mBubbleSize, mBubbleSize));
+        }
+        mExpandedAnimationController.updateResources(mOrientation, mDisplaySize);
+        mStackAnimationController.updateResources(mOrientation);
+    }
+
     @Override
     public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo inoutInfo) {
         inoutInfo.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
 
+        mTempRect.setEmpty();
         getTouchableRegion(mTempRect);
         inoutInfo.touchableRegion.set(mTempRect);
     }
@@ -1290,7 +1336,7 @@
         Log.d(TAG, "was asked to remove Bubble, but didn't find the view! " + bubble);
     }
 
-    private void updateOverflowBtnVisibility(boolean apply) {
+    private void updateOverflowBtnVisibility() {
         if (!BubbleExperimentConfig.allowBubbleOverflow(mContext)) {
             return;
         }
@@ -1299,11 +1345,6 @@
                 Log.d(TAG, "Show overflow button.");
             }
             mBubbleOverflow.setBtnVisible(VISIBLE);
-            if (apply) {
-                mExpandedAnimationController.expandFromStack(() -> {
-                    updatePointerPosition();
-                } /* after */);
-            }
         } else {
             if (DEBUG_BUBBLE_STACK_VIEW) {
                 Log.d(TAG, "Collapsed. Hide overflow button.");
@@ -1563,7 +1604,7 @@
             Log.d(TAG, BubbleDebugConfig.formatBubblesString(getBubblesOnScreen(),
                     mExpandedBubble));
         }
-        updateOverflowBtnVisibility(/* apply */ false);
+        updateOverflowBtnVisibility();
         mBubbleContainer.cancelAllAnimations();
         mExpandedAnimationController.collapseBackToStack(
                 mStackAnimationController.getStackPositionAlongNearestHorizontalEdge()
@@ -1587,7 +1628,7 @@
         beforeExpandedViewAnimation();
 
         mBubbleContainer.setActiveController(mExpandedAnimationController);
-        updateOverflowBtnVisibility(/* apply */ false);
+        updateOverflowBtnVisibility();
         mExpandedAnimationController.expandFromStack(() -> {
             updatePointerPosition();
             afterExpandedViewAnimation();
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index 35406c7..76ff1af 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -32,6 +32,7 @@
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.util.animation.PhysicsAnimator;
 import com.android.systemui.util.magnetictarget.MagnetizedObject;
 
 import com.google.android.collect.Sets;
@@ -69,6 +70,10 @@
      */
     private static final float FLING_TO_DISMISS_MIN_VELOCITY = 6000f;
 
+    private final PhysicsAnimator.SpringConfig mAnimateOutSpringConfig =
+            new PhysicsAnimator.SpringConfig(
+                    EXPAND_COLLAPSE_ANIM_STIFFNESS, SpringForce.DAMPING_RATIO_NO_BOUNCY);
+
     /** Horizontal offset between bubbles, which we need to know to re-stack them. */
     private float mStackOffsetPx;
     /** Space between status bar and bubbles in the expanded state. */
@@ -116,10 +121,17 @@
 
     private int mExpandedViewPadding;
 
+    /**
+     * Callback to run whenever any bubble is animated out. The BubbleStackView will check if the
+     * end of this animation means we have no bubbles left, and notify the BubbleController.
+     */
+    private Runnable mOnBubbleAnimatedOutAction;
+
     public ExpandedAnimationController(Point displaySize, int expandedViewPadding,
-            int orientation) {
-        updateOrientation(orientation, displaySize);
+            int orientation, Runnable onBubbleAnimatedOutAction) {
+        updateResources(orientation, displaySize);
         mExpandedViewPadding = expandedViewPadding;
+        mOnBubbleAnimatedOutAction = onBubbleAnimatedOutAction;
     }
 
     /**
@@ -168,7 +180,7 @@
      * @param orientation Landscape or portrait.
      * @param displaySize Updated display size.
      */
-    public void updateOrientation(int orientation, Point displaySize) {
+    public void updateResources(int orientation, Point displaySize) {
         mScreenOrientation = orientation;
         mDisplaySize = displaySize;
         if (mLayout != null) {
@@ -355,8 +367,8 @@
         }
         animationForChild(bubble)
                 .withStiffness(SpringForce.STIFFNESS_HIGH)
-                .scaleX(1.1f)
-                .scaleY(1.1f)
+                .scaleX(0f)
+                .scaleY(0f)
                 .translationY(bubble.getTranslationY() + translationYBy)
                 .alpha(0f, after)
                 .start();
@@ -500,18 +512,17 @@
 
     @Override
     void onChildRemoved(View child, int index, Runnable finishRemoval) {
-        final PhysicsAnimationLayout.PhysicsPropertyAnimator animator = animationForChild(child);
-
         // If we're removing the dragged-out bubble, that means it got dismissed.
         if (child.equals(getDraggedOutBubble())) {
             mMagnetizedBubbleDraggingOut = null;
             finishRemoval.run();
+            mOnBubbleAnimatedOutAction.run();
         } else {
-            animator.alpha(0f, finishRemoval /* endAction */)
-                    .withStiffness(SpringForce.STIFFNESS_HIGH)
-                    .withDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY)
-                    .scaleX(1.1f)
-                    .scaleY(1.1f)
+            PhysicsAnimator.getInstance(child)
+                    .spring(DynamicAnimation.ALPHA, 0f)
+                    .spring(DynamicAnimation.SCALE_X, 0f, mAnimateOutSpringConfig)
+                    .spring(DynamicAnimation.SCALE_Y, 0f, mAnimateOutSpringConfig)
+                    .withEndActions(finishRemoval, mOnBubbleAnimatedOutAction)
                     .start();
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
index a7d1be1..942b9a7 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
@@ -767,6 +767,10 @@
                 int targetAnimDuration,
                 TimeInterpolator targetAnimInterpolator,
                 Runnable... pathAnimEndActions) {
+            if (mPathAnimator != null) {
+                mPathAnimator.cancel();
+            }
+
             mPathAnimator = ObjectAnimator.ofFloat(
                     this, mCurrentPointOnPathXProperty, mCurrentPointOnPathYProperty, path);
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index 5f3a2bd..d52c35b 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -74,6 +74,10 @@
     private static final int FLING_FOLLOW_STIFFNESS = 20000;
     public static final float DEFAULT_BOUNCINESS = 0.9f;
 
+    private final PhysicsAnimator.SpringConfig mAnimateOutSpringConfig =
+            new PhysicsAnimator.SpringConfig(
+                    ANIMATE_IN_STIFFNESS, SpringForce.DAMPING_RATIO_NO_BOUNCY);
+
     /**
      * Friction applied to fling animations. Since the stack must land on one of the sides of the
      * screen, we want less friction horizontally so that the stack has a better chance of making it
@@ -248,12 +252,19 @@
     /** Returns the number of 'real' bubbles (excluding the overflow bubble). */
     private IntSupplier mBubbleCountSupplier;
 
+    /**
+     * Callback to run whenever any bubble is animated out. The BubbleStackView will check if the
+     * end of this animation means we have no bubbles left, and notify the BubbleController.
+     */
+    private Runnable mOnBubbleAnimatedOutAction;
+
     public StackAnimationController(
             FloatingContentCoordinator floatingContentCoordinator,
-            IntSupplier bubbleCountSupplier) {
+            IntSupplier bubbleCountSupplier,
+            Runnable onBubbleAnimatedOutAction) {
         mFloatingContentCoordinator = floatingContentCoordinator;
         mBubbleCountSupplier = bubbleCountSupplier;
-
+        mOnBubbleAnimatedOutAction = onBubbleAnimatedOutAction;
     }
 
     /**
@@ -448,6 +459,10 @@
             float friction,
             SpringForce spring,
             Float finalPosition) {
+        if (!isActiveController()) {
+            return;
+        }
+
         Log.d(TAG, String.format("Flinging %s.",
                 PhysicsAnimationLayout.getReadablePropertyName(property)));
 
@@ -652,8 +667,8 @@
     public void animateStackDismissal(float translationYBy, Runnable after) {
         animationsForChildrenFromIndex(0, (index, animation) ->
                 animation
-                        .scaleX(0.5f)
-                        .scaleY(0.5f)
+                        .scaleX(0f)
+                        .scaleY(0f)
                         .alpha(0f)
                         .translationY(
                                 mLayout.getChildAt(index).getTranslationY() + translationYBy)
@@ -668,7 +683,7 @@
             DynamicAnimation.ViewProperty property, SpringForce spring,
             float vel, float finalPosition, @Nullable Runnable... after) {
 
-        if (mLayout.getChildCount() == 0) {
+        if (mLayout.getChildCount() == 0 || !isActiveController()) {
             return;
         }
 
@@ -676,12 +691,22 @@
                 PhysicsAnimationLayout.getReadablePropertyName(property),
                 finalPosition));
 
+        // Whether we're springing towards the touch location, rather than to a position on the
+        // sides of the screen.
+        final boolean isSpringingTowardsTouch = mSpringToTouchOnNextMotionEvent;
+
         StackPositionProperty firstBubbleProperty = new StackPositionProperty(property);
         SpringAnimation springAnimation =
                 new SpringAnimation(this, firstBubbleProperty)
                         .setSpring(spring)
                         .addEndListener((dynamicAnimation, b, v, v1) -> {
-                            mRestingStackPosition.set(mStackPosition);
+                            if (!isSpringingTowardsTouch) {
+                                // If we're springing towards the touch position, don't save the
+                                // resting position - the touch location is not a valid resting
+                                // position. We'll set this when the stack springs to the left or
+                                // right side of the screen after the touch gesture ends.
+                                mRestingStackPosition.set(mStackPosition);
+                            }
 
                             if (after != null) {
                                 for (Runnable callback : after) {
@@ -760,13 +785,11 @@
 
     @Override
     void onChildRemoved(View child, int index, Runnable finishRemoval) {
-        // Animate the removing view in the opposite direction of the stack.
-        final float xOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X);
-        animationForChild(child)
-                .alpha(0f, finishRemoval /* after */)
-                .scaleX(ANIMATE_IN_STARTING_SCALE)
-                .scaleY(ANIMATE_IN_STARTING_SCALE)
-                .translationX(mStackPosition.x - (-xOffset * ANIMATE_TRANSLATION_FACTOR))
+        PhysicsAnimator.getInstance(child)
+                .spring(DynamicAnimation.ALPHA, 0f)
+                .spring(DynamicAnimation.SCALE_X, 0f, mAnimateOutSpringConfig)
+                .spring(DynamicAnimation.SCALE_Y, 0f, mAnimateOutSpringConfig)
+                .withEndActions(finishRemoval, mOnBubbleAnimatedOutAction)
                 .start();
 
         // If there are other bubbles, pull them into the correct position.
@@ -809,7 +832,7 @@
      * Update effective screen width based on current orientation.
      * @param orientation Landscape or portrait.
      */
-    public void updateOrientation(int orientation) {
+    public void updateResources(int orientation) {
         if (mLayout != null) {
             Resources res = mLayout.getContext().getResources();
             mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java
index e3b630b..d1d07f6 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java
@@ -18,6 +18,7 @@
 
 import android.app.INotificationManager;
 import android.content.Context;
+import android.view.WindowManager;
 
 import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.bubbles.BubbleData;
@@ -68,7 +69,8 @@
             FloatingContentCoordinator floatingContentCoordinator,
             BubbleDataRepository bubbleDataRepository,
             SysUiState sysUiState,
-            INotificationManager notifManager) {
+            INotificationManager notifManager,
+            WindowManager windowManager) {
         return new BubbleController(
                 context,
                 notificationShadeWindowController,
@@ -88,6 +90,7 @@
                 floatingContentCoordinator,
                 bubbleDataRepository,
                 sysUiState,
-                notifManager);
+                notifManager,
+                windowManager);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleEntity.kt
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt
rename to packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleEntity.kt
index d0f7607..4690a8e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleEntity.kt
@@ -17,7 +17,7 @@
 
 import android.annotation.UserIdInt
 
-data class BubbleXmlEntity(
+data class BubbleEntity(
     @UserIdInt val userId: Int,
     val packageName: String,
     val shortcutId: String
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt
index 149e2c4..7c3271e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubblePersistentRepository.kt
@@ -32,7 +32,7 @@
     private val bubbleFile: AtomicFile = AtomicFile(File(context.filesDir,
             "overflow_bubbles.xml"), "overflow-bubbles")
 
-    fun persistsToDisk(bubbles: List<BubbleXmlEntity>): Boolean {
+    fun persistsToDisk(bubbles: List<BubbleEntity>): Boolean {
         if (DEBUG) Log.d(TAG, "persisting ${bubbles.size} bubbles")
         synchronized(bubbleFile) {
             val stream: FileOutputStream = try { bubbleFile.startWrite() } catch (e: IOException) {
@@ -52,7 +52,7 @@
         return false
     }
 
-    fun readFromDisk(): List<BubbleXmlEntity> {
+    fun readFromDisk(): List<BubbleEntity> {
         synchronized(bubbleFile) {
             try { return bubbleFile.openRead().use(::readXml) } catch (e: Throwable) {
                 Log.e(TAG, "Failed to open bubble file", e)
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt
index e1f675b..d1eee2f6 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleVolatileRepository.kt
@@ -29,12 +29,12 @@
     /**
      * An ordered set of bubbles based on their natural ordering.
      */
-    private val entities = mutableSetOf<BubbleXmlEntity>()
+    private val entities = mutableSetOf<BubbleEntity>()
 
     /**
      * Returns a snapshot of all the bubbles.
      */
-    val bubbles: List<BubbleXmlEntity>
+    val bubbles: List<BubbleEntity>
         @Synchronized
         get() = entities.toList()
 
@@ -43,7 +43,7 @@
      * it will be moved to the last.
      */
     @Synchronized
-    fun addBubbles(bubbles: List<BubbleXmlEntity>) {
+    fun addBubbles(bubbles: List<BubbleEntity>) {
         if (bubbles.isEmpty()) return
         bubbles.forEach { entities.remove(it) }
         if (entities.size + bubbles.size >= CAPACITY) {
@@ -53,7 +53,7 @@
     }
 
     @Synchronized
-    fun removeBubbles(bubbles: List<BubbleXmlEntity>) {
+    fun removeBubbles(bubbles: List<BubbleEntity>) {
         bubbles.forEach { entities.remove(it) }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt
index 1e91653..821b64c 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt
@@ -35,7 +35,7 @@
  * Writes the bubbles in xml format into given output stream.
  */
 @Throws(IOException::class)
-fun writeXml(stream: OutputStream, bubbles: List<BubbleXmlEntity>) {
+fun writeXml(stream: OutputStream, bubbles: List<BubbleEntity>) {
     val serializer: XmlSerializer = FastXmlSerializer()
     serializer.setOutput(stream, StandardCharsets.UTF_8.name())
     serializer.startDocument(null, true)
@@ -51,7 +51,7 @@
  * <bb uid="0" pkg="com.example.messenger" sid="my-shortcut" />
  * ```
  */
-private fun writeXmlEntry(serializer: XmlSerializer, bubble: BubbleXmlEntity) {
+private fun writeXmlEntry(serializer: XmlSerializer, bubble: BubbleEntity) {
     try {
         serializer.startTag(null, TAG_BUBBLE)
         serializer.attribute(null, ATTR_USER_ID, bubble.userId.toString())
@@ -66,8 +66,8 @@
 /**
  * Reads the bubbles from xml file.
  */
-fun readXml(stream: InputStream): List<BubbleXmlEntity> {
-    val bubbles = mutableListOf<BubbleXmlEntity>()
+fun readXml(stream: InputStream): List<BubbleEntity> {
+    val bubbles = mutableListOf<BubbleEntity>()
     val parser: XmlPullParser = Xml.newPullParser()
     parser.setInput(stream, StandardCharsets.UTF_8.name())
     XmlUtils.beginDocument(parser, TAG_BUBBLES)
@@ -78,9 +78,9 @@
     return bubbles
 }
 
-private fun readXmlEntry(parser: XmlPullParser): BubbleXmlEntity? {
+private fun readXmlEntry(parser: XmlPullParser): BubbleEntity? {
     while (parser.eventType != XmlPullParser.START_TAG) { parser.next() }
-    return BubbleXmlEntity(
+    return BubbleEntity(
             parser.getAttributeWithName(ATTR_USER_ID)?.toInt() ?: return null,
             parser.getAttributeWithName(ATTR_PACKAGE) ?: return null,
             parser.getAttributeWithName(ATTR_SHORTCUT_ID) ?: return null
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index a1f4c96..181170b 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -89,35 +89,36 @@
             contentResolver, CONTROLS_AVAILABLE, DEFAULT_ENABLED, currentUserId) != 0
         private set
 
-    private var file = Environment.buildPath(
-        context.filesDir,
-        ControlsFavoritePersistenceWrapper.FILE_NAME
-    )
-    private var auxiliaryFile = Environment.buildPath(
-        context.filesDir,
-        AuxiliaryPersistenceWrapper.AUXILIARY_FILE_NAME
-    )
-    private val persistenceWrapper = optionalWrapper.orElseGet {
-        ControlsFavoritePersistenceWrapper(
-            file,
-            executor,
-            BackupManager(context)
+    private val persistenceWrapper: ControlsFavoritePersistenceWrapper
+    @VisibleForTesting
+    internal var auxiliaryPersistenceWrapper: AuxiliaryPersistenceWrapper
+
+    init {
+        val userStructure = UserStructure(context, currentUser)
+
+        persistenceWrapper = optionalWrapper.orElseGet {
+            ControlsFavoritePersistenceWrapper(
+                    userStructure.file,
+                    executor,
+                    BackupManager(userStructure.userContext)
+            )
+        }
+
+        auxiliaryPersistenceWrapper = AuxiliaryPersistenceWrapper(
+                userStructure.auxiliaryFile,
+                executor
         )
     }
 
-    @VisibleForTesting
-    internal var auxiliaryPersistenceWrapper = AuxiliaryPersistenceWrapper(auxiliaryFile, executor)
-
     private fun setValuesForUser(newUser: UserHandle) {
         Log.d(TAG, "Changing to user: $newUser")
         currentUser = newUser
-        val userContext = context.createContextAsUser(currentUser, 0)
-        file = Environment.buildPath(
-                userContext.filesDir, ControlsFavoritePersistenceWrapper.FILE_NAME)
-        auxiliaryFile = Environment.buildPath(
-            userContext.filesDir, AuxiliaryPersistenceWrapper.AUXILIARY_FILE_NAME)
-        persistenceWrapper.changeFileAndBackupManager(file, BackupManager(userContext))
-        auxiliaryPersistenceWrapper.changeFile(auxiliaryFile)
+        val userStructure = UserStructure(context, currentUser)
+        persistenceWrapper.changeFileAndBackupManager(
+                userStructure.file,
+                BackupManager(userStructure.userContext)
+        )
+        auxiliaryPersistenceWrapper.changeFile(userStructure.auxiliaryFile)
         available = Settings.Secure.getIntForUser(contentResolver, CONTROLS_AVAILABLE,
                 DEFAULT_ENABLED, newUser.identifier) != 0
         resetFavorites(available)
@@ -564,6 +565,20 @@
     }
 }
 
+class UserStructure(context: Context, user: UserHandle) {
+    val userContext = context.createContextAsUser(user, 0)
+
+    val file = Environment.buildPath(
+            context.filesDir,
+            ControlsFavoritePersistenceWrapper.FILE_NAME
+    )
+
+    val auxiliaryFile = Environment.buildPath(
+            context.filesDir,
+            AuxiliaryPersistenceWrapper.AUXILIARY_FILE_NAME
+    )
+}
+
 /**
  * Relies on immutable data for thread safety. When necessary to update favMap, use reassignment to
  * replace it, which will not disrupt any ongoing map traversal.
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/AllModel.kt b/packages/SystemUI/src/com/android/systemui/controls/management/AllModel.kt
index 175ed06..00a406e 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/AllModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/AllModel.kt
@@ -48,6 +48,8 @@
 
     private var modified = false
 
+    override val moveHelper = null
+
     override val favorites: List<ControlInfo>
         get() = favoriteIds.mapNotNull { id ->
             val control = controls.firstOrNull { it.control.controlId == id }?.control
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
index 79dd9ed..2f91710 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
@@ -18,14 +18,20 @@
 
 import android.content.ComponentName
 import android.graphics.Rect
+import android.os.Bundle
 import android.service.controls.Control
 import android.service.controls.DeviceTypes
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import android.view.accessibility.AccessibilityNodeInfo
 import android.widget.CheckBox
 import android.widget.ImageView
+import android.widget.Switch
 import android.widget.TextView
+import androidx.core.view.AccessibilityDelegateCompat
+import androidx.core.view.ViewCompat
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
 import androidx.recyclerview.widget.GridLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import com.android.systemui.R
@@ -72,7 +78,8 @@
                         elevation = this@ControlAdapter.elevation
                         background = parent.context.getDrawable(
                                 R.drawable.control_background_ripple)
-                    }
+                    },
+                    model?.moveHelper // Indicates that position information is needed
                 ) { id, favorite ->
                     model?.changeFavoriteStatus(id, favorite)
                 }
@@ -170,13 +177,21 @@
 
 /**
  * Holder for using with [ControlStatusWrapper] to display names of zones.
+ * @param moveHelper a helper interface to facilitate a11y rearranging. Null indicates no
+ *                   rearranging
  * @param favoriteCallback this callback will be called whenever the favorite state of the
  *                         [Control] this view represents changes.
  */
 internal class ControlHolder(
     view: View,
+    val moveHelper: ControlsModel.MoveHelper?,
     val favoriteCallback: ModelFavoriteChanger
 ) : Holder(view) {
+    private val favoriteStateDescription =
+        itemView.context.getString(R.string.accessibility_control_favorite)
+    private val notFavoriteStateDescription =
+        itemView.context.getString(R.string.accessibility_control_not_favorite)
+
     private val icon: ImageView = itemView.requireViewById(R.id.icon)
     private val title: TextView = itemView.requireViewById(R.id.title)
     private val subtitle: TextView = itemView.requireViewById(R.id.subtitle)
@@ -185,15 +200,42 @@
         visibility = View.VISIBLE
     }
 
+    private val accessibilityDelegate = ControlHolderAccessibilityDelegate(
+        this::stateDescription,
+        this::getLayoutPosition,
+        moveHelper
+    )
+
+    init {
+        ViewCompat.setAccessibilityDelegate(itemView, accessibilityDelegate)
+    }
+
+    // Determine the stateDescription based on favorite state and maybe position
+    private fun stateDescription(favorite: Boolean): CharSequence? {
+        if (!favorite) {
+            return notFavoriteStateDescription
+        } else if (moveHelper == null) {
+            return favoriteStateDescription
+        } else {
+            val position = layoutPosition + 1
+            return itemView.context.getString(
+                R.string.accessibility_control_favorite_position, position)
+        }
+    }
+
     override fun bindData(wrapper: ElementWrapper) {
         wrapper as ControlInterface
         val renderInfo = getRenderInfo(wrapper.component, wrapper.deviceType)
         title.text = wrapper.title
         subtitle.text = wrapper.subtitle
-        favorite.isChecked = wrapper.favorite
-        removed.text = if (wrapper.removed) "Removed" else ""
+        updateFavorite(wrapper.favorite)
+        removed.text = if (wrapper.removed) {
+            itemView.context.getText(R.string.controls_removed)
+        } else {
+            ""
+        }
         itemView.setOnClickListener {
-            favorite.isChecked = !favorite.isChecked
+            updateFavorite(!favorite.isChecked)
             favoriteCallback(wrapper.controlId, favorite.isChecked)
         }
         applyRenderInfo(renderInfo)
@@ -201,6 +243,8 @@
 
     override fun updateFavorite(favorite: Boolean) {
         this.favorite.isChecked = favorite
+        accessibilityDelegate.isFavorite = favorite
+        itemView.stateDescription = stateDescription(favorite)
     }
 
     private fun getRenderInfo(
@@ -219,6 +263,105 @@
     }
 }
 
+/**
+ * Accessibility delegate for [ControlHolder].
+ *
+ * Provides the following functionality:
+ * * Sets the state description indicating whether the controls is Favorited or Unfavorited
+ * * Adds the position to the state description if necessary.
+ * * Adds context action for moving (rearranging) a control.
+ *
+ * @param stateRetriever function to determine the state description based on the favorite state
+ * @param positionRetriever function to obtain the position of this control. It only has to be
+ *                          correct in controls that are currently favorites (and therefore can
+ *                          be moved).
+ * @param moveHelper helper interface to determine if a control can be moved and actually move it.
+ */
+private class ControlHolderAccessibilityDelegate(
+    val stateRetriever: (Boolean) -> CharSequence?,
+    val positionRetriever: () -> Int,
+    val moveHelper: ControlsModel.MoveHelper?
+) : AccessibilityDelegateCompat() {
+
+    var isFavorite = false
+
+    companion object {
+        private val MOVE_BEFORE_ID = R.id.accessibility_action_controls_move_before
+        private val MOVE_AFTER_ID = R.id.accessibility_action_controls_move_after
+    }
+
+    override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) {
+        super.onInitializeAccessibilityNodeInfo(host, info)
+
+        info.isContextClickable = false
+        addClickAction(host, info)
+        maybeAddMoveBeforeAction(host, info)
+        maybeAddMoveAfterAction(host, info)
+
+        // Determine the stateDescription based on the holder information
+        info.stateDescription = stateRetriever(isFavorite)
+        // Remove the information at the end indicating row and column.
+        info.setCollectionItemInfo(null)
+
+        info.className = Switch::class.java.name
+    }
+
+    override fun performAccessibilityAction(host: View?, action: Int, args: Bundle?): Boolean {
+        if (super.performAccessibilityAction(host, action, args)) {
+            return true
+        }
+        return when (action) {
+            MOVE_BEFORE_ID -> {
+                moveHelper?.moveBefore(positionRetriever())
+                true
+            }
+            MOVE_AFTER_ID -> {
+                moveHelper?.moveAfter(positionRetriever())
+                true
+            }
+            else -> false
+        }
+    }
+
+    private fun addClickAction(host: View, info: AccessibilityNodeInfoCompat) {
+        // Change the text for the double-tap action
+        val clickActionString = if (isFavorite) {
+            host.context.getString(R.string.accessibility_control_change_unfavorite)
+        } else {
+            host.context.getString(R.string.accessibility_control_change_favorite)
+        }
+        val click = AccessibilityNodeInfoCompat.AccessibilityActionCompat(
+            AccessibilityNodeInfo.ACTION_CLICK,
+            // “favorite/unfavorite”
+            clickActionString)
+        info.addAction(click)
+    }
+
+    private fun maybeAddMoveBeforeAction(host: View, info: AccessibilityNodeInfoCompat) {
+        if (moveHelper?.canMoveBefore(positionRetriever()) ?: false) {
+            val newPosition = positionRetriever() + 1 - 1
+            val moveBefore = AccessibilityNodeInfoCompat.AccessibilityActionCompat(
+                MOVE_BEFORE_ID,
+                host.context.getString(R.string.accessibility_control_move, newPosition)
+            )
+            info.addAction(moveBefore)
+            info.isContextClickable = true
+        }
+    }
+
+    private fun maybeAddMoveAfterAction(host: View, info: AccessibilityNodeInfoCompat) {
+        if (moveHelper?.canMoveAfter(positionRetriever()) ?: false) {
+            val newPosition = positionRetriever() + 1 + 1
+            val moveAfter = AccessibilityNodeInfoCompat.AccessibilityActionCompat(
+                MOVE_AFTER_ID,
+                host.context.getString(R.string.accessibility_control_move, newPosition)
+            )
+            info.addAction(moveAfter)
+            info.isContextClickable = true
+        }
+    }
+}
+
 class MarginItemDecorator(
     private val topMargin: Int,
     private val sideMargins: Int
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
index 4e9c550..ff40a8a 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
@@ -130,6 +130,7 @@
             inflate()
         }
         requireViewById<TextView>(R.id.title).text = structure
+        setTitle(structure)
         subtitle = requireViewById<TextView>(R.id.subtitle).apply {
             setText(SUBTITLE_ID)
         }
@@ -191,7 +192,18 @@
 
         recyclerView.apply {
             this.adapter = adapter
-            layoutManager = GridLayoutManager(recyclerView.context, 2).apply {
+            layoutManager = object : GridLayoutManager(recyclerView.context, 2) {
+
+                // This will remove from the announcement the row corresponding to the divider,
+                // as it's not something that should be announced.
+                override fun getRowCountForAccessibility(
+                    recycler: RecyclerView.Recycler,
+                    state: RecyclerView.State
+                ): Int {
+                    val initial = super.getRowCountForAccessibility(recycler, state)
+                    return if (initial > 0) initial - 1 else initial
+                }
+            }.apply {
                 spanSizeLookup = adapter.spanSizeLookup
             }
             addItemDecoration(itemDecorator)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
index eb15262..496b21b6 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
@@ -208,7 +208,7 @@
                     val name = listOfStructures[position].structureName
                     val title = if (!TextUtils.isEmpty(name)) name else appName
                     titleView.text = title
-                    setTitle(title)
+                    titleView.requestFocus()
                 }
 
                 override fun onPageScrolled(
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
index 48f191d..a2adcf9 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
@@ -106,9 +106,15 @@
 
     override fun changeUser(newUser: UserHandle) {
         backgroundExecutor.execute {
-            callbacks.clear()
-            availableServices = emptyList()
             serviceListing.setListening(false)
+
+            // Notify all callbacks in order to clear their existing state prior to attaching
+            // a new listener
+            availableServices = emptyList()
+            callbacks.forEach {
+                it.onServicesUpdated(emptyList())
+            }
+
             currentUserId = newUser.identifier
             val contextForUser = context.createContextAsUser(newUser, 0)
             serviceListing = serviceListingBuilder(contextForUser)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt
index 37b6d15..2543953 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt
@@ -42,6 +42,8 @@
      */
     val elements: List<ElementWrapper>
 
+    val moveHelper: MoveHelper?
+
     /**
      * Change the favorite status of a particular control.
      */
@@ -69,6 +71,34 @@
          */
         fun onFirstChange()
     }
+
+    /**
+     * Interface to facilitate moving controls from an [AccessibilityDelegate].
+     *
+     * All positions should be 0 based.
+     */
+    interface MoveHelper {
+
+        /**
+         * Whether the control in `position` can be moved to the position before it.
+         */
+        fun canMoveBefore(position: Int): Boolean
+
+        /**
+         * Whether the control in `position` can be moved to the position after it.
+         */
+        fun canMoveAfter(position: Int): Boolean
+
+        /**
+         * Move the control in `position` to the position before it.
+         */
+        fun moveBefore(position: Int)
+
+        /**
+         * Move the control in `position` to the position after it.
+         */
+        fun moveAfter(position: Int)
+    }
 }
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt b/packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt
index 411170cb..5242501 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.controls.management
 
 import android.content.ComponentName
+import android.util.Log
 import androidx.recyclerview.widget.ItemTouchHelper
 import androidx.recyclerview.widget.RecyclerView
 import com.android.systemui.controls.ControlInterface
@@ -39,9 +40,39 @@
     private val favoritesModelCallback: FavoritesModelCallback
 ) : ControlsModel {
 
+    companion object {
+        private const val TAG = "FavoritesModel"
+    }
+
     private var adapter: RecyclerView.Adapter<*>? = null
     private var modified = false
 
+    override val moveHelper = object : ControlsModel.MoveHelper {
+        override fun canMoveBefore(position: Int): Boolean {
+            return position > 0 && position < dividerPosition
+        }
+
+        override fun canMoveAfter(position: Int): Boolean {
+            return position >= 0 && position < dividerPosition - 1
+        }
+
+        override fun moveBefore(position: Int) {
+            if (!canMoveBefore(position)) {
+                Log.w(TAG, "Cannot move position $position before")
+            } else {
+                onMoveItem(position, position - 1)
+            }
+        }
+
+        override fun moveAfter(position: Int) {
+            if (!canMoveAfter(position)) {
+                Log.w(TAG, "Cannot move position $position after")
+            } else {
+                onMoveItem(position, position + 1)
+            }
+        }
+    }
+
     override fun attachAdapter(adapter: RecyclerView.Adapter<*>) {
         this.adapter = adapter
     }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt
index 275c778..842c39b 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt
@@ -30,6 +30,9 @@
 
     /**
      * Will be invoked on every update provided to the Control
+     *
+     * @param cws ControlWithState, as loaded from favorites and/or the application
+     * @param colorOffset An additional flag to control rendering color. See [RenderInfo]
      */
-    fun bind(cws: ControlWithState)
+    fun bind(cws: ControlWithState, colorOffset: Int = 0)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt
index 1f07e37..6c28d11 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt
@@ -50,7 +50,8 @@
     fun createPinDialog(
         cvh: ControlViewHolder,
         useAlphaNumeric: Boolean,
-        useRetryStrings: Boolean
+        useRetryStrings: Boolean,
+        onCancel: () -> Unit
     ): Dialog? {
         val lastAction = cvh.lastAction
         if (lastAction == null) {
@@ -86,7 +87,10 @@
             })
             setNegativeButton(
                 android.R.string.cancel,
-                DialogInterface.OnClickListener { dialog, _ -> dialog.cancel() }
+                DialogInterface.OnClickListener { dialog, _ ->
+                    onCancel.invoke()
+                    dialog.cancel()
+                }
             )
         }
         return builder.create().apply {
@@ -111,7 +115,7 @@
     /**
      * AlertDialogs to handle [ControlAction#RESPONSE_CHALLENGE_ACK] response type.
      */
-    fun createConfirmationDialog(cvh: ControlViewHolder): Dialog? {
+    fun createConfirmationDialog(cvh: ControlViewHolder, onCancel: () -> Unit): Dialog? {
         val lastAction = cvh.lastAction
         if (lastAction == null) {
             Log.e(ControlsUiController.TAG,
@@ -120,7 +124,7 @@
         }
         val builder = AlertDialog.Builder(cvh.context, STYLE).apply {
             val res = cvh.context.resources
-            setMessage(res.getString(
+            setTitle(res.getString(
                 R.string.controls_confirmation_message, cvh.title.getText()))
             setPositiveButton(
                 android.R.string.ok,
@@ -130,7 +134,10 @@
             })
             setNegativeButton(
                 android.R.string.cancel,
-                DialogInterface.OnClickListener { dialog, _ -> dialog.cancel() }
+                DialogInterface.OnClickListener { dialog, _ ->
+                    onCancel.invoke()
+                    dialog.cancel()
+                }
             )
         }
         return builder.create().apply {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
index 9055479..10e9137 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
@@ -58,7 +58,7 @@
 
     override fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean) {
         bouncerOrRun {
-            val effect = if (isChecked) Vibrations.toggleOnEffect else Vibrations.toggleOffEffect
+            val effect = if (!isChecked) Vibrations.toggleOnEffect else Vibrations.toggleOffEffect
             vibrate(effect)
             cvh.action(BooleanAction(templateId, !isChecked))
         }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
index 2653ce0..f979bbb 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
@@ -18,21 +18,28 @@
 
 import android.animation.Animator
 import android.animation.AnimatorListenerAdapter
+import android.animation.AnimatorSet
+import android.animation.ObjectAnimator
 import android.animation.ValueAnimator
+import android.annotation.ColorRes
 import android.app.Dialog
 import android.content.Context
+import android.content.res.ColorStateList
 import android.graphics.drawable.ClipDrawable
+import android.graphics.drawable.Drawable
 import android.graphics.drawable.GradientDrawable
 import android.graphics.drawable.LayerDrawable
 import android.service.controls.Control
 import android.service.controls.DeviceTypes
 import android.service.controls.actions.ControlAction
 import android.service.controls.templates.ControlTemplate
+import android.service.controls.templates.RangeTemplate
 import android.service.controls.templates.StatelessTemplate
 import android.service.controls.templates.TemperatureControlTemplate
 import android.service.controls.templates.ToggleRangeTemplate
 import android.service.controls.templates.ToggleTemplate
 import android.util.MathUtils
+import android.util.TypedValue
 import android.view.View
 import android.view.ViewGroup
 import android.widget.ImageView
@@ -62,6 +69,8 @@
         private const val UPDATE_DELAY_IN_MILLIS = 3000L
         private const val ALPHA_ENABLED = 255
         private const val ALPHA_DISABLED = 0
+        private const val STATUS_ALPHA_ENABLED = 1f
+        private const val STATUS_ALPHA_DIMMED = 0.45f
         private val FORCE_PANEL_DEVICES = setOf(
             DeviceTypes.TYPE_THERMOSTAT,
             DeviceTypes.TYPE_CAMERA
@@ -69,14 +78,35 @@
 
         const val MIN_LEVEL = 0
         const val MAX_LEVEL = 10000
+
+        fun findBehaviorClass(
+            status: Int,
+            template: ControlTemplate,
+            deviceType: Int
+        ): KClass<out Behavior> {
+            return when {
+                status == Control.STATUS_UNKNOWN -> StatusBehavior::class
+                status == Control.STATUS_ERROR -> StatusBehavior::class
+                status == Control.STATUS_NOT_FOUND -> StatusBehavior::class
+                deviceType == DeviceTypes.TYPE_CAMERA -> TouchBehavior::class
+                template is ToggleTemplate -> ToggleBehavior::class
+                template is StatelessTemplate -> TouchBehavior::class
+                template is ToggleRangeTemplate -> ToggleRangeBehavior::class
+                template is RangeTemplate -> ToggleRangeBehavior::class
+                template is TemperatureControlTemplate -> TemperatureControlBehavior::class
+                else -> DefaultBehavior::class
+            }
+        }
     }
 
     private val toggleBackgroundIntensity: Float = layout.context.resources
             .getFraction(R.fraction.controls_toggle_bg_intensity, 1, 1)
     private var stateAnimator: ValueAnimator? = null
+    private var statusAnimator: Animator? = null
     private val baseLayer: GradientDrawable
     val icon: ImageView = layout.requireViewById(R.id.icon)
-    val status: TextView = layout.requireViewById(R.id.status)
+    private val status: TextView = layout.requireViewById(R.id.status)
+    private var nextStatusText: CharSequence = ""
     val title: TextView = layout.requireViewById(R.id.title)
     val subtitle: TextView = layout.requireViewById(R.id.subtitle)
     val context: Context = layout.getContext()
@@ -85,7 +115,9 @@
     var cancelUpdate: Runnable? = null
     var behavior: Behavior? = null
     var lastAction: ControlAction? = null
+    var isLoading = false
     private var lastChallengeDialog: Dialog? = null
+    private val onDialogCancel: () -> Unit = { lastChallengeDialog = null }
 
     val deviceType: Int
         get() = cws.control?.let { it.getDeviceType() } ?: cws.ci.deviceType
@@ -123,20 +155,9 @@
             })
         }
 
-        val clazz = findBehavior(controlStatus, template, deviceType)
-        if (behavior == null || behavior!!::class != clazz) {
-            // Behavior changes can signal a change in template from the app or
-            // first time setup
-            behavior = clazz.java.newInstance()
-            behavior?.initialize(this)
-
-            // let behaviors define their own, if necessary, and clear any existing ones
-            layout.setAccessibilityDelegate(null)
-        }
-
-        behavior?.bind(cws)
-
-        layout.setContentDescription("${title.text} ${subtitle.text} ${status.text}")
+        isLoading = false
+        behavior = bindBehavior(behavior, findBehaviorClass(controlStatus, template, deviceType))
+        updateContentDescription()
     }
 
     fun actionResponse(@ControlAction.ResponseResult response: Int) {
@@ -154,15 +175,18 @@
                 setTransientStatus(context.resources.getString(R.string.controls_error_failed))
             }
             ControlAction.RESPONSE_CHALLENGE_PIN -> {
-                lastChallengeDialog = ChallengeDialogs.createPinDialog(this, false, failedAttempt)
+                lastChallengeDialog = ChallengeDialogs.createPinDialog(
+                    this, false, failedAttempt, onDialogCancel)
                 lastChallengeDialog?.show()
             }
             ControlAction.RESPONSE_CHALLENGE_PASSPHRASE -> {
-                lastChallengeDialog = ChallengeDialogs.createPinDialog(this, true, failedAttempt)
+                lastChallengeDialog = ChallengeDialogs.createPinDialog(
+                    this, false, failedAttempt, onDialogCancel)
                 lastChallengeDialog?.show()
             }
             ControlAction.RESPONSE_CHALLENGE_ACK -> {
-                lastChallengeDialog = ChallengeDialogs.createConfirmationDialog(this)
+                lastChallengeDialog = ChallengeDialogs.createConfirmationDialog(
+                    this, onDialogCancel)
                 lastChallengeDialog?.show()
             }
         }
@@ -177,12 +201,17 @@
         val previousText = status.getText()
 
         cancelUpdate = uiExecutor.executeDelayed({
-                status.setText(previousText)
-            }, UPDATE_DELAY_IN_MILLIS)
+            setStatusText(previousText)
+            updateContentDescription()
+        }, UPDATE_DELAY_IN_MILLIS)
 
-        status.setText(tempStatus)
+        setStatusText(tempStatus)
+        updateContentDescription()
     }
 
+    private fun updateContentDescription() =
+        layout.setContentDescription("${title.text} ${subtitle.text} ${status.text}")
+
     fun action(action: ControlAction) {
         lastAction = action
         controlsController.action(cws.componentName, cws.ci, action)
@@ -190,37 +219,74 @@
 
     fun usePanel(): Boolean = deviceType in ControlViewHolder.FORCE_PANEL_DEVICES
 
-    private fun findBehavior(
-        status: Int,
-        template: ControlTemplate,
-        deviceType: Int
-    ): KClass<out Behavior> {
-        return when {
-            status == Control.STATUS_UNKNOWN -> StatusBehavior::class
-            status == Control.STATUS_ERROR -> StatusBehavior::class
-            status == Control.STATUS_NOT_FOUND -> StatusBehavior::class
-            deviceType == DeviceTypes.TYPE_CAMERA -> TouchBehavior::class
-            template is ToggleTemplate -> ToggleBehavior::class
-            template is StatelessTemplate -> TouchBehavior::class
-            template is ToggleRangeTemplate -> ToggleRangeBehavior::class
-            template is TemperatureControlTemplate -> TemperatureControlBehavior::class
-            else -> DefaultBehavior::class
+    fun bindBehavior(
+        existingBehavior: Behavior?,
+        clazz: KClass<out Behavior>,
+        offset: Int = 0
+    ): Behavior {
+        val behavior = if (existingBehavior == null || existingBehavior!!::class != clazz) {
+            // Behavior changes can signal a change in template from the app or
+            // first time setup
+            val newBehavior = clazz.java.newInstance()
+            newBehavior.initialize(this)
+
+            // let behaviors define their own, if necessary, and clear any existing ones
+            layout.setAccessibilityDelegate(null)
+            newBehavior
+        } else {
+            existingBehavior
+        }
+
+        return behavior.also {
+            it.bind(cws, offset)
         }
     }
 
-    internal fun applyRenderInfo(enabled: Boolean, offset: Int = 0, animated: Boolean = true) {
-        setEnabled(enabled)
-
+    internal fun applyRenderInfo(enabled: Boolean, offset: Int, animated: Boolean = true) {
         val ri = RenderInfo.lookup(context, cws.componentName, deviceType, enabled, offset)
-
         val fg = context.resources.getColorStateList(ri.foreground, context.theme)
+        val newText = nextStatusText
+        nextStatusText = ""
+        val control = cws.control
+
+        var shouldAnimate = animated
+        if (newText == status.text) {
+            shouldAnimate = false
+        }
+        animateStatusChange(shouldAnimate) {
+            updateStatusRow(enabled, newText, ri.icon, fg, control)
+        }
+
+        animateBackgroundChange(shouldAnimate, enabled, ri.enabledBackground)
+    }
+
+    fun getStatusText() = status.text
+
+    fun setStatusTextSize(textSize: Float) =
+        status.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
+
+    fun setStatusText(text: CharSequence, immediately: Boolean = false) {
+        if (immediately) {
+            status.alpha = STATUS_ALPHA_ENABLED
+            status.text = text
+            nextStatusText = ""
+        } else {
+            nextStatusText = text
+        }
+    }
+
+    private fun animateBackgroundChange(
+        animated: Boolean,
+        enabled: Boolean,
+        @ColorRes bgColor: Int
+    ) {
         val bg = context.resources.getColor(R.color.control_default_background, context.theme)
         var (newClipColor, newAlpha) = if (enabled) {
             // allow color overrides for the enabled state only
             val color = cws.control?.getCustomColor()?.let {
                 val state = intArrayOf(android.R.attr.state_enabled)
                 it.getColorForState(state, it.getDefaultColor())
-            } ?: context.resources.getColor(ri.enabledBackground, context.theme)
+            } ?: context.resources.getColor(bgColor, context.theme)
             listOf(color, ALPHA_ENABLED)
         } else {
             listOf(
@@ -229,21 +295,6 @@
             )
         }
 
-        status.setTextColor(fg)
-
-        cws.control?.getCustomIcon()?.let {
-            // do not tint custom icons, assume the intended icon color is correct
-            icon.imageTintList = null
-            icon.setImageIcon(it)
-        } ?: run {
-            icon.setImageDrawable(ri.icon)
-
-            // do not color app icons
-            if (deviceType != DeviceTypes.TYPE_ROUTINE) {
-                icon.imageTintList = fg
-            }
-        }
-
         (clipLayer.getDrawable() as GradientDrawable).apply {
             val newBaseColor = if (behavior is ToggleRangeBehavior) {
                 ColorUtils.blendARGB(bg, newClipColor, toggleBackgroundIntensity)
@@ -281,6 +332,77 @@
         }
     }
 
+    private fun animateStatusChange(animated: Boolean, statusRowUpdater: () -> Unit) {
+        statusAnimator?.cancel()
+
+        if (!animated) {
+            statusRowUpdater.invoke()
+            return
+        }
+
+        if (isLoading) {
+            statusRowUpdater.invoke()
+            statusAnimator = ObjectAnimator.ofFloat(status, "alpha", STATUS_ALPHA_DIMMED).apply {
+                repeatMode = ValueAnimator.REVERSE
+                repeatCount = ValueAnimator.INFINITE
+                duration = 500L
+                interpolator = Interpolators.LINEAR
+                startDelay = 900L
+                start()
+            }
+        } else {
+            val fadeOut = ObjectAnimator.ofFloat(status, "alpha", 0f).apply {
+                duration = 200L
+                interpolator = Interpolators.LINEAR
+                addListener(object : AnimatorListenerAdapter() {
+                    override fun onAnimationEnd(animation: Animator?) {
+                        statusRowUpdater.invoke()
+                    }
+                })
+            }
+            val fadeIn = ObjectAnimator.ofFloat(status, "alpha", STATUS_ALPHA_ENABLED).apply {
+                duration = 200L
+                interpolator = Interpolators.LINEAR
+            }
+            statusAnimator = AnimatorSet().apply {
+                playSequentially(fadeOut, fadeIn)
+                addListener(object : AnimatorListenerAdapter() {
+                    override fun onAnimationEnd(animation: Animator?) {
+                        status.alpha = STATUS_ALPHA_ENABLED
+                        statusAnimator = null
+                    }
+                })
+                start()
+            }
+        }
+    }
+
+    private fun updateStatusRow(
+        enabled: Boolean,
+        text: CharSequence,
+        drawable: Drawable,
+        color: ColorStateList,
+        control: Control?
+    ) {
+        setEnabled(enabled)
+
+        status.text = text
+        status.setTextColor(color)
+
+        control?.getCustomIcon()?.let {
+            // do not tint custom icons, assume the intended icon color is correct
+            icon.imageTintList = null
+            icon.setImageIcon(it)
+        } ?: run {
+            icon.setImageDrawable(drawable)
+
+            // do not color app icons
+            if (deviceType != DeviceTypes.TYPE_ROUTINE) {
+                icon.imageTintList = color
+            }
+        }
+    }
+
     private fun setEnabled(enabled: Boolean) {
         status.setEnabled(enabled)
         icon.setEnabled(enabled)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 52d564d..ab33291 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -59,6 +59,7 @@
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.globalactions.GlobalActionsPopupMenu
 import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.statusbar.phone.ShadeController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.concurrency.DelayableExecutor
 import dagger.Lazy
@@ -79,7 +80,8 @@
     @Main val sharedPreferences: SharedPreferences,
     val controlActionCoordinator: ControlActionCoordinator,
     private val activityStarter: ActivityStarter,
-    private val keyguardStateController: KeyguardStateController
+    private val keyguardStateController: KeyguardStateController,
+    private val shadeController: ShadeController
 ) : ControlsUiController {
 
     companion object {
@@ -105,6 +107,7 @@
     private var popup: ListPopupWindow? = null
     private var hidden = true
     private lateinit var dismissGlobalActions: Runnable
+    private val popupThemedContext = ContextThemeWrapper(context, R.style.Control_ListPopupWindow)
 
     override val available: Boolean
         get() = controlsController.get().available
@@ -254,14 +257,11 @@
         intent.putExtra(ControlsUiController.EXTRA_ANIMATE, true)
         dismissGlobalActions.run()
 
-        if (!keyguardStateController.isUnlocked()) {
-            activityStarter.dismissKeyguardThenExecute({
-                context.startActivity(intent)
-                true
-            }, null, true)
-        } else {
+        activityStarter.dismissKeyguardThenExecute({
+            shadeController.collapsePanel(false)
             context.startActivity(intent)
-        }
+            true
+        }, null, true)
     }
 
     private fun showControlsView(items: List<SelectionItem>) {
@@ -284,7 +284,10 @@
         val anchor = parent.requireViewById<ImageView>(R.id.controls_more)
         anchor.setOnClickListener(object : View.OnClickListener {
             override fun onClick(v: View) {
-                popup = GlobalActionsPopupMenu(context, false /* isDropDownMode */).apply {
+                popup = GlobalActionsPopupMenu(
+                        popupThemedContext,
+                        false /* isDropDownMode */
+                ).apply {
                     setAnchorView(anchor)
                     setAdapter(adapter)
                     setOnItemClickListener(object : AdapterView.OnItemClickListener {
@@ -369,7 +372,7 @@
         val spinner = parent.requireViewById<TextView>(R.id.app_or_structure_spinner).apply {
             setText(selectionItem.getTitle())
             // override the default color on the dropdown drawable
-            (getBackground() as LayerDrawable).getDrawable(1)
+            (getBackground() as LayerDrawable).getDrawable(0)
                 .setTint(context.resources.getColor(R.color.control_spinner_dropdown, null))
         }
 
@@ -381,13 +384,12 @@
         val anchor = parent.requireViewById<ViewGroup>(R.id.controls_header)
         anchor.setOnClickListener(object : View.OnClickListener {
             override fun onClick(v: View) {
-                popup = GlobalActionsPopupMenu(context, true /* isDropDownMode */).apply {
+                popup = GlobalActionsPopupMenu(
+                        popupThemedContext,
+                        true /* isDropDownMode */
+                ).apply {
                     setAnchorView(anchor)
                     setAdapter(adapter)
-                    val theme = ContextThemeWrapper(context, R.style.Control_ListPopupWindow)
-                        .getTheme()
-                    setBackgroundDrawable(
-                        context.resources.getDrawable(R.drawable.rounded_bg_full, theme))
 
                     setOnItemClickListener(object : AdapterView.OnItemClickListener {
                         override fun onItemClick(
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DefaultBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DefaultBehavior.kt
index e850a6a..0c8e3ff 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/DefaultBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DefaultBehavior.kt
@@ -23,8 +23,8 @@
         this.cvh = cvh
     }
 
-    override fun bind(cws: ControlWithState) {
-        cvh.status.setText(cws.control?.getStatusText() ?: "")
-        cvh.applyRenderInfo(false)
+    override fun bind(cws: ControlWithState, colorOffset: Int) {
+        cvh.setStatusText(cws.control?.getStatusText() ?: "")
+        cvh.applyRenderInfo(false, colorOffset)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
index 236fa2d..f970152 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
@@ -18,7 +18,6 @@
 
 import android.app.ActivityView
 import android.app.Dialog
-import android.content.ComponentName
 import android.content.Intent
 import android.provider.Settings
 import android.view.View
@@ -58,17 +57,13 @@
             launchIntent.putExtra(EXTRA_USE_PANEL, true)
 
             // Apply flags to make behaviour match documentLaunchMode=always.
-            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
             launchIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
 
             view.startActivity(launchIntent)
         }
 
         override fun onActivityViewDestroyed(view: ActivityView) {}
-
-        override fun onTaskCreated(taskId: Int, componentName: ComponentName) {}
-
-        override fun onTaskRemovalStarted(taskId: Int) {}
     }
 
     init {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
index 124df32..ba331f4 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
@@ -97,6 +97,8 @@
 private const val THERMOSTAT_RANGE = DeviceTypes.TYPE_THERMOSTAT * BUCKET_SIZE
 
 private val deviceColorMap = mapOf<Int, Pair<Int, Int>>(
+    (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_OFF) to
+        Pair(R.color.control_default_foreground, R.color.control_default_background),
     (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_HEAT) to
         Pair(R.color.thermo_heat_foreground, R.color.control_enabled_thermo_heat_background),
     (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_COOL) to
@@ -108,13 +110,9 @@
 }
 
 private val deviceIconMap = mapOf<Int, IconState>(
-    THERMOSTAT_RANGE to IconState(
-        R.drawable.ic_device_thermostat_off,
-        R.drawable.ic_device_thermostat_on
-    ),
     (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_OFF) to IconState(
         R.drawable.ic_device_thermostat_off,
-        R.drawable.ic_device_thermostat_on
+        R.drawable.ic_device_thermostat_off
     ),
     (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_HEAT) to IconState(
         R.drawable.ic_device_thermostat_off,
@@ -130,7 +128,7 @@
     ),
     (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_ECO) to IconState(
         R.drawable.ic_device_thermostat_off,
-        R.drawable.ic_device_thermostat_on
+        R.drawable.ic_device_thermostat_off
     ),
     DeviceTypes.TYPE_THERMOSTAT to IconState(
         R.drawable.ic_device_thermostat_off,
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt
index 49c4408..bf3835d 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt
@@ -27,14 +27,17 @@
         this.cvh = cvh
     }
 
-    override fun bind(cws: ControlWithState) {
+    override fun bind(cws: ControlWithState, colorOffset: Int) {
         val status = cws.control?.status ?: Control.STATUS_UNKNOWN
         val msg = when (status) {
             Control.STATUS_ERROR -> R.string.controls_error_generic
             Control.STATUS_NOT_FOUND -> R.string.controls_error_removed
-            else -> com.android.internal.R.string.loading
+            else -> {
+                cvh.isLoading = true
+                com.android.internal.R.string.loading
+            }
         }
-        cvh.status.setText(cvh.context.getString(msg))
-        cvh.applyRenderInfo(false)
+        cvh.setStatusText(cvh.context.getString(msg))
+        cvh.applyRenderInfo(false, colorOffset)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt
index b4d0e63..a7dc09b 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt
@@ -19,6 +19,7 @@
 import android.graphics.drawable.Drawable
 import android.graphics.drawable.LayerDrawable
 import android.service.controls.Control
+import android.service.controls.templates.ControlTemplate
 import android.service.controls.templates.TemperatureControlTemplate
 
 import com.android.systemui.R
@@ -29,29 +30,46 @@
     lateinit var clipLayer: Drawable
     lateinit var control: Control
     lateinit var cvh: ControlViewHolder
-    lateinit var template: TemperatureControlTemplate
+    var subBehavior: Behavior? = null
 
     override fun initialize(cvh: ControlViewHolder) {
         this.cvh = cvh
-
-        cvh.layout.setOnClickListener { _ ->
-            cvh.controlActionCoordinator.touch(cvh, template.getTemplateId(), control)
-        }
     }
 
-    override fun bind(cws: ControlWithState) {
+    override fun bind(cws: ControlWithState, colorOffset: Int) {
         this.control = cws.control!!
 
-        cvh.status.setText(control.getStatusText())
+        cvh.setStatusText(control.getStatusText())
 
         val ld = cvh.layout.getBackground() as LayerDrawable
         clipLayer = ld.findDrawableByLayerId(R.id.clip_layer)
 
-        template = control.getControlTemplate() as TemperatureControlTemplate
-
+        val template = control.getControlTemplate() as TemperatureControlTemplate
         val activeMode = template.getCurrentActiveMode()
-        val enabled = activeMode != 0 && activeMode != TemperatureControlTemplate.MODE_OFF
-        clipLayer.setLevel(if (enabled) MAX_LEVEL else MIN_LEVEL)
-        cvh.applyRenderInfo(enabled, activeMode)
+        val subTemplate = template.getTemplate()
+        if (subTemplate == ControlTemplate.getNoTemplateObject() ||
+            subTemplate == ControlTemplate.getErrorTemplate()) {
+            // No sub template is specified, apply a default look with basic touch interaction.
+            // Treat an error as no template.
+            val enabled = activeMode != 0 && activeMode != TemperatureControlTemplate.MODE_OFF
+            clipLayer.setLevel(if (enabled) MAX_LEVEL else MIN_LEVEL)
+            cvh.applyRenderInfo(enabled, activeMode)
+
+            cvh.layout.setOnClickListener { _ ->
+                cvh.controlActionCoordinator.touch(cvh, template.getTemplateId(), control)
+            }
+        } else {
+            // A sub template has been specified, use this as the default behavior for user
+            // interactions (touch, range)
+            subBehavior = cvh.bindBehavior(
+                subBehavior,
+                ControlViewHolder.findBehaviorClass(
+                    control.status,
+                    subTemplate,
+                    control.deviceType
+                ),
+                activeMode
+            )
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt
index 3e16698..dc7247c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt
@@ -19,7 +19,9 @@
 import android.graphics.drawable.Drawable
 import android.graphics.drawable.LayerDrawable
 import android.service.controls.Control
+import android.service.controls.templates.TemperatureControlTemplate
 import android.service.controls.templates.ToggleTemplate
+import android.util.Log
 import android.view.View
 import com.android.systemui.R
 import com.android.systemui.controls.ui.ControlViewHolder.Companion.MAX_LEVEL
@@ -32,24 +34,31 @@
 
     override fun initialize(cvh: ControlViewHolder) {
         this.cvh = cvh
-        cvh.applyRenderInfo(false /* enabled */, 0 /* offset */, false /* animated */)
 
         cvh.layout.setOnClickListener(View.OnClickListener() {
             cvh.controlActionCoordinator.toggle(cvh, template.getTemplateId(), template.isChecked())
         })
     }
 
-    override fun bind(cws: ControlWithState) {
+    override fun bind(cws: ControlWithState, colorOffset: Int) {
         this.control = cws.control!!
 
-        cvh.status.setText(control.getStatusText())
-        template = control.getControlTemplate() as ToggleTemplate
+        cvh.setStatusText(control.getStatusText())
+        val controlTemplate = control.getControlTemplate()
+        template = when (controlTemplate) {
+            is ToggleTemplate -> controlTemplate
+            is TemperatureControlTemplate -> controlTemplate.getTemplate() as ToggleTemplate
+            else -> {
+                Log.e(ControlsUiController.TAG, "Unsupported template type: $controlTemplate")
+                return
+            }
+        }
 
         val ld = cvh.layout.getBackground() as LayerDrawable
         clipLayer = ld.findDrawableByLayerId(R.id.clip_layer)
         clipLayer.level = MAX_LEVEL
 
         val checked = template.isChecked()
-        cvh.applyRenderInfo(checked)
+        cvh.applyRenderInfo(checked, colorOffset)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
index 3dc0ff3..1f0ca9b 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
@@ -25,11 +25,12 @@
 import android.os.Bundle
 import android.service.controls.Control
 import android.service.controls.actions.FloatAction
+import android.service.controls.templates.ControlTemplate
 import android.service.controls.templates.RangeTemplate
+import android.service.controls.templates.TemperatureControlTemplate
 import android.service.controls.templates.ToggleRangeTemplate
 import android.util.Log
 import android.util.MathUtils
-import android.util.TypedValue
 import android.view.GestureDetector
 import android.view.GestureDetector.SimpleOnGestureListener
 import android.view.MotionEvent
@@ -37,24 +38,29 @@
 import android.view.ViewGroup
 import android.view.accessibility.AccessibilityEvent
 import android.view.accessibility.AccessibilityNodeInfo
-import android.widget.TextView
 import com.android.systemui.Interpolators
 import com.android.systemui.R
 import com.android.systemui.controls.ui.ControlViewHolder.Companion.MAX_LEVEL
 import com.android.systemui.controls.ui.ControlViewHolder.Companion.MIN_LEVEL
 import java.util.IllegalFormatException
 
+/**
+ * Supports [ToggleRangeTemplate] and [RangeTemplate], as well as when one of those templates is
+ * defined as the subtemplate in [TemperatureControlTemplate].
+ */
 class ToggleRangeBehavior : Behavior {
     private var rangeAnimator: ValueAnimator? = null
     lateinit var clipLayer: Drawable
-    lateinit var template: ToggleRangeTemplate
+    lateinit var templateId: String
     lateinit var control: Control
     lateinit var cvh: ControlViewHolder
     lateinit var rangeTemplate: RangeTemplate
-    lateinit var status: TextView
     lateinit var context: Context
     var currentStatusText: CharSequence = ""
     var currentRangeValue: String = ""
+    var isChecked: Boolean = false
+    var isToggleable: Boolean = false
+    var colorOffset: Int = 0
 
     companion object {
         private const val DEFAULT_FORMAT = "%.1f"
@@ -62,10 +68,7 @@
 
     override fun initialize(cvh: ControlViewHolder) {
         this.cvh = cvh
-        status = cvh.status
-        context = status.getContext()
-
-        cvh.applyRenderInfo(false /* enabled */, 0 /* offset */, false /* animated */)
+        context = cvh.context
 
         val gestureListener = ToggleRangeGestureListener(cvh.layout)
         val gestureDetector = GestureDetector(context, gestureListener)
@@ -86,11 +89,42 @@
         }
     }
 
-    override fun bind(cws: ControlWithState) {
+    private fun setup(template: ToggleRangeTemplate) {
+        rangeTemplate = template.getRange()
+        isToggleable = true
+        isChecked = template.isChecked()
+    }
+
+    private fun setup(template: RangeTemplate) {
+        rangeTemplate = template
+
+        // only show disabled state when value is at the minimum
+        isChecked = rangeTemplate.currentValue != rangeTemplate.minValue
+    }
+
+    private fun setupTemplate(template: ControlTemplate): Boolean {
+        return when (template) {
+            is ToggleRangeTemplate -> {
+                setup(template)
+                true
+            }
+            is RangeTemplate -> {
+                setup(template)
+                true
+            }
+            is TemperatureControlTemplate -> setupTemplate(template.getTemplate())
+            else -> {
+                Log.e(ControlsUiController.TAG, "Unsupported template type: $template")
+                false
+            }
+        }
+    }
+
+    override fun bind(cws: ControlWithState, colorOffset: Int) {
         this.control = cws.control!!
+        this.colorOffset = colorOffset
 
         currentStatusText = control.getStatusText()
-        status.setText(currentStatusText)
 
         // ControlViewHolder sets a long click listener, but we want to handle touch in
         // here instead, otherwise we'll have state conflicts.
@@ -99,13 +133,14 @@
         val ld = cvh.layout.getBackground() as LayerDrawable
         clipLayer = ld.findDrawableByLayerId(R.id.clip_layer)
 
-        template = control.getControlTemplate() as ToggleRangeTemplate
-        rangeTemplate = template.getRange()
+        val template = control.getControlTemplate()
+        if (!setupTemplate(template)) return
+        templateId = template.getTemplateId()
 
-        val checked = template.isChecked()
-        updateRange(rangeToLevelValue(rangeTemplate.currentValue), checked, /* isDragging */ false)
+        updateRange(rangeToLevelValue(rangeTemplate.currentValue), isChecked,
+            /* isDragging */ false)
 
-        cvh.applyRenderInfo(checked)
+        cvh.applyRenderInfo(isChecked, colorOffset)
 
         /*
          * This is custom widget behavior, so add a new accessibility delegate to
@@ -141,9 +176,12 @@
             ): Boolean {
                 val handled = when (action) {
                     AccessibilityNodeInfo.ACTION_CLICK -> {
-                        cvh.controlActionCoordinator.toggle(cvh, template.getTemplateId(),
-                            template.isChecked())
-                        true
+                        if (!isToggleable) {
+                            false
+                        } else {
+                            cvh.controlActionCoordinator.toggle(cvh, templateId, isChecked)
+                            true
+                        }
                     }
                     AccessibilityNodeInfo.ACTION_LONG_CLICK -> {
                         cvh.controlActionCoordinator.longPress(cvh)
@@ -157,7 +195,7 @@
                             val value = arguments.getFloat(
                                 AccessibilityNodeInfo.ACTION_ARGUMENT_PROGRESS_VALUE)
                             val level = rangeToLevelValue(value)
-                            updateRange(level, template.isChecked(), /* isDragging */ true)
+                            updateRange(level, isChecked, /* isDragging */ true)
                             endUpdateRange()
                             true
                         }
@@ -177,12 +215,19 @@
     }
 
     fun beginUpdateRange() {
-        status.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
+        cvh.setStatusTextSize(context.getResources()
                 .getDimensionPixelSize(R.dimen.control_status_expanded).toFloat())
     }
 
     fun updateRange(level: Int, checked: Boolean, isDragging: Boolean) {
-        val newLevel = if (checked) Math.max(MIN_LEVEL, Math.min(MAX_LEVEL, level)) else MIN_LEVEL
+        val newLevel = Math.max(MIN_LEVEL, Math.min(MAX_LEVEL, level))
+
+        // If the current level is at the minimum and the user is dragging, set the control to
+        // the enabled state to indicate their intention to enable the device. This will update
+        // control colors to support dragging.
+        if (clipLayer.level == MIN_LEVEL && newLevel > MIN_LEVEL) {
+            cvh.applyRenderInfo(checked, colorOffset, false /* animated */)
+        }
 
         rangeAnimator?.cancel()
         if (isDragging) {
@@ -209,14 +254,13 @@
             val newValue = levelToRangeValue(newLevel)
             currentRangeValue = format(rangeTemplate.getFormatString().toString(),
                     DEFAULT_FORMAT, newValue)
-            val text = if (isDragging) {
-                currentRangeValue
+            if (isDragging) {
+                cvh.setStatusText(currentRangeValue, /* immediately */ true)
             } else {
-                "$currentStatusText $currentRangeValue"
+                cvh.setStatusText("$currentStatusText $currentRangeValue")
             }
-            status.setText(text)
         } else {
-            status.setText(currentStatusText)
+            cvh.setStatusText(currentStatusText)
         }
     }
 
@@ -244,9 +288,9 @@
     }
 
     fun endUpdateRange() {
-        status.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
+        cvh.setStatusTextSize(context.getResources()
                 .getDimensionPixelSize(R.dimen.control_status_normal).toFloat())
-        status.setText("$currentStatusText $currentRangeValue")
+        cvh.setStatusText("$currentStatusText $currentRangeValue", /* immediately */ true)
         cvh.action(FloatAction(rangeTemplate.getTemplateId(),
             findNearestStep(levelToRangeValue(clipLayer.getLevel()))))
     }
@@ -282,7 +326,7 @@
             if (isDragging) {
                 return
             }
-            cvh.controlActionCoordinator.longPress(this@ToggleRangeBehavior.cvh)
+            cvh.controlActionCoordinator.longPress(cvh)
         }
 
         override fun onScroll(
@@ -291,26 +335,21 @@
             xDiff: Float,
             yDiff: Float
         ): Boolean {
-            if (!template.isChecked) {
-                return false
-            }
             if (!isDragging) {
                 v.getParent().requestDisallowInterceptTouchEvent(true)
-                this@ToggleRangeBehavior.beginUpdateRange()
+                beginUpdateRange()
                 isDragging = true
             }
 
             val ratioDiff = -xDiff / v.width
             val changeAmount = ((MAX_LEVEL - MIN_LEVEL) * ratioDiff).toInt()
-            this@ToggleRangeBehavior.updateRange(clipLayer.level + changeAmount,
-                    checked = true, isDragging = true)
+            updateRange(clipLayer.level + changeAmount, checked = true, isDragging = true)
             return true
         }
 
         override fun onSingleTapUp(e: MotionEvent): Boolean {
-            val th = this@ToggleRangeBehavior
-            cvh.controlActionCoordinator.toggle(th.cvh, th.template.getTemplateId(),
-                    th.template.isChecked())
+            if (!isToggleable) return false
+            cvh.controlActionCoordinator.toggle(cvh, templateId, isChecked)
             return true
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/TouchBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/TouchBehavior.kt
index 7ae3df7..48f9458 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/TouchBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/TouchBehavior.kt
@@ -23,6 +23,7 @@
 import android.service.controls.templates.ControlTemplate
 
 import com.android.systemui.R
+import com.android.systemui.controls.ui.ControlViewHolder.Companion.MAX_LEVEL
 import com.android.systemui.controls.ui.ControlViewHolder.Companion.MIN_LEVEL
 
 /**
@@ -37,22 +38,22 @@
 
     override fun initialize(cvh: ControlViewHolder) {
         this.cvh = cvh
-        cvh.applyRenderInfo(false /* enabled */, 0 /* offset */, false /* animated */)
 
         cvh.layout.setOnClickListener(View.OnClickListener() {
             cvh.controlActionCoordinator.touch(cvh, template.getTemplateId(), control)
         })
     }
 
-    override fun bind(cws: ControlWithState) {
+    override fun bind(cws: ControlWithState, colorOffset: Int) {
         this.control = cws.control!!
-        cvh.status.setText(control.getStatusText())
+        cvh.setStatusText(control.getStatusText())
         template = control.getControlTemplate()
 
         val ld = cvh.layout.getBackground() as LayerDrawable
         clipLayer = ld.findDrawableByLayerId(R.id.clip_layer)
-        clipLayer.setLevel(MIN_LEVEL)
 
-        cvh.applyRenderInfo(false)
+        val enabled = if (colorOffset > 0) true else false
+        clipLayer.setLevel(if (enabled) MAX_LEVEL else MIN_LEVEL)
+        cvh.applyRenderInfo(enabled, colorOffset)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/Vibrations.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/Vibrations.kt
index a97113c..c0f6aab 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/Vibrations.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/Vibrations.kt
@@ -20,7 +20,7 @@
 import android.os.VibrationEffect.Composition.PRIMITIVE_TICK
 
 object Vibrations {
-    private const val TOGGLE_TICK_COUNT = 12
+    private const val TOGGLE_TICK_COUNT = 40
 
     val toggleOnEffect = initToggleOnEffect()
     val toggleOffEffect = initToggleOffEffect()
@@ -29,6 +29,7 @@
 
     private fun initToggleOnEffect(): VibrationEffect {
         val composition = VibrationEffect.startComposition()
+        composition.addPrimitive(PRIMITIVE_TICK, 0.05f, 200)
         var i = 0
         while (i++ < TOGGLE_TICK_COUNT) {
             composition.addPrimitive(PRIMITIVE_TICK, 0.05f, 0)
@@ -43,7 +44,7 @@
         composition.addPrimitive(PRIMITIVE_TICK, 0.05f, 100)
         var i = 0
         while (i++ < TOGGLE_TICK_COUNT) {
-            composition?.addPrimitive(PRIMITIVE_TICK, 0.05f, 0)
+            composition.addPrimitive(PRIMITIVE_TICK, 0.05f, 0)
         }
         return composition.compose()
     }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
index 82ccb17..e2a6d6c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
@@ -21,7 +21,6 @@
 import com.android.systemui.appops.AppOpsControllerImpl;
 import com.android.systemui.classifier.FalsingManagerProxy;
 import com.android.systemui.controls.dagger.ControlsModule;
-import com.android.systemui.doze.DozeHost;
 import com.android.systemui.globalactions.GlobalActionsComponent;
 import com.android.systemui.globalactions.GlobalActionsImpl;
 import com.android.systemui.plugins.ActivityStarter;
@@ -38,7 +37,6 @@
 import com.android.systemui.statusbar.StatusBarStateControllerImpl;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
-import com.android.systemui.statusbar.phone.DozeServiceHost;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
 import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -259,11 +257,6 @@
     /**
      */
     @Binds
-    public abstract DozeHost provideDozeHost(DozeServiceHost dozeServiceHost);
-
-    /**
-     */
-    @Binds
     public abstract VolumeComponent provideVolumeComponent(
             VolumeDialogComponent volumeDialogComponent);
 
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
index 2b27436..3a8212c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
@@ -39,6 +39,7 @@
 import android.hardware.SensorPrivacyManager;
 import android.hardware.display.DisplayManager;
 import android.media.AudioManager;
+import android.media.MediaRouter2Manager;
 import android.net.ConnectivityManager;
 import android.net.NetworkScoreManager;
 import android.net.wifi.WifiManager;
@@ -211,6 +212,11 @@
     }
 
     @Provides
+    static MediaRouter2Manager provideMediaRouter2Manager(Context context) {
+        return MediaRouter2Manager.getInstance(context);
+    }
+
+    @Provides
     @Singleton
     static NetworkScoreManager provideNetworkScoreManager(Context context) {
         return context.getSystemService(NetworkScoreManager.class);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index 6d1bf72..3bb953a 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -31,6 +31,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.dock.DockManagerImpl;
+import com.android.systemui.doze.DozeHost;
 import com.android.systemui.plugins.qs.QSFactory;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.power.EnhancedEstimates;
@@ -43,6 +44,7 @@
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.phone.DozeServiceHost;
 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
@@ -148,4 +150,7 @@
     @Binds
     abstract KeyguardViewController bindKeyguardViewController(
             StatusBarKeyguardViewManager statusBarKeyguardViewManager);
+
+    @Binds
+    abstract DozeHost provideDozeHost(DozeServiceHost dozeServiceHost);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 8117bbb..6572937 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -33,8 +33,8 @@
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.statusbar.phone.BiometricUnlockController;
 import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.DozeServiceHost;
 import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.sensors.AsyncSensorManager;
 import com.android.systemui.util.sensors.ProximitySensor;
 import com.android.systemui.util.wakelock.DelayedWakeLock;
@@ -57,9 +57,10 @@
     private final ProximitySensor mProximitySensor;
     private final DelayedWakeLock.Builder mDelayedWakeLockBuilder;
     private final Handler mHandler;
+    private final DelayableExecutor mDelayableExecutor;
     private final BiometricUnlockController mBiometricUnlockController;
     private final BroadcastDispatcher mBroadcastDispatcher;
-    private final DozeServiceHost mDozeServiceHost;
+    private final DozeHost mDozeHost;
 
     @Inject
     public DozeFactory(FalsingManager falsingManager, DozeLog dozeLog,
@@ -69,8 +70,9 @@
             DockManager dockManager, @Nullable IWallpaperManager wallpaperManager,
             ProximitySensor proximitySensor,
             DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler,
+            DelayableExecutor delayableExecutor,
             BiometricUnlockController biometricUnlockController,
-            BroadcastDispatcher broadcastDispatcher, DozeServiceHost dozeServiceHost) {
+            BroadcastDispatcher broadcastDispatcher, DozeHost dozeHost) {
         mFalsingManager = falsingManager;
         mDozeLog = dozeLog;
         mDozeParameters = dozeParameters;
@@ -84,9 +86,10 @@
         mProximitySensor = proximitySensor;
         mDelayedWakeLockBuilder = delayedWakeLockBuilder;
         mHandler = handler;
+        mDelayableExecutor = delayableExecutor;
         mBiometricUnlockController = biometricUnlockController;
         mBroadcastDispatcher = broadcastDispatcher;
-        mDozeServiceHost = dozeServiceHost;
+        mDozeHost = dozeHost;
     }
 
     /** Creates a DozeMachine with its parts for {@code dozeService}. */
@@ -95,7 +98,7 @@
         WakeLock wakeLock = mDelayedWakeLockBuilder.setHandler(mHandler).setTag("Doze").build();
 
         DozeMachine.Service wrappedService = dozeService;
-        wrappedService = new DozeBrightnessHostForwarder(wrappedService, mDozeServiceHost);
+        wrappedService = new DozeBrightnessHostForwarder(wrappedService, mDozeHost);
         wrappedService = DozeScreenStatePreventingAdapter.wrapIfNeeded(
                 wrappedService, mDozeParameters);
         wrappedService = DozeSuspendScreenStatePreventingAdapter.wrapIfNeeded(
@@ -103,19 +106,19 @@
 
         DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock,
                 mWakefulnessLifecycle, mBatteryController, mDozeLog, mDockManager,
-                mDozeServiceHost);
+                mDozeHost);
         machine.setParts(new DozeMachine.Part[]{
                 new DozePauser(mHandler, machine, mAlarmManager, mDozeParameters.getPolicy()),
                 new DozeFalsingManagerAdapter(mFalsingManager),
-                createDozeTriggers(dozeService, mAsyncSensorManager, mDozeServiceHost,
-                        mAlarmManager, config, mDozeParameters, mHandler, wakeLock, machine,
-                        mDockManager, mDozeLog),
-                createDozeUi(dozeService, mDozeServiceHost, wakeLock, machine, mHandler,
+                createDozeTriggers(dozeService, mAsyncSensorManager, mDozeHost,
+                        mAlarmManager, config, mDozeParameters, mDelayableExecutor, wakeLock,
+                        machine, mDockManager, mDozeLog),
+                createDozeUi(dozeService, mDozeHost, wakeLock, machine, mHandler,
                         mAlarmManager, mDozeParameters, mDozeLog),
-                new DozeScreenState(wrappedService, mHandler, mDozeServiceHost, mDozeParameters,
+                new DozeScreenState(wrappedService, mHandler, mDozeHost, mDozeParameters,
                         wakeLock),
                 createDozeScreenBrightness(dozeService, wrappedService, mAsyncSensorManager,
-                        mDozeServiceHost, mDozeParameters, mHandler),
+                        mDozeHost, mDozeParameters, mHandler),
                 new DozeWallpaperState(mWallpaperManager, mBiometricUnlockController,
                         mDozeParameters),
                 new DozeDockHandler(config, machine, mDockManager),
@@ -136,11 +139,11 @@
 
     private DozeTriggers createDozeTriggers(Context context, AsyncSensorManager sensorManager,
             DozeHost host, AlarmManager alarmManager, AmbientDisplayConfiguration config,
-            DozeParameters params, Handler handler, WakeLock wakeLock, DozeMachine machine,
-            DockManager dockManager, DozeLog dozeLog) {
+            DozeParameters params, DelayableExecutor delayableExecutor, WakeLock wakeLock,
+            DozeMachine machine, DockManager dockManager, DozeLog dozeLog) {
         boolean allowPulseTriggers = true;
         return new DozeTriggers(context, machine, host, alarmManager, config, params,
-                sensorManager, handler, wakeLock, allowPulseTriggers, dockManager,
+                sensorManager, delayableExecutor, wakeLock, allowPulseTriggers, dockManager,
                 mProximitySensor, dozeLog, mBroadcastDispatcher);
 
     }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index e1081cd..78f8f67 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -101,7 +101,8 @@
 
     public DozeSensors(Context context, AlarmManager alarmManager, AsyncSensorManager sensorManager,
             DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock,
-            Callback callback, Consumer<Boolean> proxCallback, DozeLog dozeLog) {
+            Callback callback, Consumer<Boolean> proxCallback, DozeLog dozeLog,
+            ProximitySensor proximitySensor) {
         mContext = context;
         mAlarmManager = alarmManager;
         mSensorManager = sensorManager;
@@ -111,6 +112,7 @@
         mProxCallback = proxCallback;
         mResolver = mContext.getContentResolver();
         mCallback = callback;
+        mProximitySensor = proximitySensor;
 
         boolean alwaysOn = mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT);
         mSensors = new TriggerSensor[] {
@@ -173,7 +175,6 @@
                         dozeLog),
         };
 
-        mProximitySensor = new ProximitySensor(context.getResources(), sensorManager);
         setProxListening(false);  // Don't immediately start listening when we register.
         mProximitySensor.register(
                 proximityEvent -> {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 3510e07..6a55014 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -26,7 +26,6 @@
 import android.content.res.Configuration;
 import android.hardware.display.AmbientDisplayConfiguration;
 import android.metrics.LogMaker;
-import android.os.Handler;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.text.format.Formatter;
@@ -43,6 +42,7 @@
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.Assert;
+import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.sensors.AsyncSensorManager;
 import com.android.systemui.util.sensors.ProximitySensor;
 import com.android.systemui.util.wakelock.WakeLock;
@@ -152,9 +152,9 @@
 
     public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost,
             AlarmManager alarmManager, AmbientDisplayConfiguration config,
-            DozeParameters dozeParameters, AsyncSensorManager sensorManager, Handler handler,
-            WakeLock wakeLock, boolean allowPulseTriggers, DockManager dockManager,
-            ProximitySensor proximitySensor,
+            DozeParameters dozeParameters, AsyncSensorManager sensorManager,
+            DelayableExecutor delayableExecutor, WakeLock wakeLock, boolean allowPulseTriggers,
+            DockManager dockManager, ProximitySensor proximitySensor,
             DozeLog dozeLog, BroadcastDispatcher broadcastDispatcher) {
         mContext = context;
         mMachine = machine;
@@ -165,10 +165,10 @@
         mWakeLock = wakeLock;
         mAllowPulseTriggers = allowPulseTriggers;
         mDozeSensors = new DozeSensors(context, alarmManager, mSensorManager, dozeParameters,
-                config, wakeLock, this::onSensor, this::onProximityFar, dozeLog);
+                config, wakeLock, this::onSensor, this::onProximityFar, dozeLog, proximitySensor);
         mUiModeManager = mContext.getSystemService(UiModeManager.class);
         mDockManager = dockManager;
-        mProxCheck = new ProximitySensor.ProximityCheck(proximitySensor, handler);
+        mProxCheck = new ProximitySensor.ProximityCheck(proximitySensor, delayableExecutor);
         mDozeLog = dozeLog;
         mBroadcastDispatcher = broadcastDispatcher;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt
new file mode 100644
index 0000000..fa951fa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dump
+
+import android.content.Context
+import android.os.SystemClock
+import android.os.Trace
+import com.android.systemui.R
+import com.android.systemui.dump.DumpHandler.Companion.PRIORITY_ARG_CRITICAL
+import com.android.systemui.dump.DumpHandler.Companion.PRIORITY_ARG_HIGH
+import com.android.systemui.dump.DumpHandler.Companion.PRIORITY_ARG_NORMAL
+import com.android.systemui.log.LogBuffer
+import java.io.FileDescriptor
+import java.io.PrintWriter
+import javax.inject.Inject
+
+/**
+ * Oversees SystemUI's output during bug reports (and dumpsys in general)
+ *
+ * Dump output is split into two sections, CRITICAL and NORMAL. In general, the CRITICAL section
+ * contains all dumpables that were registered to the [DumpManager], while the NORMAL sections
+ * contains all [LogBuffer]s (due to their length).
+ *
+ * The CRITICAL and NORMAL sections can be found within a bug report by searching for
+ * "SERVICE com.android.systemui/.SystemUIService" and
+ * "SERVICE com.android.systemui/.dump.SystemUIAuxiliaryDumpService", respectively.
+ *
+ * Finally, some or all of the dump can be triggered on-demand via adb (see below).
+ *
+ * ```
+ * # For the following, let <invocation> be:
+ * $ adb shell dumpsys activity service com.android.systemui/.SystemUIService
+ *
+ * # To dump specific target(s), specify one or more registered names:
+ * $ <invocation> NotifCollection
+ * $ <invocation> StatusBar FalsingManager BootCompleteCacheImpl
+ *
+ * # Log buffers can be dumped in the same way (and can even be mixed in with other dump targets,
+ * # although it's not clear why one would want such a thing):
+ * $ <invocation> NotifLog
+ * $ <invocation> StatusBar NotifLog BootCompleteCacheImpl
+ *
+ * # If passing -t or --tail, shows only the last N lines of any log buffers:
+ * $ <invocation> NotifLog --tail 100
+ *
+ * # Dump targets are matched using String.endsWith(), so dumpables that register using their
+ * # fully-qualified class name can still be dumped using their short name:
+ * $ <invocation> com.android.keyguard.KeyguardUpdateMonitor
+ * $ <invocation> keyguard.KeyguardUpdateMonitor
+ * $ <invocation> KeyguardUpdateMonitor
+ *
+ * # To dump all dumpables or all buffers:
+ * $ <invocation> dumpables
+ * $ <invocation> buffers
+ *
+ * # Finally, the following will simulate what we dump during the CRITICAL and NORMAL sections of a
+ * # bug report:
+ * $ <invocation> bugreport-critical
+ * $ <invocation> bugreport-normal
+ *
+ * # And if you need to be reminded of this list of commands:
+ * $ <invocation> -h
+ * $ <invocation> --help
+ * ```
+ */
+class DumpHandler @Inject constructor(
+    private val context: Context,
+    private val dumpManager: DumpManager,
+    private val logBufferEulogizer: LogBufferEulogizer
+) {
+    /**
+     * Dump the diagnostics! Behavior can be controlled via [args].
+     */
+    fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) {
+        Trace.beginSection("DumpManager#dump()")
+        val start = SystemClock.uptimeMillis()
+
+        val parsedArgs = try {
+            parseArgs(args)
+        } catch (e: ArgParseException) {
+            pw.println(e.message)
+            return
+        }
+
+        when (parsedArgs.dumpPriority) {
+            PRIORITY_ARG_CRITICAL -> dumpCritical(fd, pw, parsedArgs)
+            PRIORITY_ARG_NORMAL -> dumpNormal(pw, parsedArgs)
+            else -> dumpParameterized(fd, pw, parsedArgs)
+        }
+
+        pw.println()
+        pw.println("Dump took ${SystemClock.uptimeMillis() - start}ms")
+        Trace.endSection()
+    }
+
+    private fun dumpParameterized(fd: FileDescriptor, pw: PrintWriter, args: ParsedArgs) {
+        when (args.command) {
+            "bugreport-critical" -> dumpCritical(fd, pw, args)
+            "bugreport-normal" -> dumpNormal(pw, args)
+            "dumpables" -> dumpDumpables(fd, pw, args)
+            "buffers" -> dumpBuffers(pw, args)
+            "config" -> dumpConfig(pw)
+            "help" -> dumpHelp(pw)
+            else -> dumpTargets(args.nonFlagArgs, fd, pw, args)
+        }
+    }
+
+    private fun dumpCritical(fd: FileDescriptor, pw: PrintWriter, args: ParsedArgs) {
+        dumpManager.dumpDumpables(fd, pw, args.rawArgs)
+        dumpConfig(pw)
+    }
+
+    private fun dumpNormal(pw: PrintWriter, args: ParsedArgs) {
+        dumpManager.dumpBuffers(pw, args.tailLength)
+        logBufferEulogizer.readEulogyIfPresent(pw)
+    }
+
+    private fun dumpDumpables(fw: FileDescriptor, pw: PrintWriter, args: ParsedArgs) {
+        if (args.listOnly) {
+            dumpManager.listDumpables(pw)
+        } else {
+            dumpManager.dumpDumpables(fw, pw, args.rawArgs)
+        }
+    }
+
+    private fun dumpBuffers(pw: PrintWriter, args: ParsedArgs) {
+        if (args.listOnly) {
+            dumpManager.listBuffers(pw)
+        } else {
+            dumpManager.dumpBuffers(pw, args.tailLength)
+        }
+    }
+
+    private fun dumpTargets(
+        targets: List<String>,
+        fd: FileDescriptor,
+        pw: PrintWriter,
+        args: ParsedArgs
+    ) {
+        if (targets.isNotEmpty()) {
+            for (target in targets) {
+                dumpManager.dumpTarget(target, fd, pw, args.rawArgs, args.tailLength)
+            }
+        } else {
+            if (args.listOnly) {
+                pw.println("Dumpables:")
+                dumpManager.listDumpables(pw)
+                pw.println()
+
+                pw.println("Buffers:")
+                dumpManager.listBuffers(pw)
+            } else {
+                pw.println("Nothing to dump :(")
+            }
+        }
+    }
+
+    private fun dumpConfig(pw: PrintWriter) {
+        pw.println("SystemUiServiceComponents configuration:")
+        pw.print("vendor component: ")
+        pw.println(context.resources.getString(R.string.config_systemUIVendorServiceComponent))
+        dumpServiceList(pw, "global", R.array.config_systemUIServiceComponents)
+        dumpServiceList(pw, "per-user", R.array.config_systemUIServiceComponentsPerUser)
+    }
+
+    private fun dumpServiceList(pw: PrintWriter, type: String, resId: Int) {
+        val services: Array<String>? = context.resources.getStringArray(resId)
+        pw.print(type)
+        pw.print(": ")
+        if (services == null) {
+            pw.println("N/A")
+            return
+        }
+        pw.print(services.size)
+        pw.println(" services")
+        for (i in services.indices) {
+            pw.print("  ")
+            pw.print(i)
+            pw.print(": ")
+            pw.println(services[i])
+        }
+    }
+
+    private fun dumpHelp(pw: PrintWriter) {
+        pw.println("Let <invocation> be:")
+        pw.println("$ adb shell dumpsys activity service com.android.systemui/.SystemUIService")
+        pw.println()
+
+        pw.println("Most common usage:")
+        pw.println("$ <invocation> <targets>")
+        pw.println("$ <invocation> NotifLog")
+        pw.println("$ <invocation> StatusBar FalsingManager BootCompleteCacheImpl")
+        pw.println("etc.")
+        pw.println()
+
+        pw.println("Special commands:")
+        pw.println("$ <invocation> dumpables")
+        pw.println("$ <invocation> buffers")
+        pw.println("$ <invocation> bugreport-critical")
+        pw.println("$ <invocation> bugreport-normal")
+        pw.println()
+
+        pw.println("Targets can be listed:")
+        pw.println("$ <invocation> --list")
+        pw.println("$ <invocation> dumpables --list")
+        pw.println("$ <invocation> buffers --list")
+        pw.println()
+
+        pw.println("Show only the most recent N lines of buffers")
+        pw.println("$ <invocation> NotifLog --tail 30")
+    }
+
+    private fun parseArgs(args: Array<String>): ParsedArgs {
+        val mutArgs = args.toMutableList()
+        val pArgs = ParsedArgs(args, mutArgs)
+
+        val iterator = mutArgs.iterator()
+        while (iterator.hasNext()) {
+            val arg = iterator.next()
+            if (arg.startsWith("-")) {
+                iterator.remove()
+                when (arg) {
+                    PRIORITY_ARG -> {
+                        pArgs.dumpPriority = readArgument(iterator, PRIORITY_ARG) {
+                            if (PRIORITY_OPTIONS.contains(it)) {
+                                it
+                            } else {
+                                throw IllegalArgumentException()
+                            }
+                        }
+                    }
+                    "-t", "--tail" -> {
+                        pArgs.tailLength = readArgument(iterator, arg) {
+                            it.toInt()
+                        }
+                    }
+                    "-l", "--list" -> {
+                        pArgs.listOnly = true
+                    }
+                    "-h", "--help" -> {
+                        pArgs.command = "help"
+                    }
+                    else -> {
+                        throw ArgParseException("Unknown flag: $arg")
+                    }
+                }
+            }
+        }
+
+        if (pArgs.command == null && mutArgs.isNotEmpty() && COMMANDS.contains(mutArgs[0])) {
+            pArgs.command = mutArgs.removeAt(0)
+        }
+
+        return pArgs
+    }
+
+    private fun <T> readArgument(
+        iterator: MutableIterator<String>,
+        flag: String,
+        parser: (arg: String) -> T
+    ): T {
+        if (!iterator.hasNext()) {
+            throw ArgParseException("Missing argument for $flag")
+        }
+        val value = iterator.next()
+
+        return try {
+            parser(value).also { iterator.remove() }
+        } catch (e: Exception) {
+            throw ArgParseException("Invalid argument '$value' for flag $flag")
+        }
+    }
+
+    companion object {
+        const val PRIORITY_ARG = "--dump-priority"
+        const val PRIORITY_ARG_CRITICAL = "CRITICAL"
+        const val PRIORITY_ARG_HIGH = "HIGH"
+        const val PRIORITY_ARG_NORMAL = "NORMAL"
+    }
+}
+
+private val PRIORITY_OPTIONS =
+        arrayOf(PRIORITY_ARG_CRITICAL, PRIORITY_ARG_HIGH, PRIORITY_ARG_NORMAL)
+
+private val COMMANDS = arrayOf("bugreport-critical", "bugreport-normal", "buffers", "dumpables")
+
+private class ParsedArgs(
+    val rawArgs: Array<String>,
+    val nonFlagArgs: List<String>
+) {
+    var dumpPriority: String? = null
+    var tailLength: Int = 0
+    var command: String? = null
+    var listOnly = false
+}
+
+class ArgParseException(message: String) : Exception(message)
diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
index 59a7a32..a4141b1 100644
--- a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
@@ -16,15 +16,8 @@
 
 package com.android.systemui.dump
 
-import android.content.Context
-import android.os.SystemClock
-import android.os.Trace
 import android.util.ArrayMap
 import com.android.systemui.Dumpable
-import com.android.systemui.R
-import com.android.systemui.dump.DumpManager.Companion.PRIORITY_ARG_CRITICAL
-import com.android.systemui.dump.DumpManager.Companion.PRIORITY_ARG_HIGH
-import com.android.systemui.dump.DumpManager.Companion.PRIORITY_ARG_NORMAL
 import com.android.systemui.log.LogBuffer
 import java.io.FileDescriptor
 import java.io.PrintWriter
@@ -32,58 +25,16 @@
 import javax.inject.Singleton
 
 /**
- * Oversees SystemUI's output during bug reports (and dumpsys in general)
+ * Maintains a registry of things that should be dumped when a bug report is taken
  *
  * When a bug report is taken, SystemUI dumps various diagnostic information that we hope will be
  * useful for the eventual readers of the bug report. Code that wishes to participate in this dump
  * should register itself here.
  *
- * Dump output is split into two sections, CRITICAL and NORMAL. All dumpables registered via
- * [registerDumpable] appear in the CRITICAL section, while all [LogBuffer]s appear in the NORMAL
- * section (due to their length).
- *
- * The CRITICAL and NORMAL sections can be found within a bug report by searching for
- * "SERVICE com.android.systemui/.SystemUIService" and
- * "SERVICE com.android.systemui/.dump.SystemUIAuxiliaryDumpService", respectively.
- *
- * Finally, some or all of the dump can be triggered on-demand via adb (see below).
- *
- * ```
- * # For the following, let <invocation> be:
- * $ adb shell dumpsys activity service com.android.systemui/.SystemUIService
- *
- * # To dump specific target(s), specify one or more registered names:
- * $ <invocation> NotifCollection
- * $ <invocation> StatusBar FalsingManager BootCompleteCacheImpl
- *
- * # Log buffers can be dumped in the same way (and can even be mixed in with other dump targets,
- * # although it's not clear why one would want such a thing):
- * $ <invocation> NotifLog
- * $ <invocation> StatusBar NotifLog BootCompleteCacheImpl
- *
- * # If passing -t or --tail, shows only the last N lines of any log buffers:
- * $ <invocation> NotifLog --tail 100
- *
- * # Dump targets are matched using String.endsWith(), so dumpables that register using their
- * # fully-qualified class name can still be dumped using their short name:
- * $ <invocation> com.android.keyguard.KeyguardUpdateMonitor
- * $ <invocation> keyguard.KeyguardUpdateMonitor
- * $ <invocation> KeyguardUpdateMonitor
- *
- * # To dump all dumpables or all buffers:
- * $ <invocation> dumpables
- * $ <invocation> buffers
- *
- * Finally, the following will simulate what we dump during the CRITICAL and NORMAL sections of a
- * bug report:
- * $ <invocation> bugreport-critical
- * $ <invocation> bugreport-normal
- * ```
+ * See [DumpHandler] for more information on how and when this information is dumped.
  */
 @Singleton
-class DumpManager @Inject constructor(
-    private val context: Context
-) {
+class DumpManager @Inject constructor() {
     private val dumpables: MutableMap<String, RegisteredDumpable<Dumpable>> = ArrayMap()
     private val buffers: MutableMap<String, RegisteredDumpable<LogBuffer>> = ArrayMap()
 
@@ -97,10 +48,6 @@
      */
     @Synchronized
     fun registerDumpable(name: String, module: Dumpable) {
-        if (RESERVED_NAMES.contains(name)) {
-            throw IllegalArgumentException("'$name' is reserved")
-        }
-
         if (!canAssignToNameLocked(name, module)) {
             throw IllegalArgumentException("'$name' is already registered")
         }
@@ -128,76 +75,16 @@
     }
 
     /**
-     * Dump the diagnostics! Behavior can be controlled via [args].
+     * Dumps the first dumpable or buffer whose registered name ends with [target]
      */
     @Synchronized
-    fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) {
-        Trace.beginSection("DumpManager#dump()")
-        val start = SystemClock.uptimeMillis()
-
-        val parsedArgs = try {
-            parseArgs(args)
-        } catch (e: ArgParseException) {
-            pw.println(e.message)
-            return
-        }
-
-        when (parsedArgs.dumpPriority) {
-            PRIORITY_ARG_CRITICAL -> dumpCriticalLocked(fd, pw, parsedArgs)
-            PRIORITY_ARG_NORMAL -> dumpNormalLocked(pw, parsedArgs)
-            else -> dumpParameterizedLocked(fd, pw, parsedArgs)
-        }
-
-        pw.println()
-        pw.println("Dump took ${SystemClock.uptimeMillis() - start}ms")
-        Trace.endSection()
-    }
-
-    private fun dumpCriticalLocked(fd: FileDescriptor, pw: PrintWriter, args: ParsedArgs) {
-        dumpDumpablesLocked(fd, pw, args)
-        dumpConfig(pw)
-    }
-
-    private fun dumpNormalLocked(pw: PrintWriter, args: ParsedArgs) {
-        dumpBuffersLocked(pw, args)
-    }
-
-    private fun dumpParameterizedLocked(fd: FileDescriptor, pw: PrintWriter, args: ParsedArgs) {
-        when (args.command) {
-            "bugreport-critical" -> dumpCriticalLocked(fd, pw, args)
-            "bugreport-normal" -> dumpNormalLocked(pw, args)
-            "dumpables" -> dumpDumpablesLocked(fd, pw, args)
-            "buffers" -> dumpBuffersLocked(pw, args)
-            else -> dumpTargetsLocked(args.nonFlagArgs, fd, pw, args)
-        }
-    }
-
-    private fun dumpTargetsLocked(
-        targets: List<String>,
-        fd: FileDescriptor,
-        pw: PrintWriter,
-        args: ParsedArgs
-    ) {
-        if (targets.isEmpty()) {
-            pw.println("Nothing to dump :(")
-        } else {
-            for (target in targets) {
-                dumpTarget(target, fd, pw, args)
-            }
-        }
-    }
-
-    private fun dumpTarget(
+    fun dumpTarget(
         target: String,
         fd: FileDescriptor,
         pw: PrintWriter,
-        args: ParsedArgs
+        args: Array<String>,
+        tailLength: Int
     ) {
-        if (target == "config") {
-            dumpConfig(pw)
-            return
-        }
-
         for (dumpable in dumpables.values) {
             if (dumpable.name.endsWith(target)) {
                 dumpDumpable(dumpable, fd, pw, args)
@@ -207,21 +94,49 @@
 
         for (buffer in buffers.values) {
             if (buffer.name.endsWith(target)) {
-                dumpBuffer(buffer, pw, args)
+                dumpBuffer(buffer, pw, tailLength)
                 return
             }
         }
     }
 
-    private fun dumpDumpablesLocked(fd: FileDescriptor, pw: PrintWriter, args: ParsedArgs) {
+    /**
+     * Dumps all registered dumpables to [pw]
+     */
+    @Synchronized
+    fun dumpDumpables(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) {
         for (module in dumpables.values) {
             dumpDumpable(module, fd, pw, args)
         }
     }
 
-    private fun dumpBuffersLocked(pw: PrintWriter, args: ParsedArgs) {
+    /**
+     * Dumps the names of all registered dumpables (one per line)
+     */
+    @Synchronized
+    fun listDumpables(pw: PrintWriter) {
+        for (module in dumpables.values) {
+            pw.println(module.name)
+        }
+    }
+
+    /**
+     * Dumps all registered [LogBuffer]s to [pw]
+     */
+    @Synchronized
+    fun dumpBuffers(pw: PrintWriter, tailLength: Int) {
         for (buffer in buffers.values) {
-            dumpBuffer(buffer, pw, args)
+            dumpBuffer(buffer, pw, tailLength)
+        }
+    }
+
+    /**
+     * Dumps the names of all registered buffers (one per line)
+     */
+    @Synchronized
+    fun listBuffers(pw: PrintWriter) {
+        for (buffer in buffers.values) {
+            pw.println(buffer.name)
         }
     }
 
@@ -229,139 +144,33 @@
         dumpable: RegisteredDumpable<Dumpable>,
         fd: FileDescriptor,
         pw: PrintWriter,
-        args: ParsedArgs
+        args: Array<String>
     ) {
         pw.println()
         pw.println("${dumpable.name}:")
         pw.println("----------------------------------------------------------------------------")
-        dumpable.dumpable.dump(fd, pw, args.rawArgs)
+        dumpable.dumpable.dump(fd, pw, args)
     }
 
     private fun dumpBuffer(
         buffer: RegisteredDumpable<LogBuffer>,
         pw: PrintWriter,
-        args: ParsedArgs
+        tailLength: Int
     ) {
         pw.println()
         pw.println()
         pw.println("BUFFER ${buffer.name}:")
         pw.println("============================================================================")
-        buffer.dumpable.dump(pw, args.tailLength)
-    }
-
-    private fun dumpConfig(pw: PrintWriter) {
-        pw.println("SystemUiServiceComponents configuration:")
-        pw.print("vendor component: ")
-        pw.println(context.resources.getString(R.string.config_systemUIVendorServiceComponent))
-        dumpServiceList(pw, "global", R.array.config_systemUIServiceComponents)
-        dumpServiceList(pw, "per-user", R.array.config_systemUIServiceComponentsPerUser)
-    }
-
-    private fun dumpServiceList(pw: PrintWriter, type: String, resId: Int) {
-        val services: Array<String>? = context.resources.getStringArray(resId)
-        pw.print(type)
-        pw.print(": ")
-        if (services == null) {
-            pw.println("N/A")
-            return
-        }
-        pw.print(services.size)
-        pw.println(" services")
-        for (i in services.indices) {
-            pw.print("  ")
-            pw.print(i)
-            pw.print(": ")
-            pw.println(services[i])
-        }
-    }
-
-    private fun parseArgs(args: Array<String>): ParsedArgs {
-        val mutArgs = args.toMutableList()
-        val pArgs = ParsedArgs(args, mutArgs)
-
-        val iterator = mutArgs.iterator()
-        while (iterator.hasNext()) {
-            val arg = iterator.next()
-            if (arg.startsWith("-")) {
-                iterator.remove()
-                when (arg) {
-                    PRIORITY_ARG -> {
-                        pArgs.dumpPriority = readArgument(iterator, PRIORITY_ARG) {
-                            if (PRIORITY_OPTIONS.contains(it)) {
-                                it
-                            } else {
-                                throw IllegalArgumentException()
-                            }
-                        }
-                    }
-                    "-t", "--tail" -> {
-                        pArgs.tailLength = readArgument(iterator, "--tail") {
-                            it.toInt()
-                        }
-                    }
-                    else -> {
-                        throw ArgParseException("Unknown flag: $arg")
-                    }
-                }
-            }
-        }
-
-        if (mutArgs.isNotEmpty() && COMMANDS.contains(mutArgs[0])) {
-            pArgs.command = mutArgs.removeAt(0)
-        }
-
-        return pArgs
-    }
-
-    private fun <T> readArgument(
-        iterator: MutableIterator<String>,
-        flag: String,
-        parser: (arg: String) -> T
-    ): T {
-        if (!iterator.hasNext()) {
-            throw ArgParseException("Missing argument for $flag")
-        }
-        val value = iterator.next()
-
-        return try {
-            parser(value).also { iterator.remove() }
-        } catch (e: Exception) {
-            throw ArgParseException("Invalid argument '$value' for flag $flag")
-        }
+        buffer.dumpable.dump(pw, tailLength)
     }
 
     private fun canAssignToNameLocked(name: String, newDumpable: Any): Boolean {
         val existingDumpable = dumpables[name]?.dumpable ?: buffers[name]?.dumpable
         return existingDumpable == null || newDumpable == existingDumpable
     }
-
-    companion object {
-        const val PRIORITY_ARG = "--dump-priority"
-        const val PRIORITY_ARG_CRITICAL = "CRITICAL"
-        const val PRIORITY_ARG_HIGH = "HIGH"
-        const val PRIORITY_ARG_NORMAL = "NORMAL"
-    }
 }
 
-private val PRIORITY_OPTIONS =
-        arrayOf(PRIORITY_ARG_CRITICAL, PRIORITY_ARG_HIGH, PRIORITY_ARG_NORMAL)
-
-private val COMMANDS = arrayOf("bugreport-critical", "bugreport-normal", "buffers", "dumpables")
-
-private val RESERVED_NAMES = arrayOf("config", *COMMANDS)
-
 private data class RegisteredDumpable<T>(
     val name: String,
     val dumpable: T
 )
-
-private class ParsedArgs(
-    val rawArgs: Array<String>,
-    val nonFlagArgs: List<String>
-) {
-    var dumpPriority: String? = null
-    var tailLength: Int = 0
-    var command: String? = null
-}
-
-class ArgParseException(message: String) : Exception(message)
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt b/packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
new file mode 100644
index 0000000..603cb67
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dump
+
+import android.content.Context
+import android.util.Log
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.util.io.Files
+import com.android.systemui.util.time.SystemClock
+import java.io.IOException
+import java.io.PrintWriter
+import java.io.UncheckedIOException
+import java.nio.file.Path
+import java.nio.file.Paths
+import java.nio.file.StandardOpenOption.CREATE
+import java.nio.file.StandardOpenOption.TRUNCATE_EXISTING
+import java.nio.file.attribute.BasicFileAttributes
+import java.text.SimpleDateFormat
+import java.util.Locale
+import java.util.concurrent.TimeUnit
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * Dumps all [LogBuffer]s to a file
+ *
+ * Intended for emergencies, i.e. we're about to crash. This file can then be read at a later date
+ * (usually in a bug report).
+ */
+@Singleton
+class LogBufferEulogizer(
+    private val dumpManager: DumpManager,
+    private val systemClock: SystemClock,
+    private val files: Files,
+    private val logPath: Path,
+    private val minWriteGap: Long,
+    private val maxLogAgeToDump: Long
+) {
+    @Inject constructor(
+        context: Context,
+        dumpManager: DumpManager,
+        systemClock: SystemClock,
+        files: Files
+    ) : this(
+        dumpManager,
+        systemClock,
+        files,
+        Paths.get(context.filesDir.toPath().toString(), "log_buffers.txt"),
+        MIN_WRITE_GAP,
+        MAX_AGE_TO_DUMP
+    )
+
+    /**
+     * Dumps all active log buffers to a file
+     *
+     * The file will be prefaced by the [reason], which will then be returned (presumably so it can
+     * be thrown).
+     */
+    fun <T : Exception> record(reason: T): T {
+        val start = systemClock.uptimeMillis()
+        var duration = 0L
+
+        Log.i(TAG, "Performing emergency dump of log buffers")
+
+        val millisSinceLastWrite = getMillisSinceLastWrite(logPath)
+        if (millisSinceLastWrite < minWriteGap) {
+            Log.w(TAG, "Cannot dump logs, last write was only $millisSinceLastWrite ms ago")
+            return reason
+        }
+
+        try {
+            val writer = files.newBufferedWriter(logPath, CREATE, TRUNCATE_EXISTING)
+            writer.use { out ->
+                val pw = PrintWriter(out)
+
+                pw.println(DATE_FORMAT.format(systemClock.currentTimeMillis()))
+                pw.println()
+                pw.println("Dump triggered by exception:")
+                reason.printStackTrace(pw)
+                dumpManager.dumpBuffers(pw, 0)
+                duration = systemClock.uptimeMillis() - start
+                pw.println()
+                pw.println("Buffer eulogy took ${duration}ms")
+            }
+        } catch (e: Exception) {
+            Log.e(TAG, "Exception while attempting to dump buffers, bailing", e)
+        }
+
+        Log.i(TAG, "Buffer eulogy took ${duration}ms")
+
+        return reason
+    }
+
+    /**
+     * If a eulogy file is present, writes its contents to [pw].
+     */
+    fun readEulogyIfPresent(pw: PrintWriter) {
+        try {
+            val millisSinceLastWrite = getMillisSinceLastWrite(logPath)
+            if (millisSinceLastWrite > maxLogAgeToDump) {
+                Log.i(TAG, "Not eulogizing buffers; they are " +
+                        TimeUnit.HOURS.convert(millisSinceLastWrite, TimeUnit.MILLISECONDS) +
+                        " hours old")
+                return
+            }
+
+            files.lines(logPath).use { s ->
+                pw.println()
+                pw.println()
+                pw.println("=============== BUFFERS FROM MOST RECENT CRASH ===============")
+                s.forEach { line ->
+                    pw.println(line)
+                }
+            }
+        } catch (e: IOException) {
+            // File doesn't exist, okay
+        } catch (e: UncheckedIOException) {
+            Log.e(TAG, "UncheckedIOException while dumping the core", e)
+        }
+    }
+
+    private fun getMillisSinceLastWrite(path: Path): Long {
+        val stats = try {
+            files.readAttributes(path, BasicFileAttributes::class.java)
+        } catch (e: IOException) {
+            // File doesn't exist
+            null
+        }
+        return systemClock.currentTimeMillis() - (stats?.lastModifiedTime()?.toMillis() ?: 0)
+    }
+}
+
+private const val TAG = "BufferEulogizer"
+private val MIN_WRITE_GAP = TimeUnit.MINUTES.toMillis(5)
+private val MAX_AGE_TO_DUMP = TimeUnit.HOURS.toMillis(48)
+private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/dump/SystemUIAuxiliaryDumpService.java b/packages/SystemUI/src/com/android/systemui/dump/SystemUIAuxiliaryDumpService.java
index 431cd63..da983ab 100644
--- a/packages/SystemUI/src/com/android/systemui/dump/SystemUIAuxiliaryDumpService.java
+++ b/packages/SystemUI/src/com/android/systemui/dump/SystemUIAuxiliaryDumpService.java
@@ -35,11 +35,11 @@
  * all other services.
  */
 public class SystemUIAuxiliaryDumpService extends Service {
-    private final DumpManager mDumpManager;
+    private final DumpHandler mDumpHandler;
 
     @Inject
-    public SystemUIAuxiliaryDumpService(DumpManager dumpManager) {
-        mDumpManager = dumpManager;
+    public SystemUIAuxiliaryDumpService(DumpHandler dumpHandler) {
+        mDumpHandler = dumpHandler;
     }
 
     @Override
@@ -50,9 +50,9 @@
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         // Simulate the NORMAL priority arg being passed to us
-        mDumpManager.dump(
+        mDumpHandler.dump(
                 fd,
                 pw,
-                new String[] { DumpManager.PRIORITY_ARG, DumpManager.PRIORITY_ARG_NORMAL });
+                new String[] { DumpHandler.PRIORITY_ARG, DumpHandler.PRIORITY_ARG_NORMAL });
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index e02b1ec..ac289cb 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -23,6 +23,7 @@
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_GLOBAL_ACTIONS_SHOWING;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -69,6 +70,9 @@
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
+import android.transition.AutoTransition;
+import android.transition.TransitionManager;
+import android.transition.TransitionSet;
 import android.util.ArraySet;
 import android.util.FeatureFlagUtils;
 import android.util.Log;
@@ -121,13 +125,12 @@
 import com.android.systemui.controls.ui.ControlsUiController;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
 import com.android.systemui.plugins.GlobalActionsPanelPlugin;
-import com.android.systemui.statusbar.BlurUtils;
 import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
-import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.EmergencyDialerConstants;
@@ -161,19 +164,19 @@
     /* Valid settings for global actions keys.
      * see config.xml config_globalActionList */
     @VisibleForTesting
-    protected static final String GLOBAL_ACTION_KEY_POWER = "power";
-    protected static final String GLOBAL_ACTION_KEY_AIRPLANE = "airplane";
-    protected static final String GLOBAL_ACTION_KEY_BUGREPORT = "bugreport";
-    protected static final String GLOBAL_ACTION_KEY_SILENT = "silent";
-    protected static final String GLOBAL_ACTION_KEY_USERS = "users";
-    protected static final String GLOBAL_ACTION_KEY_SETTINGS = "settings";
-    protected static final String GLOBAL_ACTION_KEY_LOCKDOWN = "lockdown";
-    protected static final String GLOBAL_ACTION_KEY_VOICEASSIST = "voiceassist";
-    protected static final String GLOBAL_ACTION_KEY_ASSIST = "assist";
-    protected static final String GLOBAL_ACTION_KEY_RESTART = "restart";
-    protected static final String GLOBAL_ACTION_KEY_LOGOUT = "logout";
-    protected static final String GLOBAL_ACTION_KEY_EMERGENCY = "emergency";
-    protected static final String GLOBAL_ACTION_KEY_SCREENSHOT = "screenshot";
+    static final String GLOBAL_ACTION_KEY_POWER = "power";
+    private static final String GLOBAL_ACTION_KEY_AIRPLANE = "airplane";
+    private static final String GLOBAL_ACTION_KEY_BUGREPORT = "bugreport";
+    private static final String GLOBAL_ACTION_KEY_SILENT = "silent";
+    private static final String GLOBAL_ACTION_KEY_USERS = "users";
+    private static final String GLOBAL_ACTION_KEY_SETTINGS = "settings";
+    private static final String GLOBAL_ACTION_KEY_LOCKDOWN = "lockdown";
+    private static final String GLOBAL_ACTION_KEY_VOICEASSIST = "voiceassist";
+    private static final String GLOBAL_ACTION_KEY_ASSIST = "assist";
+    static final String GLOBAL_ACTION_KEY_RESTART = "restart";
+    private static final String GLOBAL_ACTION_KEY_LOGOUT = "logout";
+    static final String GLOBAL_ACTION_KEY_EMERGENCY = "emergency";
+    static final String GLOBAL_ACTION_KEY_SCREENSHOT = "screenshot";
 
     private static final String PREFS_CONTROLS_SEEDING_COMPLETED = "ControlsSeedingCompleted";
     private static final String PREFS_CONTROLS_FILE = "controls_prefs";
@@ -196,7 +199,7 @@
     private final MetricsLogger mMetricsLogger;
     private final UiEventLogger mUiEventLogger;
     private final NotificationShadeDepthController mDepthController;
-    private final BlurUtils mBlurUtils;
+    private final SysUiState mSysUiState;
 
     // Used for RingerModeTracker
     private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
@@ -204,9 +207,10 @@
     @VisibleForTesting
     protected final ArrayList<Action> mItems = new ArrayList<>();
     @VisibleForTesting
-    protected final ArrayList<Action> mOverflowItems = new ArrayList<>();
+    final ArrayList<Action> mOverflowItems = new ArrayList<>();
 
-    private ActionsDialog mDialog;
+    @VisibleForTesting
+    protected ActionsDialog mDialog;
 
     private Action mSilentModeAction;
     private ToggleAction mAirplaneModeOn;
@@ -228,24 +232,27 @@
     private final SysuiColorExtractor mSysuiColorExtractor;
     private final IStatusBarService mStatusBarService;
     private final NotificationShadeWindowController mNotificationShadeWindowController;
-    private GlobalActionsPanelPlugin mPanelPlugin;
+    private GlobalActionsPanelPlugin mWalletPlugin;
     private ControlsUiController mControlsUiController;
     private final IWindowManager mIWindowManager;
     private final Executor mBackgroundExecutor;
-    private final ControlsListingController mControlsListingController;
     private List<ControlsServiceInfo> mControlsServiceInfos = new ArrayList<>();
     private ControlsController mControlsController;
     private SharedPreferences mControlsPreferences;
     private final RingerModeTracker mRingerModeTracker;
     private int mDialogPressDelay = DIALOG_PRESS_DELAY; // ms
     private Handler mMainHandler;
-    private boolean mShowLockScreenCardsAndControls = false;
+    @VisibleForTesting
+    boolean mShowLockScreenCardsAndControls = false;
 
     @VisibleForTesting
     public enum GlobalActionsEvent implements UiEventLogger.UiEventEnum {
         @UiEvent(doc = "The global actions / power menu surface became visible on the screen.")
         GA_POWER_MENU_OPEN(337),
 
+        @UiEvent(doc = "The global actions / power menu surface was dismissed.")
+        GA_POWER_MENU_CLOSE(471),
+
         @UiEvent(doc = "The global actions bugreport button was pressed.")
         GA_BUGREPORT_PRESS(344),
 
@@ -288,13 +295,13 @@
             TrustManager trustManager, IActivityManager iActivityManager,
             @Nullable TelecomManager telecomManager, MetricsLogger metricsLogger,
             NotificationShadeDepthController depthController, SysuiColorExtractor colorExtractor,
-            IStatusBarService statusBarService, BlurUtils blurUtils,
+            IStatusBarService statusBarService,
             NotificationShadeWindowController notificationShadeWindowController,
             ControlsUiController controlsUiController, IWindowManager iWindowManager,
             @Background Executor backgroundExecutor,
             ControlsListingController controlsListingController,
             ControlsController controlsController, UiEventLogger uiEventLogger,
-            RingerModeTracker ringerModeTracker, @Main Handler handler) {
+            RingerModeTracker ringerModeTracker, SysUiState sysUiState, @Main Handler handler) {
         mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme);
         mWindowManagerFuncs = windowManagerFuncs;
         mAudioManager = audioManager;
@@ -319,10 +326,9 @@
         mControlsUiController = controlsUiController;
         mIWindowManager = iWindowManager;
         mBackgroundExecutor = backgroundExecutor;
-        mControlsListingController = controlsListingController;
-        mBlurUtils = blurUtils;
         mRingerModeTracker = ringerModeTracker;
         mControlsController = controlsController;
+        mSysUiState = sysUiState;
         mMainHandler = handler;
 
         // receive broadcasts
@@ -360,21 +366,21 @@
             @Override
             public void onUnlockedChanged() {
                 if (mDialog != null) {
-                    boolean unlocked = keyguardStateController.isUnlocked()
-                            || keyguardStateController.canDismissLockScreen();
-                    if (mDialog.mPanelController != null) {
-                        mDialog.mPanelController.onDeviceLockStateChanged(unlocked);
+                    boolean unlocked = mKeyguardStateController.isUnlocked();
+                    if (mDialog.mWalletViewController != null) {
+                        mDialog.mWalletViewController.onDeviceLockStateChanged(!unlocked);
                     }
                     if (!mDialog.isShowingControls() && shouldShowControls()) {
                         mDialog.showControls(mControlsUiController);
                     }
+                    if (unlocked) {
+                        mDialog.hideLockMessage();
+                    }
                 }
             }
         });
 
-        mControlsListingController.addCallback(list -> {
-            mControlsServiceInfos = list;
-        });
+        controlsListingController.addCallback(list -> mControlsServiceInfos = list);
 
         // Need to be user-specific with the context to make sure we read the correct prefs
         Context userContext = context.createContextAsUser(
@@ -439,10 +445,10 @@
      * @param keyguardShowing True if keyguard is showing
      */
     public void showOrHideDialog(boolean keyguardShowing, boolean isDeviceProvisioned,
-            GlobalActionsPanelPlugin panelPlugin) {
+            GlobalActionsPanelPlugin walletPlugin) {
         mKeyguardShowing = keyguardShowing;
         mDeviceProvisioned = isDeviceProvisioned;
-        mPanelPlugin = panelPlugin;
+        mWalletPlugin = walletPlugin;
         if (mDialog != null && mDialog.isShowing()) {
             // In order to force global actions to hide on the same affordance press, we must
             // register a call to onGlobalActionsShown() first to prevent the default actions
@@ -509,11 +515,7 @@
      */
     @VisibleForTesting
     protected int getMaxShownPowerItems() {
-        if (shouldUseControlsLayout()) {
-            return mResources.getInteger(com.android.systemui.R.integer.power_menu_max_columns);
-        } else {
-            return Integer.MAX_VALUE;
-        }
+        return mResources.getInteger(com.android.systemui.R.integer.power_menu_max_columns);
     }
 
     /**
@@ -582,9 +584,10 @@
             } else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
                 addActionItem(getSettingsAction());
             } else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey)) {
+                int userId = getCurrentUser().id;
                 if (Settings.Secure.getIntForUser(mContentResolver,
-                        Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0, getCurrentUser().id) != 0
-                        && shouldDisplayLockdown()) {
+                        Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0, userId) != 0
+                        && shouldDisplayLockdown(userId)) {
                     addActionItem(getLockdownAction());
                 }
             } else if (GLOBAL_ACTION_KEY_VOICEASSIST.equals(actionKey)) {
@@ -628,12 +631,19 @@
         mAdapter = new MyAdapter();
         mOverflowAdapter = new MyOverflowAdapter();
 
-        mDepthController.setShowingHomeControls(shouldUseControlsLayout());
+        mDepthController.setShowingHomeControls(true);
+        GlobalActionsPanelPlugin.PanelViewController walletViewController =
+                getWalletViewController();
         ActionsDialog dialog = new ActionsDialog(mContext, mAdapter, mOverflowAdapter,
-                getWalletPanelViewController(), mDepthController, mSysuiColorExtractor,
+                walletViewController, mDepthController, mSysuiColorExtractor,
                 mStatusBarService, mNotificationShadeWindowController,
-                shouldShowControls() ? mControlsUiController : null, mBlurUtils,
-                shouldUseControlsLayout(), this::onRotate, mKeyguardShowing);
+                controlsAvailable(), shouldShowControls() ? mControlsUiController : null,
+                mSysUiState, this::onRotate, mKeyguardShowing);
+        boolean walletViewAvailable = walletViewController != null
+                && walletViewController.getPanelContent() != null;
+        if (shouldShowLockMessage(walletViewAvailable)) {
+            dialog.showLockMessage();
+        }
         dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
         dialog.setOnDismissListener(this);
         dialog.setOnShowListener(this);
@@ -641,13 +651,12 @@
         return dialog;
     }
 
-    private boolean shouldDisplayLockdown() {
+    private boolean shouldDisplayLockdown(int userId) {
         // Lockdown is meaningless without a place to go.
         if (!mKeyguardStateController.isMethodSecure()) {
             return false;
         }
 
-        int userId = getCurrentUser().id;
         // Only show the lockdown button if the device isn't locked down (for whatever reason).
         int state = mLockPatternUtils.getStrongAuthForUser(userId);
         return (state == STRONG_AUTH_NOT_REQUIRED
@@ -667,11 +676,11 @@
     }
 
     @Nullable
-    private GlobalActionsPanelPlugin.PanelViewController getWalletPanelViewController() {
-        if (mPanelPlugin == null) {
+    private GlobalActionsPanelPlugin.PanelViewController getWalletViewController() {
+        if (mWalletPlugin == null) {
             return null;
         }
-        return mPanelPlugin.onPanelShown(this, !mKeyguardStateController.isUnlocked());
+        return mWalletPlugin.onPanelShown(this, !mKeyguardStateController.isUnlocked());
     }
 
     /**
@@ -732,7 +741,7 @@
 
         @Override
         public boolean shouldBeSeparated() {
-            return !shouldUseControlsLayout();
+            return false;
         }
 
         @Override
@@ -740,18 +749,10 @@
                 Context context, View convertView, ViewGroup parent, LayoutInflater inflater) {
             View v = super.create(context, convertView, parent, inflater);
             int textColor;
-            if (shouldUseControlsLayout()) {
-                v.setBackgroundTintList(ColorStateList.valueOf(v.getResources().getColor(
-                        com.android.systemui.R.color.global_actions_emergency_background)));
-                textColor = v.getResources().getColor(
-                        com.android.systemui.R.color.global_actions_emergency_text);
-            } else if (shouldBeSeparated()) {
-                textColor = v.getResources().getColor(
-                        com.android.systemui.R.color.global_actions_alert_text);
-            } else {
-                textColor = v.getResources().getColor(
-                        com.android.systemui.R.color.global_actions_text);
-            }
+            v.setBackgroundTintList(ColorStateList.valueOf(v.getResources().getColor(
+                    com.android.systemui.R.color.global_actions_emergency_background)));
+            textColor = v.getResources().getColor(
+                    com.android.systemui.R.color.global_actions_emergency_text);
             TextView messageView = v.findViewById(R.id.message);
             messageView.setTextColor(textColor);
             messageView.setSelected(true); // necessary for marquee to work
@@ -1168,6 +1169,7 @@
         if (mDialog == dialog) {
             mDialog = null;
         }
+        mUiEventLogger.log(GlobalActionsEvent.GA_POWER_MENU_CLOSE);
         mWindowManagerFuncs.onGlobalActionsHidden();
         mLifecycle.setCurrentState(Lifecycle.State.DESTROYED);
     }
@@ -1180,13 +1182,6 @@
         mUiEventLogger.log(GlobalActionsEvent.GA_POWER_MENU_OPEN);
     }
 
-    private int getActionLayoutId() {
-        if (shouldUseControlsLayout()) {
-            return com.android.systemui.R.layout.global_actions_grid_item_v2;
-        }
-        return com.android.systemui.R.layout.global_actions_grid_item;
-    }
-
     /**
      * The adapter used for power menu items shown in the global actions dialog.
      */
@@ -1480,7 +1475,8 @@
 
         public View create(
                 Context context, View convertView, ViewGroup parent, LayoutInflater inflater) {
-            View v = inflater.inflate(getActionLayoutId(), parent, false /* attach */);
+            View v = inflater.inflate(com.android.systemui.R.layout.global_actions_grid_item_v2,
+                    parent, false /* attach */);
 
             ImageView icon = v.findViewById(R.id.icon);
             TextView messageView = v.findViewById(R.id.message);
@@ -1586,7 +1582,8 @@
                 LayoutInflater inflater) {
             willCreate();
 
-            View v = inflater.inflate(getActionLayoutId(), parent, false /* attach */);
+            View v = inflater.inflate(com.android.systemui.R.layout.global_actions_grid_item_v2,
+                    parent, false /* attach */);
 
             ImageView icon = (ImageView) v.findViewById(R.id.icon);
             TextView messageView = (TextView) v.findViewById(R.id.message);
@@ -1893,7 +1890,8 @@
         return mLifecycle;
     }
 
-    private static final class ActionsDialog extends Dialog implements DialogInterface,
+    @VisibleForTesting
+    static final class ActionsDialog extends Dialog implements DialogInterface,
             ColorExtractor.OnColorsChangedListener {
 
         private final Context mContext;
@@ -1904,7 +1902,7 @@
         private MultiListLayout mGlobalActionsLayout;
         private Drawable mBackgroundDrawable;
         private final SysuiColorExtractor mColorExtractor;
-        private final GlobalActionsPanelPlugin.PanelViewController mPanelController;
+        private final GlobalActionsPanelPlugin.PanelViewController mWalletViewController;
         private boolean mKeyguardShowing;
         private boolean mShowing;
         private float mScrimAlpha;
@@ -1912,22 +1910,24 @@
         private boolean mHadTopUi;
         private final NotificationShadeWindowController mNotificationShadeWindowController;
         private final NotificationShadeDepthController mDepthController;
-        private final BlurUtils mBlurUtils;
-        private final boolean mUseControlsLayout;
+        private final SysUiState mSysUiState;
         private ListPopupWindow mOverflowPopup;
         private final Runnable mOnRotateCallback;
+        private final boolean mControlsAvailable;
 
         private ControlsUiController mControlsUiController;
         private ViewGroup mControlsView;
         private ViewGroup mContainer;
+        @VisibleForTesting ViewGroup mLockMessageContainer;
+        private TextView mLockMessage;
 
         ActionsDialog(Context context, MyAdapter adapter, MyOverflowAdapter overflowAdapter,
-                GlobalActionsPanelPlugin.PanelViewController plugin,
+                GlobalActionsPanelPlugin.PanelViewController walletViewController,
                 NotificationShadeDepthController depthController,
                 SysuiColorExtractor sysuiColorExtractor, IStatusBarService statusBarService,
                 NotificationShadeWindowController notificationShadeWindowController,
-                ControlsUiController controlsUiController, BlurUtils blurUtils,
-                boolean useControlsLayout, Runnable onRotateCallback, boolean keyguardShowing) {
+                boolean controlsAvailable, @Nullable ControlsUiController controlsUiController,
+                SysUiState sysuiState, Runnable onRotateCallback, boolean keyguardShowing) {
             super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
             mContext = context;
             mAdapter = adapter;
@@ -1936,9 +1936,9 @@
             mColorExtractor = sysuiColorExtractor;
             mStatusBarService = statusBarService;
             mNotificationShadeWindowController = notificationShadeWindowController;
+            mControlsAvailable = controlsAvailable;
             mControlsUiController = controlsUiController;
-            mBlurUtils = blurUtils;
-            mUseControlsLayout = useControlsLayout;
+            mSysUiState = sysuiState;
             mOnRotateCallback = onRotateCallback;
             mKeyguardShowing = keyguardShowing;
 
@@ -1963,7 +1963,7 @@
             window.getAttributes().setFitInsetsTypes(0 /* types */);
             setTitle(R.string.global_actions);
 
-            mPanelController = plugin;
+            mWalletViewController = walletViewController;
             initializeLayout();
         }
 
@@ -1976,11 +1976,11 @@
             mControlsUiController.show(mControlsView, this::dismissForControlsActivity);
         }
 
-        private boolean shouldUsePanel() {
-            return mPanelController != null && mPanelController.getPanelContent() != null;
-        }
+        private void initializeWalletView() {
+            if (mWalletViewController == null || mWalletViewController.getPanelContent() == null) {
+                return;
+            }
 
-        private void initializePanel() {
             int rotation = RotationUtils.getRotation(mContext);
             boolean rotationLocked = RotationPolicy.isRotationLocked(mContext);
             if (rotation != RotationUtils.ROTATION_NONE) {
@@ -2017,18 +2017,40 @@
                 setRotationSuggestionsEnabled(false);
 
                 FrameLayout panelContainer =
-                        findViewById(com.android.systemui.R.id.global_actions_panel_container);
+                        findViewById(com.android.systemui.R.id.global_actions_wallet);
                 FrameLayout.LayoutParams panelParams =
                         new FrameLayout.LayoutParams(
                                 FrameLayout.LayoutParams.MATCH_PARENT,
                                 FrameLayout.LayoutParams.MATCH_PARENT);
-                panelContainer.addView(mPanelController.getPanelContent(), panelParams);
+                if (!mControlsAvailable) {
+                    panelParams.topMargin = mContext.getResources().getDimensionPixelSize(
+                            com.android.systemui.R.dimen.global_actions_wallet_top_margin);
+                }
+                View walletView = mWalletViewController.getPanelContent();
+                panelContainer.addView(walletView, panelParams);
+                // Smooth transitions when wallet is resized, which can happen when a card is added
+                ViewGroup root = findViewById(com.android.systemui.R.id.global_actions_grid_root);
+                if (root != null) {
+                    walletView.addOnLayoutChangeListener((v, l, t, r, b, ol, ot, or, ob) -> {
+                        int oldHeight = ob - ot;
+                        int newHeight = b - t;
+                        if (oldHeight > 0 && oldHeight != newHeight) {
+                            TransitionSet transition = new AutoTransition()
+                                    .setDuration(250)
+                                    .setOrdering(TransitionSet.ORDERING_TOGETHER);
+                            TransitionManager.beginDelayedTransition(root, transition);
+                        }
+                    });
+                }
             }
         }
 
         private ListPopupWindow createPowerOverflowPopup() {
             ListPopupWindow popup = new GlobalActionsPopupMenu(
-                    mContext, false /* isDropDownMode */);
+                    new ContextThemeWrapper(
+                        mContext,
+                        com.android.systemui.R.style.Control_ListPopupWindow
+                    ), false /* isDropDownMode */);
             View overflowButton =
                     findViewById(com.android.systemui.R.id.global_actions_overflow_button);
             popup.setAnchorView(overflowButton);
@@ -2047,7 +2069,7 @@
         }
 
         private void initializeLayout() {
-            setContentView(getGlobalActionsLayoutId(mContext));
+            setContentView(com.android.systemui.R.layout.global_actions_grid_v2);
             fixNavBarClipping();
             mControlsView = findViewById(com.android.systemui.R.id.global_actions_controls);
             mGlobalActionsLayout = findViewById(com.android.systemui.R.id.global_actions_view);
@@ -2063,10 +2085,9 @@
             mGlobalActionsLayout.setRotationListener(this::onRotate);
             mGlobalActionsLayout.setAdapter(mAdapter);
             mContainer = findViewById(com.android.systemui.R.id.global_actions_container);
-            // Some legacy dialog layouts don't have the outer container
-            if (mContainer == null) {
-                mContainer = mGlobalActionsLayout;
-            }
+            mLockMessageContainer = requireViewById(
+                    com.android.systemui.R.id.global_actions_lock_message_container);
+            mLockMessage = requireViewById(com.android.systemui.R.id.global_actions_lock_message);
 
             View overflowButton = findViewById(
                     com.android.systemui.R.id.global_actions_overflow_button);
@@ -2087,17 +2108,10 @@
                 }
             }
 
-            if (shouldUsePanel()) {
-                initializePanel();
-            }
+            initializeWalletView();
             if (mBackgroundDrawable == null) {
                 mBackgroundDrawable = new ScrimDrawable();
-                if (mUseControlsLayout) {
-                    mScrimAlpha = 1.0f;
-                } else {
-                    mScrimAlpha = mBlurUtils.supportsBlursOnWindows()
-                            ? ScrimController.BLUR_SCRIM_ALPHA : ScrimController.BUSY_SCRIM_ALPHA;
-                }
+                mScrimAlpha = 1.0f;
             }
             getWindow().setBackgroundDrawable(mBackgroundDrawable);
         }
@@ -2111,29 +2125,6 @@
             contentParent.setClipToPadding(false);
         }
 
-        private int getGlobalActionsLayoutId(Context context) {
-            if (mUseControlsLayout) {
-                return com.android.systemui.R.layout.global_actions_grid_v2;
-            }
-
-            int rotation = RotationUtils.getRotation(context);
-            boolean useGridLayout = isForceGridEnabled(context)
-                    || (shouldUsePanel() && rotation == RotationUtils.ROTATION_NONE);
-            if (rotation == RotationUtils.ROTATION_SEASCAPE) {
-                if (useGridLayout) {
-                    return com.android.systemui.R.layout.global_actions_grid_seascape;
-                } else {
-                    return com.android.systemui.R.layout.global_actions_column_seascape;
-                }
-            } else {
-                if (useGridLayout) {
-                    return com.android.systemui.R.layout.global_actions_grid;
-                } else {
-                    return com.android.systemui.R.layout.global_actions_column;
-                }
-            }
-        }
-
         @Override
         protected void onStart() {
             super.setCanceledOnTouchOutside(true);
@@ -2157,9 +2148,7 @@
             if (!(mBackgroundDrawable instanceof ScrimDrawable)) {
                 return;
             }
-            ((ScrimDrawable) mBackgroundDrawable).setColor(
-                    !mUseControlsLayout && colors.supportsDarkText()
-                            ? Color.WHITE : Color.BLACK, animate);
+            ((ScrimDrawable) mBackgroundDrawable).setColor(Color.BLACK, animate);
             View decorView = getWindow().getDecorView();
             if (colors.supportsDarkText()) {
                 decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR |
@@ -2181,15 +2170,15 @@
             mShowing = true;
             mHadTopUi = mNotificationShadeWindowController.getForceHasTopUi();
             mNotificationShadeWindowController.setForceHasTopUi(true);
+            mSysUiState.setFlag(SYSUI_STATE_GLOBAL_ACTIONS_SHOWING, true)
+                    .commitUpdate(mContext.getDisplayId());
 
             ViewGroup root = (ViewGroup) mGlobalActionsLayout.getRootView();
             root.setOnApplyWindowInsetsListener((v, windowInsets) -> {
-                if (mUseControlsLayout) {
-                    root.setPadding(windowInsets.getStableInsetLeft(),
-                            windowInsets.getStableInsetTop(),
-                            windowInsets.getStableInsetRight(),
-                            windowInsets.getStableInsetBottom());
-                }
+                root.setPadding(windowInsets.getStableInsetLeft(),
+                        windowInsets.getStableInsetTop(),
+                        windowInsets.getStableInsetRight(),
+                        windowInsets.getStableInsetBottom());
                 return WindowInsets.CONSUMED;
             });
             if (mControlsUiController != null) {
@@ -2199,7 +2188,7 @@
             mBackgroundDrawable.setAlpha(0);
             float xOffset = mGlobalActionsLayout.getAnimationOffsetX();
             ObjectAnimator alphaAnimator =
-                    ObjectAnimator.ofFloat(mContainer, "transitionAlpha", 0f, 1f);
+                    ObjectAnimator.ofFloat(mContainer, "alpha", 0f, 1f);
             alphaAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
             alphaAnimator.setDuration(183);
             alphaAnimator.addUpdateListener((animation) -> {
@@ -2212,8 +2201,8 @@
 
             ObjectAnimator xAnimator =
                     ObjectAnimator.ofFloat(mContainer, "translationX", xOffset, 0f);
-            alphaAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-            alphaAnimator.setDuration(350);
+            xAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+            xAnimator.setDuration(350);
 
             AnimatorSet animatorSet = new AnimatorSet();
             animatorSet.playTogether(alphaAnimator, xAnimator);
@@ -2225,7 +2214,7 @@
             dismissWithAnimation(() -> {
                 mContainer.setTranslationX(0);
                 ObjectAnimator alphaAnimator =
-                        ObjectAnimator.ofFloat(mContainer, "transitionAlpha", 1f, 0f);
+                        ObjectAnimator.ofFloat(mContainer, "alpha", 1f, 0f);
                 alphaAnimator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
                 alphaAnimator.setDuration(233);
                 alphaAnimator.addUpdateListener((animation) -> {
@@ -2239,8 +2228,8 @@
                 float xOffset = mGlobalActionsLayout.getAnimationOffsetX();
                 ObjectAnimator xAnimator =
                         ObjectAnimator.ofFloat(mContainer, "translationX", 0f, xOffset);
-                alphaAnimator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
-                alphaAnimator.setDuration(350);
+                xAnimator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+                xAnimator.setDuration(350);
 
                 AnimatorSet animatorSet = new AnimatorSet();
                 animatorSet.playTogether(alphaAnimator, xAnimator);
@@ -2276,17 +2265,19 @@
         private void completeDismiss() {
             mShowing = false;
             resetOrientation();
-            dismissPanel();
+            dismissWallet();
             dismissOverflow(true);
             if (mControlsUiController != null) mControlsUiController.hide();
             mNotificationShadeWindowController.setForceHasTopUi(mHadTopUi);
             mDepthController.updateGlobalDialogVisibility(0, null /* view */);
+            mSysUiState.setFlag(SYSUI_STATE_GLOBAL_ACTIONS_SHOWING, false)
+                    .commitUpdate(mContext.getDisplayId());
             super.dismiss();
         }
 
-        private void dismissPanel() {
-            if (mPanelController != null) {
-                mPanelController.onDismissed();
+        private void dismissWallet() {
+            if (mWalletViewController != null) {
+                mWalletViewController.onDismissed();
             }
         }
 
@@ -2340,6 +2331,14 @@
         }
 
         public void refreshDialog() {
+            // ensure dropdown menus are dismissed before re-initializing the dialog
+            dismissWallet();
+            dismissOverflow(true);
+            if (mControlsUiController != null) {
+                mControlsUiController.hide();
+            }
+
+            // re-create dialog
             initializeLayout();
             mGlobalActionsLayout.updateList();
             if (mControlsUiController != null) {
@@ -2354,6 +2353,25 @@
             }
         }
 
+        void hideLockMessage() {
+            if (mLockMessageContainer.getVisibility() == View.VISIBLE) {
+                mLockMessageContainer.animate().alpha(0).setDuration(150).setListener(
+                        new AnimatorListenerAdapter() {
+                            @Override
+                            public void onAnimationEnd(Animator animation) {
+                                mLockMessageContainer.setVisibility(View.GONE);
+                            }
+                        }).start();
+            }
+        }
+
+        void showLockMessage() {
+            Drawable lockIcon = mContext.getDrawable(com.android.internal.R.drawable.ic_lock);
+            lockIcon.setTint(mContext.getColor(com.android.systemui.R.color.control_primary_text));
+            mLockMessage.setCompoundDrawablesWithIntrinsicBounds(null, lockIcon, null, null);
+            mLockMessageContainer.setVisibility(View.VISIBLE);
+        }
+
         private static class ResetOrientationData {
             public boolean locked;
             public int rotation;
@@ -2376,18 +2394,21 @@
         return isPanelDebugModeEnabled(context);
     }
 
-    @VisibleForTesting
-    protected boolean shouldShowControls() {
-        boolean isUnlocked = mKeyguardStateController.isUnlocked()
-                || mKeyguardStateController.canDismissLockScreen();
-        return (isUnlocked || mShowLockScreenCardsAndControls)
+    private boolean shouldShowControls() {
+        return (mKeyguardStateController.isUnlocked() || mShowLockScreenCardsAndControls)
+                && controlsAvailable();
+    }
+
+    private boolean controlsAvailable() {
+        return mDeviceProvisioned
                 && mControlsUiController.getAvailable()
                 && !mControlsServiceInfos.isEmpty();
     }
-    // TODO: Remove legacy layout XML and classes.
-    protected boolean shouldUseControlsLayout() {
-        // always use new controls layout
-        return true;
+
+    private boolean shouldShowLockMessage(boolean walletViewAvailable) {
+        return !mKeyguardStateController.isUnlocked()
+                && !mShowLockScreenCardsAndControls
+                && (controlsAvailable() || walletViewAvailable);
     }
 
     private void onPowerMenuLockScreenSettingsChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsFlatLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsFlatLayout.java
index c7612d4..83046ef 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsFlatLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsFlatLayout.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.ViewGroup;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.HardwareBgDrawable;
@@ -78,6 +79,31 @@
         }
     }
 
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        boolean anyTruncated = false;
+        ViewGroup listView = getListView();
+        // Check to see if any of the GlobalActionsItems have had their messages truncated
+        for (int i = 0; i < listView.getChildCount(); i++) {
+            View child = listView.getChildAt(i);
+            if (child instanceof GlobalActionsItem) {
+                GlobalActionsItem item = (GlobalActionsItem) child;
+                anyTruncated = anyTruncated || item.isTruncated();
+            }
+        }
+        // If any of the items have been truncated, set the all to single-line marquee
+        if (anyTruncated) {
+            for (int i = 0; i < listView.getChildCount(); i++) {
+                View child = listView.getChildAt(i);
+                if (child instanceof GlobalActionsItem) {
+                    GlobalActionsItem item = (GlobalActionsItem) child;
+                    item.setMarquee(true);
+                }
+            }
+        }
+    }
+
     @VisibleForTesting
     protected float getGridItemSize() {
         return getContext().getResources().getDimension(R.dimen.global_actions_grid_item_height);
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index 09757a4..b55b29a 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -53,7 +53,7 @@
     private final Lazy<GlobalActionsDialog> mGlobalActionsDialogLazy;
     private final KeyguardStateController mKeyguardStateController;
     private final DeviceProvisionedController mDeviceProvisionedController;
-    private final ExtensionController.Extension<GlobalActionsPanelPlugin> mPanelExtension;
+    private final ExtensionController.Extension<GlobalActionsPanelPlugin> mWalletPluginProvider;
     private final BlurUtils mBlurUtils;
     private final CommandQueue mCommandQueue;
     private GlobalActionsDialog mGlobalActionsDialog;
@@ -69,7 +69,7 @@
         mCommandQueue = commandQueue;
         mBlurUtils = blurUtils;
         mCommandQueue.addCallback(this);
-        mPanelExtension = Dependency.get(ExtensionController.class)
+        mWalletPluginProvider = Dependency.get(ExtensionController.class)
                 .newExtension(GlobalActionsPanelPlugin.class)
                 .withPlugin(GlobalActionsPanelPlugin.class)
                 .build();
@@ -90,7 +90,7 @@
         mGlobalActionsDialog = mGlobalActionsDialogLazy.get();
         mGlobalActionsDialog.showOrHideDialog(mKeyguardStateController.isShowing(),
                 mDeviceProvisionedController.isDeviceProvisioned(),
-                mPanelExtension.get());
+                mWalletPluginProvider.get());
         Dependency.get(KeyguardUpdateMonitor.class).requestFaceAuth();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsItem.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsItem.java
new file mode 100644
index 0000000..07fa592
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsItem.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.globalactions;
+
+import android.content.Context;
+import android.text.Layout;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.R;
+
+/**
+ * Layout for GlobalActions items.
+ */
+public class GlobalActionsItem extends LinearLayout {
+    public GlobalActionsItem(Context context) {
+        super(context);
+    }
+
+    public GlobalActionsItem(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public GlobalActionsItem(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    private TextView getTextView() {
+        return (TextView) findViewById(R.id.message);
+    }
+
+    /**
+     * Sets this item to marquee or not.
+     */
+    public void setMarquee(boolean marquee) {
+        TextView text = getTextView();
+        text.setSingleLine(marquee);
+        text.setEllipsize(marquee ? TextUtils.TruncateAt.MARQUEE : TextUtils.TruncateAt.END);
+    }
+
+    /**
+     * Determines whether the message for this item has been truncated.
+     */
+    public boolean isTruncated() {
+        TextView message = getTextView();
+        if (message != null) {
+            Layout messageLayout = message.getLayout();
+            if (messageLayout != null) {
+                if (messageLayout.getLineCount() > 0) {
+                    // count the number of ellipses in the last line.
+                    int ellipses = messageLayout.getEllipsisCount(
+                            messageLayout.getLineCount() - 1);
+                    // If ellipses are present, the line was forced to truncate.
+                    return ellipses > 0;
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPopupMenu.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPopupMenu.java
index 02ea251..a5ced7b 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPopupMenu.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPopupMenu.java
@@ -19,7 +19,6 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
-import android.view.ContextThemeWrapper;
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.WindowManager;
@@ -32,6 +31,8 @@
 /**
  * Customized widget for use in the GlobalActionsDialog. Ensures common positioning and user
  * interactions.
+ *
+ * It should be created with a {@link Context} with the right theme
  */
 public class GlobalActionsPopupMenu extends ListPopupWindow {
     private Context mContext;
@@ -42,15 +43,17 @@
     private ListAdapter mAdapter;
 
     public GlobalActionsPopupMenu(@NonNull Context context, boolean isDropDownMode) {
-        super(new ContextThemeWrapper(context, R.style.Control_ListPopupWindow));
+        super(context);
         mContext = context;
+        Resources res = mContext.getResources();
+        setBackgroundDrawable(
+                res.getDrawable(R.drawable.rounded_bg_full, context.getTheme()));
         mIsDropDownMode = isDropDownMode;
 
         // required to show above the global actions dialog
         setWindowLayoutType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
         setModal(true);
 
-        Resources res = mContext.getResources();
         mGlobalActionsSidePadding = res.getDimensionPixelSize(R.dimen.global_actions_side_margin);
         if (!isDropDownMode) {
             mMenuVerticalPadding = res.getDimensionPixelSize(R.dimen.control_menu_vertical_padding);
@@ -89,11 +92,16 @@
             // width should be between [.5, .9] of screen
             int parentWidth = res.getSystem().getDisplayMetrics().widthPixels;
             int widthSpec = MeasureSpec.makeMeasureSpec(
-                    (int) (parentWidth * 0.9), MeasureSpec.AT_MOST);
-            View child = mAdapter.getView(0, null, listView);
-            child.measure(widthSpec, MeasureSpec.UNSPECIFIED);
-            int width = Math.max(child.getMeasuredWidth(), (int) (parentWidth * 0.5));
-
+                    (int) (parentWidth * 0.9) - 2 * mMenuHorizontalPadding, MeasureSpec.AT_MOST);
+            int maxWidth = 0;
+            for (int i = 0; i < mAdapter.getCount(); i++) {
+                View child = mAdapter.getView(i, null, listView);
+                child.measure(widthSpec, MeasureSpec.UNSPECIFIED);
+                int w = child.getMeasuredWidth();
+                maxWidth = Math.max(w, maxWidth);
+            }
+            int width = Math.max(maxWidth, (int) (parentWidth * 0.5) - 2 * mMenuHorizontalPadding)
+                    + 2 * mMenuHorizontalPadding;
             listView.setPadding(mMenuHorizontalPadding, mMenuVerticalPadding,
                     mMenuHorizontalPadding, mMenuVerticalPadding);
 
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
index fa45ea1..1a53c28 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
@@ -134,7 +134,7 @@
     private void setupTexture(Bitmap bitmap) {
         final int[] tids = new int[1];
 
-        if (bitmap == null) {
+        if (bitmap == null || bitmap.isRecycled()) {
             Log.w(TAG, "setupTexture: invalid bitmap");
             return;
         }
@@ -146,16 +146,20 @@
             return;
         }
 
-        // Bind a named texture to a target.
-        glBindTexture(GL_TEXTURE_2D, tids[0]);
-        // Load the bitmap data and copy it over into the texture object that is currently bound.
-        GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
-        // Use bilinear texture filtering when minification.
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        // Use bilinear texture filtering when magnification.
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-        mTextureId = tids[0];
+        try {
+            // Bind a named texture to a target.
+            glBindTexture(GL_TEXTURE_2D, tids[0]);
+            // Load the bitmap data and copy it over into the texture object
+            // that is currently bound.
+            GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
+            // Use bilinear texture filtering when minification.
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            // Use bilinear texture filtering when magnification.
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            mTextureId = tids[0];
+        } catch (IllegalArgumentException e) {
+            Log.w(TAG, "Failed uploading texture: " + e.getLocalizedMessage());
+        }
     }
 
     void useTexture() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 96494cf..3a37c0f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -451,7 +451,8 @@
      * @param metadata New metadata.
      */
     @Override
-    public void onMetadataOrStateChanged(MediaMetadata metadata, @PlaybackState.State int state) {
+    public void onPrimaryMetadataOrStateChanged(MediaMetadata metadata,
+            @PlaybackState.State int state) {
         synchronized (this) {
             boolean nextVisible = NotificationMediaManager.isPlayingState(state);
             mMediaHandler.removeCallbacksAndMessages(null);
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
index 7defef9..342db34 100644
--- a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
@@ -209,4 +209,4 @@
 }
 
 private const val TAG = "LogBuffer"
-private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.S", Locale.US)
+private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index 123cf78..9c89fee 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -61,6 +61,18 @@
         return buffer;
     }
 
+    /** Provides a logging buffer for all logs related to managing notification sections. */
+    @Provides
+    @Singleton
+    @NotificationSectionLog
+    public static LogBuffer provideNotificationSectionLogBuffer(
+            LogcatEchoTracker bufferFilter,
+            DumpManager dumpManager) {
+        LogBuffer buffer = new LogBuffer("NotifSectionLog", 500, 10, bufferFilter);
+        buffer.attach(dumpManager);
+        return buffer;
+    }
+
     /** Provides a logging buffer for all logs related to the data layer of notifications. */
     @Provides
     @Singleton
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationSectionLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationSectionLog.java
new file mode 100644
index 0000000..7259eeb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationSectionLog.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.android.systemui.log.LogBuffer;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+/** A {@link LogBuffer} for notification sections-related messages. */
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface NotificationSectionLog {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/GoneChildrenHideHelper.kt b/packages/SystemUI/src/com/android/systemui/media/GoneChildrenHideHelper.kt
new file mode 100644
index 0000000..2fe0d9f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/GoneChildrenHideHelper.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.systemui.media
+
+import android.graphics.Rect
+import android.view.View
+import android.view.ViewGroup
+
+private val EMPTY_RECT = Rect(0,0,0,0)
+
+private val LAYOUT_CHANGE_LISTENER = object : View.OnLayoutChangeListener {
+
+    override fun onLayoutChange(v: View?, left: Int, top: Int, right: Int, bottom: Int,
+                                oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) {
+        v?.let {
+            if (v.visibility == View.GONE) {
+                v.clipBounds = EMPTY_RECT
+            } else {
+                v.clipBounds = null
+            }
+        }
+    }
+}
+/**
+ * A helper class that clips all GONE children. Useful for transitions in motionlayout which
+ * don't clip its children.
+ */
+class GoneChildrenHideHelper private constructor() {
+    companion object {
+        @JvmStatic
+        fun clipGoneChildrenOnLayout(layout: ViewGroup) {
+            val childCount = layout.childCount
+            for (i in 0 until childCount) {
+                val child = layout.getChildAt(i)
+                child.addOnLayoutChangeListener(LAYOUT_CHANGE_LISTENER)
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/IlluminationDrawable.kt b/packages/SystemUI/src/com/android/systemui/media/IlluminationDrawable.kt
index 9374727..7432165 100644
--- a/packages/SystemUI/src/com/android/systemui/media/IlluminationDrawable.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/IlluminationDrawable.kt
@@ -6,6 +6,7 @@
 import android.animation.ValueAnimator
 import android.content.res.ColorStateList
 import android.content.res.Resources
+import android.content.res.TypedArray
 import android.graphics.Canvas
 import android.graphics.Color
 import android.graphics.ColorFilter
@@ -49,6 +50,7 @@
 @Keep
 class IlluminationDrawable : Drawable() {
 
+    private var themeAttrs: IntArray? = null
     private var cornerRadius = 0f
     private var highlightColor = Color.TRANSPARENT
     private val rippleData = RippleData(0f, 0f, 0f, 0f, 0f, 0f, 0f)
@@ -139,13 +141,41 @@
         theme: Resources.Theme?
     ) {
         val a = obtainAttributes(r, theme, attrs, R.styleable.IlluminationDrawable)
-        cornerRadius = a.getDimension(R.styleable.IlluminationDrawable_cornerRadius, cornerRadius)
-        rippleData.minSize = a.getDimension(R.styleable.IlluminationDrawable_rippleMinSize, 0f)
-        rippleData.maxSize = a.getDimension(R.styleable.IlluminationDrawable_rippleMaxSize, 0f)
-        rippleData.highlight = a.getInteger(R.styleable.IlluminationDrawable_highlight, 0) / 100f
+        themeAttrs = a.extractThemeAttrs()
+        updateStateFromTypedArray(a)
         a.recycle()
     }
 
+    private fun updateStateFromTypedArray(a: TypedArray) {
+        if (a.hasValue(R.styleable.IlluminationDrawable_cornerRadius)) {
+            cornerRadius = a.getDimension(R.styleable.IlluminationDrawable_cornerRadius,
+                    cornerRadius)
+        }
+        if (a.hasValue(R.styleable.IlluminationDrawable_rippleMinSize)) {
+            rippleData.minSize = a.getDimension(R.styleable.IlluminationDrawable_rippleMinSize, 0f)
+        }
+        if (a.hasValue(R.styleable.IlluminationDrawable_rippleMaxSize)) {
+            rippleData.maxSize = a.getDimension(R.styleable.IlluminationDrawable_rippleMaxSize, 0f)
+        }
+        if (a.hasValue(R.styleable.IlluminationDrawable_highlight)) {
+            rippleData.highlight = a.getInteger(R.styleable.IlluminationDrawable_highlight, 0) /
+                    100f
+        }
+    }
+
+    override fun canApplyTheme(): Boolean {
+        return themeAttrs != null && themeAttrs!!.size > 0 || super.canApplyTheme()
+    }
+
+    override fun applyTheme(t: Resources.Theme) {
+        super.applyTheme(t)
+        themeAttrs?.let {
+            val a = t.resolveAttributes(it, R.styleable.IlluminationDrawable)
+            updateStateFromTypedArray(a)
+            a.recycle()
+        }
+    }
+
     override fun setColorFilter(p0: ColorFilter?) {
         throw UnsupportedOperationException("Color filters are not supported")
     }
diff --git a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
new file mode 100644
index 0000000..85e1c6b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media
+
+import android.view.View
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.notification.stack.MediaHeaderView
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * A class that controls the media notifications on the lock screen, handles its visibility and
+ * is responsible for the embedding of he media experience.
+ */
+@Singleton
+class KeyguardMediaController @Inject constructor(
+    private val mediaHost: MediaHost,
+    private val bypassController: KeyguardBypassController,
+    private val statusBarStateController: SysuiStatusBarStateController,
+    private val notifLockscreenUserManager: NotificationLockscreenUserManager
+) {
+
+    init {
+        statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
+            override fun onStateChanged(newState: Int) {
+                updateVisibility()
+            }
+        })
+    }
+    private var view: MediaHeaderView? = null
+
+    /**
+     * Attach this controller to a media view, initializing its state
+     */
+    fun attach(mediaView: MediaHeaderView) {
+        view = mediaView
+        // First let's set the desired state that we want for this host
+        mediaHost.visibleChangedListener = { updateVisibility() }
+        mediaHost.expansion = 0.0f
+        mediaHost.showsOnlyActiveMedia = true
+
+        // Let's now initialize this view, which also creates the host view for us.
+        mediaHost.init(MediaHierarchyManager.LOCATION_LOCKSCREEN)
+        mediaView.setContentView(mediaHost.hostView)
+    }
+
+    private fun updateVisibility() {
+        val keyguardOrUserSwitcher = (statusBarStateController.state == StatusBarState.KEYGUARD ||
+                statusBarStateController.state == StatusBarState.FULLSCREEN_USER_SWITCHER)
+        val shouldBeVisible = mediaHost.visible &&
+                !bypassController.bypassEnabled &&
+                keyguardOrUserSwitcher &&
+                notifLockscreenUserManager.shouldShowLockscreenNotifications()
+        view?.visibility = if (shouldBeVisible) View.VISIBLE else View.GONE
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/LayoutAnimationHelper.kt b/packages/SystemUI/src/com/android/systemui/media/LayoutAnimationHelper.kt
new file mode 100644
index 0000000..a366725
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/LayoutAnimationHelper.kt
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.systemui.media
+
+import android.graphics.Rect
+import android.view.View
+import android.view.ViewGroup
+import android.view.ViewTreeObserver
+import com.android.systemui.statusbar.notification.AnimatableProperty
+import com.android.systemui.statusbar.notification.PropertyAnimator
+import com.android.systemui.statusbar.notification.stack.AnimationProperties
+
+/**
+ * A utility class that helps with animations of bound changes designed for motionlayout which
+ * doesn't work together with regular changeBounds.
+ */
+class LayoutAnimationHelper {
+
+    private val layout: ViewGroup
+    private var sizeAnimationPending = false
+    private val desiredBounds = mutableMapOf<View, Rect>()
+    private val animationProperties = AnimationProperties()
+    private val layoutListener = object : View.OnLayoutChangeListener {
+        override fun onLayoutChange(v: View?, left: Int, top: Int, right: Int, bottom: Int,
+                                    oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) {
+            v?.let {
+                if (v.alpha == 0.0f || v.visibility == View.GONE || oldLeft - oldRight == 0 ||
+                        oldTop - oldBottom == 0) {
+                    return
+                }
+                if (oldLeft != left || oldTop != top || oldBottom != bottom || oldRight != right) {
+                    val rect = desiredBounds.getOrPut(v, { Rect() })
+                    rect.set(left, top, right, bottom)
+                    onDesiredLocationChanged(v, rect)
+                }
+            }
+        }
+    }
+
+    constructor(layout: ViewGroup) {
+        this.layout = layout
+        val childCount = this.layout.childCount
+        for (i in 0 until childCount) {
+            val child = this.layout.getChildAt(i)
+            child.addOnLayoutChangeListener(layoutListener)
+        }
+    }
+
+    private fun onDesiredLocationChanged(v: View, rect: Rect) {
+        if (!sizeAnimationPending) {
+            applyBounds(v, rect, animate = false)
+        }
+        // We need to reapply the current bounds in every frame since the layout may override
+        // the layout bounds making this view jump and not all calls to apply bounds actually
+        // reapply them, for example if there's already an animator to the same target
+        reapplyProperty(v, AnimatableProperty.ABSOLUTE_X);
+        reapplyProperty(v, AnimatableProperty.ABSOLUTE_Y);
+        reapplyProperty(v, AnimatableProperty.WIDTH);
+        reapplyProperty(v, AnimatableProperty.HEIGHT);
+    }
+
+    private fun reapplyProperty(v: View, property: AnimatableProperty) {
+        property.property.set(v, property.property.get(v))
+    }
+
+    private fun applyBounds(v: View, newBounds: Rect, animate: Boolean) {
+        PropertyAnimator.setProperty(v, AnimatableProperty.ABSOLUTE_X, newBounds.left.toFloat(),
+                animationProperties, animate)
+        PropertyAnimator.setProperty(v, AnimatableProperty.ABSOLUTE_Y, newBounds.top.toFloat(),
+                animationProperties, animate)
+        PropertyAnimator.setProperty(v, AnimatableProperty.WIDTH, newBounds.width().toFloat(),
+                animationProperties, animate)
+        PropertyAnimator.setProperty(v, AnimatableProperty.HEIGHT, newBounds.height().toFloat(),
+                animationProperties, animate)
+    }
+
+    private fun startBoundAnimation(v: View) {
+        val target = desiredBounds[v] ?: return
+        applyBounds(v, target, animate = true)
+    }
+
+    fun animatePendingSizeChange(duration: Long, delay: Long) {
+        animationProperties.duration = duration
+        animationProperties.delay = delay
+        if (!sizeAnimationPending) {
+            sizeAnimationPending = true
+            layout.viewTreeObserver.addOnPreDrawListener (
+                    object : ViewTreeObserver.OnPreDrawListener {
+                        override fun onPreDraw(): Boolean {
+                            layout.viewTreeObserver.removeOnPreDrawListener(this)
+                            sizeAnimationPending = false
+                            val childCount = layout.childCount
+                            for (i in 0 until childCount) {
+                                val child = layout.getChildAt(i)
+                                startBoundAnimation(child)
+                            }
+                            return true
+                        }
+                    })
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/LocalMediaManagerFactory.kt b/packages/SystemUI/src/com/android/systemui/media/LocalMediaManagerFactory.kt
new file mode 100644
index 0000000..94a0835
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/LocalMediaManagerFactory.kt
@@ -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 com.android.systemui.media
+
+import android.content.Context
+
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+import com.android.settingslib.media.InfoMediaManager
+import com.android.settingslib.media.LocalMediaManager
+
+import javax.inject.Inject
+
+/**
+ * Factory to create [LocalMediaManager] objects.
+ */
+class LocalMediaManagerFactory @Inject constructor(
+    private val context: Context,
+    private val localBluetoothManager: LocalBluetoothManager?
+) {
+    /** Creates a [LocalMediaManager] for the given package. */
+    fun create(packageName: String): LocalMediaManager {
+        return InfoMediaManager(context, packageName, null, localBluetoothManager).run {
+            LocalMediaManager(context, localBluetoothManager, this, packageName)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 557132b..c7b9326 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -16,10 +16,8 @@
 
 package com.android.systemui.media;
 
-import android.annotation.LayoutRes;
 import android.app.PendingIntent;
 import android.content.ComponentName;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -27,102 +25,95 @@
 import android.content.pm.ResolveInfo;
 import android.content.res.ColorStateList;
 import android.graphics.Bitmap;
-import android.graphics.ImageDecoder;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.GradientDrawable;
 import android.graphics.drawable.Icon;
 import android.graphics.drawable.RippleDrawable;
-import android.media.MediaDescription;
-import android.media.MediaMetadata;
-import android.media.ThumbnailUtils;
 import android.media.session.MediaController;
-import android.media.session.MediaController.PlaybackInfo;
 import android.media.session.MediaSession;
 import android.media.session.PlaybackState;
-import android.net.Uri;
 import android.service.media.MediaBrowserService;
-import android.text.TextUtils;
 import android.util.Log;
-import android.view.LayoutInflater;
 import android.view.View;
-import android.view.View.OnAttachStateChangeListener;
-import android.view.ViewGroup;
 import android.widget.ImageButton;
 import android.widget.ImageView;
-import android.widget.LinearLayout;
+import android.widget.SeekBar;
 import android.widget.TextView;
 
 import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+import androidx.constraintlayout.motion.widget.Key;
+import androidx.constraintlayout.motion.widget.KeyAttributes;
+import androidx.constraintlayout.motion.widget.KeyFrames;
+import androidx.constraintlayout.motion.widget.MotionLayout;
+import androidx.constraintlayout.widget.ConstraintSet;
 import androidx.core.graphics.drawable.RoundedBitmapDrawable;
 import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
 
-import com.android.settingslib.media.LocalMediaManager;
-import com.android.settingslib.media.MediaDevice;
+import com.android.settingslib.Utils;
 import com.android.settingslib.media.MediaOutputSliceConstants;
 import com.android.settingslib.widget.AdaptiveIcon;
 import com.android.systemui.R;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.qs.QSMediaBrowser;
-import com.android.systemui.util.Assert;
+import com.android.systemui.util.concurrency.DelayableExecutor;
 
-import java.io.IOException;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Executor;
 
 /**
- * Base media control panel for System UI
+ * A view controller used for Media Playback.
  */
 public class MediaControlPanel {
     private static final String TAG = "MediaControlPanel";
-    @Nullable private final LocalMediaManager mLocalMediaManager;
+
+    // Button IDs for QS controls
+    static final int[] ACTION_IDS = {
+            R.id.action0,
+            R.id.action1,
+            R.id.action2,
+            R.id.action3,
+            R.id.action4
+    };
+
+    private final SeekBarViewModel mSeekBarViewModel;
+    private SeekBarObserver mSeekBarObserver;
     private final Executor mForegroundExecutor;
     protected final Executor mBackgroundExecutor;
     private final ActivityStarter mActivityStarter;
+    private LayoutAnimationHelper mLayoutAnimationHelper;
 
     private Context mContext;
-    protected LinearLayout mMediaNotifView;
-    private View mSeamless;
+    private PlayerViewHolder mViewHolder;
     private MediaSession.Token mToken;
     private MediaController mController;
-    private int mForegroundColor;
     private int mBackgroundColor;
-    private MediaDevice mDevice;
     protected ComponentName mServiceComponent;
     private boolean mIsRegistered = false;
+    private List<KeyFrames> mKeyFrames;
     private String mKey;
-
-    private final int[] mActionIds;
+    private int mAlbumArtSize;
+    private int mAlbumArtRadius;
+    private int mViewWidth;
 
     public static final String MEDIA_PREFERENCES = "media_control_prefs";
     public static final String MEDIA_PREFERENCE_KEY = "browser_components";
     private SharedPreferences mSharedPrefs;
     private boolean mCheckedForResumption = false;
-    private boolean mIsRemotePlayback;
     private QSMediaBrowser mQSMediaBrowser;
 
-    // Button IDs used in notifications
-    protected static final int[] NOTIF_ACTION_IDS = {
-            com.android.internal.R.id.action0,
-            com.android.internal.R.id.action1,
-            com.android.internal.R.id.action2,
-            com.android.internal.R.id.action3,
-            com.android.internal.R.id.action4
-    };
-
-    // URI fields to try loading album art from
-    private static final String[] ART_URIS = {
-            MediaMetadata.METADATA_KEY_ALBUM_ART_URI,
-            MediaMetadata.METADATA_KEY_ART_URI,
-            MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI
-    };
-
     private final MediaController.Callback mSessionCallback = new MediaController.Callback() {
         @Override
         public void onSessionDestroyed() {
             Log.d(TAG, "session destroyed");
             mController.unregisterCallback(mSessionCallback);
             clearControls();
-            makeInactive();
         }
         @Override
         public void onPlaybackStateChanged(PlaybackState state) {
@@ -130,42 +121,6 @@
             if (s == PlaybackState.STATE_NONE) {
                 Log.d(TAG, "playback state change will trigger resumption, state=" + state);
                 clearControls();
-                makeInactive();
-            }
-        }
-    };
-
-    private final OnAttachStateChangeListener mStateListener = new OnAttachStateChangeListener() {
-        @Override
-        public void onViewAttachedToWindow(View unused) {
-            makeActive();
-        }
-        @Override
-        public void onViewDetachedFromWindow(View unused) {
-            makeInactive();
-        }
-    };
-
-    private final LocalMediaManager.DeviceCallback mDeviceCallback =
-            new LocalMediaManager.DeviceCallback() {
-        @Override
-        public void onDeviceListUpdate(List<MediaDevice> devices) {
-            if (mLocalMediaManager == null) {
-                return;
-            }
-            MediaDevice currentDevice = mLocalMediaManager.getCurrentConnectedDevice();
-            // Check because this can be called several times while changing devices
-            if (mDevice == null || !mDevice.equals(currentDevice)) {
-                mDevice = currentDevice;
-                updateDevice(mDevice);
-            }
-        }
-
-        @Override
-        public void onSelectedDeviceStateChanged(MediaDevice device, int state) {
-            if (mDevice == null || !mDevice.equals(device)) {
-                mDevice = device;
-                updateDevice(mDevice);
             }
         }
     };
@@ -173,40 +128,52 @@
     /**
      * Initialize a new control panel
      * @param context
-     * @param parent
-     * @param routeManager Manager used to listen for device change events.
-     * @param layoutId layout resource to use for this control panel
-     * @param actionIds resource IDs for action buttons in the layout
      * @param foregroundExecutor foreground executor
      * @param backgroundExecutor background executor, used for processing artwork
      * @param activityStarter activity starter
      */
-    public MediaControlPanel(Context context, ViewGroup parent,
-            @Nullable LocalMediaManager routeManager, @LayoutRes int layoutId, int[] actionIds,
-            Executor foregroundExecutor, Executor backgroundExecutor,
-            ActivityStarter activityStarter) {
+    public MediaControlPanel(Context context, Executor foregroundExecutor,
+            DelayableExecutor backgroundExecutor, ActivityStarter activityStarter) {
         mContext = context;
-        LayoutInflater inflater = LayoutInflater.from(mContext);
-        mMediaNotifView = (LinearLayout) inflater.inflate(layoutId, parent, false);
-        // TODO(b/150854549): removeOnAttachStateChangeListener when this doesn't inflate views
-        // mStateListener shouldn't need to be unregistered since this object shares the same
-        // lifecycle with the inflated view. It would be better, however, if this controller used an
-        // attach/detach of views instead of inflating them in the constructor, which would allow
-        // mStateListener to be unregistered in detach.
-        mMediaNotifView.addOnAttachStateChangeListener(mStateListener);
-        mLocalMediaManager = routeManager;
-        mActionIds = actionIds;
         mForegroundExecutor = foregroundExecutor;
         mBackgroundExecutor = backgroundExecutor;
         mActivityStarter = activityStarter;
+        mSeekBarViewModel = new SeekBarViewModel(backgroundExecutor);
+        loadDimens();
+    }
+
+    public void onDestroy() {
+        if (mSeekBarObserver != null) {
+            mSeekBarViewModel.getProgress().removeObserver(mSeekBarObserver);
+        }
+        mSeekBarViewModel.onDestroy();
+    }
+
+    private void loadDimens() {
+        mAlbumArtRadius = mContext.getResources().getDimensionPixelSize(
+                Utils.getThemeAttr(mContext, android.R.attr.dialogCornerRadius));
+        mAlbumArtSize = mContext.getResources().getDimensionPixelSize(R.dimen.qs_media_album_size);
     }
 
     /**
-     * Get the view used to display media controls
-     * @return the view
+     * Get the view holder used to display media controls
+     * @return the view holder
      */
-    public View getView() {
-        return mMediaNotifView;
+    @Nullable
+    public PlayerViewHolder getView() {
+        return mViewHolder;
+    }
+
+    /**
+     * Sets the listening state of the player.
+     *
+     * Should be set to true when the QS panel is open. Otherwise, false. This is a signal to avoid
+     * unnecessary work when the QS panel is closed.
+     *
+     * @param listening True when player should be active. Otherwise, false.
+     */
+    public void setListening(boolean listening) {
+        mSeekBarViewModel.setListening(listening);
     }
 
     /**
@@ -217,21 +184,29 @@
         return mContext;
     }
 
+    /** Attaches the player to the view holder. */
+    public void attach(PlayerViewHolder vh) {
+        mViewHolder = vh;
+        MotionLayout motionView = vh.getPlayer();
+        mLayoutAnimationHelper = new LayoutAnimationHelper(motionView);
+        GoneChildrenHideHelper.clipGoneChildrenOnLayout(motionView);
+        mKeyFrames = motionView.getDefinedTransitions().get(0).getKeyFrameList();
+        mSeekBarObserver = new SeekBarObserver(vh);
+        mSeekBarViewModel.getProgress().observeForever(mSeekBarObserver);
+        SeekBar bar = vh.getSeekBar();
+        bar.setOnSeekBarChangeListener(mSeekBarViewModel.getSeekBarListener());
+        bar.setOnTouchListener(mSeekBarViewModel.getSeekBarTouchListener());
+    }
+
     /**
-     * Update the media panel view for the given media session
-     * @param token
-     * @param iconDrawable
-     * @param largeIcon
-     * @param iconColor
-     * @param bgColor
-     * @param contentIntent
-     * @param appNameString
-     * @param key
+     * Bind this view based on the data given
      */
-    public void setMediaSession(MediaSession.Token token, Drawable iconDrawable, Icon largeIcon,
-            int iconColor, int bgColor, PendingIntent contentIntent, String appNameString,
-            String key) {
-        // Ensure that component names are updated if token has changed
+    public void bind(@NotNull MediaData data) {
+        if (mViewHolder == null) {
+            return;
+        }
+        MediaSession.Token token = data.getToken();
+        mBackgroundColor = data.getBackgroundColor();
         if (mToken == null || !mToken.equals(token)) {
             if (mQSMediaBrowser != null) {
                 Log.d(TAG, "Disconnecting old media browser");
@@ -243,20 +218,21 @@
             mCheckedForResumption = false;
         }
 
-        mForegroundColor = iconColor;
-        mBackgroundColor = bgColor;
         mController = new MediaController(mContext, mToken);
-        mKey = key;
+
+        ConstraintSet expandedSet = mViewHolder.getPlayer().getConstraintSet(R.id.expanded);
+        ConstraintSet collapsedSet = mViewHolder.getPlayer().getConstraintSet(R.id.collapsed);
 
         // Try to find a browser service component for this app
         // TODO also check for a media button receiver intended for restarting (b/154127084)
         // Only check if we haven't tried yet or the session token changed
-        final String pkgName = mController.getPackageName();
+        final String pkgName = data.getPackageName();
         if (mServiceComponent == null && !mCheckedForResumption) {
             Log.d(TAG, "Checking for service component");
             PackageManager pm = mContext.getPackageManager();
             Intent resumeIntent = new Intent(MediaBrowserService.SERVICE_INTERFACE);
             List<ResolveInfo> resumeInfo = pm.queryIntentServices(resumeIntent, 0);
+            // TODO: look into this resumption
             if (resumeInfo != null) {
                 for (ResolveInfo inf : resumeInfo) {
                     if (inf.serviceInfo.packageName.equals(mController.getPackageName())) {
@@ -271,83 +247,191 @@
 
         mController.registerCallback(mSessionCallback);
 
-        mMediaNotifView.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor));
+        mViewHolder.getBackground().setBackgroundTintList(
+                ColorStateList.valueOf(mBackgroundColor));
 
         // Click action
-        if (contentIntent != null) {
-            mMediaNotifView.setOnClickListener(v -> {
-                mActivityStarter.postStartActivityDismissingKeyguard(contentIntent);
+        PendingIntent clickIntent = data.getClickIntent();
+        if (clickIntent != null) {
+            mViewHolder.getPlayer().setOnClickListener(v -> {
+                mActivityStarter.postStartActivityDismissingKeyguard(clickIntent);
             });
         }
 
+        ImageView albumView = mViewHolder.getAlbumView();
+        // TODO: migrate this to a view with rounded corners instead of baking the rounding
+        // into the bitmap
+        Drawable artwork = createRoundedBitmap(data.getArtwork());
+        albumView.setImageDrawable(artwork);
+
         // App icon
-        ImageView appIcon = mMediaNotifView.findViewById(R.id.icon);
-        iconDrawable.setTint(mForegroundColor);
-        appIcon.setImageDrawable(iconDrawable);
-
-        // Transfer chip
-        mSeamless = mMediaNotifView.findViewById(R.id.media_seamless);
-        if (mSeamless != null) {
-            if (mLocalMediaManager != null) {
-                mSeamless.setVisibility(View.VISIBLE);
-                updateDevice(mLocalMediaManager.getCurrentConnectedDevice());
-                mSeamless.setOnClickListener(v -> {
-                    final Intent intent = new Intent()
-                            .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
-                            .putExtra(MediaOutputSliceConstants.EXTRA_PACKAGE_NAME,
-                                    mController.getPackageName())
-                            .putExtra(MediaOutputSliceConstants.KEY_MEDIA_SESSION_TOKEN, mToken);
-                    mActivityStarter.startActivity(intent, false, true /* dismissShade */,
-                            Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
-                });
-            } else {
-                Log.d(TAG, "LocalMediaManager is null. Not binding output chip for pkg=" + pkgName);
-            }
-        }
-        PlaybackInfo playbackInfo = mController.getPlaybackInfo();
-        if (playbackInfo != null) {
-            mIsRemotePlayback = playbackInfo.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE;
-        } else {
-            Log.d(TAG, "PlaybackInfo was null. Defaulting to local playback.");
-            mIsRemotePlayback = false;
-        }
-
-        makeActive();
-
-        // App title (not in mini player)
-        TextView appName = mMediaNotifView.findViewById(R.id.app_name);
-        if (appName != null) {
-            appName.setText(appNameString);
-            appName.setTextColor(mForegroundColor);
-        }
-
-        // Can be null!
-        MediaMetadata mediaMetadata = mController.getMetadata();
-
-        ImageView albumView = mMediaNotifView.findViewById(R.id.album_art);
-        if (albumView != null) {
-            // Resize art in a background thread
-            mBackgroundExecutor.execute(() -> processAlbumArt(mediaMetadata, largeIcon, albumView));
-        }
+        ImageView appIcon = mViewHolder.getAppIcon();
+        appIcon.setImageDrawable(data.getAppIcon());
 
         // Song name
-        TextView titleText = mMediaNotifView.findViewById(R.id.header_title);
-        String songName = "";
-        if (mediaMetadata != null) {
-            songName = mediaMetadata.getString(MediaMetadata.METADATA_KEY_TITLE);
-        }
-        titleText.setText(songName);
-        titleText.setTextColor(mForegroundColor);
+        TextView titleText = mViewHolder.getTitleText();
+        titleText.setText(data.getSong());
 
-        // Artist name (not in mini player)
-        TextView artistText = mMediaNotifView.findViewById(R.id.header_artist);
-        if (artistText != null) {
-            String artistName = "";
-            if (mediaMetadata != null) {
-                artistName = mediaMetadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
+        // App title
+        TextView appName = mViewHolder.getAppName();
+        appName.setText(data.getApp());
+
+        // Artist name
+        TextView artistText = mViewHolder.getArtistText();
+        artistText.setText(data.getArtist());
+
+        // Transfer chip
+        mViewHolder.getSeamless().setVisibility(View.VISIBLE);
+        setVisibleAndAlpha(collapsedSet, R.id.media_seamless, true /*visible */);
+        setVisibleAndAlpha(expandedSet, R.id.media_seamless, true /*visible */);
+        mViewHolder.getSeamless().setOnClickListener(v -> {
+            final Intent intent = new Intent()
+                    .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
+                    .putExtra(MediaOutputSliceConstants.EXTRA_PACKAGE_NAME,
+                            mController.getPackageName())
+                    .putExtra(MediaOutputSliceConstants.KEY_MEDIA_SESSION_TOKEN, mToken);
+            mActivityStarter.startActivity(intent, false, true /* dismissShade */,
+                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        });
+
+        ImageView iconView = mViewHolder.getSeamlessIcon();
+        TextView deviceName = mViewHolder.getSeamlessText();
+
+        // Update the outline color
+        RippleDrawable bkgDrawable = (RippleDrawable) mViewHolder.getSeamless().getBackground();
+        GradientDrawable rect = (GradientDrawable) bkgDrawable.getDrawable(0);
+        rect.setStroke(2, deviceName.getCurrentTextColor());
+        rect.setColor(Color.TRANSPARENT);
+
+        final MediaDeviceData device = data.getDevice();
+        if (device != null && !device.getEnabled()) {
+            mViewHolder.getSeamless().setEnabled(false);
+            // TODO(b/156875717): setEnabled should cause the alpha to change.
+            mViewHolder.getSeamless().setAlpha(0.38f);
+            iconView.setImageResource(R.drawable.ic_hardware_speaker);
+            iconView.setVisibility(View.VISIBLE);
+            deviceName.setText(R.string.media_seamless_remote_device);
+        } else if (device != null) {
+            mViewHolder.getSeamless().setEnabled(true);
+            mViewHolder.getSeamless().setAlpha(1f);
+            Drawable icon = device.getIcon();
+            iconView.setVisibility(View.VISIBLE);
+
+            if (icon instanceof AdaptiveIcon) {
+                AdaptiveIcon aIcon = (AdaptiveIcon) icon;
+                aIcon.setBackgroundColor(mBackgroundColor);
+                iconView.setImageDrawable(aIcon);
+            } else {
+                iconView.setImageDrawable(icon);
             }
-            artistText.setText(artistName);
-            artistText.setTextColor(mForegroundColor);
+            deviceName.setText(device.getName());
+        } else {
+            // Reset to default
+            Log.w(TAG, "device is null. Not binding output chip.");
+            mViewHolder.getSeamless().setEnabled(true);
+            mViewHolder.getSeamless().setAlpha(1f);
+            iconView.setVisibility(View.GONE);
+            deviceName.setText(com.android.internal.R.string.ext_media_seamless_action);
+        }
+
+        List<Integer> actionsWhenCollapsed = data.getActionsToShowInCompact();
+        // Media controls
+        int i = 0;
+        List<MediaAction> actionIcons = data.getActions();
+        for (; i < actionIcons.size() && i < ACTION_IDS.length; i++) {
+            int actionId = ACTION_IDS[i];
+            final ImageButton button = mViewHolder.getAction(actionId);
+            MediaAction mediaAction = actionIcons.get(i);
+            button.setImageDrawable(mediaAction.getDrawable());
+            button.setContentDescription(mediaAction.getContentDescription());
+            PendingIntent actionIntent = mediaAction.getIntent();
+
+            button.setOnClickListener(v -> {
+                if (actionIntent != null) {
+                    try {
+                        actionIntent.send();
+                    } catch (PendingIntent.CanceledException e) {
+                        e.printStackTrace();
+                    }
+                }
+            });
+            boolean visibleInCompat = actionsWhenCollapsed.contains(i);
+            updateKeyFrameVisibility(actionId, visibleInCompat);
+            setVisibleAndAlpha(collapsedSet, actionId, visibleInCompat);
+            setVisibleAndAlpha(expandedSet, actionId, true /*visible */);
+        }
+
+        // Hide any unused buttons
+        for (; i < ACTION_IDS.length; i++) {
+            setVisibleAndAlpha(expandedSet, ACTION_IDS[i], false /*visible */);
+            setVisibleAndAlpha(collapsedSet, ACTION_IDS[i], false /*visible */);
+        }
+
+        // Seek Bar
+        final MediaController controller = getController();
+        mBackgroundExecutor.execute(() -> mSeekBarViewModel.updateController(controller));
+
+        // Set up long press menu
+        // TODO: b/156036025 bring back media guts
+
+        // Update both constraint sets to regenerate the animation.
+        mViewHolder.getPlayer().updateState(R.id.collapsed, collapsedSet);
+        mViewHolder.getPlayer().updateState(R.id.expanded, expandedSet);
+    }
+
+    @UiThread
+    private Drawable createRoundedBitmap(Icon icon) {
+        if (icon == null) {
+            return null;
+        }
+        // Let's scale down the View, such that the content always nicely fills the view.
+        // ThumbnailUtils actually scales it down such that it may not be filled for odd aspect
+        // ratios
+        Drawable drawable = icon.loadDrawable(mContext);
+        float aspectRatio = drawable.getIntrinsicHeight() / (float) drawable.getIntrinsicWidth();
+        Rect bounds;
+        if (aspectRatio > 1.0f) {
+            bounds = new Rect(0, 0, mAlbumArtSize, (int) (mAlbumArtSize * aspectRatio));
+        } else {
+            bounds = new Rect(0, 0, (int) (mAlbumArtSize / aspectRatio), mAlbumArtSize);
+        }
+        if (bounds.width() > mAlbumArtSize || bounds.height() > mAlbumArtSize) {
+            float offsetX = (bounds.width() - mAlbumArtSize) / 2.0f;
+            float offsetY = (bounds.height() - mAlbumArtSize) / 2.0f;
+            bounds.offset((int) -offsetX,(int) -offsetY);
+        }
+        drawable.setBounds(bounds);
+        Bitmap scaled = Bitmap.createBitmap(mAlbumArtSize, mAlbumArtSize,
+                Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(scaled);
+        drawable.draw(canvas);
+        RoundedBitmapDrawable artwork = RoundedBitmapDrawableFactory.create(
+                mContext.getResources(), scaled);
+        artwork.setCornerRadius(mAlbumArtRadius);
+        return artwork;
+    }
+
+    /**
+     * Updates the keyframe visibility such that only views that are not visible actually go
+     * through a transition and fade in.
+     *
+     * @param actionId the id to change
+     * @param visible is the view visible
+     */
+    private void updateKeyFrameVisibility(int actionId, boolean visible) {
+        if (mKeyFrames == null) {
+            return;
+        }
+        for (int i = 0; i < mKeyFrames.size(); i++) {
+            KeyFrames keyframe = mKeyFrames.get(i);
+            ArrayList<Key> viewKeyFrames = keyframe.getKeyFramesForView(actionId);
+            for (int j = 0; j < viewKeyFrames.size(); j++) {
+                Key key = viewKeyFrames.get(j);
+                if (key instanceof KeyAttributes) {
+                    KeyAttributes attributes = (KeyAttributes) key;
+                    attributes.setValue("alpha", visible ? 1.0f : 0.0f);
+                }
+            }
         }
     }
 
@@ -421,179 +505,6 @@
     }
 
     /**
-     * Process album art for layout
-     * @param description media description
-     * @param albumView view to hold the album art
-     */
-    protected void processAlbumArt(MediaDescription description, ImageView albumView) {
-        Bitmap albumArt = null;
-
-        // First try loading from URI
-        albumArt = loadBitmapFromUri(description.getIconUri());
-
-        // Then check bitmap
-        if (albumArt == null) {
-            albumArt = description.getIconBitmap();
-        }
-
-        processAlbumArtInternal(albumArt, albumView);
-    }
-
-    /**
-     * Process album art for layout
-     * @param metadata media metadata
-     * @param largeIcon from notification, checked as a fallback if metadata does not have art
-     * @param albumView view to hold the album art
-     */
-    private void processAlbumArt(MediaMetadata metadata, Icon largeIcon, ImageView albumView) {
-        Bitmap albumArt = null;
-
-        if (metadata != null) {
-            // First look in URI fields
-            for (String field : ART_URIS) {
-                String uriString = metadata.getString(field);
-                if (!TextUtils.isEmpty(uriString)) {
-                    albumArt = loadBitmapFromUri(Uri.parse(uriString));
-                    if (albumArt != null) {
-                        Log.d(TAG, "loaded art from " + field);
-                        break;
-                    }
-                }
-            }
-
-            // Then check bitmap field
-            if (albumArt == null) {
-                albumArt = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
-            }
-        }
-
-        // Finally try the notification's largeIcon
-        if (albumArt == null && largeIcon != null) {
-            albumArt = largeIcon.getBitmap();
-        }
-
-        processAlbumArtInternal(albumArt, albumView);
-    }
-
-    /**
-     * Load a bitmap from a URI
-     * @param uri
-     * @return bitmap, or null if couldn't be loaded
-     */
-    private Bitmap loadBitmapFromUri(Uri uri) {
-        // ImageDecoder requires a scheme of the following types
-        if (uri.getScheme() == null) {
-            return null;
-        }
-
-        if (!uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)
-                && !uri.getScheme().equals(ContentResolver.SCHEME_ANDROID_RESOURCE)
-                && !uri.getScheme().equals(ContentResolver.SCHEME_FILE)) {
-            return null;
-        }
-
-        ImageDecoder.Source source = ImageDecoder.createSource(mContext.getContentResolver(), uri);
-        try {
-            return ImageDecoder.decodeBitmap(source);
-        } catch (IOException e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-    /**
-     * Resize and crop the image if provided and update the control view
-     * @param albumArt Bitmap of art to display, or null to hide view
-     * @param albumView View that will hold the art
-     */
-    private void processAlbumArtInternal(@Nullable Bitmap albumArt, ImageView albumView) {
-        // Resize
-        RoundedBitmapDrawable roundedDrawable = null;
-        if (albumArt != null) {
-            float radius = mContext.getResources().getDimension(R.dimen.qs_media_corner_radius);
-            Bitmap original = albumArt.copy(Bitmap.Config.ARGB_8888, true);
-            int albumSize = (int) mContext.getResources().getDimension(
-                    R.dimen.qs_media_album_size);
-            Bitmap scaled = ThumbnailUtils.extractThumbnail(original, albumSize, albumSize);
-            roundedDrawable = RoundedBitmapDrawableFactory.create(mContext.getResources(), scaled);
-            roundedDrawable.setCornerRadius(radius);
-        } else {
-            Log.e(TAG, "No album art available");
-        }
-
-        // Now that it's resized, update the UI
-        final RoundedBitmapDrawable result = roundedDrawable;
-        mForegroundExecutor.execute(() -> {
-            if (result != null) {
-                albumView.setImageDrawable(result);
-                albumView.setVisibility(View.VISIBLE);
-            } else {
-                albumView.setImageDrawable(null);
-                albumView.setVisibility(View.GONE);
-            }
-        });
-    }
-
-    /**
-     * Update the current device information
-     * @param device device information to display
-     */
-    private void updateDevice(MediaDevice device) {
-        if (mSeamless == null) {
-            return;
-        }
-        mForegroundExecutor.execute(() -> {
-            updateChipInternal(device);
-        });
-    }
-
-    private void updateChipInternal(MediaDevice device) {
-        ColorStateList fgTintList = ColorStateList.valueOf(mForegroundColor);
-
-        // Update the outline color
-        LinearLayout viewLayout = (LinearLayout) mSeamless;
-        RippleDrawable bkgDrawable = (RippleDrawable) viewLayout.getBackground();
-        GradientDrawable rect = (GradientDrawable) bkgDrawable.getDrawable(0);
-        rect.setStroke(2, mForegroundColor);
-        rect.setColor(mBackgroundColor);
-
-        ImageView iconView = mSeamless.findViewById(R.id.media_seamless_image);
-        TextView deviceName = mSeamless.findViewById(R.id.media_seamless_text);
-        deviceName.setTextColor(fgTintList);
-
-        if (mIsRemotePlayback) {
-            mSeamless.setEnabled(false);
-            mSeamless.setAlpha(0.38f);
-            iconView.setImageResource(R.drawable.ic_hardware_speaker);
-            iconView.setVisibility(View.VISIBLE);
-            iconView.setImageTintList(fgTintList);
-            deviceName.setText(R.string.media_seamless_remote_device);
-        } else if (device != null) {
-            mSeamless.setEnabled(true);
-            mSeamless.setAlpha(1f);
-            Drawable icon = device.getIcon();
-            iconView.setVisibility(View.VISIBLE);
-            iconView.setImageTintList(fgTintList);
-
-            if (icon instanceof AdaptiveIcon) {
-                AdaptiveIcon aIcon = (AdaptiveIcon) icon;
-                aIcon.setBackgroundColor(mBackgroundColor);
-                iconView.setImageDrawable(aIcon);
-            } else {
-                iconView.setImageDrawable(icon);
-            }
-            deviceName.setText(device.getName());
-        } else {
-            // Reset to default
-            Log.d(TAG, "device is null. Not binding output chip.");
-            mSeamless.setEnabled(true);
-            mSeamless.setAlpha(1f);
-            iconView.setVisibility(View.GONE);
-            deviceName.setText(com.android.internal.R.string.ext_media_seamless_action);
-        }
-    }
-
-    /**
      * Puts controls into a resumption state if possible, or calls removePlayer if no component was
      * found that could resume playback
      */
@@ -612,16 +523,20 @@
      * Hide the media buttons and show only a restart button
      */
     protected void resetButtons() {
+        if (mViewHolder == null) {
+            return;
+        }
         // Hide all the old buttons
-        for (int i = 0; i < mActionIds.length; i++) {
-            ImageButton thisBtn = mMediaNotifView.findViewById(mActionIds[i]);
-            if (thisBtn != null) {
-                thisBtn.setVisibility(View.GONE);
-            }
+
+        ConstraintSet expandedSet = mViewHolder.getPlayer().getConstraintSet(R.id.expanded);
+        ConstraintSet collapsedSet = mViewHolder.getPlayer().getConstraintSet(R.id.collapsed);
+        for (int i = 1; i < ACTION_IDS.length; i++) {
+            setVisibleAndAlpha(expandedSet, ACTION_IDS[i], false /*visible */);
+            setVisibleAndAlpha(collapsedSet, ACTION_IDS[i], false /*visible */);
         }
 
         // Add a restart button
-        ImageButton btn = mMediaNotifView.findViewById(mActionIds[0]);
+        ImageButton btn = mViewHolder.getAction0();
         btn.setOnClickListener(v -> {
             Log.d(TAG, "Attempting to restart session");
             if (mQSMediaBrowser != null) {
@@ -642,30 +557,25 @@
             mQSMediaBrowser.restart();
         });
         btn.setImageDrawable(mContext.getResources().getDrawable(R.drawable.lb_ic_play));
-        btn.setImageTintList(ColorStateList.valueOf(mForegroundColor));
-        btn.setVisibility(View.VISIBLE);
+        setVisibleAndAlpha(expandedSet, ACTION_IDS[0], true /*visible */);
+        setVisibleAndAlpha(collapsedSet, ACTION_IDS[0], true /*visible */);
+
+        mSeekBarViewModel.clearController();
+        // TODO: fix guts
+        //        View guts = mMediaNotifView.findViewById(R.id.media_guts);
+        View options = mViewHolder.getOptions();
+
+        mViewHolder.getPlayer().setOnLongClickListener(v -> {
+            // Replace player view with close/cancel view
+//            guts.setVisibility(View.GONE);
+            options.setVisibility(View.VISIBLE);
+            return true; // consumed click
+        });
     }
 
-    private void makeActive() {
-        Assert.isMainThread();
-        if (!mIsRegistered) {
-            if (mLocalMediaManager != null) {
-                mLocalMediaManager.registerCallback(mDeviceCallback);
-                mLocalMediaManager.startScan();
-            }
-            mIsRegistered = true;
-        }
-    }
-
-    private void makeInactive() {
-        Assert.isMainThread();
-        if (mIsRegistered) {
-            if (mLocalMediaManager != null) {
-                mLocalMediaManager.stopScan();
-                mLocalMediaManager.unregisterCallback(mDeviceCallback);
-            }
-            mIsRegistered = false;
-        }
+    private void setVisibleAndAlpha(ConstraintSet set, int actionId, boolean visible) {
+        set.setVisibility(actionId, visible? ConstraintSet.VISIBLE : ConstraintSet.GONE);
+        set.setAlpha(actionId, visible ? 1.0f : 0.0f);
     }
 
     /**
@@ -739,4 +649,33 @@
      * Called when a player can't be resumed to give it an opportunity to hide or remove itself
      */
     protected void removePlayer() { }
+
+    public void measure(@Nullable MediaMeasurementInput input) {
+        if (mViewHolder == null) {
+            return;
+        }
+        if (input != null) {
+            int width = input.getWidth();
+            setPlayerWidth(width);
+            mViewHolder.getPlayer().measure(input.getWidthMeasureSpec(),
+                    input.getHeightMeasureSpec());
+        }
+    }
+
+    public void setPlayerWidth(int width) {
+        if (mViewHolder == null) {
+            return;
+        }
+        MotionLayout view = mViewHolder.getPlayer();
+        ConstraintSet expandedSet = view.getConstraintSet(R.id.expanded);
+        ConstraintSet collapsedSet = view.getConstraintSet(R.id.collapsed);
+        collapsedSet.setGuidelineBegin(R.id.view_width, width);
+        expandedSet.setGuidelineBegin(R.id.view_width, width);
+        view.updateState(R.id.collapsed, collapsedSet);
+        view.updateState(R.id.expanded, expandedSet);
+    }
+
+    public void animatePendingSizeChange(long duration, long startDelay) {
+        mLayoutAnimationHelper.animatePendingSizeChange(duration, startDelay);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
new file mode 100644
index 0000000..330a5c0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
@@ -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 com.android.systemui.media
+
+import android.app.PendingIntent
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.Icon
+import android.media.session.MediaSession
+
+/** State of a media view. */
+data class MediaData(
+    val initialized: Boolean = false,
+    val backgroundColor: Int,
+    val app: String?,
+    val appIcon: Drawable?,
+    val artist: CharSequence?,
+    val song: CharSequence?,
+    val artwork: Icon?,
+    val actions: List<MediaAction>,
+    val actionsToShowInCompact: List<Int>,
+    val packageName: String?,
+    val token: MediaSession.Token?,
+    val clickIntent: PendingIntent?,
+    val device: MediaDeviceData?
+)
+
+/** State of a media action. */
+data class MediaAction(
+    val drawable: Drawable?,
+    val intent: PendingIntent?,
+    val contentDescription: CharSequence?
+)
+
+/** State of the media device. */
+data class MediaDeviceData(
+    val enabled: Boolean,
+    val icon: Drawable?,
+    val name: String?
+)
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt
new file mode 100644
index 0000000..cce9838
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media
+
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * Combines updates from [MediaDataManager] with [MediaDeviceManager].
+ */
+@Singleton
+class MediaDataCombineLatest @Inject constructor(
+    private val dataSource: MediaDataManager,
+    private val deviceSource: MediaDeviceManager
+) {
+    private val listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf()
+    private val entries: MutableMap<String, Pair<MediaData?, MediaDeviceData?>> = mutableMapOf()
+
+    init {
+        dataSource.addListener(object : MediaDataManager.Listener {
+            override fun onMediaDataLoaded(key: String, data: MediaData) {
+                entries[key] = data to entries[key]?.second
+                update(key)
+            }
+            override fun onMediaDataRemoved(key: String) {
+                remove(key)
+            }
+        })
+        deviceSource.addListener(object : MediaDeviceManager.Listener {
+            override fun onMediaDeviceChanged(key: String, data: MediaDeviceData?) {
+                entries[key] = entries[key]?.first to data
+                update(key)
+            }
+            override fun onKeyRemoved(key: String) {
+                remove(key)
+            }
+        })
+    }
+
+    /**
+     * Add a listener for [MediaData] changes that has been combined with latest [MediaDeviceData].
+     */
+    fun addListener(listener: MediaDataManager.Listener) = listeners.add(listener)
+
+    /**
+     * Remove a listener registered with addListener.
+     */
+    fun removeListener(listener: MediaDataManager.Listener) = listeners.remove(listener)
+
+    private fun update(key: String) {
+        val (entry, device) = entries[key] ?: null to null
+        if (entry != null && device != null) {
+            val data = entry.copy(device = device)
+            listeners.forEach {
+                it.onMediaDataLoaded(key, data)
+            }
+        }
+    }
+
+    private fun remove(key: String) {
+        entries.remove(key)?.let {
+            listeners.forEach {
+                it.onMediaDataRemoved(key)
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
new file mode 100644
index 0000000..8cbe3ec
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media
+
+import android.app.Notification
+import android.content.ContentResolver
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.ImageDecoder
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.Icon
+import android.media.MediaMetadata
+import android.media.session.MediaSession
+import android.net.Uri
+import android.service.notification.StatusBarNotification
+import android.text.TextUtils
+import android.util.Log
+import com.android.internal.graphics.ColorUtils
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.statusbar.notification.MediaNotificationProcessor
+import com.android.systemui.statusbar.notification.row.HybridGroupManager
+import com.android.systemui.util.Utils
+import java.io.IOException
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import javax.inject.Singleton
+
+// URI fields to try loading album art from
+private val ART_URIS = arrayOf(
+        MediaMetadata.METADATA_KEY_ALBUM_ART_URI,
+        MediaMetadata.METADATA_KEY_ART_URI,
+        MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI
+)
+
+private const val TAG = "MediaDataManager"
+private const val DEFAULT_LUMINOSITY = 0.25f
+private const val LUMINOSITY_THRESHOLD = 0.05f
+private const val SATURATION_MULTIPLIER = 0.8f
+
+private val LOADING = MediaData(false, 0, null, null, null, null, null,
+        emptyList(), emptyList(), null, null, null, null)
+
+fun isMediaNotification(sbn: StatusBarNotification): Boolean {
+    if (!sbn.notification.hasMediaSession()) {
+        return false
+    }
+    val notificationStyle = sbn.notification.notificationStyle
+    if (Notification.DecoratedMediaCustomViewStyle::class.java.equals(notificationStyle) ||
+            Notification.MediaStyle::class.java.equals(notificationStyle)) {
+        return true
+    }
+    return false
+}
+
+/**
+ * A class that facilitates management and loading of Media Data, ready for binding.
+ */
+@Singleton
+class MediaDataManager @Inject constructor(
+    private val context: Context,
+    private val mediaControllerFactory: MediaControllerFactory,
+    @Background private val backgroundExecutor: Executor,
+    @Main private val foregroundExecutor: Executor
+) {
+
+    private val listeners: MutableSet<Listener> = mutableSetOf()
+    private val mediaEntries: LinkedHashMap<String, MediaData> = LinkedHashMap()
+
+    fun onNotificationAdded(key: String, sbn: StatusBarNotification) {
+        if (Utils.useQsMediaPlayer(context) && isMediaNotification(sbn)) {
+            if (!mediaEntries.containsKey(key)) {
+                mediaEntries.put(key, LOADING)
+            }
+            loadMediaData(key, sbn)
+        } else {
+            onNotificationRemoved(key)
+        }
+    }
+
+    private fun loadMediaData(key: String, sbn: StatusBarNotification) {
+        backgroundExecutor.execute {
+            loadMediaDataInBg(key, sbn)
+        }
+    }
+
+    /**
+     * Add a listener for changes in this class
+     */
+    fun addListener(listener: Listener) = listeners.add(listener)
+
+    /**
+     * Remove a listener for changes in this class
+     */
+    fun removeListener(listener: Listener) = listeners.remove(listener)
+
+    private fun loadMediaDataInBg(key: String, sbn: StatusBarNotification) {
+        val token = sbn.notification.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION)
+                as MediaSession.Token?
+        val metadata = mediaControllerFactory.create(token).metadata
+
+        if (metadata == null) {
+            // TODO: handle this better, removing media notification
+            return
+        }
+
+        // Foreground and Background colors computed from album art
+        val notif: Notification = sbn.notification
+        var bgColor = Color.WHITE
+        var artworkBitmap = metadata.getBitmap(MediaMetadata.METADATA_KEY_ART)
+        if (artworkBitmap == null) {
+            artworkBitmap = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART)
+        }
+        if (artworkBitmap == null) {
+            artworkBitmap = loadBitmapFromUri(metadata)
+        }
+        val artWorkIcon = if (artworkBitmap == null) {
+            notif.getLargeIcon()
+        } else {
+            Icon.createWithBitmap(artworkBitmap)
+        }
+        if (artWorkIcon != null) {
+            // If we have art, get colors from that
+            if (artworkBitmap == null) {
+                if (artWorkIcon.type == Icon.TYPE_BITMAP ||
+                        artWorkIcon.type == Icon.TYPE_ADAPTIVE_BITMAP) {
+                    artworkBitmap = artWorkIcon.bitmap
+                } else {
+                    val drawable: Drawable = artWorkIcon.loadDrawable(context)
+                    artworkBitmap = Bitmap.createBitmap(
+                            drawable.intrinsicWidth,
+                            drawable.intrinsicHeight,
+                            Bitmap.Config.ARGB_8888)
+                    val canvas = Canvas(artworkBitmap)
+                    drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight)
+                    drawable.draw(canvas)
+                }
+            }
+            val p = MediaNotificationProcessor.generateArtworkPaletteBuilder(artworkBitmap)
+                    .generate()
+            val swatch = MediaNotificationProcessor.findBackgroundSwatch(p)
+            bgColor = swatch.rgb
+        }
+        // Adapt background color, so it's always subdued and text is legible
+        val tmpHsl = floatArrayOf(0f, 0f, 0f)
+        ColorUtils.colorToHSL(bgColor, tmpHsl)
+
+        val l = tmpHsl[2]
+        // Colors with very low luminosity can have any saturation. This means that changing the
+        // luminosity can make a black become red. Let's remove the saturation of very light or
+        // very dark colors to avoid this issue.
+        if (l < LUMINOSITY_THRESHOLD || l > 1f - LUMINOSITY_THRESHOLD) {
+            tmpHsl[1] = 0f
+        }
+        tmpHsl[1] *= SATURATION_MULTIPLIER
+        tmpHsl[2] = DEFAULT_LUMINOSITY
+
+        bgColor = ColorUtils.HSLToColor(tmpHsl)
+
+        // App name
+        val builder = Notification.Builder.recoverBuilder(context, notif)
+        val app = builder.loadHeaderAppName()
+
+        // App Icon
+        val smallIconDrawable: Drawable = sbn.notification.smallIcon.loadDrawable(context)
+
+        // Song name
+        var song: CharSequence? = metadata.getString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE)
+        if (song == null) {
+            song = metadata.getString(MediaMetadata.METADATA_KEY_TITLE)
+        }
+        if (song == null) {
+            song = HybridGroupManager.resolveTitle(notif)
+        }
+
+        // Artist name
+        var artist: CharSequence? = metadata.getString(MediaMetadata.METADATA_KEY_ARTIST)
+        if (artist == null) {
+            artist = HybridGroupManager.resolveText(notif)
+        }
+
+        // Control buttons
+        val actionIcons: MutableList<MediaAction> = ArrayList()
+        val actions = notif.actions
+        val actionsToShowCollapsed = notif.extras.getIntArray(
+                Notification.EXTRA_COMPACT_ACTIONS)?.toList() ?: emptyList()
+        // TODO: b/153736623 look into creating actions when this isn't a media style notification
+
+        val packageContext: Context = sbn.getPackageContext(context)
+        if (actions != null) {
+            for (action in actions) {
+                val mediaAction = MediaAction(
+                        action.getIcon().loadDrawable(packageContext),
+                        action.actionIntent,
+                        action.title)
+                actionIcons.add(mediaAction)
+            }
+        }
+
+        foregroundExecutor.execute {
+            onMediaDataLoaded(key, MediaData(true, bgColor, app, smallIconDrawable, artist, song,
+                    artWorkIcon, actionIcons, actionsToShowCollapsed, sbn.packageName, token,
+                    notif.contentIntent, null))
+        }
+    }
+
+    /**
+     * Load a bitmap from the various Art metadata URIs
+     */
+    private fun loadBitmapFromUri(metadata: MediaMetadata): Bitmap? {
+        for (uri in ART_URIS) {
+            val uriString = metadata.getString(uri)
+            if (!TextUtils.isEmpty(uriString)) {
+                val albumArt = loadBitmapFromUri(Uri.parse(uriString))
+                if (albumArt != null) {
+                    Log.d(TAG, "loaded art from $uri")
+                    break
+                }
+            }
+        }
+        return null
+    }
+
+    /**
+     * Load a bitmap from a URI
+     * @param uri the uri to load
+     * @return bitmap, or null if couldn't be loaded
+     */
+    private fun loadBitmapFromUri(uri: Uri): Bitmap? {
+        // ImageDecoder requires a scheme of the following types
+        if (uri.scheme == null) {
+            return null
+        }
+
+        if (!uri.scheme.equals(ContentResolver.SCHEME_CONTENT) &&
+                !uri.scheme.equals(ContentResolver.SCHEME_ANDROID_RESOURCE) &&
+                !uri.scheme.equals(ContentResolver.SCHEME_FILE)) {
+            return null
+        }
+
+        val source = ImageDecoder.createSource(context.getContentResolver(), uri)
+        return try {
+            ImageDecoder.decodeBitmap(source)
+        } catch (e: IOException) {
+            e.printStackTrace()
+            null
+        }
+    }
+
+    fun onMediaDataLoaded(key: String, data: MediaData) {
+        if (mediaEntries.containsKey(key)) {
+            // Otherwise this was removed already
+            mediaEntries.put(key, data)
+            listeners.forEach {
+                it.onMediaDataLoaded(key, data)
+            }
+        }
+    }
+
+    fun onNotificationRemoved(key: String) {
+        val removed = mediaEntries.remove(key)
+        if (removed != null) {
+            listeners.forEach {
+                it.onMediaDataRemoved(key)
+            }
+        }
+    }
+
+    /**
+     * Are there any media notifications active?
+     */
+    fun hasActiveMedia() = mediaEntries.isNotEmpty()
+
+    fun hasAnyMedia(): Boolean {
+        // TODO: implement this when we implemented resumption
+        return hasActiveMedia()
+    }
+
+    interface Listener {
+
+        /**
+         * Called whenever there's new MediaData Loaded for the consumption in views
+         */
+        fun onMediaDataLoaded(key: String, data: MediaData) {}
+
+        /**
+         * Called whenever a previously existing Media notification was removed
+         */
+        fun onMediaDataRemoved(key: String) {}
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
new file mode 100644
index 0000000..0b04fd0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media
+
+import android.app.Notification
+import android.content.Context
+import android.service.notification.StatusBarNotification
+import android.media.MediaRouter2Manager
+import android.media.session.MediaSession
+import android.media.session.MediaController
+import com.android.settingslib.media.LocalMediaManager
+import com.android.settingslib.media.MediaDevice
+import com.android.systemui.dagger.qualifiers.Main
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * Provides information about the route (ie. device) where playback is occurring.
+ */
+@Singleton
+class MediaDeviceManager @Inject constructor(
+    private val context: Context,
+    private val localMediaManagerFactory: LocalMediaManagerFactory,
+    private val mr2manager: MediaRouter2Manager,
+    private val featureFlag: MediaFeatureFlag,
+    @Main private val fgExecutor: Executor
+) {
+    private val listeners: MutableSet<Listener> = mutableSetOf()
+    private val entries: MutableMap<String, Token> = mutableMapOf()
+
+    /**
+     * Add a listener for changes to the media route (ie. device).
+     */
+    fun addListener(listener: Listener) = listeners.add(listener)
+
+    /**
+     * Remove a listener that has been registered with addListener.
+     */
+    fun removeListener(listener: Listener) = listeners.remove(listener)
+
+    fun onNotificationAdded(key: String, sbn: StatusBarNotification) {
+        if (featureFlag.enabled && isMediaNotification(sbn)) {
+            var tok = entries[key]
+            if (tok == null) {
+                val token = sbn.notification.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION)
+                        as MediaSession.Token?
+                val controller = MediaController(context, token)
+                tok = Token(key, controller, localMediaManagerFactory.create(sbn.packageName))
+                entries[key] = tok
+                tok.start()
+            }
+        } else {
+            onNotificationRemoved(key)
+        }
+    }
+
+    fun onNotificationRemoved(key: String) {
+        val token = entries.remove(key)
+        token?.stop()
+        token?.let {
+            listeners.forEach {
+                it.onKeyRemoved(key)
+            }
+        }
+    }
+
+    private fun processDevice(key: String, device: MediaDevice?) {
+        val enabled = device != null
+        val data = MediaDeviceData(enabled, device?.icon, device?.name)
+        listeners.forEach {
+            it.onMediaDeviceChanged(key, data)
+        }
+    }
+
+    interface Listener {
+        /** Called when the route has changed for a given notification. */
+        fun onMediaDeviceChanged(key: String, data: MediaDeviceData?)
+        /** Called when the notification was removed. */
+        fun onKeyRemoved(key: String)
+    }
+
+    private inner class Token(
+        val key: String,
+        val controller: MediaController,
+        val localMediaManager: LocalMediaManager
+    ) : LocalMediaManager.DeviceCallback {
+        private var started = false
+        private var current: MediaDevice? = null
+            set(value) {
+                if (!started || value != field) {
+                    field = value
+                    processDevice(key, value)
+                }
+            }
+        fun start() {
+            localMediaManager.registerCallback(this)
+            localMediaManager.startScan()
+            updateCurrent()
+            started = true
+        }
+        fun stop() {
+            started = false
+            localMediaManager.stopScan()
+            localMediaManager.unregisterCallback(this)
+        }
+        override fun onDeviceListUpdate(devices: List<MediaDevice>?) = fgExecutor.execute {
+            updateCurrent()
+        }
+        override fun onSelectedDeviceStateChanged(device: MediaDevice, state: Int) {
+            fgExecutor.execute {
+                updateCurrent()
+            }
+        }
+        private fun updateCurrent() {
+            val device = localMediaManager.getCurrentConnectedDevice()
+            val route = mr2manager.getRoutingSessionForMediaController(controller)
+            // If we get a null route, then don't trust the device. Just set to null to disable the
+            // output switcher chip.
+            current = if (route != null) device else null
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt b/packages/SystemUI/src/com/android/systemui/media/MediaFeatureFlag.kt
similarity index 64%
copy from packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt
copy to packages/SystemUI/src/com/android/systemui/media/MediaFeatureFlag.kt
index d0f7607..75eb33d 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaFeatureFlag.kt
@@ -13,12 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.systemui.bubbles.storage
 
-import android.annotation.UserIdInt
+package com.android.systemui.media
 
-data class BubbleXmlEntity(
-    @UserIdInt val userId: Int,
-    val packageName: String,
-    val shortcutId: String
-)
+import android.content.Context
+import com.android.systemui.util.Utils
+import javax.inject.Inject
+
+/**
+ * Provides access to the current value of the feature flag.
+ */
+class MediaFeatureFlag @Inject constructor(private val context: Context) {
+    val enabled
+        get() = Utils.useQsMediaPlayer(context)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
new file mode 100644
index 0000000..3e7661a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.ValueAnimator
+import android.annotation.IntDef
+import android.content.Context
+import android.view.View
+import android.view.ViewGroup
+import android.view.ViewGroupOverlay
+import com.android.systemui.Interpolators
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.animation.UniqueObjectHostView
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * This manager is responsible for placement of the unique media view between the different hosts
+ * and animate the positions of the views to achieve seamless transitions.
+ */
+@Singleton
+class MediaHierarchyManager @Inject constructor(
+    private val context: Context,
+    private val statusBarStateController: SysuiStatusBarStateController,
+    private val keyguardStateController: KeyguardStateController,
+    private val bypassController: KeyguardBypassController,
+    private val mediaViewManager: MediaViewManager,
+    private val mediaMeasurementProvider: MediaMeasurementManager,
+    private val notifLockscreenUserManager: NotificationLockscreenUserManager
+) {
+    /**
+     * The root overlay of the hierarchy. This is where the media notification is attached to
+     * whenever the view is transitioning from one host to another. It also make sure that the
+     * view is always in its final state when it is attached to a view host.
+     */
+    private var rootOverlay: ViewGroupOverlay? = null
+    private lateinit var currentState: MediaState
+    private val mediaCarousel
+        get() = mediaViewManager.mediaCarousel
+    private var animationStartState: MediaState? = null
+    private var statusbarState: Int = statusBarStateController.state
+    private var animator = ValueAnimator.ofFloat(0.0f, 1.0f).apply {
+        interpolator = Interpolators.FAST_OUT_SLOW_IN
+        addUpdateListener {
+            updateTargetState()
+            applyState(animationStartState!!.interpolate(targetState!!, animatedFraction))
+        }
+        addListener(object : AnimatorListenerAdapter() {
+            private var cancelled: Boolean = false
+
+            override fun onAnimationCancel(animation: Animator?) {
+                cancelled = true
+            }
+            override fun onAnimationEnd(animation: Animator?) {
+                if (!cancelled) {
+                    applyTargetStateIfNotAnimating()
+                }
+            }
+
+            override fun onAnimationStart(animation: Animator?) {
+                cancelled = false
+            }
+        })
+    }
+    private var targetState: MediaState? = null
+    private val mediaHosts = arrayOfNulls<MediaHost>(LOCATION_LOCKSCREEN + 1)
+
+    /**
+     * The last location where this view was at before going to the desired location. This is
+     * useful for guided transitions.
+     */
+    @MediaLocation private var previousLocation = -1
+
+    /**
+     * The desired location where the view will be at the end of the transition.
+     */
+    @MediaLocation private var desiredLocation = -1
+
+    /**
+     * The current attachment location where the view is currently attached.
+     * Usually this matches the desired location except for animations whenever a view moves
+     * to the new desired location, during which it is in [IN_OVERLAY].
+     */
+    @MediaLocation private var currentAttachmentLocation = -1
+
+    var qsExpansion: Float = 0.0f
+        set(value) {
+            if (field != value) {
+                field = value
+                updateDesiredLocation()
+                if (getQSTransformationProgress() >= 0) {
+                    updateTargetState()
+                    applyTargetStateIfNotAnimating()
+                }
+            }
+        }
+
+    init {
+        statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
+            override fun onStatePreChange(oldState: Int, newState: Int) {
+                // We're updating the location before the state change happens, since we want the
+                // location of the previous state to still be up to date when the animation starts
+                statusbarState = newState
+                updateDesiredLocation()
+            }
+
+            override fun onStateChanged(newState: Int) {
+                updateTargetState()
+            }
+        })
+    }
+
+    /**
+     * Register a media host and create a view can be attached to a view hierarchy
+     * and where the players will be placed in when the host is the currently desired state.
+     *
+     * @return the hostView associated with this location
+     */
+    fun register(mediaObject: MediaHost): ViewGroup {
+        val viewHost = createUniqueObjectHost(mediaObject)
+        mediaObject.hostView = viewHost
+        mediaHosts[mediaObject.location] = mediaObject
+        if (mediaObject.location == desiredLocation) {
+            // In case we are overriding a view that is already visible, make sure we attach it
+            // to this new host view in the below call
+            desiredLocation = -1
+        }
+        if (mediaObject.location == currentAttachmentLocation) {
+            currentAttachmentLocation = -1
+        }
+        updateDesiredLocation()
+        return viewHost
+    }
+
+    private fun createUniqueObjectHost(host: MediaHost): UniqueObjectHostView {
+        val viewHost = UniqueObjectHostView(context)
+        viewHost.measurementCache = mediaMeasurementProvider.obtainCache(host)
+        viewHost.onMeasureListener = { input ->
+            if (host.location == desiredLocation) {
+                // Measurement of the currently active player is happening, Let's make
+                // sure the player width is up to date
+                val measuringInput = host.getMeasuringInput(input)
+                mediaViewManager.setPlayerWidth(measuringInput.width)
+            }
+        }
+
+        viewHost.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
+            override fun onViewAttachedToWindow(p0: View?) {
+                if (rootOverlay == null) {
+                    rootOverlay = (viewHost.viewRootImpl.view.overlay as ViewGroupOverlay)
+                }
+                viewHost.removeOnAttachStateChangeListener(this)
+            }
+
+            override fun onViewDetachedFromWindow(p0: View?) {
+            }
+        })
+        return viewHost
+    }
+
+    /**
+     * Updates the location that the view should be in. If it changes, an animation may be triggered
+     * going from the old desired location to the new one.
+     */
+    private fun updateDesiredLocation() {
+        val desiredLocation = calculateLocation()
+        if (desiredLocation != this.desiredLocation) {
+            if (this.desiredLocation >= 0) {
+                previousLocation = this.desiredLocation
+            }
+            val isNewView = this.desiredLocation == -1
+            this.desiredLocation = desiredLocation
+            // Let's perform a transition
+            val animate = shouldAnimateTransition(desiredLocation, previousLocation)
+            val (animDuration, delay) = getAnimationParams(previousLocation, desiredLocation)
+            mediaViewManager.onDesiredLocationChanged(getHost(desiredLocation)?.currentState,
+                    animate, animDuration, delay)
+            performTransitionToNewLocation(isNewView, animate)
+        }
+    }
+
+    private fun performTransitionToNewLocation(isNewView: Boolean, animate: Boolean) {
+        if (previousLocation < 0 || isNewView) {
+            cancelAnimationAndApplyDesiredState()
+            return
+        }
+        val currentHost = getHost(desiredLocation)
+        val previousHost = getHost(previousLocation)
+        if (currentHost == null || previousHost == null) {
+            cancelAnimationAndApplyDesiredState()
+            return
+        }
+        updateTargetState()
+        if (isCurrentlyInGuidedTransformation()) {
+            applyTargetStateIfNotAnimating()
+        } else if (animate) {
+            animator.cancel()
+            if (currentAttachmentLocation == IN_OVERLAY ||
+                    !previousHost.hostView.isAttachedToWindow) {
+                // Let's animate to the new position, starting from the current position
+                // We also go in here in case the view was detached, since the bounds wouldn't
+                // be correct anymore
+                animationStartState = currentState.copy()
+            } else {
+                // otherwise, let's take the freshest state, since the current one could
+                // be outdated
+                animationStartState = previousHost.currentState.copy()
+            }
+            adjustAnimatorForTransition(desiredLocation, previousLocation)
+            animator.start()
+        } else {
+            cancelAnimationAndApplyDesiredState()
+        }
+    }
+
+    private fun shouldAnimateTransition(
+        @MediaLocation currentLocation: Int,
+        @MediaLocation previousLocation: Int
+    ): Boolean {
+        if (currentLocation == LOCATION_QQS &&
+                previousLocation == LOCATION_LOCKSCREEN &&
+                (statusBarStateController.leaveOpenOnKeyguardHide() ||
+                        statusbarState == StatusBarState.SHADE_LOCKED)) {
+            // Usually listening to the isShown is enough to determine this, but there is some
+            // non-trivial reattaching logic happening that will make the view not-shown earlier
+            return true
+        }
+        return mediaCarousel.isShown || animator.isRunning
+    }
+
+    private fun adjustAnimatorForTransition(desiredLocation: Int, previousLocation: Int) {
+        val (animDuration, delay) = getAnimationParams(previousLocation, desiredLocation)
+        animator.apply {
+            duration = animDuration
+            startDelay = delay
+        }
+    }
+
+    private fun getAnimationParams(previousLocation: Int, desiredLocation: Int): Pair<Long, Long> {
+        var animDuration = 200L
+        var delay = 0L
+        if (previousLocation == LOCATION_LOCKSCREEN && desiredLocation == LOCATION_QQS) {
+            // Going to the full shade, let's adjust the animation duration
+            if (statusbarState == StatusBarState.SHADE &&
+                    keyguardStateController.isKeyguardFadingAway) {
+                delay = keyguardStateController.keyguardFadingAwayDelay
+            }
+            animDuration = StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE.toLong()
+        } else if (previousLocation == LOCATION_QQS && desiredLocation == LOCATION_LOCKSCREEN) {
+            animDuration = StackStateAnimator.ANIMATION_DURATION_APPEAR_DISAPPEAR.toLong()
+        }
+        return animDuration to delay
+    }
+
+    private fun applyTargetStateIfNotAnimating() {
+        if (!animator.isRunning) {
+            // Let's immediately apply the target state (which is interpolated) if there is
+            // no animation running. Otherwise the animation update will already update
+            // the location
+            applyState(targetState!!)
+        }
+    }
+
+    /**
+     * Updates the state that the view wants to be in at the end of the animation.
+     */
+    private fun updateTargetState() {
+        if (isCurrentlyInGuidedTransformation()) {
+            val progress = getTransformationProgress()
+            val currentHost = getHost(desiredLocation)!!
+            val previousHost = getHost(previousLocation)!!
+            val newState = currentHost.currentState
+            val previousState = previousHost.currentState
+            targetState = previousState.interpolate(newState, progress)
+        } else {
+            targetState = getHost(desiredLocation)?.currentState
+        }
+    }
+
+    /**
+     * @return true if this transformation is guided by an external progress like a finger
+     */
+    private fun isCurrentlyInGuidedTransformation(): Boolean {
+        return getTransformationProgress() >= 0
+    }
+
+    /**
+     * @return the current transformation progress if we're in a guided transformation and -1
+     * otherwise
+     */
+    private fun getTransformationProgress(): Float {
+        val progress = getQSTransformationProgress()
+        if (progress >= 0) {
+            return progress
+        }
+        return -1.0f
+    }
+
+    private fun getQSTransformationProgress(): Float {
+        val currentHost = getHost(desiredLocation)
+        val previousHost = getHost(previousLocation)
+        if (currentHost?.location == LOCATION_QS) {
+            if (previousHost?.location == LOCATION_QQS) {
+                return qsExpansion
+            }
+        }
+        return -1.0f
+    }
+
+    private fun getHost(@MediaLocation location: Int): MediaHost? {
+        if (location < 0) {
+            return null
+        }
+        return mediaHosts[location]
+    }
+
+    private fun cancelAnimationAndApplyDesiredState() {
+        animator.cancel()
+        getHost(desiredLocation)?.let {
+            applyState(it.currentState)
+        }
+    }
+
+    private fun applyState(state: MediaState) {
+        currentState = state.copy()
+        mediaViewManager.setCurrentState(currentState)
+        updateHostAttachment()
+        if (currentAttachmentLocation == IN_OVERLAY) {
+            val boundsOnScreen = state.boundsOnScreen
+            mediaCarousel.setLeftTopRightBottom(
+                    boundsOnScreen.left,
+                    boundsOnScreen.top,
+                    boundsOnScreen.right,
+                    boundsOnScreen.bottom)
+        }
+    }
+
+    private fun updateHostAttachment() {
+        val inOverlay = isTransitionRunning() && rootOverlay != null
+        val newLocation = if (inOverlay) IN_OVERLAY else desiredLocation
+        if (currentAttachmentLocation != newLocation) {
+            currentAttachmentLocation = newLocation
+
+            // Remove the carousel from the old host
+            (mediaCarousel.parent as ViewGroup?)?.removeView(mediaCarousel)
+
+            // Add it to the new one
+            val targetHost = getHost(desiredLocation)!!.hostView
+            if (inOverlay) {
+                rootOverlay!!.add(mediaCarousel)
+            } else {
+                targetHost.addView(mediaCarousel)
+                mediaViewManager.onViewReattached()
+            }
+        }
+    }
+
+    private fun isTransitionRunning(): Boolean {
+        return isCurrentlyInGuidedTransformation() && getTransformationProgress() != 1.0f ||
+                animator.isRunning
+    }
+
+    @MediaLocation
+    private fun calculateLocation(): Int {
+        val onLockscreen = (!bypassController.bypassEnabled &&
+                (statusbarState == StatusBarState.KEYGUARD ||
+                        statusbarState == StatusBarState.FULLSCREEN_USER_SWITCHER))
+        val allowedOnLockscreen = notifLockscreenUserManager.shouldShowLockscreenNotifications()
+        return when {
+            qsExpansion > 0.0f && !onLockscreen -> LOCATION_QS
+            qsExpansion > 0.4f && onLockscreen -> LOCATION_QS
+            onLockscreen && allowedOnLockscreen -> LOCATION_LOCKSCREEN
+            else -> LOCATION_QQS
+        }
+    }
+
+    /**
+     * The expansion of quick settings
+     */
+    @IntDef(prefix = ["LOCATION_"], value = [LOCATION_QS, LOCATION_QQS, LOCATION_LOCKSCREEN])
+    @Retention(AnnotationRetention.SOURCE)
+    annotation class MediaLocation
+
+    companion object {
+        /**
+         * Attached in expanded quick settings
+         */
+        const val LOCATION_QS = 0
+
+        /**
+         * Attached in the collapsed QS
+         */
+        const val LOCATION_QQS = 1
+
+        /**
+         * Attached on the lock screen
+         */
+        const val LOCATION_LOCKSCREEN = 2
+
+        /**
+         * Attached at the root of the hierarchy in an overlay
+         */
+        const val IN_OVERLAY = -1000
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
new file mode 100644
index 0000000..240e44c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
@@ -0,0 +1,159 @@
+package com.android.systemui.media
+
+import android.graphics.Rect
+import android.util.MathUtils
+import android.view.View
+import android.view.View.OnAttachStateChangeListener
+import android.view.ViewGroup
+import com.android.systemui.media.MediaHierarchyManager.MediaLocation
+import com.android.systemui.util.animation.MeasurementInput
+import javax.inject.Inject
+
+class MediaHost @Inject constructor(
+    private val state: MediaHostState,
+    private val mediaHierarchyManager: MediaHierarchyManager,
+    private val mediaDataManager: MediaDataManager
+) : MediaState by state {
+    lateinit var hostView: ViewGroup
+    var location: Int = -1
+        private set
+    var visibleChangedListener: ((Boolean) -> Unit)? = null
+    var visible: Boolean = false
+        private set
+
+    private val tmpLocationOnScreen: IntArray = intArrayOf(0, 0)
+
+    /**
+     * Get the current Media state. This also updates the location on screen
+     */
+    val currentState: MediaState
+        get() {
+            hostView.getLocationOnScreen(tmpLocationOnScreen)
+            var left = tmpLocationOnScreen[0] + hostView.paddingLeft
+            var top = tmpLocationOnScreen[1] + hostView.paddingTop
+            var right = tmpLocationOnScreen[0] + hostView.width - hostView.paddingRight
+            var bottom = tmpLocationOnScreen[1] + hostView.height - hostView.paddingBottom
+            // Handle cases when the width or height is 0 but it has padding. In those cases
+            // the above could return negative widths, which is wrong
+            if (right < left) {
+                left = 0
+                right = 0
+            }
+            if (bottom < top) {
+                bottom = 0
+                top = 0
+            }
+            state.boundsOnScreen.set(left, top, right, bottom)
+            return state
+        }
+
+    private val listener = object : MediaDataManager.Listener {
+        override fun onMediaDataLoaded(key: String, data: MediaData) {
+            updateViewVisibility()
+        }
+
+        override fun onMediaDataRemoved(key: String) {
+            updateViewVisibility()
+        }
+    }
+
+    /**
+     * Initialize this MediaObject and create a host view.
+     *
+     * @param location the location this host name has. Used to identify the host during
+     *                 transitions.
+     */
+    fun init(@MediaLocation location: Int) {
+        this.location = location
+        hostView = mediaHierarchyManager.register(this)
+        hostView.addOnAttachStateChangeListener(object : OnAttachStateChangeListener {
+            override fun onViewAttachedToWindow(v: View?) {
+                mediaDataManager.addListener(listener)
+                updateViewVisibility()
+            }
+
+            override fun onViewDetachedFromWindow(v: View?) {
+                mediaDataManager.removeListener(listener)
+            }
+        })
+        updateViewVisibility()
+    }
+
+    private fun updateViewVisibility() {
+        if (showsOnlyActiveMedia) {
+            visible = mediaDataManager.hasActiveMedia()
+        } else {
+            visible = mediaDataManager.hasAnyMedia()
+        }
+        hostView.visibility = if (visible) View.VISIBLE else View.GONE
+        visibleChangedListener?.invoke(visible)
+    }
+
+    class MediaHostState @Inject constructor() : MediaState {
+        var measurementInput: MediaMeasurementInput? = null
+        override var expansion: Float = 0.0f
+        override var showsOnlyActiveMedia: Boolean = false
+        override val boundsOnScreen: Rect = Rect()
+
+        override fun copy(): MediaState {
+            val mediaHostState = MediaHostState()
+            mediaHostState.expansion = expansion
+            mediaHostState.showsOnlyActiveMedia = showsOnlyActiveMedia
+            mediaHostState.boundsOnScreen.set(boundsOnScreen)
+            mediaHostState.measurementInput = measurementInput
+            return mediaHostState
+        }
+
+        override fun interpolate(other: MediaState, amount: Float): MediaState {
+            val result = MediaHostState()
+            result.expansion = MathUtils.lerp(expansion, other.expansion, amount)
+            val left = MathUtils.lerp(boundsOnScreen.left.toFloat(),
+                    other.boundsOnScreen.left.toFloat(), amount).toInt()
+            val top = MathUtils.lerp(boundsOnScreen.top.toFloat(),
+                    other.boundsOnScreen.top.toFloat(), amount).toInt()
+            val right = MathUtils.lerp(boundsOnScreen.right.toFloat(),
+                    other.boundsOnScreen.right.toFloat(), amount).toInt()
+            val bottom = MathUtils.lerp(boundsOnScreen.bottom.toFloat(),
+                    other.boundsOnScreen.bottom.toFloat(), amount).toInt()
+            result.boundsOnScreen.set(left, top, right, bottom)
+            result.showsOnlyActiveMedia = other.showsOnlyActiveMedia || showsOnlyActiveMedia
+            if (amount > 0.0f) {
+                if (other is MediaHostState) {
+                    result.measurementInput = other.measurementInput
+                }
+            } else {
+                result.measurementInput
+            }
+            return result
+        }
+
+        override fun getMeasuringInput(input: MeasurementInput): MediaMeasurementInput {
+            measurementInput = MediaMeasurementInput(input, expansion)
+            return measurementInput as MediaMeasurementInput
+        }
+    }
+}
+
+interface MediaState {
+    var expansion: Float
+    var showsOnlyActiveMedia: Boolean
+    val boundsOnScreen: Rect
+    fun copy(): MediaState
+    fun interpolate(other: MediaState, amount: Float): MediaState
+    fun getMeasuringInput(input: MeasurementInput): MediaMeasurementInput
+}
+/**
+ * The measurement input for a Media View
+ */
+data class MediaMeasurementInput(
+    private val viewInput: MeasurementInput,
+    val expansion: Float
+) : MeasurementInput by viewInput {
+
+    override fun sameAs(input: MeasurementInput?): Boolean {
+        if (!(input is MediaMeasurementInput)) {
+            return false
+        }
+        return width == input.width && expansion == input.expansion
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaMeasurementManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaMeasurementManager.kt
new file mode 100644
index 0000000..4bbf5eb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaMeasurementManager.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.media
+
+import com.android.systemui.util.animation.BaseMeasurementCache
+import com.android.systemui.util.animation.GuaranteedMeasurementCache
+import com.android.systemui.util.animation.MeasurementCache
+import com.android.systemui.util.animation.MeasurementInput
+import com.android.systemui.util.animation.MeasurementOutput
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * A class responsible creating measurement caches for media hosts which also coordinates with
+ * the view manager to obtain sizes for unknown measurement inputs.
+ */
+@Singleton
+class MediaMeasurementManager @Inject constructor(
+    private val mediaViewManager: MediaViewManager
+) {
+    private val baseCache: MeasurementCache
+
+    init {
+        baseCache = BaseMeasurementCache()
+    }
+
+    private fun provideMeasurement(input: MediaMeasurementInput) : MeasurementOutput? {
+        return mediaViewManager.obtainMeasurement(input)
+    }
+
+    /**
+     * Obtain a guaranteed measurement cache for a host view. The measurement cache makes sure that
+     * requesting any size from the cache will always return the correct value.
+     */
+    fun obtainCache(host: MediaState): GuaranteedMeasurementCache {
+        val remapper = { input: MeasurementInput ->
+            host.getMeasuringInput(input)
+        }
+        val provider = { input: MeasurementInput ->
+            provideMeasurement(input as MediaMeasurementInput)
+        }
+        return GuaranteedMeasurementCache(baseCache, remapper, provider)
+    }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt
new file mode 100644
index 0000000..17e8404
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt
@@ -0,0 +1,313 @@
+package com.android.systemui.media
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.HorizontalScrollView
+import android.widget.LinearLayout
+import com.android.systemui.R
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.statusbar.notification.VisualStabilityManager
+import com.android.systemui.util.animation.MeasurementOutput
+import com.android.systemui.util.animation.UniqueObjectHostView
+import com.android.systemui.util.concurrency.DelayableExecutor
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * Class that is responsible for keeping the view carousel up to date.
+ * This also handles changes in state and applies them to the media carousel like the expansion.
+ */
+@Singleton
+class MediaViewManager @Inject constructor(
+    private val context: Context,
+    @Main private val foregroundExecutor: Executor,
+    @Background private val backgroundExecutor: DelayableExecutor,
+    private val visualStabilityManager: VisualStabilityManager,
+    private val activityStarter: ActivityStarter,
+    mediaManager: MediaDataCombineLatest
+) {
+    private var playerWidth: Int = 0
+    private var playerWidthPlusPadding: Int = 0
+    private var desiredState: MediaHost.MediaHostState? = null
+    private var currentState: MediaState? = null
+    val mediaCarousel: HorizontalScrollView
+    private val mediaContent: ViewGroup
+    private val mediaPlayers: MutableMap<String, MediaControlPanel> = mutableMapOf()
+    private val visualStabilityCallback: VisualStabilityManager.Callback
+    private var activeMediaIndex: Int = 0
+    private var needsReordering: Boolean = false
+    private var scrollIntoCurrentMedia: Int = 0
+    private var currentlyExpanded = true
+        set(value) {
+            if (field != value) {
+                field = value
+                for (player in mediaPlayers.values) {
+                    player.setListening(field)
+                }
+            }
+        }
+    private val scrollChangedListener = object : View.OnScrollChangeListener {
+        override fun onScrollChange(
+            v: View?,
+            scrollX: Int,
+            scrollY: Int,
+            oldScrollX: Int,
+            oldScrollY: Int
+        ) {
+            if (playerWidthPlusPadding == 0) {
+                return
+            }
+            onMediaScrollingChanged(scrollX / playerWidthPlusPadding,
+                    scrollX % playerWidthPlusPadding)
+        }
+    }
+
+    init {
+        mediaCarousel = inflateMediaCarousel()
+        mediaCarousel.setOnScrollChangeListener(scrollChangedListener)
+        mediaContent = mediaCarousel.requireViewById(R.id.media_carousel)
+        visualStabilityCallback = VisualStabilityManager.Callback {
+            if (needsReordering) {
+                needsReordering = false
+                reorderAllPlayers()
+            }
+            // Let's reset our scroll position
+            mediaCarousel.scrollX = 0
+        }
+        visualStabilityManager.addReorderingAllowedCallback(visualStabilityCallback,
+                true /* persistent */)
+        mediaManager.addListener(object : MediaDataManager.Listener {
+            override fun onMediaDataLoaded(key: String, data: MediaData) {
+                updateView(key, data)
+                updatePlayerVisibilities()
+            }
+
+            override fun onMediaDataRemoved(key: String) {
+                val removed = mediaPlayers.remove(key)
+                removed?.apply {
+                    val beforeActive = mediaContent.indexOfChild(removed.view?.player) <=
+                            activeMediaIndex
+                    mediaContent.removeView(removed.view?.player)
+                    removed.onDestroy()
+                    updateMediaPaddings()
+                    if (beforeActive) {
+                        // also update the index here since the scroll below might not always lead
+                        // to a scrolling changed
+                        activeMediaIndex = Math.max(0, activeMediaIndex - 1)
+                        mediaCarousel.scrollX = Math.max(mediaCarousel.scrollX -
+                                playerWidthPlusPadding, 0)
+                    }
+                    updatePlayerVisibilities()
+                }
+            }
+        })
+    }
+
+    private fun inflateMediaCarousel(): HorizontalScrollView {
+        return LayoutInflater.from(context).inflate(R.layout.media_carousel,
+                UniqueObjectHostView(context), false) as HorizontalScrollView
+    }
+
+    private fun reorderAllPlayers() {
+        for (mediaPlayer in mediaPlayers.values) {
+            val view = mediaPlayer.view?.player
+            if (mediaPlayer.isPlaying && mediaContent.indexOfChild(view) != 0) {
+                mediaContent.removeView(view)
+                mediaContent.addView(view, 0)
+            }
+        }
+        updateMediaPaddings()
+        updatePlayerVisibilities()
+    }
+
+    private fun onMediaScrollingChanged(newIndex: Int, scrollInAmount: Int) {
+        val wasScrolledIn = scrollIntoCurrentMedia != 0
+        scrollIntoCurrentMedia = scrollInAmount
+        val nowScrolledIn = scrollIntoCurrentMedia != 0
+        if (newIndex != activeMediaIndex || wasScrolledIn != nowScrolledIn) {
+            activeMediaIndex = newIndex
+            updatePlayerVisibilities()
+        }
+    }
+
+    private fun updatePlayerVisibilities() {
+        val scrolledIn = scrollIntoCurrentMedia != 0
+        for (i in 0 until mediaContent.childCount) {
+            val view = mediaContent.getChildAt(i)
+            val visible = (i == activeMediaIndex) || ((i == (activeMediaIndex + 1)) && scrolledIn)
+            view.visibility = if (visible) View.VISIBLE else View.INVISIBLE
+        }
+    }
+
+    private fun updateView(key: String, data: MediaData) {
+        var existingPlayer = mediaPlayers[key]
+        if (existingPlayer == null) {
+            existingPlayer = MediaControlPanel(context, foregroundExecutor, backgroundExecutor,
+                    activityStarter)
+            existingPlayer.attach(PlayerViewHolder.create(LayoutInflater.from(context),
+                    mediaContent))
+            mediaPlayers[key] = existingPlayer
+            val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+                    ViewGroup.LayoutParams.WRAP_CONTENT)
+            existingPlayer.view?.player?.setLayoutParams(lp)
+            existingPlayer.setListening(currentlyExpanded)
+            if (existingPlayer.isPlaying) {
+                mediaContent.addView(existingPlayer.view?.player, 0)
+            } else {
+                mediaContent.addView(existingPlayer.view?.player)
+            }
+            updatePlayerToCurrentState(existingPlayer)
+        } else if (existingPlayer.isPlaying &&
+                    mediaContent.indexOfChild(existingPlayer.view?.player) != 0) {
+            if (visualStabilityManager.isReorderingAllowed) {
+                mediaContent.removeView(existingPlayer.view?.player)
+                mediaContent.addView(existingPlayer.view?.player, 0)
+            } else {
+                needsReordering = true
+            }
+        }
+        existingPlayer.bind(data)
+        // Resetting the progress to make sure it's taken into account for the latest
+        // motion model
+        existingPlayer.view?.player?.progress = currentState?.expansion ?: 0.0f
+        updateMediaPaddings()
+    }
+
+    private fun updatePlayerToCurrentState(existingPlayer: MediaControlPanel) {
+        if (desiredState != null && desiredState!!.measurementInput != null) {
+            // make sure the player width is set to the current state
+            existingPlayer.setPlayerWidth(playerWidth)
+        }
+    }
+
+    private fun updateMediaPaddings() {
+        val padding = context.resources.getDimensionPixelSize(R.dimen.qs_media_padding)
+        val childCount = mediaContent.childCount
+        for (i in 0 until childCount) {
+            val mediaView = mediaContent.getChildAt(i)
+            val desiredPaddingEnd = if (i == childCount - 1) 0 else padding
+            val layoutParams = mediaView.layoutParams as ViewGroup.MarginLayoutParams
+            if (layoutParams.marginEnd != desiredPaddingEnd) {
+                layoutParams.marginEnd = desiredPaddingEnd
+                mediaView.layoutParams = layoutParams
+            }
+        }
+    }
+
+    /**
+     * Set the current state of a view. This is updated often during animations and we shouldn't
+     * do anything expensive.
+     */
+    fun setCurrentState(state: MediaState) {
+        currentState = state
+        currentlyExpanded = state.expansion > 0
+        for (mediaPlayer in mediaPlayers.values) {
+            val view = mediaPlayer.view?.player
+            view?.progress = state.expansion
+        }
+    }
+
+    /**
+     * The desired location of this view has changed. We should remeasure the view to match
+     * the new bounds and kick off bounds animations if necessary.
+     * If an animation is happening, an animation is kicked of externally, which sets a new
+     * current state until we reach the targetState.
+     *
+     * @param desiredState the target state we're transitioning to
+     * @param animate should this be animated
+     */
+    fun onDesiredLocationChanged(
+        desiredState: MediaState?,
+        animate: Boolean,
+        duration: Long,
+        startDelay: Long
+    ) {
+        if (desiredState is MediaHost.MediaHostState) {
+            // This is a hosting view, let's remeasure our players
+            this.desiredState = desiredState
+            val width = desiredState.boundsOnScreen.width()
+            if (playerWidth != width) {
+                setPlayerWidth(width)
+                for (mediaPlayer in mediaPlayers.values) {
+                    if (animate && mediaPlayer.view?.player?.visibility == View.VISIBLE) {
+                        mediaPlayer.animatePendingSizeChange(duration, startDelay)
+                    }
+                }
+                val widthSpec = desiredState.measurementInput?.widthMeasureSpec ?: 0
+                val heightSpec = desiredState.measurementInput?.heightMeasureSpec ?: 0
+                var left = 0
+                for (i in 0 until mediaContent.childCount) {
+                    val view = mediaContent.getChildAt(i)
+                    view.measure(widthSpec, heightSpec)
+                    view.layout(left, 0, left + width, view.measuredHeight)
+                    left = left + playerWidthPlusPadding
+                }
+            }
+        }
+    }
+
+    fun setPlayerWidth(width: Int) {
+        if (width != playerWidth) {
+            playerWidth = width
+            playerWidthPlusPadding = playerWidth + context.resources.getDimensionPixelSize(
+                    R.dimen.qs_media_padding)
+            for (mediaPlayer in mediaPlayers.values) {
+                mediaPlayer.setPlayerWidth(width)
+            }
+            // The player width has changed, let's update the scroll position to make sure
+            // it's still at the same place
+            var newScroll = activeMediaIndex * playerWidthPlusPadding
+            if (scrollIntoCurrentMedia > playerWidthPlusPadding) {
+                newScroll += playerWidthPlusPadding
+                - (scrollIntoCurrentMedia - playerWidthPlusPadding)
+            } else {
+                newScroll += scrollIntoCurrentMedia
+            }
+            mediaCarousel.scrollX = newScroll
+        }
+    }
+
+    /**
+     * Get a measurement for the given input state. This measures the first player and returns
+     * its bounds as if it were measured with the given measurement dimensions
+     */
+    fun obtainMeasurement(input: MediaMeasurementInput): MeasurementOutput? {
+        val firstPlayer = mediaPlayers.values.firstOrNull() ?: return null
+        var result: MeasurementOutput? = null
+        firstPlayer.view?.player?.let {
+            // Let's measure the size of the first player and return its height
+            val previousProgress = it.progress
+            val previousRight = it.right
+            val previousBottom = it.bottom
+            it.progress = input.expansion
+            firstPlayer.measure(input)
+            // Relayouting is necessary in motionlayout to obtain its size properly ....
+            it.layout(0, 0, it.measuredWidth, it.measuredHeight)
+            result = MeasurementOutput(it.measuredWidth, it.measuredHeight)
+            it.progress = previousProgress
+            if (desiredState != null) {
+                // remeasure it to the old size again!
+                firstPlayer.measure(desiredState!!.measurementInput)
+                it.layout(0, 0, previousRight, previousBottom)
+            }
+        }
+        return result
+    }
+
+    fun onViewReattached() {
+        if (desiredState is MediaHost.MediaHostState) {
+            // HACK: MotionLayout doesn't always properly reevalate the state, let's kick of
+            // a measure to force it.
+            val widthSpec = desiredState!!.measurementInput?.widthMeasureSpec ?: 0
+            val heightSpec = desiredState!!.measurementInput?.heightMeasureSpec ?: 0
+            for (mediaPlayer in mediaPlayers.values) {
+                mediaPlayer.view?.player?.measure(widthSpec, heightSpec)
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
new file mode 100644
index 0000000..764dbe6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageButton
+import android.widget.ImageView
+import android.widget.SeekBar
+import android.widget.TextView
+
+import androidx.constraintlayout.motion.widget.MotionLayout
+
+import com.android.systemui.R
+
+/**
+ * ViewHolder for a media player.
+ */
+class PlayerViewHolder private constructor(itemView: View) {
+
+    val player = itemView as MotionLayout
+    val background = itemView.requireViewById<View>(R.id.media_background)
+
+    // Player information
+    val appIcon = itemView.requireViewById<ImageView>(R.id.icon)
+    val appName = itemView.requireViewById<TextView>(R.id.app_name)
+    val albumView = itemView.requireViewById<ImageView>(R.id.album_art)
+    val titleText = itemView.requireViewById<TextView>(R.id.header_title)
+    val artistText = itemView.requireViewById<TextView>(R.id.header_artist)
+
+    // Output switcher
+    val seamless = itemView.findViewById<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)
+
+    // Seek bar
+    val seekBar = itemView.requireViewById<SeekBar>(R.id.media_progress_bar)
+    val elapsedTimeView = itemView.requireViewById<TextView>(R.id.media_elapsed_time)
+    val totalTimeView = itemView.requireViewById<TextView>(R.id.media_total_time)
+
+    // Action Buttons
+    val action0 = itemView.requireViewById<ImageButton>(R.id.action0)
+    val action1 = itemView.requireViewById<ImageButton>(R.id.action1)
+    val action2 = itemView.requireViewById<ImageButton>(R.id.action2)
+    val action3 = itemView.requireViewById<ImageButton>(R.id.action3)
+    val action4 = itemView.requireViewById<ImageButton>(R.id.action4)
+
+    init {
+        (background.background as IlluminationDrawable).let {
+            it.setupTouch(seamless, player)
+            it.setupTouch(action0, player)
+            it.setupTouch(action1, player)
+            it.setupTouch(action2, player)
+            it.setupTouch(action3, player)
+            it.setupTouch(action4, player)
+        }
+    }
+
+    fun getAction(id: Int): ImageButton {
+        return when (id) {
+            R.id.action0 -> action0
+            R.id.action1 -> action1
+            R.id.action2 -> action2
+            R.id.action3 -> action3
+            R.id.action4 -> action4
+            else -> {
+                throw IllegalArgumentException()
+            }
+        }
+    }
+
+    // Settings screen
+    val options = itemView.requireViewById<View>(R.id.qs_media_controls_options)
+
+    companion object {
+        /**
+         * Creates a PlayerViewHolder.
+         *
+         * @param inflater LayoutInflater to use to inflate the layout.
+         * @param parent Parent of inflated view.
+         */
+        @JvmStatic fun create(inflater: LayoutInflater, parent: ViewGroup): PlayerViewHolder {
+            val v = inflater.inflate(R.layout.qs_media_panel, parent, false)
+            return PlayerViewHolder(v)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
index 51c157a..cd8ed26 100644
--- a/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
@@ -16,69 +16,41 @@
 
 package com.android.systemui.media
 
-import android.content.res.ColorStateList
 import android.text.format.DateUtils
-import android.view.View
-import android.widget.SeekBar
-import android.widget.TextView
 import androidx.annotation.UiThread
 import androidx.lifecycle.Observer
 
-import com.android.systemui.R
-
 /**
  * Observer for changes from SeekBarViewModel.
  *
  * <p>Updates the seek bar views in response to changes to the model.
  */
-class SeekBarObserver(view: View) : Observer<SeekBarViewModel.Progress> {
-
-    private val seekBarView: SeekBar
-    private val elapsedTimeView: TextView
-    private val totalTimeView: TextView
-
-    init {
-        seekBarView = view.findViewById(R.id.media_progress_bar)
-        elapsedTimeView = view.findViewById(R.id.media_elapsed_time)
-        totalTimeView = view.findViewById(R.id.media_total_time)
-    }
+class SeekBarObserver(private val holder: PlayerViewHolder) : Observer<SeekBarViewModel.Progress> {
 
     /** Updates seek bar views when the data model changes. */
     @UiThread
     override fun onChanged(data: SeekBarViewModel.Progress) {
-
-        data.color?.let {
-            var tintList = ColorStateList.valueOf(it)
-            seekBarView.setThumbTintList(tintList)
-            tintList = tintList.withAlpha(192) // 75%
-            seekBarView.setProgressTintList(tintList)
-            tintList = tintList.withAlpha(128) // 50%
-            seekBarView.setProgressBackgroundTintList(tintList)
-            elapsedTimeView.setTextColor(it)
-            totalTimeView.setTextColor(it)
-        }
-
         if (!data.enabled) {
-            seekBarView.setEnabled(false)
-            seekBarView.getThumb().setAlpha(0)
-            seekBarView.setProgress(0)
-            elapsedTimeView.setText("")
-            totalTimeView.setText("")
+            holder.seekBar.setEnabled(false)
+            holder.seekBar.getThumb().setAlpha(0)
+            holder.seekBar.setProgress(0)
+            holder.elapsedTimeView.setText("")
+            holder.totalTimeView.setText("")
             return
         }
 
-        seekBarView.getThumb().setAlpha(if (data.seekAvailable) 255 else 0)
-        seekBarView.setEnabled(data.seekAvailable)
+        holder.seekBar.getThumb().setAlpha(if (data.seekAvailable) 255 else 0)
+        holder.seekBar.setEnabled(data.seekAvailable)
 
         data.elapsedTime?.let {
-            seekBarView.setProgress(it)
-            elapsedTimeView.setText(DateUtils.formatElapsedTime(
+            holder.seekBar.setProgress(it)
+            holder.elapsedTimeView.setText(DateUtils.formatElapsedTime(
                     it / DateUtils.SECOND_IN_MILLIS))
         }
 
         data.duration?.let {
-            seekBarView.setMax(it)
-            totalTimeView.setText(DateUtils.formatElapsedTime(
+            holder.seekBar.setMax(it)
+            holder.totalTimeView.setText(DateUtils.formatElapsedTime(
                     it / DateUtils.SECOND_IN_MILLIS))
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
index f72a74b..06821cd6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
@@ -67,7 +67,7 @@
 /** ViewModel for seek bar in QS media player. */
 class SeekBarViewModel(val bgExecutor: DelayableExecutor) {
 
-    private var _data = Progress(false, false, null, null, null)
+    private var _data = Progress(false, false, null, null)
         set(value) {
             field = value
             _progress.postValue(value)
@@ -78,7 +78,22 @@
     val progress: LiveData<Progress>
         get() = _progress
     private var controller: MediaController? = null
+        set(value) {
+            if (field?.sessionToken != value?.sessionToken) {
+                field?.unregisterCallback(callback)
+                value?.registerCallback(callback)
+                field = value
+            }
+        }
     private var playbackState: PlaybackState? = null
+    private var callback = object : MediaController.Callback() {
+        override fun onPlaybackStateChanged(state: PlaybackState) {
+            playbackState = state
+            if (shouldPollPlaybackPosition()) {
+                checkPlaybackPosition()
+            }
+        }
+    }
 
     /** Listening state (QS open or closed) is used to control polling of progress. */
     var listening = true
@@ -95,15 +110,17 @@
     @WorkerThread
     fun onSeek(position: Long) {
         controller?.transportControls?.seekTo(position)
+        // Invalidate the cached playbackState to avoid the thumb jumping back to the previous
+        // position.
+        playbackState = null
     }
 
     /**
      * Updates media information.
      * @param mediaController controller for media session
-     * @param color foreground color for UI elements
      */
     @WorkerThread
-    fun updateController(mediaController: MediaController?, color: Int) {
+    fun updateController(mediaController: MediaController?) {
         controller = mediaController
         playbackState = controller?.playbackState
         val mediaMetadata = controller?.metadata
@@ -113,7 +130,7 @@
         val enabled = if (playbackState == null ||
                 playbackState?.getState() == PlaybackState.STATE_NONE ||
                 (duration != null && duration <= 0)) false else true
-        _data = Progress(enabled, seekAvailable, position, duration, color)
+        _data = Progress(enabled, seekAvailable, position, duration)
         if (shouldPollPlaybackPosition()) {
             checkPlaybackPosition()
         }
@@ -126,12 +143,23 @@
      */
     @AnyThread
     fun clearController() = bgExecutor.execute {
+        controller = null
+        playbackState = null
         _data = _data.copy(enabled = false)
     }
 
+    /**
+     * Call to clean up any resources.
+     */
+    @AnyThread
+    fun onDestroy() {
+        controller = null
+        playbackState = null
+    }
+
     @AnyThread
     private fun checkPlaybackPosition(): Runnable = bgExecutor.executeDelayed({
-        val duration = _data?.duration ?: -1
+        val duration = _data.duration ?: -1
         val currentPosition = playbackState?.computePosition(duration.toLong())?.toInt()
         if (currentPosition != null && _data.elapsedTime != currentPosition) {
             _data = _data.copy(elapsedTime = currentPosition)
@@ -191,7 +219,6 @@
         val enabled: Boolean,
         val seekAvailable: Boolean,
         val elapsedTime: Int?,
-        val duration: Int?,
-        val color: Int?
+        val duration: Int?
     )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/UnboundHorizontalScrollView.kt b/packages/SystemUI/src/com/android/systemui/media/UnboundHorizontalScrollView.kt
new file mode 100644
index 0000000..8efc954
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/UnboundHorizontalScrollView.kt
@@ -0,0 +1,31 @@
+package com.android.systemui.media
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.HorizontalScrollView
+
+/**
+ * A Horizontal scrollview that doesn't limit itself to the childs bounds. This is useful
+ * when only measuring children but not the parent, when trying to apply a new scroll position
+ */
+class UnboundHorizontalScrollView @JvmOverloads constructor(
+    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
+    : HorizontalScrollView(context, attrs, defStyleAttr) {
+
+    /**
+     * Allow all scrolls to go through, use base implementation
+     */
+    override fun scrollTo(x: Int, y: Int) {
+        if (mScrollX != x || mScrollY != y) {
+            val oldX: Int = mScrollX
+            val oldY: Int = mScrollY
+            mScrollX = x
+            mScrollY = y
+            invalidateParentCaches()
+            onScrollChanged(mScrollX, mScrollY, oldX, oldY)
+            if (!awakenScrollBars()) {
+                postInvalidateOnAnimation()
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/model/SysUiState.java b/packages/SystemUI/src/com/android/systemui/model/SysUiState.java
index f900f1e..ccf58ba 100644
--- a/packages/SystemUI/src/com/android/systemui/model/SysUiState.java
+++ b/packages/SystemUI/src/com/android/systemui/model/SysUiState.java
@@ -39,7 +39,7 @@
 public class SysUiState implements Dumpable {
 
     private static final String TAG = SysUiState.class.getSimpleName();
-    public static final boolean DEBUG = true;
+    public static final boolean DEBUG = false;
 
     private @QuickStepContract.SystemUiStateFlags int mFlags;
     private final List<SysUiStateCallback> mCallbacks = new ArrayList<>();
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
index f72de11..7f7e108 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
@@ -65,6 +65,10 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface TransitionDirection {}
 
+    public static boolean isInPipDirection(@TransitionDirection int direction) {
+        return direction == TRANSITION_DIRECTION_TO_PIP;
+    }
+
     public static boolean isOutPipDirection(@TransitionDirection int direction) {
         return direction == TRANSITION_DIRECTION_TO_FULLSCREEN
                 || direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN;
@@ -104,6 +108,12 @@
         if (mCurrentAnimator == null) {
             mCurrentAnimator = setupPipTransitionAnimator(
                     PipTransitionAnimator.ofBounds(leash, startBounds, endBounds));
+        } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
+                && mCurrentAnimator.isRunning()) {
+            // If we are still animating the fade into pip, then just move the surface and ensure
+            // we update with the new destination bounds, but don't interrupt the existing animation
+            // with a new bounds
+            mCurrentAnimator.setDestinationBounds(endBounds);
         } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_BOUNDS
                 && mCurrentAnimator.isRunning()) {
             mCurrentAnimator.setDestinationBounds(endBounds);
@@ -160,9 +170,9 @@
         private final @AnimationType int mAnimationType;
         private final Rect mDestinationBounds = new Rect();
 
-        private T mStartValue;
+        protected T mCurrentValue;
+        protected T mStartValue;
         private T mEndValue;
-        private T mCurrentValue;
         private PipAnimationCallback mPipAnimationCallback;
         private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
                 mSurfaceControlTransactionFactory;
@@ -265,8 +275,7 @@
 
         boolean inScaleTransition() {
             if (mAnimationType != ANIM_TYPE_BOUNDS) return false;
-            final int direction = getTransitionDirection();
-            return !isOutPipDirection(direction) && direction != TRANSITION_DIRECTION_TO_PIP;
+            return !isInPipDirection(getTransitionDirection());
         }
 
         /**
@@ -279,7 +288,6 @@
          */
         void updateEndValue(T endValue) {
             mEndValue = endValue;
-            mStartValue = mCurrentValue;
         }
 
         SurfaceControl.Transaction newSurfaceControlTransaction() {
@@ -328,6 +336,12 @@
                     tx.show(leash);
                     tx.apply();
                 }
+
+                @Override
+                void updateEndValue(Float endValue) {
+                    super.updateEndValue(endValue);
+                    mStartValue = mCurrentValue;
+                }
             };
         }
 
@@ -354,7 +368,11 @@
                             getCastedFractionValue(start.bottom, end.bottom, fraction));
                     setCurrentValue(mTmpRect);
                     if (inScaleTransition()) {
-                        getSurfaceTransactionHelper().scale(tx, leash, start, mTmpRect);
+                        if (isOutPipDirection(getTransitionDirection())) {
+                            getSurfaceTransactionHelper().scale(tx, leash, end, mTmpRect);
+                        } else {
+                            getSurfaceTransactionHelper().scale(tx, leash, start, mTmpRect);
+                        }
                     } else {
                         getSurfaceTransactionHelper().crop(tx, leash, mTmpRect);
                     }
@@ -379,6 +397,14 @@
                     getSurfaceTransactionHelper().resetScale(tx, leash, getDestinationBounds())
                             .crop(tx, leash, getDestinationBounds());
                 }
+
+                @Override
+                void updateEndValue(Rect endValue) {
+                    super.updateEndValue(endValue);
+                    if (mStartValue != null && mCurrentValue != null) {
+                        mStartValue.set(mCurrentValue);
+                    }
+                }
             };
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
index 3eeadc3..febb6e9 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -61,12 +61,6 @@
     private final DisplayInfo mDisplayInfo = new DisplayInfo();
     private final Rect mTmpInsets = new Rect();
 
-    /**
-     * Tracks the destination bounds, used for any following
-     * {@link #onMovementBoundsChanged(Rect, Rect, Rect, DisplayInfo)} calculations.
-     */
-    private final Rect mLastDestinationBounds = new Rect();
-
     private ComponentName mLastPipComponentName;
     private float mReentrySnapFraction = INVALID_SNAP_FRACTION;
     private Size mReentrySize;
@@ -198,17 +192,24 @@
         mReentrySnapFraction = INVALID_SNAP_FRACTION;
         mReentrySize = null;
         mLastPipComponentName = null;
-        mLastDestinationBounds.setEmpty();
     }
 
-    public Rect getLastDestinationBounds() {
-        return mLastDestinationBounds;
+    /**
+     * Returns ture if there's a valid snap fraction. This is used with {@link EXTRA_IS_FIRST_ENTRY}
+     * to see if this is the first time user has entered PIP for the component.
+     */
+    public boolean hasSaveReentryBounds() {
+        return mReentrySnapFraction != INVALID_SNAP_FRACTION;
     }
 
     public Rect getDisplayBounds() {
         return new Rect(0, 0, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
     }
 
+    public int getDisplayRotation() {
+        return mDisplayInfo.rotation;
+    }
+
     /**
      * Responds to IPinnedStackListener on {@link DisplayInfo} change.
      * It will normally follow up with a
@@ -258,7 +259,6 @@
                     false /* useCurrentMinEdgeSize */);
         }
         mAspectRatio = aspectRatio;
-        mLastDestinationBounds.set(destinationBounds);
         return destinationBounds;
     }
 
@@ -272,8 +272,8 @@
      *
      * @return {@code true} if internal {@link DisplayInfo} is rotated, {@code false} otherwise.
      */
-    public boolean onDisplayRotationChanged(Rect outBounds, int displayId, int fromRotation,
-            int toRotation, WindowContainerTransaction t) {
+    public boolean onDisplayRotationChanged(Rect outBounds, Rect oldBounds, int displayId,
+            int fromRotation, int toRotation, WindowContainerTransaction t) {
         // Bail early if the event is not sent to current {@link #mDisplayInfo}
         if ((displayId != mDisplayInfo.displayId) || (fromRotation == toRotation)) {
             return false;
@@ -291,7 +291,7 @@
         }
 
         // Calculate the snap fraction of the current stack along the old movement bounds
-        final Rect postChangeStackBounds = new Rect(mLastDestinationBounds);
+        final Rect postChangeStackBounds = new Rect(oldBounds);
         final float snapFraction = getSnapFraction(postChangeStackBounds);
 
         // Populate the new {@link #mDisplayInfo}.
@@ -309,7 +309,6 @@
                 snapFraction);
 
         outBounds.set(postChangeStackBounds);
-        mLastDestinationBounds.set(outBounds);
         t.setBounds(pinnedStackInfo.stackToken, outBounds);
         return true;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 8d6ce47..c2f8cb9 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.pip;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 
 import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_ALPHA;
@@ -25,32 +28,39 @@
 import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_FULLSCREEN;
 import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
 import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_SPLIT_SCREEN;
+import static com.android.systemui.pip.PipAnimationController.isInPipDirection;
 import static com.android.systemui.pip.PipAnimationController.isOutPipDirection;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
 import android.app.PictureInPictureParams;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.RemoteException;
 import android.util.Log;
 import android.util.Size;
 import android.view.SurfaceControl;
 import android.window.TaskOrganizer;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
+import android.window.WindowContainerTransactionCallback;
 import android.window.WindowOrganizer;
 
 import com.android.internal.os.SomeArgs;
 import com.android.systemui.R;
 import com.android.systemui.pip.phone.PipUpdateThread;
 import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.wm.DisplayController;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -73,8 +83,10 @@
  * see also {@link com.android.systemui.pip.phone.PipMotionHelper}.
  */
 @Singleton
-public class PipTaskOrganizer extends TaskOrganizer {
+public class PipTaskOrganizer extends TaskOrganizer implements
+        DisplayController.OnDisplaysChangedListener {
     private static final String TAG = PipTaskOrganizer.class.getSimpleName();
+    private static final boolean DEBUG = false;
 
     private static final int MSG_RESIZE_IMMEDIATE = 1;
     private static final int MSG_RESIZE_ANIMATE = 2;
@@ -90,7 +102,7 @@
     private final Rect mLastReportedBounds = new Rect();
     private final int mEnterExitAnimationDuration;
     private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
-    private final Map<IBinder, Rect> mBoundsToRestore = new HashMap<>();
+    private final Map<IBinder, Configuration> mInitialState = new HashMap<>();
     private final Divider mSplitDivider;
 
     // These callbacks are called on the update thread
@@ -110,7 +122,8 @@
         @Override
         public void onPipAnimationEnd(SurfaceControl.Transaction tx,
                 PipAnimationController.PipTransitionAnimator animator) {
-            finishResize(tx, animator.getDestinationBounds(), animator.getTransitionDirection());
+            finishResize(tx, animator.getDestinationBounds(), animator.getTransitionDirection(),
+                    animator.getAnimationType());
             mMainHandler.post(() -> {
                 for (int i = mPipTransitionCallbacks.size() - 1; i >= 0; i--) {
                     final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
@@ -170,7 +183,7 @@
             case MSG_FINISH_RESIZE: {
                 SurfaceControl.Transaction tx = (SurfaceControl.Transaction) args.arg2;
                 Rect toBounds = (Rect) args.arg3;
-                finishResize(tx, toBounds, args.argi1 /* direction */);
+                finishResize(tx, toBounds, args.argi1 /* direction */, -1);
                 if (updateBoundsCallback != null) {
                     updateBoundsCallback.accept(toBounds);
                 }
@@ -196,10 +209,17 @@
             mSurfaceControlTransactionFactory;
     private PictureInPictureParams mPictureInPictureParams;
 
+    /**
+     * If set to {@code true}, the entering animation will be skipped and we will wait for
+     * {@link #onFixedRotationFinished(int)} callback to actually enter PiP.
+     */
+    private boolean mShouldDeferEnteringPip;
+
     @Inject
     public PipTaskOrganizer(Context context, @NonNull PipBoundsHandler boundsHandler,
             @NonNull PipSurfaceTransactionHelper surfaceTransactionHelper,
-            @Nullable Divider divider) {
+            @Nullable Divider divider,
+            @NonNull DisplayController displayController) {
         mMainHandler = new Handler(Looper.getMainLooper());
         mUpdateHandler = new Handler(PipUpdateThread.get().getLooper(), mUpdateCallbacks);
         mPipBoundsHandler = boundsHandler;
@@ -209,6 +229,7 @@
         mPipAnimationController = new PipAnimationController(context, surfaceTransactionHelper);
         mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
         mSplitDivider = divider;
+        displayController.addDisplayWindowListener(this);
     }
 
     public Handler getUpdateHandler() {
@@ -240,64 +261,145 @@
     }
 
     /**
-     * Dismiss PiP, this is done in two phases using {@link WindowContainerTransaction}
-     * - setActivityWindowingMode to undefined at beginning of the transaction. without changing
-     *   the windowing mode of the Task itself. This makes sure the activity render it's final
-     *   configuration while the Task is still in PiP.
+     * Expands PiP to the previous bounds, this is done in two phases using
+     * {@link WindowContainerTransaction}
+     * - setActivityWindowingMode to either fullscreen or split-secondary at beginning of the
+     *   transaction. without changing the windowing mode of the Task itself. This makes sure the
+     *   activity render it's final configuration while the Task is still in PiP.
      * - setWindowingMode to undefined at the end of transition
      * @param animationDurationMs duration in millisecond for the exiting PiP transition
      */
-    public void dismissPip(int animationDurationMs) {
+    public void exitPip(int animationDurationMs) {
         if (!mInPip || mToken == null) {
-            Log.wtf(TAG, "Not allowed to dismissPip in current state"
+            Log.wtf(TAG, "Not allowed to exitPip in current state"
                     + " mInPip=" + mInPip + " mToken=" + mToken);
             return;
         }
+
+        final Configuration initialConfig = mInitialState.remove(mToken.asBinder());
+        final boolean orientationDiffers = initialConfig.windowConfiguration.getRotation()
+                != mPipBoundsHandler.getDisplayRotation();
         final WindowContainerTransaction wct = new WindowContainerTransaction();
-        wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
-        WindowOrganizer.applyTransaction(wct);
-        final Rect destinationBounds = mBoundsToRestore.remove(mToken.asBinder());
-        final int direction = syncWithSplitScreenBounds(destinationBounds)
-                ? TRANSITION_DIRECTION_TO_SPLIT_SCREEN : TRANSITION_DIRECTION_TO_FULLSCREEN;
-        scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
-                direction, animationDurationMs, null /* updateBoundsCallback */);
-        mInPip = false;
+        if (orientationDiffers) {
+            // Don't bother doing an animation if the display rotation differs or if it's in
+            // a non-supported windowing mode
+            wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+            wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+            WindowOrganizer.applyTransaction(wct);
+            mInPip = false;
+        } else {
+            final Rect destinationBounds = initialConfig.windowConfiguration.getBounds();
+            final int direction = syncWithSplitScreenBounds(destinationBounds)
+                    ? TRANSITION_DIRECTION_TO_SPLIT_SCREEN
+                    : TRANSITION_DIRECTION_TO_FULLSCREEN;
+            final SurfaceControl.Transaction tx =
+                    mSurfaceControlTransactionFactory.getTransaction();
+            mSurfaceTransactionHelper.scale(tx, mLeash, destinationBounds,
+                    mLastReportedBounds);
+            tx.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height());
+            wct.setActivityWindowingMode(mToken, direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN
+                    ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
+                    : WINDOWING_MODE_FULLSCREEN);
+            wct.setBounds(mToken, destinationBounds);
+            wct.setBoundsChangeTransaction(mToken, tx);
+            applySyncTransaction(wct, new WindowContainerTransactionCallback() {
+                @Override
+                public void onTransactionReady(int id, SurfaceControl.Transaction t) {
+                    t.apply();
+                    scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
+                            direction, animationDurationMs, null /* updateBoundsCallback */);
+                    mInPip = false;
+                }
+            });
+        }
+    }
+
+    /**
+     * Removes PiP immediately.
+     */
+    public void removePip() {
+        if (!mInPip || mToken == null) {
+            Log.wtf(TAG, "Not allowed to removePip in current state"
+                    + " mInPip=" + mInPip + " mToken=" + mToken);
+            return;
+        }
+        getUpdateHandler().post(() -> {
+            try {
+                ActivityTaskManager.getService().removeStacksInWindowingModes(
+                        new int[]{ WINDOWING_MODE_PINNED });
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to remove PiP", e);
+            }
+        });
+        mInitialState.remove(mToken.asBinder());
     }
 
     @Override
     public void onTaskAppeared(ActivityManager.RunningTaskInfo info, SurfaceControl leash) {
         Objects.requireNonNull(info, "Requires RunningTaskInfo");
-        mPictureInPictureParams = info.pictureInPictureParams;
-        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                info.topActivity, getAspectRatioOrDefault(mPictureInPictureParams),
-                null /* bounds */, getMinimalSize(info.topActivityInfo));
-        Objects.requireNonNull(destinationBounds, "Missing destination bounds");
         mTaskInfo = info;
         mToken = mTaskInfo.token;
         mInPip = true;
         mLeash = leash;
+        mInitialState.put(mToken.asBinder(), new Configuration(mTaskInfo.configuration));
+        mPictureInPictureParams = mTaskInfo.pictureInPictureParams;
 
+        if (mShouldDeferEnteringPip) {
+            if (DEBUG) Log.d(TAG, "Defer entering PiP animation, fixed rotation is ongoing");
+            // if deferred, hide the surface till fixed rotation is completed
+            final SurfaceControl.Transaction tx =
+                    mSurfaceControlTransactionFactory.getTransaction();
+            tx.setAlpha(mLeash, 0f);
+            tx.apply();
+            return;
+        }
+
+        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
+                mTaskInfo.topActivity, getAspectRatioOrDefault(mPictureInPictureParams),
+                null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
+        Objects.requireNonNull(destinationBounds, "Missing destination bounds");
         final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
-        mBoundsToRestore.put(mToken.asBinder(), currentBounds);
+
         if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
             scheduleAnimateResizePip(currentBounds, destinationBounds,
                     TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
                     null /* updateBoundsCallback */);
         } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
-            mUpdateHandler.post(() -> mPipAnimationController
-                    .getAnimator(mLeash, destinationBounds, 0f, 1f)
-                    .setTransitionDirection(TRANSITION_DIRECTION_TO_PIP)
-                    .setPipAnimationCallback(mPipAnimationCallback)
-                    .setDuration(mEnterExitAnimationDuration)
-                    .start());
+            enterPipWithAlphaAnimation(destinationBounds, mEnterExitAnimationDuration);
             mOneShotAnimationType = ANIM_TYPE_BOUNDS;
         } else {
             throw new RuntimeException("Unrecognized animation type: " + mOneShotAnimationType);
         }
     }
 
+    private void enterPipWithAlphaAnimation(Rect destinationBounds, long durationMs) {
+        // If we are fading the PIP in, then we should move the pip to the final location as
+        // soon as possible, but set the alpha immediately since the transaction can take a
+        // while to process
+        final SurfaceControl.Transaction tx =
+                mSurfaceControlTransactionFactory.getTransaction();
+        tx.setAlpha(mLeash, 0f);
+        tx.apply();
+        final WindowContainerTransaction wct = new WindowContainerTransaction();
+        wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+        wct.setBounds(mToken, destinationBounds);
+        wct.scheduleFinishEnterPip(mToken, destinationBounds);
+        applySyncTransaction(wct, new WindowContainerTransactionCallback() {
+            @Override
+            public void onTransactionReady(int id, SurfaceControl.Transaction t) {
+                t.apply();
+                mUpdateHandler.post(() -> mPipAnimationController
+                        .getAnimator(mLeash, destinationBounds, 0f, 1f)
+                        .setTransitionDirection(TRANSITION_DIRECTION_TO_PIP)
+                        .setPipAnimationCallback(mPipAnimationCallback)
+                        .setDuration(durationMs)
+                        .start());
+            }
+        });
+    }
+
     /**
-     * Note that dismissing PiP is now originated from SystemUI, see {@link #dismissPip(int)}.
+     * Note that dismissing PiP is now originated from SystemUI, see {@link #exitPip(int)}.
      * Meanwhile this callback is invoked whenever the task is removed. For instance:
      *   - as a result of removeStacksInWindowingModes from WM
      *   - activity itself is died
@@ -315,6 +417,7 @@
             Log.wtf(TAG, "Unrecognized token: " + token);
             return;
         }
+        mShouldDeferEnteringPip = false;
         mPictureInPictureParams = null;
         mInPip = false;
     }
@@ -323,7 +426,7 @@
     public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
         Objects.requireNonNull(mToken, "onTaskInfoChanged requires valid existing mToken");
         final PictureInPictureParams newParams = info.pictureInPictureParams;
-        if (!applyPictureInPictureParams(newParams)) {
+        if (newParams == null || !applyPictureInPictureParams(newParams)) {
             Log.d(TAG, "Ignored onTaskInfoChanged with PiP param: " + newParams);
             return;
         }
@@ -340,6 +443,23 @@
         // Do nothing
     }
 
+    @Override
+    public void onFixedRotationStarted(int displayId, int newRotation) {
+        mShouldDeferEnteringPip = true;
+    }
+
+    @Override
+    public void onFixedRotationFinished(int displayId) {
+        if (mShouldDeferEnteringPip && mInPip) {
+            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
+                    mTaskInfo.topActivity, getAspectRatioOrDefault(mPictureInPictureParams),
+                    null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
+            // schedule a regular animation to ensure all the callbacks are still being sent
+            enterPipWithAlphaAnimation(destinationBounds, 0 /* durationMs */);
+        }
+        mShouldDeferEnteringPip = false;
+    }
+
     /**
      * TODO(b/152809058): consolidate the display info handling logic in SysUI
      *
@@ -400,6 +520,10 @@
      */
     public void scheduleAnimateResizePip(Rect toBounds, int duration,
             Consumer<Rect> updateBoundsCallback) {
+        if (mShouldDeferEnteringPip) {
+            Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
+            return;
+        }
         scheduleAnimateResizePip(mLastReportedBounds, toBounds,
                 TRANSITION_DIRECTION_NONE, duration, updateBoundsCallback);
     }
@@ -411,6 +535,7 @@
             // can be initiated in other component, ignore if we are no longer in PIP
             return;
         }
+
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = updateBoundsCallback;
         args.arg2 = currentBounds;
@@ -449,12 +574,21 @@
      * {@link #scheduleResizePip}.
      */
     public void scheduleFinishResizePip(Rect destinationBounds) {
+        scheduleFinishResizePip(destinationBounds, null);
+    }
+
+    /**
+     * Same as {@link #scheduleFinishResizePip} but with a callback.
+     */
+    public void scheduleFinishResizePip(Rect destinationBounds,
+            Consumer<Rect> updateBoundsCallback) {
         final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
         mSurfaceTransactionHelper
                 .crop(tx, mLeash, destinationBounds)
                 .resetScale(tx, mLeash, destinationBounds)
                 .round(tx, mLeash, mInPip);
-        scheduleFinishResizePip(tx, destinationBounds, TRANSITION_DIRECTION_NONE, null);
+        scheduleFinishResizePip(tx, destinationBounds, TRANSITION_DIRECTION_NONE,
+                updateBoundsCallback);
     }
 
     private void scheduleFinishResizePip(SurfaceControl.Transaction tx,
@@ -481,6 +615,10 @@
             // can be initiated in other component, ignore if we are no longer in PIP
             return;
         }
+        if (mShouldDeferEnteringPip) {
+            Log.d(TAG, "skip scheduleOffsetPip, entering pip deferred");
+            return;
+        }
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = updateBoundsCallback;
         args.arg2 = originalBounds;
@@ -509,11 +647,12 @@
             throw new RuntimeException("Callers should call scheduleResizePip() instead of this "
                     + "directly");
         }
-        // Could happen when dismissPip
+        // Could happen when exitPip
         if (mToken == null || mLeash == null) {
             Log.w(TAG, "Abort animation, invalid leash");
             return;
         }
+        mLastReportedBounds.set(destinationBounds);
         final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
         mSurfaceTransactionHelper
                 .crop(tx, mLeash, destinationBounds)
@@ -526,7 +665,7 @@
             throw new RuntimeException("Callers should call scheduleUserResizePip() instead of "
                     + "this directly");
         }
-        // Could happen when dismissPip
+        // Could happen when exitPip
         if (mToken == null || mLeash == null) {
             Log.w(TAG, "Abort animation, invalid leash");
             return;
@@ -537,29 +676,43 @@
     }
 
     private void finishResize(SurfaceControl.Transaction tx, Rect destinationBounds,
-            @PipAnimationController.TransitionDirection int direction) {
+            @PipAnimationController.TransitionDirection int direction,
+            @PipAnimationController.AnimationType int type) {
         if (Looper.myLooper() != mUpdateHandler.getLooper()) {
             throw new RuntimeException("Callers should call scheduleResizePip() instead of this "
                     + "directly");
         }
         mLastReportedBounds.set(destinationBounds);
+        if (isInPipDirection(direction) && type == ANIM_TYPE_ALPHA) {
+            return;
+        }
+
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         final Rect taskBounds;
-        if (isOutPipDirection(direction)) {
+        if (isInPipDirection(direction)) {
+            // If we are animating from fullscreen using a bounds animation, then reset the
+            // activity windowing mode set by WM, and set the task bounds to the final bounds
+            taskBounds = destinationBounds;
+            wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+            wct.scheduleFinishEnterPip(mToken, destinationBounds);
+        } else if (isOutPipDirection(direction)) {
             // If we are animating to fullscreen, then we need to reset the override bounds
             // on the task to ensure that the task "matches" the parent's bounds.
             taskBounds = (direction == TRANSITION_DIRECTION_TO_FULLSCREEN)
                     ? null : destinationBounds;
-            // As for the final windowing mode, simply reset it to undefined.
+            // As for the final windowing mode, simply reset it to undefined and reset the activity
+            // mode set prior to the animation running
             wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+            wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+            if (mSplitDivider != null && direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN) {
+                wct.reparent(mToken, mSplitDivider.getSecondaryRoot(), true /* onTop */);
+            }
         } else {
+            // Just a resize in PIP
             taskBounds = destinationBounds;
         }
-        if (direction == TRANSITION_DIRECTION_TO_PIP) {
-            wct.scheduleFinishEnterPip(mToken, taskBounds);
-        } else {
-            wct.setBounds(mToken, taskBounds);
-        }
+
+        wct.setBounds(mToken, taskBounds);
         wct.setBoundsChangeTransaction(mToken, tx);
         WindowOrganizer.applyTransaction(wct);
     }
@@ -570,17 +723,17 @@
             throw new RuntimeException("Callers should call scheduleAnimateResizePip() instead of "
                     + "this directly");
         }
-        // Could happen when dismissPip
+        // Could happen when exitPip
         if (mToken == null || mLeash == null) {
             Log.w(TAG, "Abort animation, invalid leash");
             return;
         }
-        mUpdateHandler.post(() -> mPipAnimationController
+        mPipAnimationController
                 .getAnimator(mLeash, currentBounds, destinationBounds)
                 .setTransitionDirection(direction)
                 .setPipAnimationCallback(mPipAnimationCallback)
                 .setDuration(durationMs)
-                .start());
+                .start();
     }
 
     private Size getMinimalSize(ActivityInfo activityInfo) {
@@ -609,7 +762,7 @@
      * @return {@code true} if destinationBounds is altered for split screen
      */
     private boolean syncWithSplitScreenBounds(Rect destinationBoundsOut) {
-        if (mSplitDivider == null || !mSplitDivider.inSplitMode()) {
+        if (mSplitDivider == null || !mSplitDivider.isDividerVisible()) {
             // bail early if system is not in split screen mode
             return false;
         }
@@ -621,6 +774,27 @@
     }
 
     /**
+     * Dumps internal states.
+     */
+    public void dump(PrintWriter pw, String prefix) {
+        final String innerPrefix = prefix + "  ";
+        pw.println(prefix + TAG);
+        pw.println(innerPrefix + "mTaskInfo=" + mTaskInfo);
+        pw.println(innerPrefix + "mToken=" + mToken
+                + " binder=" + (mToken != null ? mToken.asBinder() : null));
+        pw.println(innerPrefix + "mLeash=" + mLeash);
+        pw.println(innerPrefix + "mInPip=" + mInPip);
+        pw.println(innerPrefix + "mOneShotAnimationType=" + mOneShotAnimationType);
+        pw.println(innerPrefix + "mPictureInPictureParams=" + mPictureInPictureParams);
+        pw.println(innerPrefix + "mLastReportedBounds=" + mLastReportedBounds);
+        pw.println(innerPrefix + "mInitialState:");
+        for (Map.Entry<IBinder, Configuration> e : mInitialState.entrySet()) {
+            pw.println(innerPrefix + "  binder=" + e.getKey()
+                    + " winConfig=" + e.getValue().windowConfiguration);
+        }
+    }
+
+    /**
      * Callback interface for PiP transitions (both from and to PiP mode)
      */
     public interface PipTransitionCallback {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
index 84f7e89..f1eef43 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
@@ -101,7 +101,7 @@
                     result = true;
                     break;
                 case AccessibilityNodeInfo.ACTION_EXPAND:
-                    mMotionHelper.expandPip();
+                    mMotionHelper.expandPipToFullscreen();
                     result = true;
                     break;
                 default:
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 0841bb7..64df2ff 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -25,7 +25,6 @@
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.IActivityManager;
-import android.app.IActivityTaskManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
@@ -96,7 +95,7 @@
     private final DisplayChangeController.OnDisplayChangingListener mRotationController = (
             int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> {
         final boolean changed = mPipBoundsHandler.onDisplayRotationChanged(mTmpNormalBounds,
-                displayId, fromRotation, toRotation, t);
+                mPipTaskOrganizer.getLastReportedBounds(), displayId, fromRotation, toRotation, t);
         if (changed) {
             updateMovementBounds(mTmpNormalBounds, true /* fromRotation */,
                     false /* fromImeAdjustment */, false /* fromShelfAdjustment */);
@@ -140,7 +139,7 @@
                     != WINDOWING_MODE_PINNED) {
                 return;
             }
-            mTouchHandler.getMotionHelper().expandPip(clearedTask /* skipAnimation */);
+            mTouchHandler.getMotionHelper().expandPipToFullscreen(clearedTask /* skipAnimation */);
         }
     };
 
@@ -214,7 +213,6 @@
         }
         ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
 
-        final IActivityTaskManager activityTaskManager = ActivityTaskManager.getService();
         mPipBoundsHandler = pipBoundsHandler;
         mPipTaskOrganizer = pipTaskOrganizer;
         mPipTaskOrganizer.registerPipTransitionCallback(this);
@@ -222,7 +220,7 @@
         mMediaController = new PipMediaController(context, mActivityManager, broadcastDispatcher);
         mMenuController = new PipMenuActivityController(context, mMediaController,
                 mInputConsumerController);
-        mTouchHandler = new PipTouchHandler(context, mActivityManager, activityTaskManager,
+        mTouchHandler = new PipTouchHandler(context, mActivityManager,
                 mMenuController, mInputConsumerController, mPipBoundsHandler, mPipTaskOrganizer,
                 floatingContentCoordinator, deviceConfig, pipSnapAlgorithm);
         mAppOpsListener = new PipAppOpsListener(context, mActivityManager,
@@ -237,7 +235,7 @@
 
         try {
             mPipTaskOrganizer.registerOrganizer(WINDOWING_MODE_PINNED);
-            ActivityManager.StackInfo stackInfo = activityTaskManager.getStackInfo(
+            ActivityManager.StackInfo stackInfo = ActivityTaskManager.getService().getStackInfo(
                     WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
             if (stackInfo != null) {
                 // If SystemUI restart, and it already existed a pinned stack,
@@ -261,7 +259,7 @@
      */
     @Override
     public void expandPip() {
-        mTouchHandler.getMotionHelper().expandPip(false /* skipAnimation */);
+        mTouchHandler.getMotionHelper().expandPipToFullscreen(false /* skipAnimation */);
     }
 
     /**
@@ -295,7 +293,7 @@
             final boolean changed = mPipBoundsHandler.setShelfHeight(visible, height);
             if (changed) {
                 mTouchHandler.onShelfVisibilityChanged(visible, height);
-                updateMovementBounds(mPipBoundsHandler.getLastDestinationBounds(),
+                updateMovementBounds(mPipTaskOrganizer.getLastReportedBounds(),
                         false /* fromRotation */, false /* fromImeAdjustment */,
                         true /* fromShelfAdjustment */);
             }
@@ -378,5 +376,6 @@
         mMenuController.dump(pw, innerPrefix);
         mTouchHandler.dump(pw, innerPrefix);
         mPipBoundsHandler.dump(pw, innerPrefix);
+        mPipTaskOrganizer.dump(pw, innerPrefix);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 1982227..461fdef 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -21,6 +21,7 @@
 import static android.provider.Settings.ACTION_PICTURE_IN_PICTURE_SETTINGS;
 import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS;
 import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_ICONS;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
 
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ACTIONS;
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ALLOW_TIMEOUT;
@@ -28,6 +29,7 @@
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_DISMISS_FRACTION;
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MENU_STATE;
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_SHOW_MENU_WITH_DELAY;
+import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_SHOW_RESIZE_HANDLE;
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_STACK_BOUNDS;
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_WILL_RESIZE_MENU;
 import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE;
@@ -68,6 +70,7 @@
 import android.view.ViewGroup;
 import android.view.WindowManager.LayoutParams;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.FrameLayout;
 import android.widget.ImageButton;
 import android.widget.LinearLayout;
@@ -117,6 +120,7 @@
     private LinearLayout mActionsGroup;
     private View mSettingsButton;
     private View mDismissButton;
+    private View mResizeHandle;
     private int mBetweenActionPaddingLand;
 
     private AnimatorSet mMenuContainerAnimator;
@@ -140,7 +144,8 @@
                             data.getParcelable(EXTRA_STACK_BOUNDS),
                             data.getBoolean(EXTRA_ALLOW_TIMEOUT),
                             data.getBoolean(EXTRA_WILL_RESIZE_MENU),
-                            data.getBoolean(EXTRA_SHOW_MENU_WITH_DELAY));
+                            data.getBoolean(EXTRA_SHOW_MENU_WITH_DELAY),
+                            data.getBoolean(EXTRA_SHOW_RESIZE_HANDLE));
                     break;
                 }
                 case MESSAGE_POKE_MENU:
@@ -210,6 +215,8 @@
                 expandPip();
             }
         });
+        mResizeHandle = findViewById(R.id.resize_handle);
+        mResizeHandle.setAlpha(0);
         mActionsGroup = findViewById(R.id.actions_group);
         mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
                 R.dimen.pip_between_action_padding_land);
@@ -220,6 +227,29 @@
 
         // Hide without an animation.
         getWindow().setExitTransition(null);
+
+        initAccessibility();
+    }
+
+    private void initAccessibility() {
+        getWindow().getDecorView().setAccessibilityDelegate(new View.AccessibilityDelegate() {
+            @Override
+            public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+                super.onInitializeAccessibilityNodeInfo(host, info);
+                String label = getResources().getString(R.string.pip_menu_title);
+                info.addAction(new AccessibilityNodeInfo.AccessibilityAction(ACTION_CLICK, label));
+            }
+
+            @Override
+            public boolean performAccessibilityAction(View host, int action, Bundle args) {
+                if (action == ACTION_CLICK && mMenuState == MENU_STATE_CLOSE) {
+                    Message m = Message.obtain();
+                    m.what = PipMenuActivityController.MESSAGE_SHOW_MENU;
+                    sendMessage(m, "Could not notify controller to show PIP menu");
+                }
+                return super.performAccessibilityAction(host, action, args);
+            }
+        });
     }
 
     @Override
@@ -317,7 +347,7 @@
     }
 
     private void showMenu(int menuState, Rect stackBounds, boolean allowMenuTimeout,
-            boolean resizeMenuOnShow, boolean withDelay) {
+            boolean resizeMenuOnShow, boolean withDelay, boolean showResizeHandle) {
         mAllowMenuTimeout = allowMenuTimeout;
         if (mMenuState != menuState) {
             // Disallow touches if the menu needs to resize while showing, and we are transitioning
@@ -338,10 +368,14 @@
                     mSettingsButton.getAlpha(), 1f);
             ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
                     mDismissButton.getAlpha(), 1f);
+            ObjectAnimator resizeAnim = ObjectAnimator.ofFloat(mResizeHandle, View.ALPHA,
+                    mResizeHandle.getAlpha(), menuState == MENU_STATE_CLOSE && showResizeHandle
+                            ? 1f : 0f);
             if (menuState == MENU_STATE_FULL) {
-                mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim);
+                mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim,
+                        resizeAnim);
             } else {
-                mMenuContainerAnimator.playTogether(dismissAnim);
+                mMenuContainerAnimator.playTogether(dismissAnim, resizeAnim);
             }
             mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN);
             mMenuContainerAnimator.setDuration(MENU_FADE_DURATION);
@@ -374,11 +408,12 @@
     }
 
     private void hideMenu(Runnable animationEndCallback) {
-        hideMenu(animationEndCallback, true /* notifyMenuVisibility */, false /* isDismissing */);
+        hideMenu(animationEndCallback, true /* notifyMenuVisibility */, false /* isDismissing */,
+                true /* animate */);
     }
 
     private void hideMenu(final Runnable animationFinishedRunnable, boolean notifyMenuVisibility,
-            boolean isDismissing) {
+            boolean isDismissing, boolean animate) {
         if (mMenuState != MENU_STATE_NONE) {
             cancelDelayedFinish();
             if (notifyMenuVisibility) {
@@ -392,9 +427,11 @@
                     mSettingsButton.getAlpha(), 0f);
             ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
                     mDismissButton.getAlpha(), 0f);
-            mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim);
+            ObjectAnimator resizeAnim = ObjectAnimator.ofFloat(mResizeHandle, View.ALPHA,
+                    mResizeHandle.getAlpha(), 0f);
+            mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim, resizeAnim);
             mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT);
-            mMenuContainerAnimator.setDuration(MENU_FADE_DURATION);
+            mMenuContainerAnimator.setDuration(animate ? MENU_FADE_DURATION : 0);
             mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animation) {
@@ -437,7 +474,9 @@
             boolean allowMenuTimeout = intent.getBooleanExtra(EXTRA_ALLOW_TIMEOUT, true);
             boolean willResizeMenu = intent.getBooleanExtra(EXTRA_WILL_RESIZE_MENU, false);
             boolean withDelay = intent.getBooleanExtra(EXTRA_SHOW_MENU_WITH_DELAY, false);
-            showMenu(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay);
+            boolean showResizeHandle = intent.getBooleanExtra(EXTRA_SHOW_RESIZE_HANDLE, false);
+            showMenu(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay,
+                    showResizeHandle);
         }
     }
 
@@ -557,16 +596,20 @@
         hideMenu(() -> {
             sendEmptyMessage(PipMenuActivityController.MESSAGE_EXPAND_PIP,
                     "Could not notify controller to expand PIP");
-        }, false /* notifyMenuVisibility */, false /* isDismissing */);
+        }, false /* notifyMenuVisibility */, false /* isDismissing */, true /* animate */);
     }
 
     private void dismissPip() {
+        // Since tapping on the close-button invokes a double-tap wait callback in PipTouchHandler,
+        // we want to disable animating the fadeout animation of the buttons in order to call on
+        // PipTouchHandler#onPipDismiss fast enough.
+        final boolean animate = mMenuState != MENU_STATE_CLOSE;
         // Do not notify menu visibility when hiding the menu, the controller will do this when it
         // handles the message
         hideMenu(() -> {
             sendEmptyMessage(PipMenuActivityController.MESSAGE_DISMISS_PIP,
                     "Could not notify controller to dismiss PIP");
-        }, false /* notifyMenuVisibility */, true /* isDismissing */);
+        }, false /* notifyMenuVisibility */, true /* isDismissing */, animate);
     }
 
     private void showSettings() {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 1608f83..36a9a34 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -65,6 +65,7 @@
     public static final String EXTRA_DISMISS_FRACTION = "dismiss_fraction";
     public static final String EXTRA_MENU_STATE = "menu_state";
     public static final String EXTRA_SHOW_MENU_WITH_DELAY = "show_menu_with_delay";
+    public static final String EXTRA_SHOW_RESIZE_HANDLE = "show_resize_handle";
 
     public static final int MESSAGE_MENU_STATE_CHANGED = 100;
     public static final int MESSAGE_EXPAND_PIP = 101;
@@ -248,7 +249,7 @@
             // start, then start it
             startMenuActivity(MENU_STATE_NONE, null /* stackBounds */,
                     false /* allowMenuTimeout */, false /* resizeMenuOnShow */,
-                    false /* withDelay */);
+                    false /* withDelay */, false /* showResizeHandle */);
         }
     }
 
@@ -257,28 +258,29 @@
      * PiP window transition is finished.
      */
     public void showMenuWithDelay(int menuState, Rect stackBounds, boolean allowMenuTimeout,
-            boolean willResizeMenu) {
+            boolean willResizeMenu, boolean showResizeHandle) {
         showMenuInternal(menuState, stackBounds, allowMenuTimeout, willResizeMenu,
-                true /* withDelay */);
+                true /* withDelay */, showResizeHandle);
     }
 
     /**
      * Shows the menu activity immediately.
      */
     public void showMenu(int menuState, Rect stackBounds, boolean allowMenuTimeout,
-            boolean willResizeMenu) {
+            boolean willResizeMenu, boolean showResizeHandle) {
         showMenuInternal(menuState, stackBounds, allowMenuTimeout, willResizeMenu,
-                false /* withDelay */);
+                false /* withDelay */, showResizeHandle);
     }
 
     private void showMenuInternal(int menuState, Rect stackBounds, boolean allowMenuTimeout,
-            boolean willResizeMenu, boolean withDelay) {
+            boolean willResizeMenu, boolean withDelay, boolean showResizeHandle) {
         if (DEBUG) {
             Log.d(TAG, "showMenu() state=" + menuState
                     + " hasActivity=" + (mToActivityMessenger != null)
                     + " allowMenuTimeout=" + allowMenuTimeout
                     + " willResizeMenu=" + willResizeMenu
                     + " withDelay=" + withDelay
+                    + " showResizeHandle=" + showResizeHandle
                     + " callers=\n" + Debug.getCallers(5, "    "));
         }
 
@@ -291,6 +293,7 @@
             data.putBoolean(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout);
             data.putBoolean(EXTRA_WILL_RESIZE_MENU, willResizeMenu);
             data.putBoolean(EXTRA_SHOW_MENU_WITH_DELAY, withDelay);
+            data.putBoolean(EXTRA_SHOW_RESIZE_HANDLE, showResizeHandle);
             Message m = Message.obtain();
             m.what = PipMenuActivity.MESSAGE_SHOW_MENU;
             m.obj = data;
@@ -302,7 +305,8 @@
         } else if (!mStartActivityRequested || isStartActivityRequestedElapsed()) {
             // If we haven't requested the start activity, or if it previously took too long to
             // start, then start it
-            startMenuActivity(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay);
+            startMenuActivity(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay,
+                    showResizeHandle);
         }
     }
 
@@ -405,7 +409,7 @@
      * Starts the menu activity on the top task of the pinned stack.
      */
     private void startMenuActivity(int menuState, Rect stackBounds, boolean allowMenuTimeout,
-            boolean willResizeMenu, boolean withDelay) {
+            boolean willResizeMenu, boolean withDelay, boolean showResizeHandle) {
         try {
             StackInfo pinnedStackInfo = ActivityTaskManager.getService().getStackInfo(
                     WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
@@ -422,6 +426,7 @@
                 intent.putExtra(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout);
                 intent.putExtra(EXTRA_WILL_RESIZE_MENU, willResizeMenu);
                 intent.putExtra(EXTRA_SHOW_MENU_WITH_DELAY, withDelay);
+                intent.putExtra(EXTRA_SHOW_RESIZE_HANDLE, showResizeHandle);
                 ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
                 options.setLaunchTaskId(
                         pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 08d4222..74c72fd 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -16,16 +16,12 @@
 
 package com.android.systemui.pip.phone;
 
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.IActivityTaskManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Debug;
-import android.os.RemoteException;
 import android.util.Log;
 
 import androidx.dynamicanimation.animation.SpringForce;
@@ -33,7 +29,6 @@
 import com.android.systemui.pip.PipSnapAlgorithm;
 import com.android.systemui.pip.PipTaskOrganizer;
 import com.android.systemui.shared.system.WindowManagerWrapper;
-import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.util.FloatingContentCoordinator;
 import com.android.systemui.util.animation.FloatProperties;
 import com.android.systemui.util.animation.PhysicsAnimator;
@@ -60,12 +55,10 @@
     private static final float DEFAULT_FRICTION = 2f;
 
     private final Context mContext;
-    private final IActivityTaskManager mActivityTaskManager;
     private final PipTaskOrganizer mPipTaskOrganizer;
 
     private PipMenuActivityController mMenuController;
     private PipSnapAlgorithm mSnapAlgorithm;
-    private FlingAnimationUtils mFlingAnimationUtils;
 
     private final Rect mStableInsets = new Rect();
 
@@ -147,16 +140,13 @@
         public void onPipTransitionCanceled(ComponentName activity, int direction) {}
     };
 
-    public PipMotionHelper(Context context, IActivityTaskManager activityTaskManager,
-            PipTaskOrganizer pipTaskOrganizer, PipMenuActivityController menuController,
-            PipSnapAlgorithm snapAlgorithm, FlingAnimationUtils flingAnimationUtils,
+    public PipMotionHelper(Context context, PipTaskOrganizer pipTaskOrganizer,
+            PipMenuActivityController menuController, PipSnapAlgorithm snapAlgorithm,
             FloatingContentCoordinator floatingContentCoordinator) {
         mContext = context;
-        mActivityTaskManager = activityTaskManager;
         mPipTaskOrganizer = pipTaskOrganizer;
         mMenuController = menuController;
         mSnapAlgorithm = snapAlgorithm;
-        mFlingAnimationUtils = flingAnimationUtils;
         mFloatingContentCoordinator = floatingContentCoordinator;
         onConfigurationChanged();
         mPipTaskOrganizer.registerPipTransitionCallback(mPipTransitionCallback);
@@ -247,7 +237,8 @@
                     .spring(FloatProperties.RECT_Y, toBounds.top, mSpringConfig)
                     .withEndActions(() -> mSpringingToTouch = false);
 
-            startBoundsAnimator(toBounds.left /* toX */, toBounds.top /* toY */);
+            startBoundsAnimator(toBounds.left /* toX */, toBounds.top /* toY */,
+                    false /* dismiss */);
         }
     }
 
@@ -267,22 +258,24 @@
     /**
      * Resizes the pinned stack back to fullscreen.
      */
-    void expandPip() {
-        expandPip(false /* skipAnimation */);
+    void expandPipToFullscreen() {
+        expandPipToFullscreen(false /* skipAnimation */);
     }
 
     /**
      * Resizes the pinned stack back to fullscreen.
      */
-    void expandPip(boolean skipAnimation) {
+    void expandPipToFullscreen(boolean skipAnimation) {
         if (DEBUG) {
-            Log.d(TAG, "expandPip: skipAnimation=" + skipAnimation
+            Log.d(TAG, "exitPip: skipAnimation=" + skipAnimation
                     + " callers=\n" + Debug.getCallers(5, "    "));
         }
         cancelAnimations();
         mMenuController.hideMenuWithoutResize();
         mPipTaskOrganizer.getUpdateHandler().post(() -> {
-            mPipTaskOrganizer.dismissPip(skipAnimation ? 0 : EXPAND_STACK_TO_FULLSCREEN_DURATION);
+            mPipTaskOrganizer.exitPip(skipAnimation
+                    ? 0
+                    : EXPAND_STACK_TO_FULLSCREEN_DURATION);
         });
     }
 
@@ -292,18 +285,11 @@
     @Override
     public void dismissPip() {
         if (DEBUG) {
-            Log.d(TAG, "dismissPip: callers=\n" + Debug.getCallers(5, "    "));
+            Log.d(TAG, "removePip: callers=\n" + Debug.getCallers(5, "    "));
         }
         cancelAnimations();
         mMenuController.hideMenuWithoutResize();
-        mPipTaskOrganizer.getUpdateHandler().post(() -> {
-            try {
-                mActivityTaskManager.removeStacksInWindowingModes(
-                        new int[]{ WINDOWING_MODE_PINNED });
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to remove PiP", e);
-            }
-        });
+        mPipTaskOrganizer.removePip();
     }
 
     /** Sets the movement bounds to use to constrain PIP position animations. */
@@ -349,7 +335,8 @@
         final float estimatedFlingYEndValue =
                 PhysicsAnimator.estimateFlingEndValue(mBounds.top, velocityY, mFlingConfigY);
 
-        startBoundsAnimator(xEndValue /* toX */, estimatedFlingYEndValue /* toY */);
+        startBoundsAnimator(xEndValue /* toX */, estimatedFlingYEndValue /* toY */,
+                false /* dismiss */);
     }
 
     /**
@@ -361,30 +348,26 @@
         mAnimatedBoundsPhysicsAnimator
                 .spring(FloatProperties.RECT_X, bounds.left, springConfig)
                 .spring(FloatProperties.RECT_Y, bounds.top, springConfig);
-        startBoundsAnimator(bounds.left /* toX */, bounds.top /* toY */);
+        startBoundsAnimator(bounds.left /* toX */, bounds.top /* toY */,
+                false /* dismiss */);
     }
 
     /**
      * Animates the dismissal of the PiP off the edge of the screen.
      */
-    void animateDismiss(float velocityX, float velocityY, @Nullable Runnable updateAction) {
+    void animateDismiss() {
         mAnimatedBounds.set(mBounds);
 
         // Animate off the bottom of the screen, then dismiss PIP.
         mAnimatedBoundsPhysicsAnimator
                 .spring(FloatProperties.RECT_Y,
                         mBounds.bottom + mBounds.height(),
-                        velocityY,
+                        0,
                         mSpringConfig)
                 .withEndActions(this::dismissPip);
 
-        // If we were provided with an update action, run it whenever there's an update.
-        if (updateAction != null) {
-            mAnimatedBoundsPhysicsAnimator.addUpdateListener(
-                    (target, values) -> updateAction.run());
-        }
-
-        startBoundsAnimator(mBounds.left /* toX */, mBounds.bottom + mBounds.height() /* toY */);
+        startBoundsAnimator(mBounds.left /* toX */, mBounds.bottom + mBounds.height() /* toY */,
+                true /* dismiss */);
     }
 
     /**
@@ -455,7 +438,7 @@
      * This will also add end actions to the bounds animator that cancel the TimeAnimator and update
      * the 'real' bounds to equal the final animated bounds.
      */
-    private void startBoundsAnimator(float toX, float toY) {
+    private void startBoundsAnimator(float toX, float toY, boolean dismiss) {
         if (!mSpringingToTouch) {
             cancelAnimations();
         }
@@ -471,7 +454,9 @@
 
         mAnimatedBoundsPhysicsAnimator
                 .withEndActions(() -> {
-                    mPipTaskOrganizer.scheduleFinishResizePip(mAnimatedBounds);
+                    if (!dismiss) {
+                        mPipTaskOrganizer.scheduleFinishResizePip(mAnimatedBounds);
+                    }
                     mAnimatingToBounds.setEmpty();
                 })
                 .addUpdateListener(mResizePipUpdateListener)
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
index d80f18a..5f0bf56 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
@@ -29,6 +29,7 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.hardware.input.InputManager;
+import android.os.Handler;
 import android.os.Looper;
 import android.provider.DeviceConfig;
 import android.util.DisplayMetrics;
@@ -45,6 +46,7 @@
 import com.android.systemui.util.DeviceConfigProxy;
 
 import java.util.concurrent.Executor;
+import java.util.function.Supplier;
 
 /**
  * Helper on top of PipTouchHandler that handles inputs OUTSIDE of the PIP window, which is used to
@@ -66,8 +68,15 @@
     private final Point mMinSize = new Point();
     private final Rect mLastResizeBounds = new Rect();
     private final Rect mLastDownBounds = new Rect();
-    private final Rect mTmpBounds = new Rect();
+    private final Rect mDragCornerSize = new Rect();
+    private final Rect mTmpTopLeftCorner = new Rect();
+    private final Rect mTmpTopRightCorner = new Rect();
+    private final Rect mTmpBottomLeftCorner = new Rect();
+    private final Rect mTmpBottomRightCorner = new Rect();
+    private final Rect mDisplayBounds = new Rect();
     private final int mDelta;
+    private final Supplier<Rect> mMovementBoundsSupplier;
+    private final Runnable mUpdateMovementBoundsRunnable;
 
     private boolean mAllowGesture;
     private boolean mIsAttached;
@@ -82,7 +91,8 @@
 
     public PipResizeGestureHandler(Context context, PipBoundsHandler pipBoundsHandler,
             PipMotionHelper motionHelper, DeviceConfigProxy deviceConfig,
-            PipTaskOrganizer pipTaskOrganizer) {
+            PipTaskOrganizer pipTaskOrganizer, Supplier<Rect> movementBoundsSupplier,
+            Runnable updateMovementBoundsRunnable) {
         final Resources res = context.getResources();
         context.getDisplay().getMetrics(mDisplayMetrics);
         mDisplayId = context.getDisplayId();
@@ -90,6 +100,8 @@
         mPipBoundsHandler = pipBoundsHandler;
         mMotionHelper = motionHelper;
         mPipTaskOrganizer = pipTaskOrganizer;
+        mMovementBoundsSupplier = movementBoundsSupplier;
+        mUpdateMovementBoundsRunnable = updateMovementBoundsRunnable;
 
         context.getDisplay().getRealSize(mMaxSize);
         mDelta = res.getDimensionPixelSize(R.dimen.pip_resize_edge_size);
@@ -110,6 +122,14 @@
                 });
     }
 
+    private void resetDragCorners() {
+        mDragCornerSize.set(0, 0, mDelta, mDelta);
+        mTmpTopLeftCorner.set(mDragCornerSize);
+        mTmpTopRightCorner.set(mDragCornerSize);
+        mTmpBottomLeftCorner.set(mDragCornerSize);
+        mTmpBottomRightCorner.set(mDragCornerSize);
+    }
+
     private void disposeInputChannel() {
         if (mInputEventReceiver != null) {
             mInputEventReceiver.dispose();
@@ -154,34 +174,75 @@
         }
     }
 
-    private boolean isWithinTouchRegion(int x, int y) {
+    /**
+     * Check whether the current x,y coordinate is within the region in which drag-resize should
+     * start.
+     * This consists of 4 small squares on the 4 corners of the PIP window, a quarter of which
+     * overlaps with the PIP window while the rest goes outside of the PIP window.
+     *  _ _           _ _
+     * |_|_|_________|_|_|
+     * |_|_|         |_|_|
+     *   |     PIP     |
+     *   |   WINDOW    |
+     *  _|_           _|_
+     * |_|_|_________|_|_|
+     * |_|_|         |_|_|
+     */
+    public boolean isWithinTouchRegion(int x, int y) {
         final Rect currentPipBounds = mMotionHelper.getBounds();
         if (currentPipBounds == null) {
             return false;
         }
+        resetDragCorners();
+        mTmpTopLeftCorner.offset(currentPipBounds.left - mDelta / 2,
+                currentPipBounds.top - mDelta /  2);
+        mTmpTopRightCorner.offset(currentPipBounds.right - mDelta / 2,
+                currentPipBounds.top - mDelta /  2);
+        mTmpBottomLeftCorner.offset(currentPipBounds.left - mDelta / 2,
+                currentPipBounds.bottom - mDelta /  2);
+        mTmpBottomRightCorner.offset(currentPipBounds.right - mDelta / 2,
+                currentPipBounds.bottom - mDelta /  2);
 
-        mTmpBounds.set(currentPipBounds);
-        mTmpBounds.inset(-mDelta, -mDelta);
+        mTmpRegion.setEmpty();
+        mTmpRegion.op(mTmpTopLeftCorner, Region.Op.UNION);
+        mTmpRegion.op(mTmpTopRightCorner, Region.Op.UNION);
+        mTmpRegion.op(mTmpBottomLeftCorner, Region.Op.UNION);
+        mTmpRegion.op(mTmpBottomRightCorner, Region.Op.UNION);
 
-        mTmpRegion.set(mTmpBounds);
-        mTmpRegion.op(currentPipBounds, Region.Op.DIFFERENCE);
+        return mTmpRegion.contains(x, y);
+    }
 
-        if (mTmpRegion.contains(x, y)) {
-            if (x < currentPipBounds.left) {
-                mCtrlType |= CTRL_LEFT;
-            }
-            if (x > currentPipBounds.right) {
-                mCtrlType |= CTRL_RIGHT;
-            }
-            if (y < currentPipBounds.top) {
-                mCtrlType |= CTRL_TOP;
-            }
-            if (y > currentPipBounds.bottom) {
-                mCtrlType |= CTRL_BOTTOM;
-            }
-            return true;
+    private void setCtrlType(int x, int y) {
+        final Rect currentPipBounds = mMotionHelper.getBounds();
+
+        Rect movementBounds = mMovementBoundsSupplier.get();
+        mDisplayBounds.set(movementBounds.left,
+                movementBounds.top,
+                movementBounds.right + currentPipBounds.width(),
+                movementBounds.bottom + currentPipBounds.height());
+
+        if (mTmpTopLeftCorner.contains(x, y) && currentPipBounds.top != mDisplayBounds.top
+                && currentPipBounds.left != mDisplayBounds.left) {
+            mCtrlType |= CTRL_LEFT;
+            mCtrlType |= CTRL_TOP;
         }
-        return false;
+        if (mTmpTopRightCorner.contains(x, y) && currentPipBounds.top != mDisplayBounds.top
+                && currentPipBounds.right != mDisplayBounds.right) {
+            mCtrlType |= CTRL_RIGHT;
+            mCtrlType |= CTRL_TOP;
+        }
+        if (mTmpBottomRightCorner.contains(x, y)
+                && currentPipBounds.bottom != mDisplayBounds.bottom
+                && currentPipBounds.right != mDisplayBounds.right) {
+            mCtrlType |= CTRL_RIGHT;
+            mCtrlType |= CTRL_BOTTOM;
+        }
+        if (mTmpBottomLeftCorner.contains(x, y)
+                && currentPipBounds.bottom != mDisplayBounds.bottom
+                && currentPipBounds.left != mDisplayBounds.left) {
+            mCtrlType |= CTRL_LEFT;
+            mCtrlType |= CTRL_BOTTOM;
+        }
     }
 
     private void onMotionEvent(MotionEvent ev) {
@@ -190,6 +251,7 @@
             mLastResizeBounds.setEmpty();
             mAllowGesture = isWithinTouchRegion((int) ev.getX(), (int) ev.getY());
             if (mAllowGesture) {
+                setCtrlType((int) ev.getX(), (int) ev.getY());
                 mDownPoint.set(ev.getX(), ev.getY());
                 mLastDownBounds.set(mMotionHelper.getBounds());
             }
@@ -214,10 +276,14 @@
                     break;
                 case MotionEvent.ACTION_UP:
                 case MotionEvent.ACTION_CANCEL:
-                    mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds);
-                    mMotionHelper.synchronizePinnedStackBounds();
-                    mCtrlType = CTRL_NONE;
-                    mAllowGesture = false;
+                    mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds, (Rect bounds) -> {
+                        new Handler(Looper.getMainLooper()).post(() -> {
+                            mMotionHelper.synchronizePinnedStackBounds();
+                            mUpdateMovementBoundsRunnable.run();
+                            mCtrlType = CTRL_NONE;
+                            mAllowGesture = false;
+                        });
+                    });
                     break;
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index b70fb3f..ecd80a3 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -23,7 +23,6 @@
 
 import android.annotation.SuppressLint;
 import android.app.IActivityManager;
-import android.app.IActivityTaskManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Resources;
@@ -188,7 +187,7 @@
 
         @Override
         public void onPipExpand() {
-            mMotionHelper.expandPip();
+            mMotionHelper.expandPipToFullscreen();
         }
 
         @Override
@@ -198,19 +197,20 @@
             if (topPipActivity.first != null) {
                 MetricsLoggerWrapper.logPictureInPictureDismissByTap(mContext, topPipActivity);
             }
+            mTouchState.removeDoubleTapTimeoutCallback();
             mMotionHelper.dismissPip();
         }
 
         @Override
         public void onPipShowMenu() {
             mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
-                    true /* allowMenuTimeout */, willResizeMenu());
+                    true /* allowMenuTimeout */, willResizeMenu(), shouldShowResizeHandle());
         }
     }
 
     @SuppressLint("InflateParams")
     public PipTouchHandler(Context context, IActivityManager activityManager,
-            IActivityTaskManager activityTaskManager, PipMenuActivityController menuController,
+            PipMenuActivityController menuController,
             InputConsumerController inputConsumerController,
             PipBoundsHandler pipBoundsHandler,
             PipTaskOrganizer pipTaskOrganizer,
@@ -228,14 +228,15 @@
         mFlingAnimationUtils = new FlingAnimationUtils(context.getResources().getDisplayMetrics(),
                 2.5f);
         mGesture = new DefaultPipTouchGesture();
-        mMotionHelper = new PipMotionHelper(mContext, activityTaskManager, pipTaskOrganizer,
-                mMenuController, mSnapAlgorithm, mFlingAnimationUtils, floatingContentCoordinator);
+        mMotionHelper = new PipMotionHelper(mContext, pipTaskOrganizer, mMenuController,
+                mSnapAlgorithm, floatingContentCoordinator);
         mPipResizeGestureHandler =
                 new PipResizeGestureHandler(context, pipBoundsHandler, mMotionHelper,
-                        deviceConfig, pipTaskOrganizer);
+                        deviceConfig, pipTaskOrganizer, this::getMovementBounds,
+                        this::updateMovementBounds);
         mTouchState = new PipTouchState(ViewConfiguration.get(context), mHandler,
                 () -> mMenuController.showMenuWithDelay(MENU_STATE_FULL, mMotionHelper.getBounds(),
-                        true /* allowMenuTimeout */, willResizeMenu()));
+                        true /* allowMenuTimeout */, willResizeMenu(), shouldShowResizeHandle()));
 
         Resources res = context.getResources();
         mExpandedShortestEdgeSize = res.getDimensionPixelSize(
@@ -297,7 +298,7 @@
             @Override
             public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target) {
                 mHandler.post(() -> {
-                    mMotionHelper.animateDismiss(0, 0, null);
+                    mMotionHelper.animateDismiss();
                     hideDismissTarget();
                 });
 
@@ -310,6 +311,10 @@
         mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView);
     }
 
+    private boolean shouldShowResizeHandle() {
+        return !mPipBoundsHandler.hasSaveReentryBounds();
+    }
+
     public void setTouchGesture(PipTouchGesture gesture) {
         mGesture = gesture;
     }
@@ -322,7 +327,8 @@
         // Only show the menu if the user isn't currently interacting with the PiP
         if (!mTouchState.isUserInteracting()) {
             mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
-                    false /* allowMenuTimeout */, willResizeMenu());
+                    false /* allowMenuTimeout */, willResizeMenu(),
+                    shouldShowResizeHandle());
         }
     }
 
@@ -358,7 +364,8 @@
 
         if (mShowPipMenuOnAnimationEnd) {
             mMenuController.showMenu(MENU_STATE_CLOSE, mMotionHelper.getBounds(),
-                    true /* allowMenuTimeout */, false /* willResizeMenu */);
+                    true /* allowMenuTimeout */, false /* willResizeMenu */,
+                    shouldShowResizeHandle());
             mShowPipMenuOnAnimationEnd = false;
         }
     }
@@ -424,20 +431,28 @@
 
         // If this is from an IME or shelf adjustment, then we should move the PiP so that it is not
         // occluded by the IME or shelf.
-        if (fromImeAdjustment || fromShelfAdjustment || fromDisplayRotationChanged) {
+        if (fromImeAdjustment || fromShelfAdjustment) {
             if (mTouchState.isUserInteracting()) {
                 // Defer the update of the current movement bounds until after the user finishes
                 // touching the screen
             } else {
                 final float offsetBufferPx = BOTTOM_OFFSET_BUFFER_DP
                         * mContext.getResources().getDisplayMetrics().density;
-                final Rect toMovementBounds = mMenuState == MENU_STATE_FULL && willResizeMenu()
+                final boolean isExpanded = mMenuState == MENU_STATE_FULL && willResizeMenu();
+                final Rect toMovementBounds = isExpanded
                         ? new Rect(expandedMovementBounds)
                         : new Rect(normalMovementBounds);
                 final int prevBottom = mMovementBounds.bottom - mMovementBoundsExtraOffsets;
                 final int toBottom = toMovementBounds.bottom < toMovementBounds.top
                         ? toMovementBounds.bottom
                         : toMovementBounds.bottom - extraOffset;
+
+                if (isExpanded) {
+                    curBounds.set(mExpandedBounds);
+                    mSnapAlgorithm.applySnapFraction(curBounds, toMovementBounds,
+                            mSavedSnapFraction);
+                }
+
                 if ((Math.min(prevBottom, toBottom) - offsetBufferPx) <= curBounds.top
                         && curBounds.top <= (Math.max(prevBottom, toBottom) + offsetBufferPx)) {
                     mMotionHelper.animateToOffset(curBounds, toBottom - curBounds.top);
@@ -557,7 +572,8 @@
 
     private void onAccessibilityShowMenu() {
         mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
-                true /* allowMenuTimeout */, willResizeMenu());
+                true /* allowMenuTimeout */, willResizeMenu(),
+                shouldShowResizeHandle());
     }
 
     private boolean handleTouchEvent(InputEvent inputEvent) {
@@ -572,6 +588,11 @@
 
         MotionEvent ev = (MotionEvent) inputEvent;
 
+
+        if (mPipResizeGestureHandler.isWithinTouchRegion((int) ev.getX(), (int) ev.getY())) {
+            return true;
+        }
+
         if (mMagnetizedPip.maybeConsumeMotionEvent(ev)) {
             // If the first touch event occurs within the magnetic field, pass the ACTION_DOWN event
             // to the touch state. Touch state needs a DOWN event in order to later process MOVE
@@ -628,7 +649,8 @@
                 // Let's not enable menu show/hide for a11y services.
                 if (!mAccessibilityManager.isTouchExplorationEnabled()) {
                     mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
-                            false /* allowMenuTimeout */, false /* willResizeMenu */);
+                            false /* allowMenuTimeout */, false /* willResizeMenu */,
+                            shouldShowResizeHandle());
                 }
             case MotionEvent.ACTION_HOVER_MOVE: {
                 if (!shouldDeliverToMenu && !mSendingHoverAccessibilityEvents) {
@@ -809,6 +831,7 @@
     private class DefaultPipTouchGesture extends PipTouchGesture {
         private final Point mStartPosition = new Point();
         private final PointF mDelta = new PointF();
+        private boolean mShouldHideMenuAfterFling;
 
         @Override
         public void onDown(PipTouchState touchState) {
@@ -886,32 +909,30 @@
             final float velocity = PointF.length(vel.x, vel.y);
 
             if (touchState.isDragging()) {
-                Runnable endAction = null;
                 if (mMenuState != MENU_STATE_NONE) {
                     // If the menu is still visible, then just poke the menu so that
                     // it will timeout after the user stops touching it
                     mMenuController.showMenu(mMenuState, mMotionHelper.getBounds(),
-                            true /* allowMenuTimeout */, willResizeMenu());
-                } else {
-                    // If the menu is not visible, then we can still be showing the activity for the
-                    // dismiss overlay, so just finish it after the animation completes
-                    endAction = mMenuController::hideMenu;
+                            true /* allowMenuTimeout */, willResizeMenu(),
+                            shouldShowResizeHandle());
                 }
+                mShouldHideMenuAfterFling = mMenuState == MENU_STATE_NONE;
 
                 mMotionHelper.flingToSnapTarget(vel.x, vel.y,
                         PipTouchHandler.this::updateDismissFraction /* updateAction */,
-                        endAction /* endAction */);
+                        this::flingEndAction /* endAction */);
             } else if (mTouchState.isDoubleTap()) {
                 // Expand to fullscreen if this is a double tap
                 // the PiP should be frozen until the transition ends
                 setTouchEnabled(false);
-                mMotionHelper.expandPip();
+                mMotionHelper.expandPipToFullscreen();
             } else if (mMenuState != MENU_STATE_FULL) {
                 if (!mTouchState.isWaitingForDoubleTap()) {
                     // User has stalled long enough for this not to be a drag or a double tap, just
                     // expand the menu
                     mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
-                            true /* allowMenuTimeout */, willResizeMenu());
+                            true /* allowMenuTimeout */, willResizeMenu(),
+                            shouldShowResizeHandle());
                 } else {
                     // Next touch event _may_ be the second tap for the double-tap, schedule a
                     // fallback runnable to trigger the menu if no touch event occurs before the
@@ -921,6 +942,15 @@
             }
             return true;
         }
+
+        private void flingEndAction() {
+            mTouchState.setAllowTouches(true);
+            if (mShouldHideMenuAfterFling) {
+                // If the menu is not visible, then we can still be showing the activity for the
+                // dismiss overlay, so just finish it after the animation completes
+                mMenuController.hideMenu();
+            }
+        }
     };
 
     /**
@@ -937,6 +967,10 @@
                 isMenuExpanded  && willResizeMenu() ? mExpandedShortestEdgeSize : 0);
     }
 
+    private Rect getMovementBounds() {
+        return mMovementBounds;
+    }
+
     /**
      * @return whether the menu will resize as a part of showing the full menu.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
index dc286c1..4be0c15 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
@@ -318,6 +318,14 @@
         return -1;
     }
 
+    /**
+     * Removes the timeout callback if it's in queue.
+     */
+    public void removeDoubleTapTimeoutCallback() {
+        mIsWaitingForDoubleTap = false;
+        mHandler.removeCallbacks(mDoubleTapTimeoutCallback);
+    }
+
     void addMovementToVelocityTracker(MotionEvent event) {
         if (mVelocityTracker == null) {
             return;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index f49732d..6282236 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -468,7 +468,7 @@
             mPipTaskOrganizer.scheduleAnimateResizePip(mCurrentPipBounds, mResizeAnimationDuration,
                     null);
         } else {
-            mPipTaskOrganizer.dismissPip(mResizeAnimationDuration);
+            mPipTaskOrganizer.exitPip(mResizeAnimationDuration);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java b/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java
index cf1bc7d..1ed98c0 100644
--- a/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java
+++ b/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java
@@ -119,7 +119,7 @@
         final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.MATCH_PARENT,
-                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
+                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
                 PixelFormat.TRANSLUCENT);
         lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index c8cf02a..10b04c0 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -302,13 +302,15 @@
     }
 
     private void showAutoSaverSuggestionNotification() {
+        final CharSequence message = mContext.getString(R.string.auto_saver_text);
         final Notification.Builder nb =
                 new Notification.Builder(mContext, NotificationChannels.HINTS)
                         .setSmallIcon(R.drawable.ic_power_saver)
                         .setWhen(0)
                         .setShowWhen(false)
                         .setContentTitle(mContext.getString(R.string.auto_saver_title))
-                        .setContentText(mContext.getString(R.string.auto_saver_text));
+                        .setStyle(new Notification.BigTextStyle().bigText(message))
+                        .setContentText(message);
         nb.setContentIntent(pendingBroadcast(ACTION_ENABLE_AUTO_SAVER));
         nb.setDeleteIntent(pendingBroadcast(ACTION_DISMISS_AUTO_SAVER_SUGGESTION));
         nb.addAction(0,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
index c5ae3ab..40d317c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
@@ -117,7 +117,7 @@
             it.tileView.measure(exactly(smallTileSize), exactly(smallTileSize))
         }
 
-        val height = twoLineHeight
+        val height = twoLineHeight + paddingBottom + paddingTop
         setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height)
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index b157f4b..aaff9ac 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -152,15 +152,33 @@
     }
 
     @Override
+    public void fakeDragBy(float xOffset) {
+        try {
+            super.fakeDragBy(xOffset);
+            // Keep on drawing until the animation has finished.
+            postInvalidateOnAnimation();
+        } catch (NullPointerException e) {
+            Log.e(TAG, "FakeDragBy called before begin", e);
+            // If we were trying to fake drag, it means we just added a new tile to the last
+            // page, so animate there.
+            final int lastPageNumber = mPages.size() - 1;
+            post(() -> {
+                setCurrentItem(lastPageNumber, true);
+                if (mBounceAnimatorSet != null) {
+                    mBounceAnimatorSet.start();
+                }
+                setOffscreenPageLimit(1);
+            });
+        }
+    }
+
+    @Override
     public void computeScroll() {
         if (!mScroller.isFinished() && mScroller.computeScrollOffset()) {
             if (!isFakeDragging()) {
                 beginFakeDrag();
             }
             fakeDragBy(getScrollX() - mScroller.getCurrX());
-            // Keep on drawing until the animation has finished.
-            postInvalidateOnAnimation();
-            return;
         } else if (isFakeDragging()) {
             endFakeDrag();
             mBounceAnimatorSet.start();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index a0ea7fa..ce00229 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -269,14 +269,6 @@
             count++;
         }
 
-
-        if (Utils.useQsMediaPlayer(mQsPanel.getContext())) {
-            View qsMediaView = mQsPanel.getMediaPanel();
-            View qqsMediaView = mQuickQsPanel.getMediaPlayer().getView();
-            translationXBuilder.addFloat(qsMediaView, "alpha", 0, 1);
-            translationXBuilder.addFloat(qqsMediaView, "alpha", 1, 0);
-        }
-
         if (mAllowFancy) {
             // Make brightness appear static position and alpha in through second half.
             View brightness = mQsPanel.getBrightnessView();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index be8a8fd..6b0775f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -42,7 +42,7 @@
     private QuickStatusBarHeader mHeader;
     private float mQsExpansion;
     private QSCustomizer mQSCustomizer;
-    private View mQSFooter;
+    private View mDragHandle;
 
     private View mBackground;
     private View mBackgroundGradient;
@@ -62,7 +62,7 @@
         mQSDetail = findViewById(R.id.qs_detail);
         mHeader = findViewById(R.id.header);
         mQSCustomizer = findViewById(R.id.qs_customize);
-        mQSFooter = findViewById(R.id.qs_footer);
+        mDragHandle = findViewById(R.id.qs_drag_handle_view);
         mBackground = findViewById(R.id.quick_settings_background);
         mStatusBarBackground = findViewById(R.id.quick_settings_status_bar_background);
         mBackgroundGradient = findViewById(R.id.quick_settings_gradient_view);
@@ -167,8 +167,8 @@
         int height = calculateContainerHeight();
         setBottom(getTop() + height);
         mQSDetail.setBottom(getTop() + height);
-        // Pin QS Footer to the bottom of the panel.
-        mQSFooter.setTranslationY(height - mQSFooter.getHeight());
+        // Pin the drag handle to the bottom of the panel.
+        mDragHandle.setTranslationY(height - mDragHandle.getHeight());
         mBackground.setTop(mQSPanel.getTop());
         mBackground.setBottom(height);
     }
@@ -192,13 +192,13 @@
 
     public void setExpansion(float expansion) {
         mQsExpansion = expansion;
+        mDragHandle.setAlpha(1.0f - expansion);
         updateExpansion();
     }
 
     private void setMargins() {
         setMargins(mQSDetail);
         setMargins(mBackground);
-        setMargins(mQSFooter);
         mQSPanel.setMargins(mSideMargins);
         mHeader.setMargins(mSideMargins);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index 5de6d1c..fc8e36f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -98,7 +98,6 @@
     private TouchAnimator mSettingsCogAnimator;
 
     private View mActionsContainer;
-    private View mDragHandle;
 
     private OnClickListener mExpandClickListener;
 
@@ -146,7 +145,6 @@
         mMultiUserSwitch = findViewById(R.id.multi_user_switch);
         mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
 
-        mDragHandle = findViewById(R.id.qs_drag_handle_view);
         mActionsContainer = findViewById(R.id.qs_footer_actions_container);
         mEditContainer = findViewById(R.id.qs_footer_actions_edit_container);
 
@@ -219,7 +217,6 @@
         return new TouchAnimator.Builder()
                 .addFloat(mActionsContainer, "alpha", 0, 1)
                 .addFloat(mEditContainer, "alpha", 0, 1)
-                .addFloat(mDragHandle, "alpha", 1, 0, 0)
                 .addFloat(mPageIndicator, "alpha", 0, 1)
                 .setStartDelay(0.15f)
                 .build();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 5b09267..b877e87 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -37,6 +37,7 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.R.id;
+import com.android.systemui.media.MediaHost;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.qs.customize.QSCustomizer;
@@ -47,6 +48,7 @@
 import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
 import com.android.systemui.util.InjectionInflationController;
 import com.android.systemui.util.LifecycleFragment;
+import com.android.systemui.util.Utils;
 
 import javax.inject.Inject;
 
@@ -91,6 +93,7 @@
      */
     private int mState;
     private QSContainerImplController mQSContainerImplController;
+    private int[] mTmpLocation = new int[2];
 
     @Inject
     public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
@@ -154,6 +157,7 @@
         if (mListening) {
             setListening(false);
         }
+        mQSCustomizer.setQs(null);
     }
 
     @Override
@@ -377,8 +381,7 @@
         mLastKeyguardAndExpanded = onKeyguardAndExpanded;
 
         boolean fullyExpanded = expansion == 1;
-        int heightDiff = mQSPanel.getBottom() - mHeader.getBottom() + mHeader.getPaddingBottom()
-                + mFooter.getHeight();
+        int heightDiff = mQSPanel.getBottom() - mHeader.getBottom() + mHeader.getPaddingBottom();
         float panelTranslationY = translationScaleY * heightDiff;
 
         // Let the views animate their contents correctly by giving them the necessary context.
@@ -404,6 +407,32 @@
         if (mQSAnimator != null) {
             mQSAnimator.setPosition(expansion);
         }
+        updateMediaPositions();
+    }
+
+    private void updateMediaPositions() {
+        if (Utils.useQsMediaPlayer(getContext())) {
+            mContainer.getLocationOnScreen(mTmpLocation);
+            float absoluteBottomPosition = mTmpLocation[1] + mContainer.getHeight();
+            pinToBottom(absoluteBottomPosition, mQSPanel.getMediaHost());
+            pinToBottom(absoluteBottomPosition - mHeader.getPaddingBottom(),
+                    mHeader.getHeaderQsPanel().getMediaHost());
+        }
+    }
+
+    private void pinToBottom(float absoluteBottomPosition, MediaHost mediaHost) {
+        View hostView = mediaHost.getHostView();
+        if (mLastQSExpansion > 0) {
+            ViewGroup.MarginLayoutParams params =
+                    (ViewGroup.MarginLayoutParams) hostView.getLayoutParams();
+            float targetPosition = absoluteBottomPosition - params.bottomMargin
+                    - hostView.getHeight();
+            float currentPosition = mediaHost.getCurrentState().getBoundsOnScreen().top
+                    - hostView.getTranslationY();
+            hostView.setTranslationY(targetPosition - currentPosition);
+        } else {
+            hostView.setTranslationY(0);
+        }
     }
 
     private boolean headerWillBeAnimating() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
deleted file mode 100644
index 174441b..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2019 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;
-
-import static com.android.systemui.util.SysuiLifecycle.viewAttachLifecycle;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.res.ColorStateList;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
-import android.media.MediaDescription;
-import android.media.session.MediaController;
-import android.media.session.MediaSession;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.SeekBar;
-import android.widget.TextView;
-
-import com.android.settingslib.media.LocalMediaManager;
-import com.android.systemui.R;
-import com.android.systemui.media.IlluminationDrawable;
-import com.android.systemui.media.MediaControlPanel;
-import com.android.systemui.media.SeekBarObserver;
-import com.android.systemui.media.SeekBarViewModel;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.util.concurrency.DelayableExecutor;
-
-import java.util.concurrent.Executor;
-
-/**
- * Single media player for carousel in QSPanel
- */
-public class QSMediaPlayer extends MediaControlPanel {
-
-    private static final String TAG = "QSMediaPlayer";
-
-    // Button IDs for QS controls
-    static final int[] QS_ACTION_IDS = {
-            R.id.action0,
-            R.id.action1,
-            R.id.action2,
-            R.id.action3,
-            R.id.action4
-    };
-
-    private final QSPanel mParent;
-    private final Executor mForegroundExecutor;
-    private final DelayableExecutor mBackgroundExecutor;
-    private final SeekBarViewModel mSeekBarViewModel;
-    private final SeekBarObserver mSeekBarObserver;
-    private String mPackageName;
-
-    /**
-     * Initialize quick shade version of player
-     * @param context
-     * @param parent
-     * @param routeManager Provides information about device
-     * @param foregroundExecutor
-     * @param backgroundExecutor
-     * @param activityStarter
-     */
-    public QSMediaPlayer(Context context, ViewGroup parent, LocalMediaManager routeManager,
-            Executor foregroundExecutor, DelayableExecutor backgroundExecutor,
-            ActivityStarter activityStarter) {
-        super(context, parent, routeManager, R.layout.qs_media_panel, QS_ACTION_IDS,
-                foregroundExecutor, backgroundExecutor, activityStarter);
-        mParent = (QSPanel) parent;
-        mForegroundExecutor = foregroundExecutor;
-        mBackgroundExecutor = backgroundExecutor;
-        mSeekBarViewModel = new SeekBarViewModel(backgroundExecutor);
-        mSeekBarObserver = new SeekBarObserver(getView());
-        // Can't use the viewAttachLifecycle of media player because remove/add is used to adjust
-        // priority of players. As soon as it is removed, the lifecycle will end and the seek bar
-        // will stop updating. So, use the lifecycle of the parent instead.
-        mSeekBarViewModel.getProgress().observe(viewAttachLifecycle(parent), mSeekBarObserver);
-        SeekBar bar = getView().findViewById(R.id.media_progress_bar);
-        bar.setOnSeekBarChangeListener(mSeekBarViewModel.getSeekBarListener());
-        bar.setOnTouchListener(mSeekBarViewModel.getSeekBarTouchListener());
-    }
-
-    /**
-     * Add a media panel view based on a media description. Used for resumption
-     * @param description
-     * @param iconColor
-     * @param bgColor
-     * @param contentIntent
-     * @param pkgName
-     */
-    public void setMediaSession(MediaSession.Token token, MediaDescription description,
-            int iconColor, int bgColor, PendingIntent contentIntent, String pkgName) {
-        mPackageName = pkgName;
-        PackageManager pm = getContext().getPackageManager();
-        Drawable icon = null;
-        CharSequence appName = pkgName.substring(pkgName.lastIndexOf("."));
-        try {
-            icon = pm.getApplicationIcon(pkgName);
-            appName = pm.getApplicationLabel(pm.getApplicationInfo(pkgName, 0));
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.e(TAG, "Error getting package information", e);
-        }
-
-        // Set what we can normally
-        super.setMediaSession(token, icon, null, iconColor, bgColor, contentIntent,
-                appName.toString(), null);
-
-        // Then add info from MediaDescription
-        ImageView albumView = mMediaNotifView.findViewById(R.id.album_art);
-        if (albumView != null) {
-            // Resize art in a background thread
-            mBackgroundExecutor.execute(() -> processAlbumArt(description, albumView));
-        }
-
-        // Song name
-        TextView titleText = mMediaNotifView.findViewById(R.id.header_title);
-        CharSequence songName = description.getTitle();
-        titleText.setText(songName);
-        titleText.setTextColor(iconColor);
-
-        // Artist name (not in mini player)
-        TextView artistText = mMediaNotifView.findViewById(R.id.header_artist);
-        if (artistText != null) {
-            CharSequence artistName = description.getSubtitle();
-            artistText.setText(artistName);
-            artistText.setTextColor(iconColor);
-        }
-
-        initLongPressMenu(iconColor);
-
-        // Set buttons to resume state
-        resetButtons();
-    }
-
-    /**
-     * Update media panel view for the given media session
-     * @param token token for this media session
-     * @param icon app notification icon
-     * @param largeIcon notification's largeIcon, used as a fallback for album art
-     * @param iconColor foreground color (for text, icons)
-     * @param bgColor background color
-     * @param actionsContainer a LinearLayout containing the media action buttons
-     * @param contentIntent Intent to send when user taps on player
-     * @param appName Application title
-     * @param key original notification's key
-     */
-    public void setMediaSession(MediaSession.Token token, Drawable icon, Icon largeIcon,
-            int iconColor, int bgColor, View actionsContainer, PendingIntent contentIntent,
-            String appName, String key) {
-
-        super.setMediaSession(token, icon, largeIcon, iconColor, bgColor, contentIntent, appName,
-                key);
-
-        // Media controls
-        if (actionsContainer != null) {
-            LinearLayout parentActionsLayout = (LinearLayout) actionsContainer;
-            int i = 0;
-            for (; i < parentActionsLayout.getChildCount() && i < QS_ACTION_IDS.length; i++) {
-                final ImageButton thisBtn = mMediaNotifView.findViewById(QS_ACTION_IDS[i]);
-                ImageButton thatBtn = parentActionsLayout.findViewById(NOTIF_ACTION_IDS[i]);
-                if (thatBtn == null || thatBtn.getDrawable() == null
-                        || thatBtn.getVisibility() != View.VISIBLE) {
-                    thisBtn.setVisibility(View.GONE);
-                    continue;
-                }
-
-                if (mMediaNotifView.getBackground() instanceof IlluminationDrawable) {
-                    ((IlluminationDrawable) mMediaNotifView.getBackground())
-                            .setupTouch(thisBtn, mMediaNotifView);
-                }
-
-                Drawable thatIcon = thatBtn.getDrawable();
-                thisBtn.setImageDrawable(thatIcon.mutate());
-                thisBtn.setVisibility(View.VISIBLE);
-                thisBtn.setOnClickListener(v -> {
-                    Log.d(TAG, "clicking on other button");
-                    thatBtn.performClick();
-                });
-            }
-
-            // Hide any unused buttons
-            for (; i < QS_ACTION_IDS.length; i++) {
-                ImageButton thisBtn = mMediaNotifView.findViewById(QS_ACTION_IDS[i]);
-                thisBtn.setVisibility(View.GONE);
-            }
-        }
-
-        // Seek Bar
-        final MediaController controller = new MediaController(getContext(), token);
-        mBackgroundExecutor.execute(
-                () -> mSeekBarViewModel.updateController(controller, iconColor));
-
-        initLongPressMenu(iconColor);
-    }
-
-    private void initLongPressMenu(int iconColor) {
-        // Set up long press menu
-        View guts = mMediaNotifView.findViewById(R.id.media_guts);
-        View options = mMediaNotifView.findViewById(R.id.qs_media_controls_options);
-        options.setMinimumHeight(guts.getHeight());
-
-        View clearView = options.findViewById(R.id.remove);
-        clearView.setOnClickListener(b -> {
-            removePlayer();
-        });
-        ImageView removeIcon = options.findViewById(R.id.remove_icon);
-        removeIcon.setImageTintList(ColorStateList.valueOf(iconColor));
-        TextView removeText = options.findViewById(R.id.remove_text);
-        removeText.setTextColor(iconColor);
-
-        TextView cancelView = options.findViewById(R.id.cancel);
-        cancelView.setTextColor(iconColor);
-        cancelView.setOnClickListener(b -> {
-            options.setVisibility(View.GONE);
-            guts.setVisibility(View.VISIBLE);
-        });
-        // ... but don't enable it yet, and make sure is reset when the session is updated
-        mMediaNotifView.setOnLongClickListener(null);
-        options.setVisibility(View.GONE);
-        guts.setVisibility(View.VISIBLE);
-    }
-
-    @Override
-    protected void resetButtons() {
-        super.resetButtons();
-        mSeekBarViewModel.clearController();
-        View guts = mMediaNotifView.findViewById(R.id.media_guts);
-        View options = mMediaNotifView.findViewById(R.id.qs_media_controls_options);
-
-        mMediaNotifView.setOnLongClickListener(v -> {
-            // Replace player view with close/cancel view
-            guts.setVisibility(View.GONE);
-            options.setVisibility(View.VISIBLE);
-            return true; // consumed click
-        });
-    }
-
-    /**
-     * Sets the listening state of the player.
-     *
-     * Should be set to true when the QS panel is open. Otherwise, false. This is a signal to avoid
-     * unnecessary work when the QS panel is closed.
-     *
-     * @param listening True when player should be active. Otherwise, false.
-     */
-    public void setListening(boolean listening) {
-        mSeekBarViewModel.setListening(listening);
-    }
-
-    @Override
-    public void removePlayer() {
-        Log.d(TAG, "removing player from parent: " + mParent);
-        // Ensure this happens on the main thread (could happen in QSMediaBrowser callback)
-        mForegroundExecutor.execute(() -> mParent.removeMediaPlayer(QSMediaPlayer.this));
-    }
-
-    @Override
-    public String getMediaPlayerPackage() {
-        if (getController() == null) {
-            return mPackageName;
-        }
-        return super.getMediaPlayerPackage();
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index e8f6c96..cdde06b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -21,7 +21,6 @@
 import static com.android.systemui.util.Utils.useQsMediaPlayer;
 
 import android.annotation.Nullable;
-import android.app.Notification;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -30,44 +29,33 @@
 import android.content.SharedPreferences;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.graphics.Color;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
 import android.media.MediaDescription;
-import android.media.session.MediaSession;
 import android.metrics.LogMaker;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.service.notification.StatusBarNotification;
 import android.service.quicksettings.Tile;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.HorizontalScrollView;
 import android.widget.LinearLayout;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.statusbar.NotificationVisibility;
 import com.android.settingslib.Utils;
-import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.settingslib.media.InfoMediaManager;
-import com.android.settingslib.media.LocalMediaManager;
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.media.MediaControlPanel;
-import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.media.MediaHierarchyManager;
+import com.android.systemui.media.MediaHost;
 import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTileView;
@@ -77,20 +65,15 @@
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.settings.BrightnessController;
 import com.android.systemui.settings.ToggleSliderView;
-import com.android.systemui.statusbar.notification.NotificationEntryListener;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController.BrightnessMirrorListener;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
-import com.android.systemui.util.concurrency.DelayableExecutor;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.concurrent.Executor;
 import java.util.stream.Collectors;
 
 import javax.inject.Inject;
@@ -108,21 +91,13 @@
     protected final Context mContext;
     protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
     private final BroadcastDispatcher mBroadcastDispatcher;
+    protected final MediaHost mMediaHost;
     private String mCachedSpecs = "";
     protected final View mBrightnessView;
     private final H mHandler = new H();
     private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
     private final QSTileRevealController mQsTileRevealController;
 
-    private final LinearLayout mMediaCarousel;
-    private final ArrayList<QSMediaPlayer> mMediaPlayers = new ArrayList<>();
-    private final LocalBluetoothManager mLocalBluetoothManager;
-    private final Executor mForegroundExecutor;
-    private final DelayableExecutor mBackgroundExecutor;
-    private boolean mUpdateCarousel = false;
-    private ActivityStarter mActivityStarter;
-    private NotificationEntryManager mNotificationEntryManager;
-
     protected boolean mExpanded;
     protected boolean mListening;
 
@@ -158,15 +133,6 @@
         }
     };
 
-    private final NotificationEntryListener mNotificationEntryListener =
-            new NotificationEntryListener() {
-        @Override
-        public void onEntryRemoved(NotificationEntry entry, NotificationVisibility visibility,
-                boolean removedByUser, int reason) {
-            checkToRemoveMediaNotification(entry);
-        }
-    };
-
     @Inject
     public QSPanel(
             @Named(VIEW_CONTEXT) Context context,
@@ -174,23 +140,15 @@
             DumpManager dumpManager,
             BroadcastDispatcher broadcastDispatcher,
             QSLogger qsLogger,
-            @Main Executor foregroundExecutor,
-            @Background DelayableExecutor backgroundExecutor,
-            @Nullable LocalBluetoothManager localBluetoothManager,
-            ActivityStarter activityStarter,
-            NotificationEntryManager entryManager,
+            MediaHost mediaHost,
             UiEventLogger uiEventLogger
     ) {
         super(context, attrs);
+        mMediaHost = mediaHost;
         mContext = context;
         mQSLogger = qsLogger;
         mDumpManager = dumpManager;
-        mForegroundExecutor = foregroundExecutor;
-        mBackgroundExecutor = backgroundExecutor;
-        mLocalBluetoothManager = localBluetoothManager;
         mBroadcastDispatcher = broadcastDispatcher;
-        mActivityStarter = activityStarter;
-        mNotificationEntryManager = entryManager;
         mUiEventLogger = uiEventLogger;
 
         setOrientation(VERTICAL);
@@ -210,16 +168,6 @@
 
         addDivider();
 
-        // Add media carousel
-        if (useQsMediaPlayer(context)) {
-            HorizontalScrollView mediaScrollView = (HorizontalScrollView) LayoutInflater.from(
-                    mContext).inflate(R.layout.media_carousel, this, false);
-            mMediaCarousel = mediaScrollView.findViewById(R.id.media_carousel);
-            addView(mediaScrollView, 0);
-        } else {
-            mMediaCarousel = null;
-        }
-
         mFooter = new QSSecurityFooter(this, context);
         addView(mFooter.getView());
 
@@ -230,145 +178,39 @@
     }
 
     @Override
-    public void onVisibilityAggregated(boolean isVisible) {
-        super.onVisibilityAggregated(isVisible);
-        if (!isVisible && mUpdateCarousel) {
-            for (QSMediaPlayer player : mMediaPlayers) {
-                if (player.isPlaying()) {
-                    LayoutParams lp = (LayoutParams) player.getView().getLayoutParams();
-                    mMediaCarousel.removeView(player.getView());
-                    mMediaCarousel.addView(player.getView(), 0, lp);
-                    ((HorizontalScrollView) mMediaCarousel.getParent()).fullScroll(View.FOCUS_LEFT);
-                    mUpdateCarousel = false;
-                    break;
-                }
-            }
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        // Add media carousel at the end
+        if (useQsMediaPlayer(getContext())) {
+            addMediaHostView();
         }
     }
 
-    /**
-     * Add or update a player for the associated media session
-     * @param token
-     * @param icon
-     * @param largeIcon
-     * @param iconColor
-     * @param bgColor
-     * @param actionsContainer
-     * @param notif
-     * @param key
-     */
-    public void addMediaSession(MediaSession.Token token, Drawable icon, Icon largeIcon,
-            int iconColor, int bgColor, View actionsContainer, StatusBarNotification notif,
-            String key) {
-        if (!useQsMediaPlayer(mContext)) {
-            // Shouldn't happen, but just in case
-            Log.e(TAG, "Tried to add media session without player!");
-            return;
-        }
-        if (token == null) {
-            Log.e(TAG, "Media session token was null!");
-            return;
-        }
-
-        String packageName = notif.getPackageName();
-        QSMediaPlayer player = findMediaPlayer(packageName, token, key);
-
-        int playerWidth = (int) getResources().getDimension(R.dimen.qs_media_width);
-        int padding = (int) getResources().getDimension(R.dimen.qs_media_padding);
-        LayoutParams lp = new LayoutParams(playerWidth, ViewGroup.LayoutParams.MATCH_PARENT);
-        lp.setMarginStart(padding);
-        lp.setMarginEnd(padding);
-
-        if (player == null) {
-            Log.d(TAG, "creating new player for " + packageName);
-            // Set up listener for device changes
-            // TODO: integrate with MediaTransferManager?
-            InfoMediaManager imm = new InfoMediaManager(mContext, notif.getPackageName(),
-                    notif.getNotification(), mLocalBluetoothManager);
-            LocalMediaManager routeManager = new LocalMediaManager(mContext, mLocalBluetoothManager,
-                    imm, notif.getPackageName());
-
-            player = new QSMediaPlayer(mContext, this, routeManager, mForegroundExecutor,
-                    mBackgroundExecutor, mActivityStarter);
-            player.setListening(mListening);
-            if (player.isPlaying()) {
-                mMediaCarousel.addView(player.getView(), 0, lp); // add in front
-            } else {
-                mMediaCarousel.addView(player.getView(), lp); // add at end
-            }
-            mMediaPlayers.add(player);
-        } else if (player.isPlaying()) {
-            mUpdateCarousel = true;
-        }
-
-        Log.d(TAG, "setting player session");
-        String appName = Notification.Builder.recoverBuilder(getContext(), notif.getNotification())
-                .loadHeaderAppName();
-        player.setMediaSession(token, icon, largeIcon, iconColor, bgColor, actionsContainer,
-                notif.getNotification().contentIntent, appName, key);
-
-        if (mMediaPlayers.size() > 0) {
-            ((View) mMediaCarousel.getParent()).setVisibility(View.VISIBLE);
-        }
-    }
-
-    /**
-     * Check for an existing media player using the given information
-     * @param packageName
-     * @param token
-     * @param key
-     * @return a player, or null if no match found
-     */
-    private QSMediaPlayer findMediaPlayer(String packageName, MediaSession.Token token,
-            String key) {
-        for (QSMediaPlayer player : mMediaPlayers) {
-            if (player.getKey() == null || key == null) {
-                // No notification key = loaded via mediabrowser, so just match on package
-                if (packageName.equals(player.getMediaPlayerPackage())) {
-                    Log.d(TAG, "Found matching resume player by package: " + packageName);
-                    return player;
-                }
-            } else if (player.getMediaSessionToken().equals(token)) {
-                Log.d(TAG, "Found matching player by token " + packageName);
-                return player;
-            } else if (packageName.equals(player.getMediaPlayerPackage())
-                    && key.equals(player.getKey())) {
-                // Also match if it's the same package and notification key
-                Log.d(TAG, "Found matching player by package " + packageName + ", " + key);
-                return player;
-            }
-        }
-        return null;
-    }
-
-    protected View getMediaPanel() {
-        return mMediaCarousel;
-    }
-
-    /**
-     * Remove the media player from the carousel
-     * @param player Player to remove
-     * @return true if removed, false if player was not found
-     */
-    protected boolean removeMediaPlayer(QSMediaPlayer player) {
-        // Remove from list
-        if (!mMediaPlayers.remove(player)) {
-            return false;
-        }
-
-        // Check if we need to collapse the carousel now
-        mMediaCarousel.removeView(player.getView());
-        if (mMediaPlayers.size() == 0) {
-            ((View) mMediaCarousel.getParent()).setVisibility(View.GONE);
-        }
-        return true;
+    protected void addMediaHostView() {
+        mMediaHost.init(MediaHierarchyManager.LOCATION_QS);
+        mMediaHost.setExpansion(1.0f);
+        mMediaHost.setShowsOnlyActiveMedia(false);
+        ViewGroup hostView = mMediaHost.getHostView();
+        addView(hostView);
+        int sidePaddings = getResources().getDimensionPixelSize(
+                R.dimen.quick_settings_side_margins);
+        int bottomPadding = getResources().getDimensionPixelSize(
+                R.dimen.quick_settings_expanded_bottom_margin);
+        MarginLayoutParams layoutParams = (MarginLayoutParams) hostView.getLayoutParams();
+        layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+        layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
+        layoutParams.bottomMargin = bottomPadding;
+        hostView.setLayoutParams(layoutParams);
+        hostView.setPadding(sidePaddings, hostView.getPaddingTop(), sidePaddings,
+                hostView.getPaddingBottom());
     }
 
     private final QSMediaBrowser.Callback mMediaBrowserCallback = new QSMediaBrowser.Callback() {
         @Override
         public void addTrack(MediaDescription desc, ComponentName component,
                 QSMediaBrowser browser) {
-            if (component == null) {
+            // TODO: Fix Resumption b/156104922
+/*            if (component == null) {
                 Log.e(TAG, "Component cannot be null");
                 return;
             }
@@ -404,7 +246,7 @@
             int iconColor = Color.DKGRAY;
             int bgColor = Color.LTGRAY;
             player.setMediaSession(token, desc, iconColor, bgColor, browser.getAppIntent(),
-                    pkgName);
+                    pkgName);*/
         }
     };
 
@@ -441,27 +283,6 @@
         mHasLoadedMediaControls = true;
     }
 
-    private void checkToRemoveMediaNotification(NotificationEntry entry) {
-        if (!useQsMediaPlayer(mContext)) {
-            return;
-        }
-
-        if (!entry.isMediaNotification()) {
-            return;
-        }
-
-        // If this entry corresponds to an existing set of controls, clear the controls
-        // This will handle apps that use an action to clear their notification
-        for (QSMediaPlayer p : mMediaPlayers) {
-            if (p.getKey() != null && p.getKey().equals(entry.getKey())) {
-                Log.d(TAG, "Clearing controls since notification removed " + entry.getKey());
-                p.clearControls();
-                return;
-            }
-        }
-        Log.d(TAG, "Media notification removed but no player found " + entry.getKey());
-    }
-
     protected void addDivider() {
         mDivider = LayoutInflater.from(mContext).inflate(R.layout.qs_divider, this, false);
         mDivider.setBackgroundColor(Utils.applyAlpha(mDivider.getAlpha(),
@@ -482,7 +303,11 @@
         int numChildren = getChildCount();
         for (int i = 0; i < numChildren; i++) {
             View child = getChildAt(i);
-            if (child.getVisibility() != View.GONE) height += child.getMeasuredHeight();
+            if (child.getVisibility() != View.GONE) {
+                height += child.getMeasuredHeight();
+                MarginLayoutParams layoutParams = (MarginLayoutParams) child.getLayoutParams();
+                height += layoutParams.topMargin + layoutParams.bottomMargin;
+            }
         }
         setMeasuredDimension(getMeasuredWidth(), height);
     }
@@ -528,7 +353,6 @@
                 loadMediaResumptionControls();
             }
         }
-        mNotificationEntryManager.addNotificationEntryListener(mNotificationEntryListener);
     }
 
     @Override
@@ -537,15 +361,18 @@
         if (mHost != null) {
             mHost.removeCallback(this);
         }
+        if (mTileLayout != null) {
+            mTileLayout.setListening(false);
+        }
         for (TileRecord record : mRecords) {
             record.tile.removeCallbacks();
         }
+        mRecords.clear();
         if (mBrightnessMirrorController != null) {
             mBrightnessMirrorController.removeCallback(this);
         }
         mDumpManager.unregisterDumpable(getDumpableTag());
         mBroadcastDispatcher.unregisterReceiver(mUserChangeReceiver);
-        mNotificationEntryManager.removeNotificationEntryListener(mNotificationEntryListener);
         super.onDetachedFromWindow();
     }
 
@@ -724,9 +551,6 @@
         if (mListening) {
             refreshAllTiles();
         }
-        for (QSMediaPlayer player : mMediaPlayers) {
-            player.setListening(mListening);
-        }
     }
 
     private String getTilesSpecs() {
@@ -1027,6 +851,10 @@
         }
     }
 
+    public MediaHost getMediaHost() {
+        return mMediaHost;
+    }
+
     private class H extends Handler {
         private static final int SHOW_DETAIL = 1;
         private static final int SET_TILE_VISIBILITY = 2;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 54a928d..4008918 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -339,13 +339,18 @@
         changeTileSpecs(tileSpecs-> !tileSpecs.contains(spec) && tileSpecs.add(spec));
     }
 
+    private void saveTilesToSettings(List<String> tileSpecs) {
+        Settings.Secure.putStringForUser(mContext.getContentResolver(), TILES_SETTING,
+                TextUtils.join(",", tileSpecs), null /* tag */,
+                false /* default */, mCurrentUser, true /* overrideable by restore */);
+    }
+
     private void changeTileSpecs(Predicate<List<String>> changeFunction) {
         final String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
-            TILES_SETTING, ActivityManager.getCurrentUser());
+                TILES_SETTING, mCurrentUser);
         final List<String> tileSpecs = loadTileSpecs(mContext, setting);
         if (changeFunction.test(tileSpecs)) {
-            Settings.Secure.putStringForUser(mContext.getContentResolver(), TILES_SETTING,
-                TextUtils.join(",", tileSpecs), ActivityManager.getCurrentUser());
+            saveTilesToSettings(tileSpecs);
         }
     }
 
@@ -375,7 +380,7 @@
                 Intent intent = new Intent().setComponent(component);
                 TileLifecycleManager lifecycleManager = new TileLifecycleManager(new Handler(),
                         mContext, mServices, new Tile(), intent,
-                        new UserHandle(ActivityManager.getCurrentUser()),
+                        new UserHandle(mCurrentUser),
                         mBroadcastDispatcher);
                 lifecycleManager.onStopListening();
                 lifecycleManager.onTileRemoved();
@@ -384,8 +389,7 @@
             }
         }
         if (DEBUG) Log.d(TAG, "saveCurrentTiles " + newTiles);
-        Secure.putStringForUser(getContext().getContentResolver(), QSTileHost.TILES_SETTING,
-                TextUtils.join(",", newTiles), ActivityManager.getCurrentUser());
+        saveTilesToSettings(newTiles);
     }
 
     public QSTile createTile(String tileSpec) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java
deleted file mode 100644
index 5cb75e6..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2019 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;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
-import android.media.session.MediaController;
-import android.media.session.MediaSession;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
-
-import com.android.systemui.R;
-import com.android.systemui.media.IlluminationDrawable;
-import com.android.systemui.media.MediaControlPanel;
-import com.android.systemui.plugins.ActivityStarter;
-
-import java.util.concurrent.Executor;
-
-/**
- * QQS mini media player
- */
-public class QuickQSMediaPlayer extends MediaControlPanel {
-
-    private static final String TAG = "QQSMediaPlayer";
-
-    // Button IDs for QS controls
-    private static final int[] QQS_ACTION_IDS = {R.id.action0, R.id.action1, R.id.action2};
-
-    /**
-     * Initialize mini media player for QQS
-     * @param context
-     * @param parent
-     * @param foregroundExecutor
-     * @param backgroundExecutor
-     * @param activityStarter
-     */
-    public QuickQSMediaPlayer(Context context, ViewGroup parent, Executor foregroundExecutor,
-            Executor backgroundExecutor, ActivityStarter activityStarter) {
-        super(context, parent, null, R.layout.qqs_media_panel, QQS_ACTION_IDS,
-                foregroundExecutor, backgroundExecutor, activityStarter);
-    }
-
-    /**
-     * Update media panel view for the given media session
-     * @param token token for this media session
-     * @param icon app notification icon
-     * @param largeIcon notification's largeIcon, used as a fallback for album art
-     * @param iconColor foreground color (for text, icons)
-     * @param bgColor background color
-     * @param actionsContainer a LinearLayout containing the media action buttons
-     * @param actionsToShow indices of which actions to display in the mini player
-     *                      (max 3: Notification.MediaStyle.MAX_MEDIA_BUTTONS_IN_COMPACT)
-     * @param contentIntent Intent to send when user taps on the view
-     * @param key original notification's key
-     */
-    public void setMediaSession(MediaSession.Token token, Drawable icon, Icon largeIcon,
-            int iconColor, int bgColor, View actionsContainer, int[] actionsToShow,
-            PendingIntent contentIntent, String key) {
-        // Only update if this is a different session and currently playing
-        String oldPackage = "";
-        if (getController() != null) {
-            oldPackage = getController().getPackageName();
-        }
-        MediaController controller = new MediaController(getContext(), token);
-        MediaSession.Token currentToken = getMediaSessionToken();
-        boolean samePlayer = currentToken != null
-                && currentToken.equals(token)
-                && oldPackage.equals(controller.getPackageName());
-        if (getController() != null && !samePlayer && !isPlaying(controller)) {
-            return;
-        }
-
-        super.setMediaSession(token, icon, largeIcon, iconColor, bgColor, contentIntent, null, key);
-
-        LinearLayout parentActionsLayout = (LinearLayout) actionsContainer;
-        int i = 0;
-        if (actionsToShow != null) {
-            int maxButtons = Math.min(actionsToShow.length, parentActionsLayout.getChildCount());
-            maxButtons = Math.min(maxButtons, QQS_ACTION_IDS.length);
-            for (; i < maxButtons; i++) {
-                ImageButton thisBtn = mMediaNotifView.findViewById(QQS_ACTION_IDS[i]);
-                int thatId = NOTIF_ACTION_IDS[actionsToShow[i]];
-                ImageButton thatBtn = parentActionsLayout.findViewById(thatId);
-                if (thatBtn == null || thatBtn.getDrawable() == null
-                        || thatBtn.getVisibility() != View.VISIBLE) {
-                    thisBtn.setVisibility(View.GONE);
-                    continue;
-                }
-
-                if (mMediaNotifView.getBackground() instanceof IlluminationDrawable) {
-                    ((IlluminationDrawable) mMediaNotifView.getBackground())
-                            .setupTouch(thisBtn, mMediaNotifView);
-                }
-
-                Drawable thatIcon = thatBtn.getDrawable();
-                thisBtn.setImageDrawable(thatIcon.mutate());
-                thisBtn.setVisibility(View.VISIBLE);
-                thisBtn.setOnClickListener(v -> {
-                    thatBtn.performClick();
-                });
-            }
-        }
-
-        // Hide any unused buttons
-        for (; i < QQS_ACTION_IDS.length; i++) {
-            ImageButton thisBtn = mMediaNotifView.findViewById(QQS_ACTION_IDS[i]);
-            thisBtn.setVisibility(View.GONE);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 6683a1c..2f06c4b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -18,38 +18,33 @@
 
 import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
 
-import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.LinearLayout;
 
 import com.android.internal.logging.UiEventLogger;
-import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.broadcast.BroadcastDispatcher;
-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.media.MediaHierarchyManager;
+import com.android.systemui.media.MediaHost;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.SignalState;
 import com.android.systemui.plugins.qs.QSTile.State;
 import com.android.systemui.qs.customize.QSCustomizer;
 import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 import com.android.systemui.util.Utils;
-import com.android.systemui.util.concurrency.DelayableExecutor;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -67,16 +62,17 @@
     private boolean mDisabledByPolicy;
     private int mMaxTiles;
     protected QSPanel mFullPanel;
-    private QuickQSMediaPlayer mMediaPlayer;
     /** Whether or not the QS media player feature is enabled. */
     private boolean mUsingMediaPlayer;
     /** Whether or not the QuickQSPanel currently contains a media player. */
-    private boolean mHasMediaPlayer;
+    private boolean mShowHorizontalTileLayout;
     private LinearLayout mHorizontalLinearLayout;
 
     // Only used with media
-    private QSTileLayout mMediaTileLayout;
+    private QSTileLayout mHorizontalTileLayout;
     private QSTileLayout mRegularTileLayout;
+    private int mLastOrientation = -1;
+    private int mMediaBottomMargin;
 
     @Inject
     public QuickQSPanel(
@@ -85,16 +81,11 @@
             DumpManager dumpManager,
             BroadcastDispatcher broadcastDispatcher,
             QSLogger qsLogger,
-            @Main Executor foregroundExecutor,
-            @Background DelayableExecutor backgroundExecutor,
-            @Nullable LocalBluetoothManager localBluetoothManager,
-            ActivityStarter activityStarter,
-            NotificationEntryManager entryManager,
+            MediaHost mediaHost,
             UiEventLogger uiEventLogger
     ) {
-        super(context, attrs, dumpManager, broadcastDispatcher, qsLogger,
-                foregroundExecutor, backgroundExecutor, localBluetoothManager, activityStarter,
-                entryManager, uiEventLogger);
+        super(context, attrs, dumpManager, broadcastDispatcher, qsLogger, mediaHost,
+                uiEventLogger);
         if (mFooter != null) {
             removeView(mFooter.getView());
         }
@@ -104,6 +95,8 @@
             }
             removeView((View) mTileLayout);
         }
+        mMediaBottomMargin = getResources().getDimensionPixelSize(
+                R.dimen.quick_settings_media_extra_bottom_margin);
 
         mUsingMediaPlayer = Utils.useQsMediaPlayer(context);
         if (mUsingMediaPlayer) {
@@ -112,40 +105,95 @@
             mHorizontalLinearLayout.setClipChildren(false);
             mHorizontalLinearLayout.setClipToPadding(false);
 
-            int marginSize = (int) mContext.getResources().getDimension(R.dimen.qqs_media_spacing);
-            mMediaPlayer = new QuickQSMediaPlayer(mContext, mHorizontalLinearLayout,
-                    foregroundExecutor, backgroundExecutor, activityStarter);
-            LayoutParams lp2 = new LayoutParams(0, LayoutParams.MATCH_PARENT, 1);
-            lp2.setMarginEnd(marginSize);
-            lp2.setMarginStart(0);
-            mHorizontalLinearLayout.addView(mMediaPlayer.getView(), lp2);
-
-            mTileLayout = new DoubleLineTileLayout(context, mUiEventLogger);
-            mMediaTileLayout = mTileLayout;
+            DoubleLineTileLayout horizontalTileLayout = new DoubleLineTileLayout(context,
+                    mUiEventLogger);
+            horizontalTileLayout.setPaddingRelative(
+                    horizontalTileLayout.getPaddingStart(),
+                    horizontalTileLayout.getPaddingTop(),
+                    horizontalTileLayout.getPaddingEnd(),
+                    mContext.getResources().getDimensionPixelSize(
+                            R.dimen.qqs_horizonal_tile_padding_bottom));
+            mHorizontalTileLayout = horizontalTileLayout;
             mRegularTileLayout = new HeaderTileLayout(context, mUiEventLogger);
-            LayoutParams lp = new LayoutParams(0, LayoutParams.MATCH_PARENT, 1);
-            lp.setMarginEnd(0);
-            lp.setMarginStart(marginSize);
-            mHorizontalLinearLayout.addView((View) mTileLayout, lp);
+            LayoutParams lp = new LayoutParams(0, LayoutParams.WRAP_CONTENT, 1);
+            int marginSize = (int) mContext.getResources().getDimension(R.dimen.qqs_media_spacing);
+            lp.setMarginStart(0);
+            lp.setMarginEnd(marginSize);
+            lp.gravity = Gravity.CENTER_VERTICAL;
+            mHorizontalLinearLayout.addView((View) mHorizontalTileLayout, lp);
 
             sDefaultMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
 
+            boolean useHorizontal = shouldUseHorizontalTileLayout();
+            mTileLayout = useHorizontal ? mHorizontalTileLayout : mRegularTileLayout;
             mTileLayout.setListening(mListening);
             addView(mHorizontalLinearLayout, 0 /* Between brightness and footer */);
-            ((View) mRegularTileLayout).setVisibility(View.GONE);
+            ((View) mRegularTileLayout).setVisibility(!useHorizontal ? View.VISIBLE : View.GONE);
+            mHorizontalLinearLayout.setVisibility(useHorizontal ? View.VISIBLE : View.GONE);
             addView((View) mRegularTileLayout, 0);
             super.setPadding(0, 0, 0, 0);
+            applySideMargins(mHorizontalLinearLayout);
+            applyBottomMargin((View) mRegularTileLayout);
         } else {
             sDefaultMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
             mTileLayout = new HeaderTileLayout(context, mUiEventLogger);
             mTileLayout.setListening(mListening);
             addView((View) mTileLayout, 0 /* Between brightness and footer */);
             super.setPadding(0, 0, 0, 0);
+            applyBottomMargin((View) mTileLayout);
         }
     }
 
-    public QuickQSMediaPlayer getMediaPlayer() {
-        return mMediaPlayer;
+    private void applyBottomMargin(View view) {
+        int margin = getResources().getDimensionPixelSize(R.dimen.qs_header_tile_margin_bottom);
+        MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams();
+        layoutParams.bottomMargin = margin;
+        view.setLayoutParams(layoutParams);
+    }
+
+    private void applySideMargins(View view) {
+        int margin = getResources().getDimensionPixelSize(R.dimen.qs_header_tile_margin_horizontal);
+        MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams();
+        layoutParams.setMarginStart(margin);
+        layoutParams.setMarginEnd(margin);
+        view.setLayoutParams(layoutParams);
+    }
+
+    private void reAttachMediaHost() {
+        if (mMediaHost == null) {
+            return;
+        }
+        boolean horizontal = shouldUseHorizontalTileLayout();
+        ViewGroup host = mMediaHost.getHostView();
+        ViewGroup newParent = horizontal ? mHorizontalLinearLayout : this;
+        ViewGroup currentParent = (ViewGroup) host.getParent();
+        if (currentParent != newParent) {
+            if (currentParent != null) {
+                currentParent.removeView(host);
+            }
+            newParent.addView(host);
+            LinearLayout.LayoutParams layoutParams = (LayoutParams) host.getLayoutParams();
+            layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+            layoutParams.width = horizontal ? 0 : ViewGroup.LayoutParams.MATCH_PARENT;
+            layoutParams.weight = horizontal ? 1.5f : 0;
+            layoutParams.bottomMargin = mMediaBottomMargin;
+            int marginStart = horizontal
+                    ? getResources().getDimensionPixelSize(R.dimen.qs_header_tile_margin_horizontal)
+                    : 0;
+            layoutParams.setMarginStart(marginStart);
+        }
+    }
+
+    @Override
+    protected void addMediaHostView() {
+        mMediaHost.setVisibleChangedListener((visible) -> {
+            switchTileLayout();
+            return null;
+        });
+        mMediaHost.init(MediaHierarchyManager.LOCATION_QQS);
+        mMediaHost.setExpansion(0.0f);
+        mMediaHost.setShowsOnlyActiveMedia(true);
+        reAttachMediaHost();
     }
 
     @Override
@@ -179,6 +227,11 @@
     }
 
     @Override
+    protected boolean shouldShowDetail() {
+        return !mExpanded;
+    }
+
+    @Override
     protected void drawTile(TileRecord r, State state) {
         if (state instanceof SignalState) {
             SignalState copy = new SignalState();
@@ -191,10 +244,19 @@
         super.drawTile(r, state);
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        if (newConfig.orientation != mLastOrientation) {
+            mLastOrientation = newConfig.orientation;
+            switchTileLayout();
+        }
+    }
+
     boolean switchTileLayout() {
         if (!mUsingMediaPlayer) return false;
-        mHasMediaPlayer = mMediaPlayer.hasMediaSession();
-        if (mHasMediaPlayer && mHorizontalLinearLayout.getVisibility() == View.GONE) {
+        mShowHorizontalTileLayout = shouldUseHorizontalTileLayout();
+        if (mShowHorizontalTileLayout && mHorizontalLinearLayout.getVisibility() == View.GONE) {
             mHorizontalLinearLayout.setVisibility(View.VISIBLE);
             ((View) mRegularTileLayout).setVisibility(View.GONE);
             mTileLayout.setListening(false);
@@ -202,11 +264,13 @@
                 mTileLayout.removeTile(record);
                 record.tile.removeCallback(record.callback);
             }
-            mTileLayout = mMediaTileLayout;
+            mTileLayout = mHorizontalTileLayout;
             if (mHost != null) setTiles(mHost.getTiles());
             mTileLayout.setListening(mListening);
+            reAttachMediaHost();
             return true;
-        } else if (!mHasMediaPlayer && mHorizontalLinearLayout.getVisibility() == View.VISIBLE) {
+        } else if (!mShowHorizontalTileLayout
+                && mHorizontalLinearLayout.getVisibility() == View.VISIBLE) {
             mHorizontalLinearLayout.setVisibility(View.GONE);
             ((View) mRegularTileLayout).setVisibility(View.VISIBLE);
             mTileLayout.setListening(false);
@@ -217,14 +281,21 @@
             mTileLayout = mRegularTileLayout;
             if (mHost != null) setTiles(mHost.getTiles());
             mTileLayout.setListening(mListening);
+            reAttachMediaHost();
             return true;
         }
         return false;
     }
 
-    /** Returns true if this panel currently contains a media player. */
-    public boolean hasMediaPlayer() {
-        return mHasMediaPlayer;
+    private boolean shouldUseHorizontalTileLayout() {
+        return mMediaHost.getVisible()
+                && getResources().getConfiguration().orientation
+                        == Configuration.ORIENTATION_LANDSCAPE;
+    }
+
+    /** Returns true if this panel currently uses a horizontal tile layout. */
+    public boolean usesHorizontalLayout() {
+        return mShowHorizontalTileLayout;
     }
 
     @Override
@@ -341,7 +412,7 @@
             setClipChildren(false);
             setClipToPadding(false);
             LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
-                    LayoutParams.MATCH_PARENT);
+                    LayoutParams.WRAP_CONTENT);
             lp.gravity = Gravity.CENTER_HORIZONTAL;
             setLayoutParams(lp);
         }
@@ -354,6 +425,7 @@
 
         @Override
         public void onFinishInflate(){
+            super.onFinishInflate();
             updateResources();
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index b15c6a3..3b2bea8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -220,6 +220,10 @@
         mNextAlarmTextView.setSelected(true);
     }
 
+    public QuickQSPanel getHeaderQsPanel() {
+        return mHeaderQsPanel;
+    }
+
     private List<String> getIgnoredIconSlots() {
         ArrayList<String> ignored = new ArrayList<>();
         ignored.add(mContext.getResources().getString(
@@ -336,23 +340,6 @@
                 com.android.internal.R.dimen.quick_qs_offset_height);
         mSystemIconsView.setLayoutParams(mSystemIconsView.getLayoutParams());
 
-        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
-
-        if (mQsDisabled) {
-            lp.height = resources.getDimensionPixelSize(
-                    com.android.internal.R.dimen.quick_qs_offset_height);
-        } else if (useQsMediaPlayer(mContext) && mHeaderQsPanel.hasMediaPlayer()) {
-            lp.height = Math.max(getMinimumHeight(),
-                    resources.getDimensionPixelSize(
-                            com.android.internal.R.dimen.quick_qs_total_height_with_media));
-        } else {
-            lp.height = Math.max(getMinimumHeight(),
-                    resources.getDimensionPixelSize(
-                            com.android.internal.R.dimen.quick_qs_total_height));
-        }
-
-        setLayoutParams(lp);
-
         updateStatusIconAlphaAnimator();
         updateHeaderTextContainerAlphaAnimator();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index f821b19..9e2bb98 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -36,7 +36,6 @@
 import android.util.Log;
 import android.util.PathParser;
 import android.view.Gravity;
-import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
@@ -44,7 +43,6 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.Switch;
-import android.widget.TextView;
 
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
@@ -70,7 +68,6 @@
     private float mStrokeWidthInactive;
 
     private final ImageView mBg;
-    private final TextView mDetailText;
     private final int mColorActive;
     private final int mColorInactive;
     private final int mColorDisabled;
@@ -112,12 +109,6 @@
                 ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT,
                 Gravity.CENTER);
         mIconFrame.addView(mIcon, params);
-
-        // "..." afforadance below icon
-        mDetailText = (TextView) LayoutInflater.from(context).inflate(R.layout.qs_tile_detail_text,
-                mIconFrame, false);
-        mIconFrame.addView(mDetailText);
-
         mIconFrame.setClipChildren(false);
         mIconFrame.setClipToPadding(false);
 
@@ -173,10 +164,6 @@
             tile.longClick();
             return true;
         });
-
-        if (tile.supportsDetailView()) {
-            mDetailText.setVisibility(View.VISIBLE);
-        }
     }
 
     public void init(OnClickListener click, OnClickListener secondaryClick,
@@ -254,8 +241,6 @@
             mCircleColor = circleColor;
         }
 
-        mDetailText.setTextColor(QSTileImpl.getColorForState(getContext(), state.state));
-
         mShowRippleEffect = state.showRippleEffect;
         setClickable(state.state != Tile.STATE_UNAVAILABLE);
         setLongClickable(state.handlesLongClick);
@@ -400,4 +385,4 @@
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 7e5f2e19..87faacc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -68,8 +68,6 @@
 import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.QuickStatusBarHeader;
 import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.qs.tiles.QSSettingsControllerKt;
-import com.android.systemui.qs.tiles.QSSettingsPanel;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -152,19 +150,12 @@
      */
     abstract public int getMetricsCategory();
 
-    /**
-     * Experimental option on whether to use settings panels. Only loaded on creation, so the tile
-     * needs to be removed and added for this to take effect.
-     */
-    protected final QSSettingsPanel mQSSettingsPanelOption;
-
     protected QSTileImpl(QSHost host) {
         mHost = host;
         mContext = host.getContext();
         mInstanceId = host.getNewInstanceId();
         mState = newTileState();
         mTmpState = newTileState();
-        mQSSettingsPanelOption = QSSettingsControllerKt.getQSSettingsPanelOption();
         mQSLogger = host.getQSLogger();
         mUiEventLogger = host.getUiEventLogger();
     }
@@ -366,10 +357,6 @@
      * {@link QSTileImpl#getLongClickIntent}
      */
     protected void handleLongClick() {
-        if (mQSSettingsPanelOption == QSSettingsPanel.USE_DETAIL) {
-            showDetail(true);
-            return;
-        }
         Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(
                 getLongClickIntent(), 0);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QSSettingsController.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/QSSettingsController.kt
deleted file mode 100644
index c7ef0be..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QSSettingsController.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2019 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.tiles
-
-import android.provider.DeviceConfig
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
-
-enum class QSSettingsPanel {
-    DEFAULT,
-    OPEN_LONG_PRESS,
-    OPEN_CLICK,
-    USE_DETAIL
-}
-
-fun getQSSettingsPanelOption(): QSSettingsPanel =
-        when (DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI,
-                SystemUiDeviceConfigFlags.QS_USE_SETTINGS_PANELS, 0)) {
-            1 -> QSSettingsPanel.OPEN_LONG_PRESS
-            2 -> QSSettingsPanel.OPEN_CLICK
-            3 -> QSSettingsPanel.USE_DETAIL
-            else -> QSSettingsPanel.DEFAULT
-        }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
index da78903..d7dd6f2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
@@ -79,19 +79,15 @@
         state.value = isRecording || isStarting;
         state.state = (isRecording || isStarting) ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
         state.label = mContext.getString(R.string.quick_settings_screen_record_label);
+        state.icon = ResourceIcon.get(R.drawable.ic_screenrecord);
 
         if (isRecording) {
-            state.icon = ResourceIcon.get(R.drawable.ic_qs_screenrecord);
             state.secondaryLabel = mContext.getString(R.string.quick_settings_screen_record_stop);
         } else if (isStarting) {
             // round, since the timer isn't exact
             int countdown = (int) Math.floorDiv(mMillisUntilFinished + 500, 1000);
-            // TODO update icon
-            state.icon = ResourceIcon.get(R.drawable.ic_qs_screenrecord);
             state.secondaryLabel = String.format("%d...", countdown);
         } else {
-            // TODO update icon
-            state.icon = ResourceIcon.get(R.drawable.ic_qs_screenrecord);
             state.secondaryLabel = mContext.getString(R.string.quick_settings_screen_record_start);
         }
         state.contentDescription = TextUtils.isEmpty(state.secondaryLabel)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
index 6249f82..aa63b40 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
@@ -106,6 +106,7 @@
     }
 
     public void setEnabled(boolean enabled) {
+        super.setEnabled(enabled);
         mName.setEnabled(enabled);
         mAvatar.setEnabled(enabled);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index f169501..1279d42 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -56,7 +56,6 @@
 /** Quick settings tile: Wifi **/
 public class WifiTile extends QSTileImpl<SignalState> {
     private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS);
-    private static final Intent WIFI_PANEL = new Intent(Settings.Panel.ACTION_WIFI);
 
     protected final NetworkController mController;
     private final AccessPointController mWifiController;
@@ -109,21 +108,11 @@
 
     @Override
     public Intent getLongClickIntent() {
-        if (mQSSettingsPanelOption == QSSettingsPanel.OPEN_LONG_PRESS) return WIFI_PANEL;
-        else return WIFI_SETTINGS;
-    }
-
-    @Override
-    public boolean supportsDetailView() {
-        return getDetailAdapter() != null && mQSSettingsPanelOption == QSSettingsPanel.OPEN_CLICK;
+        return WIFI_SETTINGS;
     }
 
     @Override
     protected void handleClick() {
-        if (mQSSettingsPanelOption == QSSettingsPanel.OPEN_CLICK) {
-            mActivityStarter.postStartActivityDismissingKeyguard(WIFI_PANEL, 0);
-            return;
-        }
         // Secondary clicks are header clicks, just toggle.
         mState.copyTo(mStateBeforeClick);
         boolean wifiEnabled = mState.value;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 34a9e28..b272b60 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -842,7 +842,26 @@
                 Log.e(TAG_OPS, "Failed to get overview proxy for assistant visibility.");
             }
         } catch (RemoteException e) {
-            Log.e(TAG_OPS, "Failed to call onAssistantVisibilityChanged()", e);
+            Log.e(TAG_OPS, "Failed to call notifyAssistantVisibilityChanged()", e);
+        }
+    }
+
+    /**
+     * Notifies the Launcher of split screen size changes
+     * @param secondaryWindowBounds Bounds of the secondary window including the insets
+     * @param secondaryWindowInsets stable insets received by the secondary window
+     */
+    public void notifySplitScreenBoundsChanged(
+            Rect secondaryWindowBounds, Rect secondaryWindowInsets) {
+        try {
+            if (mOverviewProxy != null) {
+                mOverviewProxy.onSplitScreenSecondaryBoundsChanged(
+                        secondaryWindowBounds, secondaryWindowInsets);
+            } else {
+                Log.e(TAG_OPS, "Failed to get overview proxy for split screen bounds.");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG_OPS, "Failed to call onSplitScreenSecondaryBoundsChanged()", e);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index cf098d5..960c501 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -156,7 +156,7 @@
                 sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
 
                 // Remove notification
-                notificationManager.cancel(NOTIFICATION_RECORDING_ID);
+                notificationManager.cancel(NOTIFICATION_VIEW_ID);
 
                 startActivity(Intent.createChooser(shareIntent, shareLabel)
                         .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
@@ -175,7 +175,7 @@
                         Toast.LENGTH_LONG).show();
 
                 // Remove notification
-                notificationManager.cancel(NOTIFICATION_RECORDING_ID);
+                notificationManager.cancel(NOTIFICATION_VIEW_ID);
                 Log.d(TAG, "Deleted recording " + uri);
                 break;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
index c2473280..abd7e71 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
@@ -72,6 +72,7 @@
         window.getDecorView();
         window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
         window.setGravity(Gravity.TOP);
+        setTitle(R.string.screenrecord_name);
 
         setContentView(R.layout.screen_record_dialog);
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 4148289..f2d2eb3 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.screenshot;
 
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 
@@ -54,6 +56,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
+import android.provider.Settings;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.MathUtils;
@@ -61,16 +64,19 @@
 import android.view.Display;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
+import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewOutlineProvider;
 import android.view.ViewTreeObserver;
 import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.widget.FrameLayout;
+import android.widget.HorizontalScrollView;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.Toast;
@@ -155,6 +161,9 @@
     static final String EXTRA_CANCEL_NOTIFICATION = "android:screenshot_cancel_notification";
     static final String EXTRA_DISALLOW_ENTER_PIP = "android:screenshot_disallow_enter_pip";
 
+    // From WizardManagerHelper.java
+    private static final String SETTINGS_SECURE_USER_SETUP_COMPLETE = "user_setup_complete";
+
     private static final String TAG = "GlobalScreenshot";
 
     private static final long SCREENSHOT_FLASH_IN_DURATION_MS = 133;
@@ -169,7 +178,7 @@
     private static final long SCREENSHOT_DISMISS_ALPHA_OFFSET_MS = 50; // delay before starting fade
     private static final float SCREENSHOT_ACTIONS_START_SCALE_X = .7f;
     private static final float ROUNDED_CORNER_RADIUS = .05f;
-    private static final long SCREENSHOT_CORNER_TIMEOUT_MILLIS = 6000;
+    private static final int SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS = 6000;
     private static final int MESSAGE_CORNER_TIMEOUT = 2;
 
     private final Interpolator mAccelerateInterpolator = new AccelerateInterpolator();
@@ -183,24 +192,25 @@
     private final Display mDisplay;
     private final DisplayMetrics mDisplayMetrics;
 
-    private final View mScreenshotLayout;
-    private final ScreenshotSelectorView mScreenshotSelectorView;
-    private final ImageView mScreenshotAnimatedView;
-    private final ImageView mScreenshotPreview;
-    private final ImageView mScreenshotFlash;
-    private final ImageView mActionsContainerBackground;
-    private final FrameLayout mActionsContainer;
-    private final LinearLayout mActionsView;
-    private final ImageView mBackgroundProtection;
-    private final FrameLayout mDismissButton;
-    private final ImageView mDismissImage;
+    private View mScreenshotLayout;
+    private ScreenshotSelectorView mScreenshotSelectorView;
+    private ImageView mScreenshotAnimatedView;
+    private ImageView mScreenshotPreview;
+    private ImageView mScreenshotFlash;
+    private ImageView mActionsContainerBackground;
+    private HorizontalScrollView mActionsContainer;
+    private LinearLayout mActionsView;
+    private ImageView mBackgroundProtection;
+    private FrameLayout mDismissButton;
 
     private Bitmap mScreenBitmap;
     private SaveImageInBackgroundTask mSaveInBgTask;
     private Animator mScreenshotAnimation;
     private Runnable mOnCompleteRunnable;
-    private boolean mInDarkMode = false;
     private Animator mDismissAnimation;
+    private boolean mInDarkMode = false;
+    private boolean mDirectionLTR = true;
+    private boolean mOrientationPortrait = true;
 
     private float mScreenshotOffsetXPx;
     private float mScreenshotOffsetYPx;
@@ -232,57 +242,18 @@
      */
     @Inject
     public GlobalScreenshot(
-            Context context, @Main Resources resources, LayoutInflater layoutInflater,
+            Context context, @Main Resources resources,
             ScreenshotNotificationsController screenshotNotificationsController,
             UiEventLogger uiEventLogger) {
         mContext = context;
         mNotificationsController = screenshotNotificationsController;
         mUiEventLogger = uiEventLogger;
 
-        // Inflate the screenshot layout
-        mScreenshotLayout = layoutInflater.inflate(R.layout.global_screenshot, null);
-        mScreenshotAnimatedView =
-                mScreenshotLayout.findViewById(R.id.global_screenshot_animated_view);
-        mScreenshotAnimatedView.setClipToOutline(true);
-        mScreenshotAnimatedView.setOutlineProvider(new ViewOutlineProvider() {
-            @Override
-            public void getOutline(View view, Outline outline) {
-                outline.setRoundRect(new Rect(0, 0, view.getWidth(), view.getHeight()),
-                        ROUNDED_CORNER_RADIUS * view.getWidth());
-            }
-        });
-        mScreenshotPreview = mScreenshotLayout.findViewById(R.id.global_screenshot_preview);
-        mScreenshotPreview.setClipToOutline(true);
-        mScreenshotPreview.setOutlineProvider(new ViewOutlineProvider() {
-            @Override
-            public void getOutline(View view, Outline outline) {
-                outline.setRoundRect(new Rect(0, 0, view.getWidth(), view.getHeight()),
-                        ROUNDED_CORNER_RADIUS * view.getWidth());
-            }
-        });
-
-        mActionsContainerBackground = mScreenshotLayout.findViewById(
-                R.id.global_screenshot_actions_container_background);
-        mActionsContainer = mScreenshotLayout.findViewById(
-                R.id.global_screenshot_actions_container);
-        mActionsView = mScreenshotLayout.findViewById(R.id.global_screenshot_actions);
-        mBackgroundProtection = mScreenshotLayout.findViewById(
-                R.id.global_screenshot_actions_background);
-        mDismissButton = mScreenshotLayout.findViewById(R.id.global_screenshot_dismiss_button);
-        mDismissButton.setOnClickListener(view -> {
-            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EXPLICIT_DISMISSAL);
-            dismissScreenshot("dismiss_button", false);
-            mOnCompleteRunnable.run();
-        });
-        mDismissImage = mDismissButton.findViewById(R.id.global_screenshot_dismiss_image);
-
-        mScreenshotFlash = mScreenshotLayout.findViewById(R.id.global_screenshot_flash);
-        mScreenshotSelectorView = mScreenshotLayout.findViewById(R.id.global_screenshot_selector);
-        mScreenshotLayout.setFocusable(true);
-        mScreenshotSelectorView.setFocusable(true);
-        mScreenshotSelectorView.setFocusableInTouchMode(true);
-        mScreenshotAnimatedView.setPivotX(0);
-        mScreenshotAnimatedView.setPivotY(0);
+        reloadAssets();
+        Configuration config = mContext.getResources().getConfiguration();
+        mInDarkMode = config.isNightModeActive();
+        mDirectionLTR = config.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
+        mOrientationPortrait = config.orientation == ORIENTATION_PORTRAIT;
 
         // Setup the window that we are going to use
         mWindowLayoutParams = new WindowManager.LayoutParams(
@@ -333,6 +304,121 @@
         inoutInfo.touchableRegion.set(touchRegion);
     }
 
+    private void onConfigChanged(Configuration newConfig) {
+        boolean needsUpdate = false;
+        // dark mode
+        if (newConfig.isNightModeActive()) {
+            // Night mode is active, we're using dark theme
+            if (!mInDarkMode) {
+                mInDarkMode = true;
+                needsUpdate = true;
+            }
+        } else {
+            // Night mode is not active, we're using the light theme
+            if (mInDarkMode) {
+                mInDarkMode = false;
+                needsUpdate = true;
+            }
+        }
+
+        // RTL configuration
+        switch (newConfig.getLayoutDirection()) {
+            case View.LAYOUT_DIRECTION_LTR:
+                if (!mDirectionLTR) {
+                    mDirectionLTR = true;
+                    needsUpdate = true;
+                }
+                break;
+            case View.LAYOUT_DIRECTION_RTL:
+                if (mDirectionLTR) {
+                    mDirectionLTR = false;
+                    needsUpdate = true;
+                }
+                break;
+        }
+
+        // portrait/landscape orientation
+        switch (newConfig.orientation) {
+            case ORIENTATION_PORTRAIT:
+                if (!mOrientationPortrait) {
+                    mOrientationPortrait = true;
+                    needsUpdate = true;
+                }
+                break;
+            case ORIENTATION_LANDSCAPE:
+                if (mOrientationPortrait) {
+                    mOrientationPortrait = false;
+                    needsUpdate = true;
+                }
+                break;
+        }
+
+        if (needsUpdate) {
+            reloadAssets();
+        }
+    }
+
+    /**
+     * Update assets (called when the dark theme status changes). We only need to update the dismiss
+     * button and the actions container background, since the buttons are re-inflated on demand.
+     */
+    private void reloadAssets() {
+        boolean wasAttached = mScreenshotLayout != null && mScreenshotLayout.isAttachedToWindow();
+        if (wasAttached) {
+            mWindowManager.removeView(mScreenshotLayout);
+        }
+
+        // Inflate the screenshot layout
+        mScreenshotLayout = LayoutInflater.from(mContext).inflate(R.layout.global_screenshot, null);
+        mScreenshotAnimatedView =
+                mScreenshotLayout.findViewById(R.id.global_screenshot_animated_view);
+        mScreenshotAnimatedView.setClipToOutline(true);
+        mScreenshotAnimatedView.setOutlineProvider(new ViewOutlineProvider() {
+            @Override
+            public void getOutline(View view, Outline outline) {
+                outline.setRoundRect(new Rect(0, 0, view.getWidth(), view.getHeight()),
+                        ROUNDED_CORNER_RADIUS * view.getWidth());
+            }
+        });
+        mScreenshotPreview = mScreenshotLayout.findViewById(R.id.global_screenshot_preview);
+        mScreenshotPreview.setClipToOutline(true);
+        mScreenshotPreview.setOutlineProvider(new ViewOutlineProvider() {
+            @Override
+            public void getOutline(View view, Outline outline) {
+                outline.setRoundRect(new Rect(0, 0, view.getWidth(), view.getHeight()),
+                        ROUNDED_CORNER_RADIUS * view.getWidth());
+            }
+        });
+
+        mActionsContainerBackground = mScreenshotLayout.findViewById(
+                R.id.global_screenshot_actions_container_background);
+        mActionsContainer = mScreenshotLayout.findViewById(
+                R.id.global_screenshot_actions_container);
+        mActionsView = mScreenshotLayout.findViewById(R.id.global_screenshot_actions);
+        mBackgroundProtection = mScreenshotLayout.findViewById(
+                R.id.global_screenshot_actions_background);
+        mDismissButton = mScreenshotLayout.findViewById(R.id.global_screenshot_dismiss_button);
+        mDismissButton.setOnClickListener(view -> {
+            mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EXPLICIT_DISMISSAL);
+            dismissScreenshot("dismiss_button", false);
+            mOnCompleteRunnable.run();
+        });
+
+        mScreenshotFlash = mScreenshotLayout.findViewById(R.id.global_screenshot_flash);
+        mScreenshotSelectorView = mScreenshotLayout.findViewById(R.id.global_screenshot_selector);
+        mScreenshotLayout.setFocusable(true);
+        mScreenshotSelectorView.setFocusable(true);
+        mScreenshotSelectorView.setFocusableInTouchMode(true);
+        mScreenshotAnimatedView.setPivotX(0);
+        mScreenshotAnimatedView.setPivotY(0);
+        mActionsContainer.setScrollX(0);
+
+        if (wasAttached) {
+            mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
+        }
+    }
+
+
     /**
      * Creates a new worker thread and saves the screenshot to the media store.
      */
@@ -378,14 +464,19 @@
             return;
         }
 
+        if (!isUserSetupComplete()) {
+            // User setup isn't complete, so we don't want to show any UI beyond a toast, as editing
+            // and sharing shouldn't be exposed to the user.
+            saveScreenshotAndToast(finisher);
+            return;
+        }
+
         // Optimizations
         mScreenBitmap.setHasAlpha(false);
         mScreenBitmap.prepareToDraw();
 
-        updateDarkTheme();
+        onConfigChanged(mContext.getResources().getConfiguration());
 
-        mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
-        mScreenshotLayout.getViewTreeObserver().addOnComputeInternalInsetsListener(this);
 
         if (mDismissAnimation != null && mDismissAnimation.isRunning()) {
             mDismissAnimation.cancel();
@@ -395,7 +486,6 @@
     }
 
     void takeScreenshot(Consumer<Uri> finisher, Runnable onComplete) {
-        dismissScreenshot("new screenshot requested", true);
         mOnCompleteRunnable = onComplete;
 
         mDisplay.getRealMetrics(mDisplayMetrics);
@@ -407,7 +497,6 @@
     void handleImageAsScreenshot(Bitmap screenshot, Rect screenshotScreenBounds,
             Insets visibleInsets, int taskId, Consumer<Uri> finisher, Runnable onComplete) {
         // TODO use taskId and visibleInsets
-        dismissScreenshot("new screenshot requested", true);
         mOnCompleteRunnable = onComplete;
         takeScreenshot(screenshot, finisher, screenshotScreenBounds);
     }
@@ -468,6 +557,41 @@
     }
 
     /**
+     * Save the bitmap but don't show the normal screenshot UI.. just a toast (or notification on
+     * failure).
+     */
+    private void saveScreenshotAndToast(Consumer<Uri> finisher) {
+        // Play the shutter sound to notify that we've taken a screenshot
+        mScreenshotHandler.post(() -> {
+            mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
+        });
+
+        saveScreenshotInWorkerThread(finisher, new ActionsReadyListener() {
+            @Override
+            void onActionsReady(SavedImageData imageData) {
+                finisher.accept(imageData.uri);
+                if (imageData.uri == null) {
+                    mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_NOT_SAVED);
+                    mNotificationsController.notifyScreenshotError(
+                            R.string.screenshot_failed_to_capture_text);
+                } else {
+                    mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED);
+
+                    mScreenshotHandler.post(() -> {
+                        Toast.makeText(mContext, R.string.screenshot_saved_title,
+                                Toast.LENGTH_SHORT).show();
+                    });
+                }
+            }
+        });
+    }
+
+    private boolean isUserSetupComplete() {
+        return Settings.Secure.getInt(mContext.getContentResolver(),
+                SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1;
+    }
+
+    /**
      * Clears current screenshot
      */
     private void dismissScreenshot(String reason, boolean immediate) {
@@ -513,53 +637,15 @@
     }
 
     /**
-     * Update assets (called when the dark theme status changes). We only need to update the
-     * dismiss
-     * button and the actions container background, since the buttons are re-inflated on demand.
-     */
-    private void reloadAssets() {
-        mDismissImage.setImageDrawable(mContext.getDrawable(R.drawable.screenshot_cancel));
-        mActionsContainerBackground.setBackground(
-                mContext.getDrawable(R.drawable.action_chip_container_background));
-    }
-
-    /**
-     * Checks the current dark theme status and updates if it has changed.
-     */
-    private void updateDarkTheme() {
-        int currentNightMode = mContext.getResources().getConfiguration().uiMode
-                & Configuration.UI_MODE_NIGHT_MASK;
-        switch (currentNightMode) {
-            case Configuration.UI_MODE_NIGHT_NO:
-                // Night mode is not active, we're using the light theme
-                if (mInDarkMode) {
-                    mInDarkMode = false;
-                    reloadAssets();
-                }
-                break;
-            case Configuration.UI_MODE_NIGHT_YES:
-                // Night mode is active, we're using dark theme
-                if (!mInDarkMode) {
-                    mInDarkMode = true;
-                    reloadAssets();
-                }
-                break;
-        }
-    }
-
-    /**
      * Starts the animation after taking the screenshot
      */
     private void startAnimation(final Consumer<Uri> finisher, int w, int h,
             @Nullable Rect screenRect) {
         // If power save is on, show a toast so there is some visual indication that a
-        // screenshot
-        // has been taken.
-        PowerManager powerManager = (PowerManager) mContext.getSystemService(
-                Context.POWER_SERVICE);
+        // screenshot has been taken.
+        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         if (powerManager.isPowerSaveMode()) {
-            Toast.makeText(mContext, R.string.screenshot_saved_title,
-                    Toast.LENGTH_SHORT).show();
+            Toast.makeText(mContext, R.string.screenshot_saved_title, Toast.LENGTH_SHORT).show();
         }
 
         mScreenshotAnimation = createScreenshotDropInAnimation(w, h, screenRect);
@@ -588,31 +674,56 @@
                         } else {
                             createScreenshotActionsShadeAnimation(imageData).start();
                         }
+                        AccessibilityManager accessibilityManager = (AccessibilityManager)
+                                mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+                        long timeoutMs = accessibilityManager.getRecommendedTimeoutMillis(
+                                SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS,
+                                AccessibilityManager.FLAG_CONTENT_CONTROLS);
+
                         mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
                         mScreenshotHandler.sendMessageDelayed(
                                 mScreenshotHandler.obtainMessage(MESSAGE_CORNER_TIMEOUT),
-                                SCREENSHOT_CORNER_TIMEOUT_MILLIS);
+                                timeoutMs);
                     });
                 }
             }
         });
         mScreenshotHandler.post(() -> {
-            // Play the shutter sound to notify that we've taken a screenshot
-            mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
+            if (!mScreenshotLayout.isAttachedToWindow()) {
+                mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
+            }
+            mScreenshotLayout.getViewTreeObserver().addOnComputeInternalInsetsListener(this);
 
-            mScreenshotPreview.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-            mScreenshotPreview.buildLayer();
-            mScreenshotAnimation.start();
+            mScreenshotHandler.post(() -> {
+
+                // Play the shutter sound to notify that we've taken a screenshot
+                mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
+
+                mScreenshotPreview.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+                mScreenshotPreview.buildLayer();
+                mScreenshotAnimation.start();
+            });
         });
     }
 
     private AnimatorSet createScreenshotDropInAnimation(int width, int height, Rect bounds) {
-        float cornerScale = mCornerSizeX / (float) width;
+        float screenWidth = mDisplayMetrics.widthPixels;
+        float screenHeight = mDisplayMetrics.heightPixels;
 
-        mScreenshotAnimatedView.setScaleX(1);
-        mScreenshotAnimatedView.setScaleY(1);
-        mScreenshotAnimatedView.setX(0);
-        mScreenshotAnimatedView.setY(0);
+        int rotation = mContext.getDisplay().getRotation();
+        float cornerScale;
+        if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
+            cornerScale = (mCornerSizeX /  screenHeight);
+        } else {
+            cornerScale = (mCornerSizeX / screenWidth);
+        }
+        float currentScale = width / screenWidth;
+
+        mScreenshotAnimatedView.setScaleX(currentScale);
+        mScreenshotAnimatedView.setScaleY(currentScale);
+
+        mScreenshotAnimatedView.setPivotX(0);
+        mScreenshotAnimatedView.setPivotY(0);
 
         mScreenshotAnimatedView.setImageBitmap(mScreenBitmap);
         mScreenshotPreview.setImageBitmap(mScreenBitmap);
@@ -632,14 +743,12 @@
 
         final PointF startPos = new PointF(bounds.centerX(), bounds.centerY());
         float finalX;
-        if (mContext.getResources().getConfiguration().getLayoutDirection()
-                == View.LAYOUT_DIRECTION_LTR) {
-            finalX = mScreenshotOffsetXPx + width * cornerScale / 2f;
+        if (mDirectionLTR) {
+            finalX = mScreenshotOffsetXPx + screenWidth * cornerScale / 2f;
         } else {
-            finalX = width - mScreenshotOffsetXPx - width * cornerScale / 2f;
+            finalX = screenWidth - mScreenshotOffsetXPx - screenWidth * cornerScale / 2f;
         }
-        float finalY =
-                mDisplayMetrics.heightPixels - mScreenshotOffsetYPx - height * cornerScale / 2f;
+        float finalY = screenHeight - mScreenshotOffsetYPx - screenHeight * cornerScale / 2f;
         final PointF finalPos = new PointF(finalX, finalY);
 
         ValueAnimator toCorner = ValueAnimator.ofFloat(0, 1);
@@ -647,13 +756,12 @@
         float xPositionPct =
                 SCREENSHOT_TO_CORNER_X_DURATION_MS / (float) SCREENSHOT_TO_CORNER_Y_DURATION_MS;
         float scalePct =
-                SCREENSHOT_TO_CORNER_SCALE_DURATION_MS
-                        / (float) SCREENSHOT_TO_CORNER_Y_DURATION_MS;
+                SCREENSHOT_TO_CORNER_SCALE_DURATION_MS / (float) SCREENSHOT_TO_CORNER_Y_DURATION_MS;
         toCorner.addUpdateListener(animation -> {
             float t = animation.getAnimatedFraction();
             if (t < scalePct) {
                 float scale = MathUtils.lerp(
-                        1, cornerScale, mFastOutSlowIn.getInterpolation(t / scalePct));
+                        currentScale, cornerScale, mFastOutSlowIn.getInterpolation(t / scalePct));
                 mScreenshotAnimatedView.setScaleX(scale);
                 mScreenshotAnimatedView.setScaleY(scale);
             } else {
@@ -667,13 +775,13 @@
             if (t < xPositionPct) {
                 float xCenter = MathUtils.lerp(startPos.x, finalPos.x,
                         mFastOutSlowIn.getInterpolation(t / xPositionPct));
-                mScreenshotAnimatedView.setX(xCenter - width * currentScaleX / 2f);
+                mScreenshotAnimatedView.setX(xCenter - screenWidth * currentScaleX / 2f);
             } else {
-                mScreenshotAnimatedView.setX(finalPos.x - width * currentScaleX / 2f);
+                mScreenshotAnimatedView.setX(finalPos.x - screenWidth * currentScaleX / 2f);
             }
             float yCenter = MathUtils.lerp(startPos.y, finalPos.y,
                     mFastOutSlowIn.getInterpolation(t));
-            mScreenshotAnimatedView.setY(yCenter - height * currentScaleY / 2f);
+            mScreenshotAnimatedView.setY(yCenter - screenHeight * currentScaleY / 2f);
         });
 
         toCorner.addListener(new AnimatorListenerAdapter() {
@@ -713,7 +821,6 @@
     private ValueAnimator createScreenshotActionsShadeAnimation(SavedImageData imageData) {
         LayoutInflater inflater = LayoutInflater.from(mContext);
         mActionsView.removeAllViews();
-        mActionsContainer.setScrollX(0);
         mScreenshotLayout.invalidate();
         mScreenshotLayout.requestLayout();
         mScreenshotLayout.getViewTreeObserver().dispatchOnGlobalLayout();
@@ -803,14 +910,11 @@
         animator.setDuration(SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS);
         float alphaFraction = (float) SCREENSHOT_ACTIONS_ALPHA_DURATION_MS
                 / SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS;
-        mActionsContainer.setVisibility(View.VISIBLE);
         mActionsContainer.setAlpha(0f);
         mActionsContainerBackground.setAlpha(0f);
+        mActionsContainer.setVisibility(View.VISIBLE);
         mActionsContainerBackground.setVisibility(View.VISIBLE);
 
-        mActionsContainer.setPivotX(0);
-        mActionsContainerBackground.setPivotX(0);
-
         animator.addUpdateListener(animation -> {
             float t = animation.getAnimatedFraction();
             mBackgroundProtection.setAlpha(t);
@@ -825,6 +929,10 @@
                 chip.setAlpha(t);
                 chip.setScaleX(1 / containerScale); // invert to keep size of children constant
             }
+            mActionsContainer.setScrollX(mDirectionLTR ? 0 : mActionsContainer.getWidth());
+            mActionsContainer.setPivotX(mDirectionLTR ? 0 : mActionsContainer.getWidth());
+            mActionsContainerBackground.setPivotX(
+                    mDirectionLTR ? 0 : mActionsContainerBackground.getWidth());
         });
         return animator;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index bc3c33d..e88ce5a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -331,7 +331,7 @@
         int requestCode = mContext.getUserId();
 
         // Create a edit action
-        PendingIntent editAction = PendingIntent.getBroadcastAsUser(context, requestCode,
+        PendingIntent editAction = PendingIntent.getBroadcast(context, requestCode,
                 new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
                         .putExtra(GlobalScreenshot.EXTRA_ACTION_INTENT, editIntent)
                         .putExtra(GlobalScreenshot.EXTRA_CANCEL_NOTIFICATION,
@@ -341,7 +341,7 @@
                                 mSmartActionsEnabled)
                         .setAction(Intent.ACTION_EDIT)
                         .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
-                PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
+                PendingIntent.FLAG_CANCEL_CURRENT);
         Notification.Action.Builder editActionBuilder = new Notification.Action.Builder(
                 Icon.createWithResource(r, R.drawable.ic_screenshot_edit),
                 r.getString(com.android.internal.R.string.screenshot_edit), editAction);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java
index 44b20e5..b5209bb 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java
@@ -22,8 +22,8 @@
 import android.graphics.drawable.Icon;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
-import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import com.android.systemui.R;
@@ -31,7 +31,7 @@
 /**
  * View for a chip with an icon and text.
  */
-public class ScreenshotActionChip extends LinearLayout {
+public class ScreenshotActionChip extends FrameLayout {
 
     private static final String TAG = "ScreenshotActionChip";
 
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 4f20492..f7f1223 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -92,7 +92,7 @@
     }
 
     private void handleDockKey(long shortcutCode) {
-        if (mDivider == null || !mDivider.inSplitMode()) {
+        if (mDivider == null || !mDivider.isDividerVisible()) {
             // Split the screen
             mRecents.splitPrimaryTask((shortcutCode == SC_DOCK_LEFT)
                     ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index e67b3d7..95aceed 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -16,16 +16,12 @@
 
 package com.android.systemui.stackdivider;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
-import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
-import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.content.Context;
@@ -35,15 +31,11 @@
 import android.provider.Settings;
 import android.util.Slog;
 import android.view.LayoutInflater;
-import android.view.SurfaceControl;
 import android.view.View;
-import android.window.TaskOrganizer;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 import android.window.WindowOrganizer;
 
-import androidx.annotation.Nullable;
-
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
@@ -80,7 +72,6 @@
     static final boolean DEBUG = false;
 
     static final int DEFAULT_APP_TRANSITION_DURATION = 336;
-    static final float ADJUSTED_NONFOCUS_DIM = 0.3f;
 
     private final Optional<Lazy<Recents>> mRecentsOptionalLazy;
 
@@ -123,315 +114,22 @@
                 SplitDisplayLayout sdl = new SplitDisplayLayout(mContext, displayLayout, mSplits);
                 sdl.rotateTo(toRotation);
                 mRotateSplitLayout = sdl;
-                int position = mMinimized ? mView.mSnapTargetBeforeMinimized.position
-                        : mView.getCurrentPosition();
+                final int position = isDividerVisible()
+                        ? (mMinimized ? mView.mSnapTargetBeforeMinimized.position
+                                : mView.getCurrentPosition())
+                        // snap resets to middle target when not in split-mode
+                        : sdl.getSnapAlgorithm().getMiddleTarget().position;
                 DividerSnapAlgorithm snap = sdl.getSnapAlgorithm();
                 final DividerSnapAlgorithm.SnapTarget target =
                         snap.calculateNonDismissingSnapTarget(position);
                 sdl.resizeSplits(target.position, t);
 
-                if (inSplitMode()) {
+                if (isSplitActive()) {
                     WindowManagerProxy.applyHomeTasksMinimized(sdl, mSplits.mSecondary.token, t);
                 }
             };
 
-    private class DividerImeController implements DisplayImeController.ImePositionProcessor {
-        /**
-         * These are the y positions of the top of the IME surface when it is hidden and when it is
-         * shown respectively. These are NOT necessarily the top of the visible IME itself.
-         */
-        private int mHiddenTop = 0;
-        private int mShownTop = 0;
-
-        // The following are target states (what we are curretly animating towards).
-        /**
-         * {@code true} if, at the end of the animation, the split task positions should be
-         * adjusted by height of the IME. This happens when the secondary split is the IME target.
-         */
-        private boolean mTargetAdjusted = false;
-        /**
-         * {@code true} if, at the end of the animation, the IME should be shown/visible
-         * regardless of what has focus.
-         */
-        private boolean mTargetShown = false;
-        private float mTargetPrimaryDim = 0.f;
-        private float mTargetSecondaryDim = 0.f;
-
-        // The following are the current (most recent) states set during animation
-        /** {@code true} if the secondary split has IME focus. */
-        private boolean mSecondaryHasFocus = false;
-        /** The dimming currently applied to the primary/secondary splits. */
-        private float mLastPrimaryDim = 0.f;
-        private float mLastSecondaryDim = 0.f;
-        /** The most recent y position of the top of the IME surface */
-        private int mLastAdjustTop = -1;
-
-        // The following are states reached last time an animation fully completed.
-        /** {@code true} if the IME was shown/visible by the last-completed animation. */
-        private boolean mImeWasShown = false;
-        /** {@code true} if the split positions were adjusted by the last-completed animation. */
-        private boolean mAdjusted = false;
-
-        /**
-         * When some aspect of split-screen needs to animate independent from the IME,
-         * this will be non-null and control split animation.
-         */
-        @Nullable
-        private ValueAnimator mAnimation = null;
-
-        private boolean mPaused = true;
-        private boolean mPausedTargetAdjusted = false;
-
-        private boolean getSecondaryHasFocus(int displayId) {
-            WindowContainerToken imeSplit = TaskOrganizer.getImeTarget(displayId);
-            return imeSplit != null
-                    && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder());
-        }
-
-        private void updateDimTargets() {
-            final boolean splitIsVisible = !mView.isHidden();
-            mTargetPrimaryDim = (mSecondaryHasFocus && mTargetShown && splitIsVisible)
-                    ? ADJUSTED_NONFOCUS_DIM : 0.f;
-            mTargetSecondaryDim = (!mSecondaryHasFocus && mTargetShown && splitIsVisible)
-                    ? ADJUSTED_NONFOCUS_DIM : 0.f;
-        }
-
-        @Override
-        public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
-                boolean imeShouldShow, SurfaceControl.Transaction t) {
-            if (!inSplitMode()) {
-                return;
-            }
-            final boolean splitIsVisible = !mView.isHidden();
-            mSecondaryHasFocus = getSecondaryHasFocus(displayId);
-            final boolean targetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus
-                    && !mSplitLayout.mDisplayLayout.isLandscape();
-            mHiddenTop = hiddenTop;
-            mShownTop = shownTop;
-            mTargetShown = imeShouldShow;
-            if (mLastAdjustTop < 0) {
-                mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop;
-            } else if (mLastAdjustTop != (imeShouldShow ? mShownTop : mHiddenTop)) {
-                if (mTargetAdjusted != targetAdjusted && targetAdjusted == mAdjusted) {
-                    // Check for an "interruption" of an existing animation. In this case, we
-                    // need to fake-flip the last-known state direction so that the animation
-                    // completes in the other direction.
-                    mAdjusted = mTargetAdjusted;
-                } else if (targetAdjusted && mTargetAdjusted && mAdjusted) {
-                    // Already fully adjusted for IME, but IME height has changed; so, force-start
-                    // an async animation to the new IME height.
-                    mAdjusted = false;
-                }
-            }
-            if (mPaused) {
-                mPausedTargetAdjusted = targetAdjusted;
-                if (DEBUG) Slog.d(TAG, " ime starting but paused " + dumpState());
-                return;
-            }
-            mTargetAdjusted = targetAdjusted;
-            updateDimTargets();
-            if (DEBUG) Slog.d(TAG, " ime starting. vis:" + splitIsVisible + "  " + dumpState());
-            if (mAnimation != null || (mImeWasShown && imeShouldShow
-                    && mTargetAdjusted != mAdjusted)) {
-                // We need to animate adjustment independently of the IME position, so
-                // start our own animation to drive adjustment. This happens when a
-                // different split's editor has gained focus while the IME is still visible.
-                startAsyncAnimation();
-            }
-            if (splitIsVisible) {
-                // If split is hidden, we don't want to trigger any relayouts that would cause the
-                // divider to show again.
-                updateImeAdjustState();
-            }
-        }
-
-        private void updateImeAdjustState() {
-            // Reposition the server's secondary split position so that it evaluates
-            // insets properly.
-            WindowContainerTransaction wct = new WindowContainerTransaction();
-            if (mTargetAdjusted) {
-                mSplitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop);
-                wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mAdjustedSecondary);
-                // "Freeze" the configuration size so that the app doesn't get a config
-                // or relaunch. This is required because normally nav-bar contributes
-                // to configuration bounds (via nondecorframe).
-                Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration
-                        .windowConfiguration.getAppBounds());
-                adjustAppBounds.offset(0, mSplitLayout.mAdjustedSecondary.top
-                        - mSplitLayout.mSecondary.top);
-                wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds);
-                wct.setScreenSizeDp(mSplits.mSecondary.token,
-                        mSplits.mSecondary.configuration.screenWidthDp,
-                        mSplits.mSecondary.configuration.screenHeightDp);
-
-                wct.setBounds(mSplits.mPrimary.token, mSplitLayout.mAdjustedPrimary);
-                adjustAppBounds = new Rect(mSplits.mPrimary.configuration
-                        .windowConfiguration.getAppBounds());
-                adjustAppBounds.offset(0, mSplitLayout.mAdjustedPrimary.top
-                        - mSplitLayout.mPrimary.top);
-                wct.setAppBounds(mSplits.mPrimary.token, adjustAppBounds);
-                wct.setScreenSizeDp(mSplits.mPrimary.token,
-                        mSplits.mPrimary.configuration.screenWidthDp,
-                        mSplits.mPrimary.configuration.screenHeightDp);
-            } else {
-                wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mSecondary);
-                wct.setAppBounds(mSplits.mSecondary.token, null);
-                wct.setScreenSizeDp(mSplits.mSecondary.token,
-                        SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
-                wct.setBounds(mSplits.mPrimary.token, mSplitLayout.mPrimary);
-                wct.setAppBounds(mSplits.mPrimary.token, null);
-                wct.setScreenSizeDp(mSplits.mPrimary.token,
-                        SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
-            }
-
-            WindowOrganizer.applyTransaction(wct);
-
-            // Update all the adjusted-for-ime states
-            if (!mPaused) {
-                mView.setAdjustedForIme(mTargetShown, mTargetShown
-                        ? DisplayImeController.ANIMATION_DURATION_SHOW_MS
-                        : DisplayImeController.ANIMATION_DURATION_HIDE_MS);
-            }
-            setAdjustedForIme(mTargetShown && !mPaused);
-        }
-
-        @Override
-        public void onImePositionChanged(int displayId, int imeTop,
-                SurfaceControl.Transaction t) {
-            if (mAnimation != null || !inSplitMode() || mPaused) {
-                // Not synchronized with IME anymore, so return.
-                return;
-            }
-            final float fraction = ((float) imeTop - mHiddenTop) / (mShownTop - mHiddenTop);
-            final float progress = mTargetShown ? fraction : 1.f - fraction;
-            onProgress(progress, t);
-        }
-
-        @Override
-        public void onImeEndPositioning(int displayId, boolean cancelled,
-                SurfaceControl.Transaction t) {
-            if (mAnimation != null || !inSplitMode() || mPaused) {
-                // Not synchronized with IME anymore, so return.
-                return;
-            }
-            onEnd(cancelled, t);
-        }
-
-        private void onProgress(float progress, SurfaceControl.Transaction t) {
-            if (mTargetAdjusted != mAdjusted && !mPaused) {
-                final float fraction = mTargetAdjusted ? progress : 1.f - progress;
-                mLastAdjustTop = (int) (fraction * mShownTop + (1.f - fraction) * mHiddenTop);
-                mSplitLayout.updateAdjustedBounds(mLastAdjustTop, mHiddenTop, mShownTop);
-                mView.resizeSplitSurfaces(t, mSplitLayout.mAdjustedPrimary,
-                        mSplitLayout.mAdjustedSecondary);
-            }
-            final float invProg = 1.f - progress;
-            mView.setResizeDimLayer(t, true /* primary */,
-                    mLastPrimaryDim * invProg + progress * mTargetPrimaryDim);
-            mView.setResizeDimLayer(t, false /* primary */,
-                    mLastSecondaryDim * invProg + progress * mTargetSecondaryDim);
-        }
-
-        private void onEnd(boolean cancelled, SurfaceControl.Transaction t) {
-            if (!cancelled) {
-                onProgress(1.f, t);
-                mAdjusted = mTargetAdjusted;
-                mImeWasShown = mTargetShown;
-                mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop;
-                mLastPrimaryDim = mTargetPrimaryDim;
-                mLastSecondaryDim = mTargetSecondaryDim;
-            }
-        }
-
-        private void startAsyncAnimation() {
-            if (mAnimation != null) {
-                mAnimation.cancel();
-            }
-            mAnimation = ValueAnimator.ofFloat(0.f, 1.f);
-            mAnimation.setDuration(DisplayImeController.ANIMATION_DURATION_SHOW_MS);
-            if (mTargetAdjusted != mAdjusted) {
-                final float fraction =
-                        ((float) mLastAdjustTop - mHiddenTop) / (mShownTop - mHiddenTop);
-                final float progress = mTargetAdjusted ? fraction : 1.f - fraction;
-                mAnimation.setCurrentFraction(progress);
-            }
-
-            mAnimation.addUpdateListener(animation -> {
-                SurfaceControl.Transaction t = mTransactionPool.acquire();
-                float value = (float) animation.getAnimatedValue();
-                onProgress(value, t);
-                t.apply();
-                mTransactionPool.release(t);
-            });
-            mAnimation.setInterpolator(DisplayImeController.INTERPOLATOR);
-            mAnimation.addListener(new AnimatorListenerAdapter() {
-                private boolean mCancel = false;
-                @Override
-                public void onAnimationCancel(Animator animation) {
-                    mCancel = true;
-                }
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    SurfaceControl.Transaction t = mTransactionPool.acquire();
-                    onEnd(mCancel, t);
-                    t.apply();
-                    mTransactionPool.release(t);
-                    mAnimation = null;
-                }
-            });
-            mAnimation.start();
-        }
-
-        private String dumpState() {
-            return "top:" + mHiddenTop + "->" + mShownTop
-                    + " adj:" + mAdjusted + "->" + mTargetAdjusted + "(" + mLastAdjustTop + ")"
-                    + " shw:" + mImeWasShown + "->" + mTargetShown
-                    + " dims:" + mLastPrimaryDim + "," + mLastSecondaryDim
-                    + "->" + mTargetPrimaryDim + "," + mTargetSecondaryDim
-                    + " shf:" + mSecondaryHasFocus + " desync:" + (mAnimation != null)
-                    + " paus:" + mPaused + "[" + mPausedTargetAdjusted + "]";
-        }
-
-        /** Completely aborts/resets adjustment state */
-        public void pause(int displayId) {
-            if (DEBUG) Slog.d(TAG, "ime pause posting " + dumpState());
-            mHandler.post(() -> {
-                if (DEBUG) Slog.d(TAG, "ime pause run posted " + dumpState());
-                if (mPaused) {
-                    return;
-                }
-                mPaused = true;
-                mPausedTargetAdjusted = mTargetAdjusted;
-                mTargetAdjusted = false;
-                mTargetPrimaryDim = mTargetSecondaryDim = 0.f;
-                updateImeAdjustState();
-                startAsyncAnimation();
-                if (mAnimation != null) {
-                    mAnimation.end();
-                }
-            });
-        }
-
-        public void resume(int displayId) {
-            if (DEBUG) Slog.d(TAG, "ime resume posting " + dumpState());
-            mHandler.post(() -> {
-                if (DEBUG) Slog.d(TAG, "ime resume run posted " + dumpState());
-                if (!mPaused) {
-                    return;
-                }
-                mPaused = false;
-                mTargetAdjusted = mPausedTargetAdjusted;
-                updateDimTargets();
-                if ((mTargetAdjusted != mAdjusted) && !mMinimized && mView != null) {
-                    // End unminimize animations since they conflict with adjustment animations.
-                    mView.finishAnimations();
-                }
-                updateImeAdjustState();
-                startAsyncAnimation();
-            });
-        }
-    }
-    private final DividerImeController mImePositionProcessor = new DividerImeController();
+    private final DividerImeController mImePositionProcessor;
 
     private TaskStackChangeListener mActivityRestartListener = new TaskStackChangeListener() {
         @Override
@@ -461,6 +159,7 @@
         mRecentsOptionalLazy = recentsOptionalLazy;
         mForcedResizableController = new ForcedResizableInfoActivityController(context, this);
         mTransactionPool = transactionPool;
+        mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler);
     }
 
     @Override
@@ -479,7 +178,7 @@
 
             @Override
             public void onKeyguardShowingChanged() {
-                if (!inSplitMode() || mView == null) {
+                if (!isDividerVisible() || mView == null) {
                     return;
                 }
                 mView.setHidden(mKeyguardStateController.isShowing());
@@ -559,16 +258,27 @@
     }
 
     /** {@code true} if this is visible */
-    public boolean inSplitMode() {
+    public boolean isDividerVisible() {
         return mView != null && mView.getVisibility() == View.VISIBLE;
     }
 
+    /**
+     * This indicates that at-least one of the splits has content. This differs from
+     * isDividerVisible because the divider is only visible once *everything* is in split mode
+     * while this only cares if some things are (eg. while entering/exiting as well).
+     */
+    private boolean isSplitActive() {
+        return mSplits.mPrimary.topActivityType != ACTIVITY_TYPE_UNDEFINED
+                || mSplits.mSecondary.topActivityType != ACTIVITY_TYPE_UNDEFINED;
+    }
+
     private void addDivider(Configuration configuration) {
         Context dctx = mDisplayController.getDisplayContext(mContext.getDisplayId());
         mView = (DividerView)
                 LayoutInflater.from(dctx).inflate(R.layout.docked_stack_divider, null);
         DisplayLayout displayLayout = mDisplayController.getDisplayLayout(mContext.getDisplayId());
-        mView.injectDependencies(mWindowManager, mDividerState, this, mSplits, mSplitLayout);
+        mView.injectDependencies(mWindowManager, mDividerState, this, mSplits, mSplitLayout,
+                mImePositionProcessor);
         mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE);
         mView.setMinimizedDockStack(mMinimized, mHomeStackResizable);
         final int size = dctx.getResources().getDimensionPixelSize(
@@ -592,13 +302,11 @@
         removeDivider();
         addDivider(configuration);
 
-        if (mView != null) {
-            if (mMinimized) {
-                mView.setMinimizedDockStack(true, mHomeStackResizable);
-                updateTouchable();
-            }
-            mView.setHidden(isDividerHidden);
+        if (mMinimized) {
+            mView.setMinimizedDockStack(true, mHomeStackResizable);
+            updateTouchable();
         }
+        mView.setHidden(isDividerHidden);
     }
 
     void onTaskVanished() {
@@ -610,7 +318,7 @@
                 mContext.getDisplayId()).getResources().getConfiguration()));
     }
 
-    void updateVisibility(final boolean visible) {
+    private void updateVisibility(final boolean visible) {
         if (DEBUG) Slog.d(TAG, "Updating visibility " + mVisible + "->" + visible);
         if (mVisible != visible) {
             mVisible = visible;
@@ -637,8 +345,9 @@
     }
 
     void onSplitDismissed() {
-        mMinimized = false;
         updateVisibility(false /* visible */);
+        mMinimized = false;
+        removeDivider();
     }
 
     /** Switch to minimized state if appropriate */
@@ -656,7 +365,8 @@
     private void setHomeMinimized(final boolean minimized, boolean homeStackResizable) {
         if (DEBUG) {
             Slog.d(TAG, "setHomeMinimized  min:" + mMinimized + "->" + minimized + " hrsz:"
-                    + mHomeStackResizable + "->" + homeStackResizable + " split:" + inSplitMode());
+                    + mHomeStackResizable + "->" + homeStackResizable
+                    + " split:" + isDividerVisible());
         }
         WindowContainerTransaction wct = new WindowContainerTransaction();
         final boolean minimizedChanged = mMinimized != minimized;
@@ -671,7 +381,7 @@
         final boolean homeResizableChanged = mHomeStackResizable != homeStackResizable;
         if (homeResizableChanged) {
             mHomeStackResizable = homeStackResizable;
-            if (inSplitMode()) {
+            if (isDividerVisible()) {
                 WindowManagerProxy.applyHomeTasksMinimized(
                         mSplitLayout, mSplits.mSecondary.token, wct);
             }
@@ -781,20 +491,22 @@
 
     /** Register a listener that gets called whenever the existence of the divider changes */
     public void registerInSplitScreenListener(Consumer<Boolean> listener) {
-        listener.accept(inSplitMode());
+        listener.accept(isDividerVisible());
         synchronized (mDockedStackExistsListeners) {
             mDockedStackExistsListeners.add(new WeakReference<>(listener));
         }
     }
 
     void startEnterSplit() {
+        update(mDisplayController.getDisplayContext(
+                mContext.getDisplayId()).getResources().getConfiguration());
         // Set resizable directly here because applyEnterSplit already resizes home stack.
         mHomeStackResizable = WindowManagerProxy.applyEnterSplit(mSplits, mSplitLayout);
     }
 
     void ensureMinimizedSplit() {
         setHomeMinimized(true /* minimized */, mSplits.mSecondary.isResizable());
-        if (!inSplitMode()) {
+        if (!isDividerVisible()) {
             // Wasn't in split-mode yet, so enter now.
             if (DEBUG) {
                 Slog.d(TAG, " entering split mode with minimized=true");
@@ -805,7 +517,7 @@
 
     void ensureNormalSplit() {
         setHomeMinimized(false /* minimized */, mHomeStackResizable);
-        if (!inSplitMode()) {
+        if (!isDividerVisible()) {
             // Wasn't in split-mode, so enter now.
             if (DEBUG) {
                 Slog.d(TAG, " enter split mode unminimized ");
@@ -813,4 +525,16 @@
             updateVisibility(true /* visible */);
         }
     }
+
+    SplitDisplayLayout getSplitLayout() {
+        return mSplitLayout;
+    }
+
+    /** @return the container token for the secondary split root task. */
+    public WindowContainerToken getSecondaryRoot() {
+        if (mSplits == null || mSplits.mSecondary == null) {
+            return null;
+        }
+        return mSplits.mSecondary.token;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java
new file mode 100644
index 0000000..1e0c07b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.stackdivider;
+
+import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
+import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.util.Slog;
+import android.view.SurfaceControl;
+import android.window.TaskOrganizer;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
+import android.window.WindowOrganizer;
+
+import androidx.annotation.Nullable;
+
+import com.android.systemui.TransactionPool;
+import com.android.systemui.wm.DisplayImeController;
+
+class DividerImeController implements DisplayImeController.ImePositionProcessor {
+    private static final String TAG = "DividerImeController";
+    private static final boolean DEBUG = Divider.DEBUG;
+
+    private static final float ADJUSTED_NONFOCUS_DIM = 0.3f;
+
+    private final SplitScreenTaskOrganizer mSplits;
+    private final TransactionPool mTransactionPool;
+    private final Handler mHandler;
+
+    /**
+     * These are the y positions of the top of the IME surface when it is hidden and when it is
+     * shown respectively. These are NOT necessarily the top of the visible IME itself.
+     */
+    private int mHiddenTop = 0;
+    private int mShownTop = 0;
+
+    // The following are target states (what we are curretly animating towards).
+    /**
+     * {@code true} if, at the end of the animation, the split task positions should be
+     * adjusted by height of the IME. This happens when the secondary split is the IME target.
+     */
+    private boolean mTargetAdjusted = false;
+    /**
+     * {@code true} if, at the end of the animation, the IME should be shown/visible
+     * regardless of what has focus.
+     */
+    private boolean mTargetShown = false;
+    private float mTargetPrimaryDim = 0.f;
+    private float mTargetSecondaryDim = 0.f;
+
+    // The following are the current (most recent) states set during animation
+    /** {@code true} if the secondary split has IME focus. */
+    private boolean mSecondaryHasFocus = false;
+    /** The dimming currently applied to the primary/secondary splits. */
+    private float mLastPrimaryDim = 0.f;
+    private float mLastSecondaryDim = 0.f;
+    /** The most recent y position of the top of the IME surface */
+    private int mLastAdjustTop = -1;
+
+    // The following are states reached last time an animation fully completed.
+    /** {@code true} if the IME was shown/visible by the last-completed animation. */
+    private boolean mImeWasShown = false;
+    /** {@code true} if the split positions were adjusted by the last-completed animation. */
+    private boolean mAdjusted = false;
+
+    /**
+     * When some aspect of split-screen needs to animate independent from the IME,
+     * this will be non-null and control split animation.
+     */
+    @Nullable
+    private ValueAnimator mAnimation = null;
+
+    private boolean mPaused = true;
+    private boolean mPausedTargetAdjusted = false;
+
+    DividerImeController(SplitScreenTaskOrganizer splits, TransactionPool pool, Handler handler) {
+        mSplits = splits;
+        mTransactionPool = pool;
+        mHandler = handler;
+    }
+
+    private DividerView getView() {
+        return mSplits.mDivider.getView();
+    }
+
+    private SplitDisplayLayout getLayout() {
+        return mSplits.mDivider.getSplitLayout();
+    }
+
+    private boolean isDividerVisible() {
+        return mSplits.mDivider.isDividerVisible();
+    }
+
+    private boolean getSecondaryHasFocus(int displayId) {
+        WindowContainerToken imeSplit = TaskOrganizer.getImeTarget(displayId);
+        return imeSplit != null
+                && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder());
+    }
+
+    private void updateDimTargets() {
+        final boolean splitIsVisible = !getView().isHidden();
+        mTargetPrimaryDim = (mSecondaryHasFocus && mTargetShown && splitIsVisible)
+                ? ADJUSTED_NONFOCUS_DIM : 0.f;
+        mTargetSecondaryDim = (!mSecondaryHasFocus && mTargetShown && splitIsVisible)
+                ? ADJUSTED_NONFOCUS_DIM : 0.f;
+    }
+
+    @Override
+    public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
+            boolean imeShouldShow, SurfaceControl.Transaction t) {
+        if (!isDividerVisible()) {
+            return;
+        }
+        final boolean splitIsVisible = !getView().isHidden();
+        mSecondaryHasFocus = getSecondaryHasFocus(displayId);
+        final boolean targetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus
+                && !getLayout().mDisplayLayout.isLandscape();
+        mHiddenTop = hiddenTop;
+        mShownTop = shownTop;
+        mTargetShown = imeShouldShow;
+        if (mLastAdjustTop < 0) {
+            mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop;
+        } else if (mLastAdjustTop != (imeShouldShow ? mShownTop : mHiddenTop)) {
+            if (mTargetAdjusted != targetAdjusted && targetAdjusted == mAdjusted) {
+                // Check for an "interruption" of an existing animation. In this case, we
+                // need to fake-flip the last-known state direction so that the animation
+                // completes in the other direction.
+                mAdjusted = mTargetAdjusted;
+            } else if (targetAdjusted && mTargetAdjusted && mAdjusted) {
+                // Already fully adjusted for IME, but IME height has changed; so, force-start
+                // an async animation to the new IME height.
+                mAdjusted = false;
+            }
+        }
+        if (mPaused) {
+            mPausedTargetAdjusted = targetAdjusted;
+            if (DEBUG) Slog.d(TAG, " ime starting but paused " + dumpState());
+            return;
+        }
+        mTargetAdjusted = targetAdjusted;
+        updateDimTargets();
+        if (DEBUG) Slog.d(TAG, " ime starting. vis:" + splitIsVisible + "  " + dumpState());
+        if (mAnimation != null || (mImeWasShown && imeShouldShow
+                && mTargetAdjusted != mAdjusted)) {
+            // We need to animate adjustment independently of the IME position, so
+            // start our own animation to drive adjustment. This happens when a
+            // different split's editor has gained focus while the IME is still visible.
+            startAsyncAnimation();
+        }
+        if (splitIsVisible) {
+            // If split is hidden, we don't want to trigger any relayouts that would cause the
+            // divider to show again.
+            updateImeAdjustState();
+        }
+    }
+
+    private void updateImeAdjustState() {
+        // Reposition the server's secondary split position so that it evaluates
+        // insets properly.
+        WindowContainerTransaction wct = new WindowContainerTransaction();
+        final SplitDisplayLayout splitLayout = getLayout();
+        if (mTargetAdjusted) {
+            splitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop);
+            wct.setBounds(mSplits.mSecondary.token, splitLayout.mAdjustedSecondary);
+            // "Freeze" the configuration size so that the app doesn't get a config
+            // or relaunch. This is required because normally nav-bar contributes
+            // to configuration bounds (via nondecorframe).
+            Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration
+                    .windowConfiguration.getAppBounds());
+            adjustAppBounds.offset(0, splitLayout.mAdjustedSecondary.top
+                    - splitLayout.mSecondary.top);
+            wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds);
+            wct.setScreenSizeDp(mSplits.mSecondary.token,
+                    mSplits.mSecondary.configuration.screenWidthDp,
+                    mSplits.mSecondary.configuration.screenHeightDp);
+
+            wct.setBounds(mSplits.mPrimary.token, splitLayout.mAdjustedPrimary);
+            adjustAppBounds = new Rect(mSplits.mPrimary.configuration
+                    .windowConfiguration.getAppBounds());
+            adjustAppBounds.offset(0, splitLayout.mAdjustedPrimary.top
+                    - splitLayout.mPrimary.top);
+            wct.setAppBounds(mSplits.mPrimary.token, adjustAppBounds);
+            wct.setScreenSizeDp(mSplits.mPrimary.token,
+                    mSplits.mPrimary.configuration.screenWidthDp,
+                    mSplits.mPrimary.configuration.screenHeightDp);
+        } else {
+            wct.setBounds(mSplits.mSecondary.token, splitLayout.mSecondary);
+            wct.setAppBounds(mSplits.mSecondary.token, null);
+            wct.setScreenSizeDp(mSplits.mSecondary.token,
+                    SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
+            wct.setBounds(mSplits.mPrimary.token, splitLayout.mPrimary);
+            wct.setAppBounds(mSplits.mPrimary.token, null);
+            wct.setScreenSizeDp(mSplits.mPrimary.token,
+                    SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
+        }
+
+        WindowOrganizer.applyTransaction(wct);
+
+        // Update all the adjusted-for-ime states
+        if (!mPaused) {
+            final DividerView view = getView();
+            if (view != null) {
+                view.setAdjustedForIme(mTargetShown, mTargetShown
+                        ? DisplayImeController.ANIMATION_DURATION_SHOW_MS
+                        : DisplayImeController.ANIMATION_DURATION_HIDE_MS);
+            }
+        }
+        mSplits.mDivider.setAdjustedForIme(mTargetShown && !mPaused);
+    }
+
+    @Override
+    public void onImePositionChanged(int displayId, int imeTop,
+            SurfaceControl.Transaction t) {
+        if (mAnimation != null || !isDividerVisible() || mPaused) {
+            // Not synchronized with IME anymore, so return.
+            return;
+        }
+        final float fraction = ((float) imeTop - mHiddenTop) / (mShownTop - mHiddenTop);
+        final float progress = mTargetShown ? fraction : 1.f - fraction;
+        onProgress(progress, t);
+    }
+
+    @Override
+    public void onImeEndPositioning(int displayId, boolean cancelled,
+            SurfaceControl.Transaction t) {
+        if (mAnimation != null || !isDividerVisible() || mPaused) {
+            // Not synchronized with IME anymore, so return.
+            return;
+        }
+        onEnd(cancelled, t);
+    }
+
+    private void onProgress(float progress, SurfaceControl.Transaction t) {
+        final DividerView view = getView();
+        if (mTargetAdjusted != mAdjusted && !mPaused) {
+            final SplitDisplayLayout splitLayout = getLayout();
+            final float fraction = mTargetAdjusted ? progress : 1.f - progress;
+            mLastAdjustTop = (int) (fraction * mShownTop + (1.f - fraction) * mHiddenTop);
+            splitLayout.updateAdjustedBounds(mLastAdjustTop, mHiddenTop, mShownTop);
+            view.resizeSplitSurfaces(t, splitLayout.mAdjustedPrimary,
+                    splitLayout.mAdjustedSecondary);
+        }
+        final float invProg = 1.f - progress;
+        view.setResizeDimLayer(t, true /* primary */,
+                mLastPrimaryDim * invProg + progress * mTargetPrimaryDim);
+        view.setResizeDimLayer(t, false /* primary */,
+                mLastSecondaryDim * invProg + progress * mTargetSecondaryDim);
+    }
+
+    void setDimsHidden(SurfaceControl.Transaction t, boolean hidden) {
+        final DividerView view = getView();
+        if (hidden) {
+            view.setResizeDimLayer(t, true /* primary */, 0.f /* alpha */);
+            view.setResizeDimLayer(t, false /* primary */, 0.f /* alpha */);
+        } else {
+            updateDimTargets();
+            view.setResizeDimLayer(t, true /* primary */, mTargetPrimaryDim);
+            view.setResizeDimLayer(t, false /* primary */, mTargetSecondaryDim);
+        }
+    }
+
+    private void onEnd(boolean cancelled, SurfaceControl.Transaction t) {
+        if (!cancelled) {
+            onProgress(1.f, t);
+            mAdjusted = mTargetAdjusted;
+            mImeWasShown = mTargetShown;
+            mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop;
+            mLastPrimaryDim = mTargetPrimaryDim;
+            mLastSecondaryDim = mTargetSecondaryDim;
+        }
+    }
+
+    private void startAsyncAnimation() {
+        if (mAnimation != null) {
+            mAnimation.cancel();
+        }
+        mAnimation = ValueAnimator.ofFloat(0.f, 1.f);
+        mAnimation.setDuration(DisplayImeController.ANIMATION_DURATION_SHOW_MS);
+        if (mTargetAdjusted != mAdjusted) {
+            final float fraction =
+                    ((float) mLastAdjustTop - mHiddenTop) / (mShownTop - mHiddenTop);
+            final float progress = mTargetAdjusted ? fraction : 1.f - fraction;
+            mAnimation.setCurrentFraction(progress);
+        }
+
+        mAnimation.addUpdateListener(animation -> {
+            SurfaceControl.Transaction t = mTransactionPool.acquire();
+            float value = (float) animation.getAnimatedValue();
+            onProgress(value, t);
+            t.apply();
+            mTransactionPool.release(t);
+        });
+        mAnimation.setInterpolator(DisplayImeController.INTERPOLATOR);
+        mAnimation.addListener(new AnimatorListenerAdapter() {
+            private boolean mCancel = false;
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mCancel = true;
+            }
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                SurfaceControl.Transaction t = mTransactionPool.acquire();
+                onEnd(mCancel, t);
+                t.apply();
+                mTransactionPool.release(t);
+                mAnimation = null;
+            }
+        });
+        mAnimation.start();
+    }
+
+    private String dumpState() {
+        return "top:" + mHiddenTop + "->" + mShownTop
+                + " adj:" + mAdjusted + "->" + mTargetAdjusted + "(" + mLastAdjustTop + ")"
+                + " shw:" + mImeWasShown + "->" + mTargetShown
+                + " dims:" + mLastPrimaryDim + "," + mLastSecondaryDim
+                + "->" + mTargetPrimaryDim + "," + mTargetSecondaryDim
+                + " shf:" + mSecondaryHasFocus + " desync:" + (mAnimation != null)
+                + " paus:" + mPaused + "[" + mPausedTargetAdjusted + "]";
+    }
+
+    /** Completely aborts/resets adjustment state */
+    public void pause(int displayId) {
+        if (DEBUG) Slog.d(TAG, "ime pause posting " + dumpState());
+        mHandler.post(() -> {
+            if (DEBUG) Slog.d(TAG, "ime pause run posted " + dumpState());
+            if (mPaused) {
+                return;
+            }
+            mPaused = true;
+            mPausedTargetAdjusted = mTargetAdjusted;
+            mTargetAdjusted = false;
+            mTargetPrimaryDim = mTargetSecondaryDim = 0.f;
+            updateImeAdjustState();
+            startAsyncAnimation();
+            if (mAnimation != null) {
+                mAnimation.end();
+            }
+        });
+    }
+
+    public void resume(int displayId) {
+        if (DEBUG) Slog.d(TAG, "ime resume posting " + dumpState());
+        mHandler.post(() -> {
+            if (DEBUG) Slog.d(TAG, "ime resume run posted " + dumpState());
+            if (!mPaused) {
+                return;
+            }
+            mPaused = false;
+            mTargetAdjusted = mPausedTargetAdjusted;
+            updateDimTargets();
+            final DividerView view = getView();
+            if ((mTargetAdjusted != mAdjusted) && !mSplits.mDivider.isMinimized() && view != null) {
+                // End unminimize animations since they conflict with adjustment animations.
+                view.finishAnimations();
+            }
+            updateImeAdjustState();
+            startAsyncAnimation();
+        });
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 060760a..e349b5af 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -19,7 +19,6 @@
 import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
 import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
 import static android.view.WindowManager.DOCKED_RIGHT;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
 
 import android.animation.AnimationHandler;
 import android.animation.Animator;
@@ -28,16 +27,17 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.Region.Op;
 import android.hardware.display.DisplayManager;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.RemoteException;
 import android.util.AttributeSet;
 import android.util.Slog;
 import android.view.Display;
-import android.view.InsetsState;
 import android.view.MotionEvent;
 import android.view.PointerIcon;
 import android.view.SurfaceControl;
@@ -46,10 +46,8 @@
 import android.view.View;
 import android.view.View.OnTouchListener;
 import android.view.ViewConfiguration;
-import android.view.ViewRootImpl;
 import android.view.ViewTreeObserver.InternalInsetsInfo;
 import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
-import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
@@ -63,9 +61,10 @@
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
 import com.android.internal.policy.DockedDividerUtils;
+import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.shared.system.WindowManagerWrapper;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 
 import java.util.function.Consumer;
@@ -118,7 +117,6 @@
     private int mStartY;
     private int mStartPosition;
     private int mDockSide;
-    private final int[] mTempInt2 = new int[2];
     private boolean mMoving;
     private int mTouchSlop;
     private boolean mBackgroundLifted;
@@ -145,8 +143,8 @@
     private VelocityTracker mVelocityTracker;
     private FlingAnimationUtils mFlingAnimationUtils;
     private SplitDisplayLayout mSplitLayout;
+    private DividerImeController mImeController;
     private DividerCallbacks mCallback;
-    private final Rect mStableInsets = new Rect();
     private final AnimationHandler mAnimationHandler = new AnimationHandler();
 
     private boolean mGrowRecents;
@@ -164,6 +162,9 @@
     int mDividerPositionX;
     int mDividerPositionY;
 
+    private final Matrix mTmpMatrix = new Matrix();
+    private final float[] mTmpValues = new float[9];
+
     // The view is removed or in the process of been removed from the system.
     private boolean mRemoved;
 
@@ -249,6 +250,22 @@
         }
     };
 
+    private Runnable mUpdateEmbeddedMatrix = () -> {
+        if (getViewRootImpl() == null) {
+            return;
+        }
+        if (isHorizontalDivision()) {
+            mTmpMatrix.setTranslate(0, mDividerPositionY - mDividerInsets);
+        } else {
+            mTmpMatrix.setTranslate(mDividerPositionX - mDividerInsets, 0);
+        }
+        mTmpMatrix.getValues(mTmpValues);
+        try {
+            getViewRootImpl().getAccessibilityEmbeddedConnection().setScreenMatrix(mTmpValues);
+        } catch (RemoteException e) {
+        }
+    };
+
     public DividerView(Context context) {
         this(context, null);
     }
@@ -315,29 +332,6 @@
     }
 
     @Override
-    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-        if (isAttachedToWindow()
-                && ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL) {
-            // Our window doesn't cover entire display, so we use the display frame to re-calculate
-            // the insets.
-            final InsetsState state = getWindowInsetsController().getState();
-            insets = state.calculateInsets(state.getDisplayFrame(),
-                    null /* ignoringVisibilityState */, insets.isRound(),
-                    insets.shouldAlwaysConsumeSystemBars(), insets.getDisplayCutout(),
-                    0 /* legacySystemUiFlags */,
-                    SOFT_INPUT_ADJUST_NOTHING, null /* typeSideMap */);
-        }
-        if (mStableInsets.left != insets.getStableInsetLeft()
-                || mStableInsets.top != insets.getStableInsetTop()
-                || mStableInsets.right != insets.getStableInsetRight()
-                || mStableInsets.bottom != insets.getStableInsetBottom()) {
-            mStableInsets.set(insets.getStableInsetLeft(), insets.getStableInsetTop(),
-                    insets.getStableInsetRight(), insets.getStableInsetBottom());
-        }
-        return super.onApplyWindowInsets(insets);
-    }
-
-    @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
         if (mFirstLayout) {
@@ -360,16 +354,19 @@
         if (changed) {
             mWindowManagerProxy.setTouchRegion(new Rect(mHandle.getLeft(), mHandle.getTop(),
                     mHandle.getRight(), mHandle.getBottom()));
+            notifySplitScreenBoundsChanged();
         }
     }
 
     public void injectDependencies(DividerWindowManager windowManager, DividerState dividerState,
-            DividerCallbacks callback, SplitScreenTaskOrganizer tiles, SplitDisplayLayout sdl) {
+            DividerCallbacks callback, SplitScreenTaskOrganizer tiles, SplitDisplayLayout sdl,
+            DividerImeController imeController) {
         mWindowManager = windowManager;
         mState = dividerState;
         mCallback = callback;
         mTiles = tiles;
         mSplitLayout = sdl;
+        mImeController = imeController;
 
         if (mState.mRatioPositionBeforeMinimized == 0) {
             // Set the middle target as the initial state
@@ -384,19 +381,7 @@
     }
 
     public Rect getNonMinimizedSplitScreenSecondaryBounds() {
-        calculateBoundsForPosition(mSnapTargetBeforeMinimized.position,
-                DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
-        mOtherTaskRect.bottom -= mStableInsets.bottom;
-        switch (mDockSide) {
-            case WindowManager.DOCKED_LEFT:
-                mOtherTaskRect.top += mStableInsets.top;
-                mOtherTaskRect.right -= mStableInsets.right;
-                break;
-            case WindowManager.DOCKED_RIGHT:
-                mOtherTaskRect.top += mStableInsets.top;
-                mOtherTaskRect.left += mStableInsets.left;
-                break;
-        }
+        mOtherTaskRect.set(mSplitLayout.mSecondary);
         return mOtherTaskRect;
     }
 
@@ -421,6 +406,7 @@
             } else {
                 t.show(sc);
             }
+            mImeController.setDimsHidden(t, hidden);
             t.apply();
             mTiles.releaseTransaction(t);
         });
@@ -660,6 +646,7 @@
                     saveSnapTargetBeforeMinimized(saveTarget);
                 }
             }
+            notifySplitScreenBoundsChanged();
         };
         anim.addListener(new AnimatorListenerAdapter() {
 
@@ -692,6 +679,25 @@
         return anim;
     }
 
+    private void notifySplitScreenBoundsChanged() {
+        mOtherTaskRect.set(mSplitLayout.mSecondary);
+
+        mTmpRect.set(mSplitLayout.mDisplayLayout.stableInsets());
+        switch (mSplitLayout.getPrimarySplitSide()) {
+            case WindowManager.DOCKED_LEFT:
+                mTmpRect.left = 0;
+                break;
+            case WindowManager.DOCKED_RIGHT:
+                mTmpRect.right = 0;
+                break;
+            case WindowManager.DOCKED_TOP:
+                mTmpRect.top = 0;
+                break;
+        }
+        Dependency.get(OverviewProxyService.class)
+                .notifySplitScreenBoundsChanged(mOtherTaskRect, mTmpRect);
+    }
+
     private void cancelFlingAnimation() {
         if (mCurrentAnimator != null) {
             mCurrentAnimator.cancel();
@@ -825,8 +831,7 @@
             mDockedStackMinimized = minimized;
             if (mSplitLayout.mDisplayLayout.rotation() != mDefaultDisplay.getRotation()) {
                 // Splitscreen to minimize is about to starts after rotating landscape to seascape,
-                // update insets, display info and snap algorithm targets
-                WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
+                // update display info and snap algorithm targets
                 repositionSnapTargetBeforeMinimized();
             }
             if (mIsInMinimizeInteraction != minimized || mCurrentAnimator != null) {
@@ -1084,6 +1089,10 @@
                 t.setPosition(dividerCtrl, mDividerPositionX - mDividerInsets, 0);
             }
         }
+        if (getViewRootImpl() != null) {
+            mHandler.removeCallbacks(mUpdateEmbeddedMatrix);
+            mHandler.post(mUpdateEmbeddedMatrix);
+        }
     }
 
     void setResizeDimLayer(Transaction t, boolean primary, float alpha) {
@@ -1124,7 +1133,7 @@
 
             // Move a right-docked-app to line up with the divider while dragging it
             if (mDockSide == DOCKED_RIGHT) {
-                mDockedTaskRect.offset(Math.max(position, mStableInsets.left - mDividerSize)
+                mDockedTaskRect.offset(Math.max(position, -mDividerSize)
                         - mDockedTaskRect.left + mDividerSize, 0);
             }
             resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect,
@@ -1139,7 +1148,7 @@
 
             // Move a docked app if from the right in position with the divider up to insets
             if (mDockSide == DOCKED_RIGHT) {
-                mDockedTaskRect.offset(Math.max(position, mStableInsets.left - mDividerSize)
+                mDockedTaskRect.offset(Math.max(position, -mDividerSize)
                         - mDockedTaskRect.left + mDividerSize, 0);
             }
             calculateBoundsForPosition(taskPosition, DockedDividerUtils.invertDockSide(mDockSide),
@@ -1155,7 +1164,7 @@
 
             // Move a right-docked-app to line up with the divider while dragging it
             if (mDockSide == DOCKED_RIGHT) {
-                mDockedTaskRect.offset(position - mStableInsets.left + mDividerSize, 0);
+                mDockedTaskRect.offset(position + mDividerSize, 0);
             }
             resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect);
         } else if (taskPosition != TASK_POSITION_SAME) {
@@ -1213,34 +1222,10 @@
         float fraction = getSnapAlgorithm().calculateDismissingFraction(position);
         fraction = Math.max(0, Math.min(fraction, 1f));
         fraction = DIM_INTERPOLATOR.getInterpolation(fraction);
-        if (hasInsetsAtDismissTarget(dismissTarget)) {
-
-            // Less darkening with system insets.
-            fraction *= 0.8f;
-        }
         return fraction;
     }
 
     /**
-     * @return true if and only if there are system insets at the location of the dismiss target
-     */
-    private boolean hasInsetsAtDismissTarget(SnapTarget dismissTarget) {
-        if (isHorizontalDivision()) {
-            if (dismissTarget == getSnapAlgorithm().getDismissStartTarget()) {
-                return mStableInsets.top != 0;
-            } else {
-                return mStableInsets.bottom != 0;
-            }
-        } else {
-            if (dismissTarget == getSnapAlgorithm().getDismissStartTarget()) {
-                return mStableInsets.left != 0;
-            } else {
-                return mStableInsets.right != 0;
-            }
-        }
-    }
-
-    /**
      * When the snap target is dismissing one side, make sure that the dismissing side doesn't get
      * 0 size.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
index 2862c83..c496d22 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
@@ -193,7 +193,7 @@
                 Log.d(TAG, " at-least one split empty " + mPrimary.topActivityType
                         + "  " + mSecondary.topActivityType);
             }
-            if (mDivider.inSplitMode()) {
+            if (mDivider.isDividerVisible()) {
                 // Was in split-mode, which means we are leaving split, so continue that.
                 // This happens when the stack in the primary-split is dismissed.
                 if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt
new file mode 100644
index 0000000..7f7ff9cf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar
+
+import android.app.PendingIntent
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.dagger.NotifInteractionLog
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import javax.inject.Inject
+
+/**
+ * Logger class for events related to the user clicking on notification actions
+ */
+class ActionClickLogger @Inject constructor(
+    @NotifInteractionLog private val buffer: LogBuffer
+) {
+    fun logInitialClick(
+        entry: NotificationEntry?,
+        pendingIntent: PendingIntent
+    ) {
+        buffer.log(TAG, LogLevel.DEBUG, {
+            str1 = entry?.key
+            str2 = entry?.ranking?.channel?.id
+            str3 = pendingIntent.intent.toString()
+        }, {
+            "ACTION CLICK $str1 (channel=$str2) for pending intent $str3"
+        })
+    }
+
+    fun logRemoteInputWasHandled(
+        entry: NotificationEntry?
+    ) {
+        buffer.log(TAG, LogLevel.DEBUG, {
+            str1 = entry?.key
+        }, {
+            "  [Action click] Triggered remote input (for $str1))"
+        })
+    }
+
+    fun logStartingIntentWithDefaultHandler(
+        entry: NotificationEntry?,
+        pendingIntent: PendingIntent
+    ) {
+        buffer.log(TAG, LogLevel.DEBUG, {
+            str1 = entry?.key
+            str2 = pendingIntent.intent.toString()
+        }, {
+            "  [Action click] Launching intent $str2 via default handler (for $str1)"
+        })
+    }
+
+    fun logWaitingToCloseKeyguard(
+        pendingIntent: PendingIntent
+    ) {
+        buffer.log(TAG, LogLevel.DEBUG, {
+            str1 = pendingIntent.intent.toString()
+        }, {
+            "  [Action click] Intent $str1 launches an activity, dismissing keyguard first..."
+        })
+    }
+
+    fun logKeyguardGone(
+        pendingIntent: PendingIntent
+    ) {
+        buffer.log(TAG, LogLevel.DEBUG, {
+            str1 = pendingIntent.intent.toString()
+        }, {
+            "  [Action click] Keyguard dismissed, calling default handler for intent $str1"
+        })
+    }
+}
+
+private const val TAG = "ActionClickLogger"
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt
new file mode 100644
index 0000000..8248fc9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt
@@ -0,0 +1,87 @@
+package com.android.systemui.statusbar
+
+import android.app.Notification
+import android.os.RemoteException
+import com.android.internal.statusbar.IStatusBarService
+import com.android.internal.statusbar.NotificationVisibility
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.util.Assert
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * Class to shim calls to IStatusBarManager#onNotificationClick/#onNotificationActionClick that
+ * allow an in-process notification to go out (e.g., for tracking interactions) as well as
+ * sending the messages along to system server.
+ *
+ * NOTE: this class eats exceptions from system server, as no current client of these APIs cares
+ * about errors
+ */
+@Singleton
+public class NotificationClickNotifier @Inject constructor(
+    val barService: IStatusBarService,
+    @Main val mainExecutor: Executor
+) {
+    val listeners = mutableListOf<NotificationInteractionListener>()
+
+    fun addNotificationInteractionListener(listener: NotificationInteractionListener) {
+        Assert.isMainThread()
+        listeners.add(listener)
+    }
+
+    fun removeNotificationInteractionListener(listener: NotificationInteractionListener) {
+        Assert.isMainThread()
+        listeners.remove(listener)
+    }
+
+    private fun notifyListenersAboutInteraction(key: String) {
+        for (l in listeners) {
+            l.onNotificationInteraction(key)
+        }
+    }
+
+    fun onNotificationActionClick(
+        key: String,
+        actionIndex: Int,
+        action: Notification.Action,
+        visibility: NotificationVisibility,
+        generatedByAssistant: Boolean
+    ) {
+        try {
+            barService.onNotificationActionClick(
+                    key, actionIndex, action, visibility, generatedByAssistant)
+        } catch (e: RemoteException) {
+            // nothing
+        }
+
+        mainExecutor.execute {
+            notifyListenersAboutInteraction(key)
+        }
+    }
+
+    fun onNotificationClick(
+        key: String,
+        visibility: NotificationVisibility
+    ) {
+        try {
+            barService.onNotificationClick(key, visibility)
+        } catch (e: RemoteException) {
+            // nothing
+        }
+
+        mainExecutor.execute {
+            notifyListenersAboutInteraction(key)
+        }
+    }
+}
+
+/**
+ * Interface for listeners to get notified when a notification is interacted with via a click or
+ * interaction with remote input or actions
+ */
+interface NotificationInteractionListener {
+    fun onNotificationInteraction(key: String)
+}
+
+private const val TAG = "NotificationClickNotifier"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
new file mode 100644
index 0000000..2ed04eb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
@@ -0,0 +1,40 @@
+package com.android.systemui.statusbar
+
+import com.android.systemui.statusbar.notification.NotificationEntryManager
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * Class to track user interaction with notifications. It's a glorified map of key : bool that can
+ * merge multiple "user interacted with notification" signals into a single place.
+ */
+@Singleton
+class NotificationInteractionTracker @Inject constructor(
+    private val clicker: NotificationClickNotifier,
+    private val entryManager: NotificationEntryManager
+) : NotifCollectionListener, NotificationInteractionListener {
+    private val interactions = mutableMapOf<String, Boolean>()
+
+    init {
+        clicker.addNotificationInteractionListener(this)
+        entryManager.addCollectionListener(this)
+    }
+
+    fun hasUserInteractedWith(key: String): Boolean = key in interactions
+
+    override fun onEntryAdded(entry: NotificationEntry) {
+        interactions[entry.key] = false
+    }
+
+    override fun onEntryCleanUp(entry: NotificationEntry) {
+        interactions.remove(entry.key)
+    }
+
+    override fun onNotificationInteraction(key: String) {
+        interactions[key] = true
+    }
+}
+
+private const val TAG = "NotificationInteractionTracker"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 2647c04..03424c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -19,8 +19,8 @@
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
 
 import static com.android.systemui.DejankUtils.whitelistIpcs;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_MEDIA_CONTROLS;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_MEDIA_CONTROLS;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
 
 import android.app.ActivityManager;
 import android.app.KeyguardManager;
@@ -35,7 +35,6 @@
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.os.Handler;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -43,7 +42,6 @@
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 
-import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
@@ -92,9 +90,9 @@
     private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
     private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
     private final UserManager mUserManager;
-    private final IStatusBarService mBarService;
     private final List<UserChangedListener> mListeners = new ArrayList<>();
     private final BroadcastDispatcher mBroadcastDispatcher;
+    private final NotificationClickNotifier mClickNotifier;
 
     private boolean mShowLockscreenNotifications;
     private boolean mAllowLockscreenRemoteInput;
@@ -170,11 +168,7 @@
                         final NotificationVisibility nv = NotificationVisibility.obtain(
                                 notificationKey,
                                 rank, count, true, location);
-                        try {
-                            mBarService.onNotificationClick(notificationKey, nv);
-                        } catch (RemoteException exception) {
-                            /* ignore */
-                        }
+                        mClickNotifier.onNotificationClick(notificationKey, nv);
                     }
                     break;
             }
@@ -203,7 +197,7 @@
             BroadcastDispatcher broadcastDispatcher,
             DevicePolicyManager devicePolicyManager,
             UserManager userManager,
-            IStatusBarService iStatusBarService,
+            NotificationClickNotifier clickNotifier,
             KeyguardManager keyguardManager,
             StatusBarStateController statusBarStateController,
             @Main Handler mainHandler,
@@ -214,7 +208,7 @@
         mDevicePolicyManager = devicePolicyManager;
         mUserManager = userManager;
         mCurrentUserId = ActivityManager.getCurrentUser();
-        mBarService = iStatusBarService;
+        mClickNotifier = clickNotifier;
         statusBarStateController.addCallback(this);
         mLockPatternUtils = new LockPatternUtils(context);
         mKeyguardManager = keyguardManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index e32d174..8ed69d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -16,6 +16,7 @@
 package com.android.systemui.statusbar;
 
 import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
+import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON;
 import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_MEDIA_FAKE_ARTWORK;
 import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_LOCKSCREEN_WALLPAPER;
 import static com.android.systemui.statusbar.phone.StatusBar.SHOW_LOCKSCREEN_MEDIA_ARTWORK;
@@ -46,12 +47,13 @@
 
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.internal.statusbar.NotificationVisibility;
-import com.android.keyguard.KeyguardMediaPlayer;
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.Interpolators;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.media.MediaDataManager;
+import com.android.systemui.media.MediaDeviceManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.dagger.StatusBarModule;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
@@ -67,6 +69,7 @@
 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;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -76,7 +79,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
 
 import dagger.Lazy;
 
@@ -87,6 +90,7 @@
 public class NotificationMediaManager implements Dumpable {
     private static final String TAG = "NotificationMediaManager";
     public static final boolean DEBUG_MEDIA = false;
+    private static final long PAUSED_MEDIA_TIMEOUT = TimeUnit.MINUTES.toMillis(10);
 
     private final StatusBarStateController mStatusBarStateController
             = Dependency.get(StatusBarStateController.class);
@@ -103,6 +107,7 @@
     }
 
     private final NotificationEntryManager mEntryManager;
+    private final MediaDataManager mMediaDataManager;
 
     @Nullable
     private Lazy<NotificationShadeWindowController> mNotificationShadeWindowController;
@@ -113,9 +118,8 @@
     private ScrimController mScrimController;
     @Nullable
     private LockscreenWallpaper mLockscreenWallpaper;
-    private final KeyguardMediaPlayer mMediaPlayer;
 
-    private final Executor mMainExecutor;
+    private final DelayableExecutor mMainExecutor;
 
     private final Context mContext;
     private final MediaSessionManager mMediaSessionManager;
@@ -128,6 +132,7 @@
     private MediaController mMediaController;
     private String mMediaNotificationKey;
     private MediaMetadata mMediaMetadata;
+    private Runnable mMediaTimeoutCancellation;
 
     private BackDropView mBackdrop;
     private ImageView mBackdropFront;
@@ -157,11 +162,36 @@
             if (DEBUG_MEDIA) {
                 Log.v(TAG, "DEBUG_MEDIA: onPlaybackStateChanged: " + state);
             }
+            if (mMediaTimeoutCancellation != null) {
+                mMediaTimeoutCancellation.run();
+                mMediaTimeoutCancellation = null;
+            }
             if (state != null) {
                 if (!isPlaybackActive(state.getState())) {
                     clearCurrentMediaNotification();
                 }
                 findAndUpdateMediaNotifications();
+                scheduleMediaTimeout(state);
+            }
+        }
+
+        private void scheduleMediaTimeout(PlaybackState state) {
+            final NotificationEntry entry;
+            synchronized (mEntryManager) {
+                entry = mEntryManager.getActiveNotificationUnfiltered(mMediaNotificationKey);
+            }
+            if (entry != null) {
+                if (!isPlayingState(state.getState())) {
+                    mMediaTimeoutCancellation = mMainExecutor.executeDelayed(() -> {
+                        synchronized (mEntryManager) {
+                            if (mMediaNotificationKey == null) {
+                                return;
+                            }
+                            mEntryManager.removeNotification(mMediaNotificationKey, null,
+                                    UNDEFINED_DISMISS_REASON);
+                        }
+                    }, PAUSED_MEDIA_TIMEOUT);
+                }
             }
         }
 
@@ -187,13 +217,13 @@
             NotificationEntryManager notificationEntryManager,
             MediaArtworkProcessor mediaArtworkProcessor,
             KeyguardBypassController keyguardBypassController,
-            KeyguardMediaPlayer keyguardMediaPlayer,
-            @Main Executor mainExecutor,
-            DeviceConfigProxy deviceConfig) {
+            @Main DelayableExecutor mainExecutor,
+            DeviceConfigProxy deviceConfig,
+            MediaDataManager mediaDataManager,
+            MediaDeviceManager mediaDeviceManager) {
         mContext = context;
         mMediaArtworkProcessor = mediaArtworkProcessor;
         mKeyguardBypassController = keyguardBypassController;
-        mMediaPlayer = keyguardMediaPlayer;
         mMediaListeners = new ArrayList<>();
         // TODO: use MediaSessionManager.SessionListener to hook us up to future updates
         // in session state
@@ -204,14 +234,29 @@
         mNotificationShadeWindowController = notificationShadeWindowController;
         mEntryManager = notificationEntryManager;
         mMainExecutor = mainExecutor;
+        mMediaDataManager = mediaDataManager;
+
         notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
+
             @Override
             public void onPendingEntryAdded(NotificationEntry entry) {
-                findAndUpdateMediaNotifications();
+                mediaDataManager.onNotificationAdded(entry.getKey(), entry.getSbn());
+                mediaDeviceManager.onNotificationAdded(entry.getKey(), entry.getSbn());
             }
 
             @Override
             public void onPreEntryUpdated(NotificationEntry entry) {
+                mediaDataManager.onNotificationAdded(entry.getKey(), entry.getSbn());
+                mediaDeviceManager.onNotificationAdded(entry.getKey(), entry.getSbn());
+            }
+
+            @Override
+            public void onEntryInflated(NotificationEntry entry) {
+                findAndUpdateMediaNotifications();
+            }
+
+            @Override
+            public void onEntryReinflated(NotificationEntry entry) {
                 findAndUpdateMediaNotifications();
             }
 
@@ -222,6 +267,8 @@
                     boolean removedByUser,
                     int reason) {
                 onNotificationRemoved(entry.getKey());
+                mediaDataManager.onNotificationRemoved(entry.getKey());
+                mediaDeviceManager.onNotificationRemoved(entry.getKey());
             }
         });
 
@@ -278,7 +325,7 @@
 
     public void addCallback(MediaListener callback) {
         mMediaListeners.add(callback);
-        callback.onMetadataOrStateChanged(mMediaMetadata,
+        callback.onPrimaryMetadataOrStateChanged(mMediaMetadata,
                 getMediaControllerPlaybackState(mMediaController));
     }
 
@@ -392,7 +439,7 @@
         @PlaybackState.State int state = getMediaControllerPlaybackState(mMediaController);
         ArrayList<MediaListener> callbacks = new ArrayList<>(mMediaListeners);
         for (int i = 0; i < callbacks.size(); i++) {
-            callbacks.get(i).onMetadataOrStateChanged(mMediaMetadata, state);
+            callbacks.get(i).onPrimaryMetadataOrStateChanged(mMediaMetadata, state);
         }
     }
 
@@ -473,7 +520,6 @@
             && mBiometricUnlockController.isWakeAndUnlock();
         if (mKeyguardStateController.isLaunchTransitionFadingAway() || wakeAndUnlock) {
             mBackdrop.setVisibility(View.INVISIBLE);
-            mMediaPlayer.clearControls();
             Trace.endSection();
             return;
         }
@@ -496,14 +542,6 @@
             }
         }
 
-        NotificationEntry entry = mEntryManager
-                .getActiveNotificationUnfiltered(mMediaNotificationKey);
-        if (entry != null) {
-            mMediaPlayer.updateControls(entry, getMediaIcon(), mediaMetadata);
-        } else {
-            mMediaPlayer.clearControls();
-        }
-
         // Process artwork on a background thread and send the resulting bitmap to
         // finishUpdateMediaMetaData.
         if (metaDataChanged) {
@@ -626,7 +664,6 @@
                     // We are unlocking directly - no animation!
                     mBackdrop.setVisibility(View.GONE);
                     mBackdropBack.setImageDrawable(null);
-                    mMediaPlayer.clearControls();
                     if (windowController != null) {
                         windowController.setBackdropShowing(false);
                     }
@@ -643,7 +680,6 @@
                                 mBackdrop.setVisibility(View.GONE);
                                 mBackdropFront.animate().cancel();
                                 mBackdropBack.setImageDrawable(null);
-                                mMediaPlayer.clearControls();
                                 mMainExecutor.execute(mHideBackdropFront);
                             });
                     if (mKeyguardStateController.isKeyguardFadingAway()) {
@@ -750,6 +786,7 @@
          * @param state Current playback state
          * @see PlaybackState.State
          */
-        void onMetadataOrStateChanged(MediaMetadata metadata, @PlaybackState.State int state);
+        default void onPrimaryMetadataOrStateChanged(MediaMetadata metadata,
+                @PlaybackState.State int state) {}
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
index 3cb2a2a..1079f10 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
@@ -52,7 +52,7 @@
     /**
      * Updates the visual representation of the notifications.
      */
-    void updateNotificationViews();
+    void updateNotificationViews(String reason);
 
     /**
      * Returns the maximum number of notifications to show while locked.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index bf28040..710ac9e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -28,6 +28,7 @@
 import android.app.RemoteInputHistoryItem;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.UserInfo;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.RemoteException;
@@ -54,7 +55,7 @@
 import com.android.systemui.R;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.dagger.StatusBarModule;
+import com.android.systemui.statusbar.dagger.StatusBarDependenciesModule;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -114,6 +115,7 @@
     private final SmartReplyController mSmartReplyController;
     private final NotificationEntryManager mEntryManager;
     private final Handler mMainHandler;
+    private final ActionClickLogger mLogger;
 
     private final Lazy<StatusBar> mStatusBarLazy;
 
@@ -122,6 +124,7 @@
     private final KeyguardManager mKeyguardManager;
     private final StatusBarStateController mStatusBarStateController;
     private final RemoteInputUriController mRemoteInputUriController;
+    private final NotificationClickNotifier mClickNotifier;
 
     protected RemoteInputController mRemoteInputController;
     protected NotificationLifetimeExtender.NotificationSafeToRemoveCallback
@@ -138,14 +141,18 @@
             mStatusBarLazy.get().wakeUpIfDozing(SystemClock.uptimeMillis(), view,
                     "NOTIFICATION_CLICK");
 
+            final NotificationEntry entry = getNotificationForParent(view.getParent());
+            mLogger.logInitialClick(entry, pendingIntent);
+
             if (handleRemoteInput(view, pendingIntent)) {
+                mLogger.logRemoteInputWasHandled(entry);
                 return true;
             }
 
             if (DEBUG) {
                 Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent);
             }
-            logActionClick(view, pendingIntent);
+            logActionClick(view, entry, pendingIntent);
             // The intent we are sending is for the application, which
             // won't have permission to immediately start an activity after
             // the user switches to home.  We know it is safe to do at this
@@ -158,11 +165,15 @@
                 Pair<Intent, ActivityOptions> options = response.getLaunchOptions(view);
                 options.second.setLaunchWindowingMode(
                         WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
+                mLogger.logStartingIntentWithDefaultHandler(entry, pendingIntent);
                 return RemoteViews.startPendingIntent(view, pendingIntent, options);
             });
         }
 
-        private void logActionClick(View view, PendingIntent actionIntent) {
+        private void logActionClick(
+                View view,
+                NotificationEntry entry,
+                PendingIntent actionIntent) {
             Integer actionIndex = (Integer)
                     view.getTag(com.android.internal.R.id.notification_action_index_tag);
             if (actionIndex == null) {
@@ -170,7 +181,7 @@
                 return;
             }
             ViewParent parent = view.getParent();
-            StatusBarNotification statusBarNotification = getNotificationForParent(parent);
+            StatusBarNotification statusBarNotification = entry.getSbn();
             if (statusBarNotification == null) {
                 Log.w(TAG, "Couldn't determine notification for click.");
                 return;
@@ -205,17 +216,13 @@
                             mEntryManager.getActiveNotificationUnfiltered(key));
             final NotificationVisibility nv =
                     NotificationVisibility.obtain(key, rank, count, true, location);
-            try {
-                mBarService.onNotificationActionClick(key, buttonIndex, action, nv, false);
-            } catch (RemoteException e) {
-                // Ignore
-            }
+            mClickNotifier.onNotificationActionClick(key, buttonIndex, action, nv, false);
         }
 
-        private StatusBarNotification getNotificationForParent(ViewParent parent) {
+        private NotificationEntry getNotificationForParent(ViewParent parent) {
             while (parent != null) {
                 if (parent instanceof ExpandableNotificationRow) {
-                    return ((ExpandableNotificationRow) parent).getEntry().getSbn();
+                    return ((ExpandableNotificationRow) parent).getEntry();
                 }
                 parent = parent.getParent();
             }
@@ -255,7 +262,7 @@
     };
 
     /**
-     * Injected constructor. See {@link StatusBarModule}.
+     * Injected constructor. See {@link StatusBarDependenciesModule}.
      */
     public NotificationRemoteInputManager(
             Context context,
@@ -265,13 +272,16 @@
             Lazy<StatusBar> statusBarLazy,
             StatusBarStateController statusBarStateController,
             @Main Handler mainHandler,
-            RemoteInputUriController remoteInputUriController) {
+            RemoteInputUriController remoteInputUriController,
+            NotificationClickNotifier clickNotifier,
+            ActionClickLogger logger) {
         mContext = context;
         mLockscreenUserManager = lockscreenUserManager;
         mSmartReplyController = smartReplyController;
         mEntryManager = notificationEntryManager;
         mStatusBarLazy = statusBarLazy;
         mMainHandler = mainHandler;
+        mLogger = logger;
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
@@ -279,6 +289,7 @@
         mKeyguardManager = context.getSystemService(KeyguardManager.class);
         mStatusBarStateController = statusBarStateController;
         mRemoteInputUriController = remoteInputUriController;
+        mClickNotifier = clickNotifier;
 
         notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
             @Override
@@ -390,15 +401,35 @@
 
         if (!mLockscreenUserManager.shouldAllowLockscreenRemoteInput()) {
             final int userId = pendingIntent.getCreatorUserHandle().getIdentifier();
+
+            final boolean isLockedManagedProfile =
+                    mUserManager.getUserInfo(userId).isManagedProfile()
+                    && mKeyguardManager.isDeviceLocked(userId);
+
+            final boolean isParentUserLocked;
+            if (isLockedManagedProfile) {
+                final UserInfo profileParent = mUserManager.getProfileParent(userId);
+                isParentUserLocked = (profileParent != null)
+                        && mKeyguardManager.isDeviceLocked(profileParent.id);
+            } else {
+                isParentUserLocked = false;
+            }
+
             if (mLockscreenUserManager.isLockscreenPublicMode(userId)
                     || mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
-                // Even if we don't have security we should go through this flow, otherwise we won't
-                // go to the shade
-                mCallback.onLockedRemoteInput(row, view);
+                // If the parent user is no longer locked, and the user to which the remote input
+                // is destined is a locked, managed profile, then onLockedWorkRemoteInput should be
+                // called to unlock it.
+                if (isLockedManagedProfile && !isParentUserLocked) {
+                    mCallback.onLockedWorkRemoteInput(userId, row, view);
+                } else {
+                    // Even if we don't have security we should go through this flow, otherwise
+                    // we won't go to the shade.
+                    mCallback.onLockedRemoteInput(row, view);
+                }
                 return true;
             }
-            if (mUserManager.getUserInfo(userId).isManagedProfile()
-                    && mKeyguardManager.isDeviceLocked(userId)) {
+            if (isLockedManagedProfile) {
                 mCallback.onLockedWorkRemoteInput(userId, row, view);
                 return true;
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 7aae724..d3819e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -37,6 +37,7 @@
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator
 import com.android.systemui.statusbar.phone.BiometricUnlockController
 import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK
+import com.android.systemui.statusbar.phone.DozeParameters
 import com.android.systemui.statusbar.phone.NotificationShadeWindowController
 import com.android.systemui.statusbar.phone.PanelExpansionListener
 import com.android.systemui.statusbar.phone.ScrimController
@@ -60,6 +61,7 @@
     private val choreographer: Choreographer,
     private val wallpaperManager: WallpaperManager,
     private val notificationShadeWindowController: NotificationShadeWindowController,
+    private val dozeParameters: DozeParameters,
     dumpManager: DumpManager
 ) : PanelExpansionListener, Dumpable {
     companion object {
@@ -206,9 +208,12 @@
 
             keyguardAnimator?.cancel()
             keyguardAnimator = ValueAnimator.ofFloat(1f, 0f).apply {
-                duration = keyguardStateController.keyguardFadingAwayDuration
+                // keyguardStateController.keyguardFadingAwayDuration might be zero when unlock by
+                // fingerprint due to there is no window container, see AppTransition#goodToGo.
+                // We use DozeParameters.wallpaperFadeOutDuration as an alternative.
+                duration = dozeParameters.wallpaperFadeOutDuration
                 startDelay = keyguardStateController.keyguardFadingAwayDelay
-                interpolator = Interpolators.DECELERATE_QUINT
+                interpolator = Interpolators.FAST_OUT_SLOW_IN
                 addUpdateListener { animation: ValueAnimator ->
                     wakeAndUnlockBlurRadius =
                             blurUtils.blurRadiusOfRatio(animation.animatedValue as Float)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index e7f2618..3dda15b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -186,8 +186,7 @@
 
             boolean groupChangesAllowed =
                     mVisualStabilityManager.areGroupChangesAllowed() // user isn't looking at notifs
-                    || !ent.hasFinishedInitialization() // notif recently added
-                    || !mListContainer.containsView(ent.getRow()); // notif recently unfiltered
+                    || !ent.hasFinishedInitialization(); // notif recently added
 
             NotificationEntry parent = mGroupManager.getGroupSummary(ent.getSbn());
             if (!groupChangesAllowed) {
@@ -195,13 +194,15 @@
                 boolean wasChildInGroup = ent.isChildInGroup();
                 if (isChildInGroup && !wasChildInGroup) {
                     isChildInGroup = wasChildInGroup;
-                    mVisualStabilityManager.addGroupChangesAllowedCallback(mEntryManager);
+                    mVisualStabilityManager.addGroupChangesAllowedCallback(mEntryManager,
+                            false /* persistent */);
                 } else if (!isChildInGroup && wasChildInGroup) {
                     // We allow grouping changes if the group was collapsed
                     if (mGroupManager.isLogicalGroupExpanded(ent.getSbn())) {
                         isChildInGroup = wasChildInGroup;
                         parent = ent.getRow().getNotificationParent().getEntry();
-                        mVisualStabilityManager.addGroupChangesAllowedCallback(mEntryManager);
+                        mVisualStabilityManager.addGroupChangesAllowedCallback(mEntryManager,
+                                false /* persistent */);
                     }
                 }
             }
@@ -286,7 +287,8 @@
                 if (mVisualStabilityManager.canReorderNotification(targetChild)) {
                     mListContainer.changeViewPosition(targetChild, i);
                 } else {
-                    mVisualStabilityManager.addReorderingAllowedCallback(mEntryManager);
+                    mVisualStabilityManager.addReorderingAllowedCallback(mEntryManager,
+                            false  /* persistent */);
                 }
             }
             j++;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
index 02c98ae..6d2cc6b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -125,7 +125,7 @@
     }
 
     private fun canHandleMotionEvent(): Boolean {
-        return !wakeUpCoordinator.canShowPulsingHuns || qsExpanded || bouncerShowing
+        return wakeUpCoordinator.canShowPulsingHuns && !qsExpanded && !bouncerShowing
     }
 
     private fun startExpansion(event: MotionEvent): Boolean {
@@ -184,7 +184,6 @@
         if (!isExpanding || event.actionMasked == MotionEvent.ACTION_DOWN) {
             return startExpansion(event)
         }
-
         velocityTracker!!.addMovement(event)
         val y = event.y
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScreenRecordDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScreenRecordDrawable.java
index 44ef6b4..006b219 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ScreenRecordDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScreenRecordDrawable.java
@@ -39,10 +39,13 @@
  */
 public class ScreenRecordDrawable extends DrawableWrapper {
     private Drawable mFillDrawable;
+    private Drawable mIconDrawable;
     private int mHorizontalPadding;
     private int mLevel;
     private float mTextSize;
-    private float mIconRadius;
+    private int mIconRadius;
+    private int mWidthPx;
+    private int mHeightPx;
     private Paint mPaint;
 
     /** No-arg constructor used by drawable inflation. */
@@ -57,6 +60,7 @@
         super.inflate(r, parser, attrs, theme);
         setDrawable(r.getDrawable(R.drawable.ic_screen_record_background, theme).mutate());
         mFillDrawable = r.getDrawable(R.drawable.ic_screen_record_background, theme).mutate();
+        mIconDrawable = r.getDrawable(R.drawable.ic_screenrecord, theme).mutate();
         mHorizontalPadding = r.getDimensionPixelSize(R.dimen.status_bar_horizontal_padding);
 
         mTextSize = r.getDimensionPixelSize(R.dimen.screenrecord_status_text_size);
@@ -68,6 +72,19 @@
         mPaint.setColor(Color.WHITE);
         mPaint.setTextSize(mTextSize);
         mPaint.setFakeBoldText(true);
+
+        mWidthPx = r.getDimensionPixelSize(R.dimen.screenrecord_status_icon_width);
+        mHeightPx = r.getDimensionPixelSize(R.dimen.screenrecord_status_icon_height);
+    }
+
+    @Override
+    public int getIntrinsicWidth() {
+        return mWidthPx;
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        return mHeightPx;
     }
 
     @Override
@@ -103,10 +120,14 @@
             String val = String.valueOf(mLevel);
             Rect textBounds = new Rect();
             mPaint.getTextBounds(val, 0, val.length(), textBounds);
-            float yOffset = textBounds.height() / 4; // half, and half again since it's centered
-            canvas.drawText(val, b.centerX(), b.centerY() + yOffset, mPaint);
+            canvas.drawText(val, b.centerX(), b.centerY() + textBounds.height() / 2, mPaint);
         } else {
-            canvas.drawCircle(b.centerX(), b.centerY() - mIconRadius / 2, mIconRadius, mPaint);
+            Rect iconBounds = new Rect(b.centerX() - mIconRadius,
+                    b.centerY() - mIconRadius,
+                    b.centerX() + mIconRadius,
+                    b.centerY() + mIconRadius);
+            mIconDrawable.setBounds(iconBounds);
+            mIconDrawable.draw(canvas);
         }
     }
 
@@ -114,9 +135,6 @@
     public boolean getPadding(Rect padding) {
         padding.left += mHorizontalPadding;
         padding.right += mHorizontalPadding;
-        padding.top = 0;
-        padding.bottom = 0;
-        android.util.Log.d("ScreenRecordDrawable", "set zero top/bottom pad");
         return true;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
index bb96f42..7fc18b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
@@ -35,6 +35,7 @@
 public class SmartReplyController {
     private final IStatusBarService mBarService;
     private final NotificationEntryManager mEntryManager;
+    private final NotificationClickNotifier mClickNotifier;
     private Set<String> mSendingKeys = new ArraySet<>();
     private Callback mCallback;
 
@@ -42,9 +43,11 @@
      * Injected constructor. See {@link StatusBarModule}.
      */
     public SmartReplyController(NotificationEntryManager entryManager,
-            IStatusBarService statusBarService) {
+            IStatusBarService statusBarService,
+            NotificationClickNotifier clickNotifier) {
         mBarService = statusBarService;
         mEntryManager = entryManager;
+        mClickNotifier = clickNotifier;
     }
 
     public void setCallback(Callback callback) {
@@ -78,12 +81,8 @@
                 NotificationLogger.getNotificationLocation(entry);
         final NotificationVisibility nv = NotificationVisibility.obtain(
                 entry.getKey(), rank, count, true, location);
-        try {
-            mBarService.onNotificationActionClick(
-                    entry.getKey(), actionIndex, action, nv, generatedByAssistant);
-        } catch (RemoteException e) {
-            // Nothing to do, system going down
-        }
+        mClickNotifier.onNotificationActionClick(
+                entry.getKey(), actionIndex, action, nv, generatedByAssistant);
     }
 
     /**
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 de7e36d9..c988e12 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
@@ -21,12 +21,15 @@
 import android.os.Handler;
 
 import com.android.internal.statusbar.IStatusBarService;
-import com.android.keyguard.KeyguardMediaPlayer;
 import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.media.MediaDataManager;
+import com.android.systemui.media.MediaDeviceManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.ActionClickLogger;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.MediaArtworkProcessor;
+import com.android.systemui.statusbar.NotificationClickNotifier;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
@@ -46,6 +49,7 @@
 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 java.util.concurrent.Executor;
 
@@ -73,7 +77,9 @@
             Lazy<StatusBar> statusBarLazy,
             StatusBarStateController statusBarStateController,
             Handler mainHandler,
-            RemoteInputUriController remoteInputUriController) {
+            RemoteInputUriController remoteInputUriController,
+            NotificationClickNotifier clickNotifier,
+            ActionClickLogger actionClickLogger) {
         return new NotificationRemoteInputManager(
                 context,
                 lockscreenUserManager,
@@ -82,7 +88,9 @@
                 statusBarLazy,
                 statusBarStateController,
                 mainHandler,
-                remoteInputUriController);
+                remoteInputUriController,
+                clickNotifier,
+                actionClickLogger);
     }
 
     /** */
@@ -95,9 +103,10 @@
             NotificationEntryManager notificationEntryManager,
             MediaArtworkProcessor mediaArtworkProcessor,
             KeyguardBypassController keyguardBypassController,
-            KeyguardMediaPlayer keyguardMediaPlayer,
-            @Main Executor mainExecutor,
-            DeviceConfigProxy deviceConfigProxy) {
+            @Main DelayableExecutor mainExecutor,
+            DeviceConfigProxy deviceConfigProxy,
+            MediaDataManager mediaDataManager,
+            MediaDeviceManager mediaDeviceManager) {
         return new NotificationMediaManager(
                 context,
                 statusBarLazy,
@@ -105,9 +114,10 @@
                 notificationEntryManager,
                 mediaArtworkProcessor,
                 keyguardBypassController,
-                keyguardMediaPlayer,
                 mainExecutor,
-                deviceConfigProxy);
+                deviceConfigProxy,
+                mediaDataManager,
+                mediaDeviceManager);
     }
 
     /** */
@@ -125,8 +135,10 @@
     @Singleton
     @Provides
     static SmartReplyController provideSmartReplyController(
-            NotificationEntryManager entryManager, IStatusBarService statusBarService) {
-        return new SmartReplyController(entryManager, statusBarService);
+            NotificationEntryManager entryManager,
+            IStatusBarService statusBarService,
+            NotificationClickNotifier clickNotifier) {
+        return new SmartReplyController(entryManager, statusBarService, clickNotifier);
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AnimatableProperty.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AnimatableProperty.java
index 75b41ca..eee9cc6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AnimatableProperty.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AnimatableProperty.java
@@ -16,7 +16,9 @@
 
 package com.android.systemui.statusbar.notification;
 
+import android.graphics.drawable.Drawable;
 import android.util.FloatProperty;
+import android.util.Log;
 import android.util.Property;
 import android.view.View;
 
@@ -35,6 +37,100 @@
     public static final AnimatableProperty Y = AnimatableProperty.from(View.Y,
             R.id.y_animator_tag, R.id.y_animator_tag_start_value, R.id.y_animator_tag_end_value);
 
+    /**
+     * Similar to X, however this doesn't allow for any other modifications other than from this
+     * property. When using X, it's possible that the view is laid out during the animation,
+     * which could break the continuity
+     */
+    public static final AnimatableProperty ABSOLUTE_X = AnimatableProperty.from(
+            new FloatProperty<View>("ViewAbsoluteX") {
+                @Override
+                public void setValue(View view, float value) {
+                    view.setTag(R.id.absolute_x_current_value, value);
+                    View.X.set(view, value);
+                }
+
+                @Override
+                public Float get(View view) {
+                    Object tag = view.getTag(R.id.absolute_x_current_value);
+                    if (tag instanceof Float) {
+                        return (Float) tag;
+                    }
+                    return View.X.get(view);
+                }
+            },
+            R.id.absolute_x_animator_tag,
+            R.id.absolute_x_animator_start_tag,
+            R.id.absolute_x_animator_end_tag);
+
+    /**
+     * Similar to Y, however this doesn't allow for any other modifications other than from this
+     * property. When using X, it's possible that the view is laid out during the animation,
+     * which could break the continuity
+     */
+    public static final AnimatableProperty ABSOLUTE_Y = AnimatableProperty.from(
+            new FloatProperty<View>("ViewAbsoluteY") {
+                @Override
+                public void setValue(View view, float value) {
+                    view.setTag(R.id.absolute_y_current_value, value);
+                    View.Y.set(view, value);
+                }
+
+                @Override
+                public Float get(View view) {
+                    Object tag = view.getTag(R.id.absolute_y_current_value);
+                    if (tag instanceof Float) {
+                        return (Float) tag;
+                    }
+                    return View.Y.get(view);
+                }
+            },
+            R.id.absolute_y_animator_tag,
+            R.id.absolute_y_animator_start_tag,
+            R.id.absolute_y_animator_end_tag);
+
+    public static final AnimatableProperty WIDTH = AnimatableProperty.from(
+            new FloatProperty<View>("ViewWidth") {
+                @Override
+                public void setValue(View view, float value) {
+                    view.setTag(R.id.view_width_current_value, value);
+                    view.setRight((int) (view.getLeft() + value));
+                }
+
+                @Override
+                public Float get(View view) {
+                    Object tag = view.getTag(R.id.view_width_current_value);
+                    if (tag instanceof Float) {
+                        return (Float) tag;
+                    }
+                    return (float) view.getWidth();
+                }
+            },
+            R.id.view_width_animator_tag,
+            R.id.view_width_animator_start_tag,
+            R.id.view_width_animator_end_tag);
+
+    public static final AnimatableProperty HEIGHT = AnimatableProperty.from(
+            new FloatProperty<View>("ViewHeight") {
+                @Override
+                public void setValue(View view, float value) {
+                    view.setTag(R.id.view_height_current_value, value);
+                    view.setBottom((int) (view.getTop() + value));
+                }
+
+                @Override
+                public Float get(View view) {
+                    Object tag = view.getTag(R.id.view_height_current_value);
+                    if (tag instanceof Float) {
+                        return (Float) tag;
+                    }
+                    return (float) view.getHeight();
+                }
+            },
+            R.id.view_height_animator_tag,
+            R.id.view_height_animator_start_tag,
+            R.id.view_height_animator_end_tag);
+
     public abstract int getAnimationStartTag();
 
     public abstract int getAnimationEndTag();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
index 53ec570..fc6c2be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
@@ -45,8 +45,8 @@
                     Notification.MessagingStyle.CONVERSATION_TYPE_NORMAL
         entry.ranking.shortcutInfo?.let { shortcutInfo ->
             messagingStyle.shortcutIcon = launcherApps.getShortcutIcon(shortcutInfo)
-            shortcutInfo.shortLabel?.let { shortLabel ->
-                messagingStyle.conversationTitle = shortLabel
+            shortcutInfo.label?.let { label ->
+                messagingStyle.conversationTitle = label
             }
         }
         messagingStyle.unreadMessageCount =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationChannelHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationChannelHelper.java
index 1c2a00e..5794f73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationChannelHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationChannelHelper.java
@@ -67,14 +67,14 @@
         return channel;
     }
 
-    private static String getName(NotificationEntry entry) {
-        if (entry.getRanking().getShortcutInfo().getShortLabel() != null) {
-            return entry.getRanking().getShortcutInfo().getShortLabel().toString();
+    private static CharSequence getName(NotificationEntry entry) {
+        if (entry.getRanking().getShortcutInfo().getLabel() != null) {
+            return entry.getRanking().getShortcutInfo().getLabel().toString();
         }
         Bundle extras = entry.getSbn().getNotification().extras;
-        String nameString = extras.getString(Notification.EXTRA_CONVERSATION_TITLE);
+        CharSequence nameString = extras.getCharSequence(Notification.EXTRA_CONVERSATION_TITLE);
         if (TextUtils.isEmpty(nameString)) {
-            nameString = extras.getString(Notification.EXTRA_TITLE);
+            nameString = extras.getCharSequence(Notification.EXTRA_TITLE);
         }
         if (TextUtils.isEmpty(nameString)) {
             nameString = "fallback";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
index 2beceb2..97ae83e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
@@ -90,7 +90,7 @@
      * @param removedByUser true if the notification was removed by a user action
      */
     default void onEntryRemoved(
-            NotificationEntry entry,
+            @NonNull NotificationEntry entry,
             @Nullable NotificationVisibility visibility,
             boolean removedByUser,
             int reason) {
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 d251777..adb51a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -151,6 +151,16 @@
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("NotificationEntryManager state:");
+        pw.println("  mAllNotifications=");
+        if (mAllNotifications.size() == 0) {
+            pw.println("null");
+        } else {
+            int i = 0;
+            for (NotificationEntry entry : mAllNotifications) {
+                dumpEntry(pw, "  ", i, entry);
+                i++;
+            }
+        }
         pw.print("  mPendingNotifications=");
         if (mPendingNotifications.size() == 0) {
             pw.println("null");
@@ -350,8 +360,8 @@
     private final NotificationHandler mNotifListener = new NotificationHandler() {
         @Override
         public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
-            final boolean isUpdate = mActiveNotifications.containsKey(sbn.getKey());
-            if (isUpdate) {
+            final boolean isUpdateToInflatedNotif = mActiveNotifications.containsKey(sbn.getKey());
+            if (isUpdateToInflatedNotif) {
                 updateNotification(sbn, rankingMap);
             } else {
                 addNotification(sbn, rankingMap);
@@ -442,16 +452,12 @@
                 }
                 if (!lifetimeExtended) {
                     // At this point, we are guaranteed the notification will be removed
+                    abortExistingInflation(key, "removeNotification");
                     mAllNotifications.remove(pendingEntry);
+                    mLeakDetector.trackGarbage(pendingEntry);
                 }
             }
-        }
-
-        if (!lifetimeExtended) {
-            abortExistingInflation(key, "removeNotification");
-        }
-
-        if (entry != null) {
+        } else {
             // If a manager needs to keep the notification around for whatever reason, we
             // keep the notification
             boolean entryDismissed = entry.isRowDismissed();
@@ -469,6 +475,8 @@
 
             if (!lifetimeExtended) {
                 // At this point, we are guaranteed the notification will be removed
+                abortExistingInflation(key, "removeNotification");
+                mAllNotifications.remove(entry);
 
                 // Ensure any managers keeping the lifetime extended stop managing the entry
                 cancelLifetimeExtension(entry);
@@ -477,13 +485,10 @@
                     entry.removeRow();
                 }
 
-                mAllNotifications.remove(entry);
-
                 // Let's remove the children if this was a summary
                 handleGroupSummaryRemoved(key);
                 removeVisibleNotification(key);
                 updateNotifications("removeNotificationInternal");
-                mLeakDetector.trackGarbage(entry);
                 removedByUser |= entryDismissed;
 
                 mLogger.logNotifRemoved(entry.getKey(), removedByUser);
@@ -497,6 +502,7 @@
                 for (NotifCollectionListener listener : mNotifCollectionListeners) {
                     listener.onEntryCleanUp(entry);
                 }
+                mLeakDetector.trackGarbage(entry);
             }
         }
     }
@@ -556,21 +562,26 @@
         Ranking ranking = new Ranking();
         rankingMap.getRanking(key, ranking);
 
-        NotificationEntry entry = new NotificationEntry(
-                notification,
-                ranking,
-                mFgsFeatureController.isForegroundServiceDismissalEnabled(),
-                SystemClock.uptimeMillis());
+        NotificationEntry entry = mPendingNotifications.get(key);
+        if (entry != null) {
+            entry.setSbn(notification);
+        } else {
+            entry = new NotificationEntry(
+                    notification,
+                    ranking,
+                    mFgsFeatureController.isForegroundServiceDismissalEnabled(),
+                    SystemClock.uptimeMillis());
+            mAllNotifications.add(entry);
+            mLeakDetector.trackInstance(entry);
+
+            for (NotifCollectionListener listener : mNotifCollectionListeners) {
+                listener.onEntryInit(entry);
+            }
+        }
+
         for (NotifCollectionListener listener : mNotifCollectionListeners) {
             listener.onEntryBind(entry, notification);
         }
-        mAllNotifications.add(entry);
-
-        mLeakDetector.trackInstance(entry);
-
-        for (NotifCollectionListener listener : mNotifCollectionListeners) {
-            listener.onEntryInit(entry);
-        }
 
         // Construct the expanded view.
         if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
@@ -581,7 +592,6 @@
                             mInflationCallback);
         }
 
-        abortExistingInflation(key, "addNotification");
         mPendingNotifications.put(key, entry);
         mLogger.logNotifAdded(entry.getKey());
         for (NotificationEntryListener listener : mNotificationEntryListeners) {
@@ -674,7 +684,7 @@
     public void updateNotifications(String reason) {
         reapplyFilterAndSort(reason);
         if (mPresenter != null && !mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
-            mPresenter.updateNotificationViews();
+            mPresenter.updateNotificationViews(reason);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
index e2b01ff..ce6013f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
@@ -21,11 +21,12 @@
 
 import com.android.internal.annotations.VisibleForTesting
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NOTIFICATIONS_USE_PEOPLE_FILTERING
-import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
-import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_HEADS_UP
-import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_MEDIA_CONTROLS
-import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE
-import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT
+import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING
+import com.android.systemui.statusbar.notification.stack.BUCKET_FOREGROUND_SERVICE
+import com.android.systemui.statusbar.notification.stack.BUCKET_HEADS_UP
+import com.android.systemui.statusbar.notification.stack.BUCKET_MEDIA_CONTROLS
+import com.android.systemui.statusbar.notification.stack.BUCKET_PEOPLE
+import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
 import com.android.systemui.util.DeviceConfigProxy
 import com.android.systemui.util.Utils
 
@@ -52,12 +53,14 @@
     fun getNotificationBuckets(): IntArray {
         return when {
             isFilteringEnabled() && isMediaControlsEnabled() ->
-                intArrayOf(BUCKET_HEADS_UP, BUCKET_MEDIA_CONTROLS, BUCKET_PEOPLE, BUCKET_ALERTING,
-                    BUCKET_SILENT)
+                intArrayOf(BUCKET_HEADS_UP, BUCKET_FOREGROUND_SERVICE, BUCKET_MEDIA_CONTROLS,
+                        BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT)
             !isFilteringEnabled() && isMediaControlsEnabled() ->
-                intArrayOf(BUCKET_HEADS_UP, BUCKET_MEDIA_CONTROLS, BUCKET_ALERTING, BUCKET_SILENT)
+                intArrayOf(BUCKET_HEADS_UP, BUCKET_FOREGROUND_SERVICE, BUCKET_MEDIA_CONTROLS,
+                        BUCKET_ALERTING, BUCKET_SILENT)
             isFilteringEnabled() && !isMediaControlsEnabled() ->
-                intArrayOf(BUCKET_HEADS_UP, BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT)
+                intArrayOf(BUCKET_HEADS_UP, BUCKET_FOREGROUND_SERVICE, BUCKET_PEOPLE,
+                        BUCKET_ALERTING, BUCKET_SILENT)
             NotificationUtils.useNewInterruptionModel(context) ->
                 intArrayOf(BUCKET_ALERTING, BUCKET_SILENT)
             else ->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
index 1f9d3af..3517e24 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
@@ -34,13 +34,20 @@
  */
 public class PropertyAnimator {
 
+    /**
+     * Set a property on a view, updating its value, even if it's already animating.
+     * The @param animated can be used to request an animation.
+     * If the view isn't animated, this utility will update the current animation if existent,
+     * such that the end value will point to @param newEndValue or apply it directly if there's
+     * no animation.
+     */
     public static <T extends View> void setProperty(final T view,
             AnimatableProperty animatableProperty, float newEndValue,
             AnimationProperties properties, boolean animated) {
         int animatorTag = animatableProperty.getAnimatorTag();
         ValueAnimator previousAnimator = ViewState.getChildTag(view, animatorTag);
         if (previousAnimator != null || animated) {
-            startAnimation(view, animatableProperty, newEndValue, properties);
+            startAnimation(view, animatableProperty, newEndValue, animated ? properties : null);
         } else {
             // no new animation needed, let's just apply the value
             animatableProperty.getProperty().set(view, newEndValue);
@@ -60,8 +67,8 @@
         }
         int animatorTag = animatableProperty.getAnimatorTag();
         ValueAnimator previousAnimator = ViewState.getChildTag(view, animatorTag);
-        AnimationFilter filter = properties.getAnimationFilter();
-        if (!filter.shouldAnimateProperty(property)) {
+        AnimationFilter filter = properties != null ? properties.getAnimationFilter() : null;
+        if (filter == null || !filter.shouldAnimateProperty(property)) {
             // just a local update was performed
             if (previousAnimator != null) {
                 // we need to increase all animation keyframes of the previous animator by the
@@ -82,6 +89,17 @@
         }
 
         Float currentValue = property.get(view);
+        AnimatorListenerAdapter listener = properties.getAnimationFinishListener(property);
+        if (currentValue.equals(newEndValue)) {
+            // Skip the animation!
+            if (previousAnimator != null) {
+                previousAnimator.cancel();
+            }
+            if (listener != null) {
+                listener.onAnimationEnd(null);
+            }
+            return;
+        }
         ValueAnimator animator = ValueAnimator.ofFloat(currentValue, newEndValue);
         animator.addUpdateListener(
                 animation -> property.set(view, (Float) animation.getAnimatedValue()));
@@ -96,7 +114,6 @@
                 || previousAnimator.getAnimatedFraction() == 0)) {
             animator.setStartDelay(properties.delay);
         }
-        AnimatorListenerAdapter listener = properties.getAnimationFinishListener(property);
         if (listener != null) {
             animator.addListener(listener);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
index 7ac5995..8341c02 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
@@ -43,7 +43,9 @@
     private static final long TEMPORARY_REORDERING_ALLOWED_DURATION = 1000;
 
     private final ArrayList<Callback> mReorderingAllowedCallbacks = new ArrayList<>();
+    private final ArraySet<Callback> mPersistentReorderingCallbacks = new ArraySet<>();
     private final ArrayList<Callback> mGroupChangesAllowedCallbacks = new ArrayList<>();
+    private final ArraySet<Callback> mPersistentGroupCallbacks = new ArraySet<>();
     private final Handler mHandler;
 
     private boolean mPanelExpanded;
@@ -85,8 +87,15 @@
 
     /**
      * Add a callback to invoke when reordering is allowed again.
+     *
+     * @param callback the callback to add
+     * @param persistent {@code true} if this callback should this callback be persisted, otherwise
+     *                               it will be removed after a single invocation
      */
-    public void addReorderingAllowedCallback(Callback callback) {
+    public void addReorderingAllowedCallback(Callback callback, boolean persistent) {
+        if (persistent) {
+            mPersistentReorderingCallbacks.add(callback);
+        }
         if (mReorderingAllowedCallbacks.contains(callback)) {
             return;
         }
@@ -95,8 +104,15 @@
 
     /**
      * Add a callback to invoke when group changes are allowed again.
+     *
+     * @param callback the callback to add
+     * @param persistent {@code true} if this callback should this callback be persisted, otherwise
+     *                               it will be removed after a single invocation
      */
-    public void addGroupChangesAllowedCallback(Callback callback) {
+    public void addGroupChangesAllowedCallback(Callback callback, boolean persistent) {
+        if (persistent) {
+            mPersistentGroupCallbacks.add(callback);
+        }
         if (mGroupChangesAllowedCallbacks.contains(callback)) {
             return;
         }
@@ -136,21 +152,26 @@
         boolean changedToTrue = reorderingAllowed && !mReorderingAllowed;
         mReorderingAllowed = reorderingAllowed;
         if (changedToTrue) {
-            notifyChangeAllowed(mReorderingAllowedCallbacks);
+            notifyChangeAllowed(mReorderingAllowedCallbacks, mPersistentReorderingCallbacks);
         }
         boolean groupChangesAllowed = (!mScreenOn || !mPanelExpanded) && !mPulsing;
         changedToTrue = groupChangesAllowed && !mGroupChangedAllowed;
         mGroupChangedAllowed = groupChangesAllowed;
         if (changedToTrue) {
-            notifyChangeAllowed(mGroupChangesAllowedCallbacks);
+            notifyChangeAllowed(mGroupChangesAllowedCallbacks, mPersistentGroupCallbacks);
         }
     }
 
-    private void notifyChangeAllowed(ArrayList<Callback> callbacks) {
+    private void notifyChangeAllowed(ArrayList<Callback> callbacks,
+            ArraySet<Callback> persistentCallbacks) {
         for (int i = 0; i < callbacks.size(); i++) {
-            callbacks.get(i).onChangeAllowed();
+            Callback callback = callbacks.get(i);
+            callback.onChangeAllowed();
+            if (!persistentCallbacks.contains(callback)) {
+                callbacks.remove(callback);
+                i--;
+            }
         }
-        callbacks.clear();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
index 0caf0dc..97c1523 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
@@ -19,6 +19,8 @@
 import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_NOT_CANCELED;
 import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.NOT_DISMISSED;
 
+import com.android.systemui.statusbar.NotificationInteractionTracker;
+
 import java.util.Arrays;
 import java.util.List;
 
@@ -35,6 +37,7 @@
      */
     public static String dumpTree(
             List<ListEntry> entries,
+            NotificationInteractionTracker interactionTracker,
             boolean includeRecordKeeping,
             String indent) {
         StringBuilder sb = new StringBuilder();
@@ -46,7 +49,8 @@
                     indent,
                     sb,
                     true,
-                    includeRecordKeeping);
+                    includeRecordKeeping,
+                    interactionTracker.hasUserInteractedWith(entry.getKey()));
             if (entry instanceof GroupEntry) {
                 GroupEntry ge = (GroupEntry) entry;
                 List<NotificationEntry> children = ge.getChildren();
@@ -56,7 +60,8 @@
                             childEntryIndent,
                             sb,
                             true,
-                            includeRecordKeeping);
+                            includeRecordKeeping,
+                            interactionTracker.hasUserInteractedWith(entry.getKey()));
                 }
             }
         }
@@ -80,7 +85,8 @@
                     indent,
                     sb,
                     false,
-                    includeRecordKeeping);
+                    includeRecordKeeping,
+                    false);
         }
         return sb.toString();
     }
@@ -91,7 +97,9 @@
             String indent,
             StringBuilder sb,
             boolean includeParent,
-            boolean includeRecordKeeping) {
+            boolean includeRecordKeeping,
+            boolean hasBeenInteractedWith
+    ) {
         sb.append(indent)
                 .append("[").append(index).append("] ")
                 .append(entry.getKey());
@@ -157,6 +165,8 @@
                         .append(" ");
             }
 
+            rksb.append("interacted=").append(hasBeenInteractedWith ? "yes" : "no").append(" ");
+
             String rkString = rksb.toString();
             if (!rkString.isEmpty()) {
                 sb.append("\n\t")
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index a3621b6..d7365e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -61,6 +61,7 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.Dumpable;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.dump.LogBufferEulogizer;
 import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.notification.collection.coalescer.CoalescedEvent;
 import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
@@ -126,6 +127,7 @@
     private final IStatusBarService mStatusBarService;
     private final FeatureFlags mFeatureFlags;
     private final NotifCollectionLogger mLogger;
+    private final LogBufferEulogizer mEulogizer;
 
     private final Map<String, NotificationEntry> mNotificationSet = new ArrayMap<>();
     private final Collection<NotificationEntry> mReadOnlyNotificationSet =
@@ -146,10 +148,12 @@
             IStatusBarService statusBarService,
             DumpManager dumpManager,
             FeatureFlags featureFlags,
-            NotifCollectionLogger logger) {
+            NotifCollectionLogger logger,
+            LogBufferEulogizer logBufferEulogizer) {
         Assert.isMainThread();
         mStatusBarService = statusBarService;
         mLogger = logger;
+        mEulogizer = logBufferEulogizer;
         dumpManager.registerDumpable(TAG, this);
         mFeatureFlags = featureFlags;
     }
@@ -223,7 +227,8 @@
 
             requireNonNull(stats);
             if (entry != mNotificationSet.get(entry.getKey())) {
-                throw new IllegalStateException("Invalid entry: " + entry.getKey());
+                throw mEulogizer.record(
+                        new IllegalStateException("Invalid entry: " + entry.getKey()));
             }
 
             if (entry.getDismissState() == DISMISSED) {
@@ -367,8 +372,11 @@
 
         final NotificationEntry entry = mNotificationSet.get(sbn.getKey());
         if (entry == null) {
-            throw new IllegalStateException("No notification to remove with key " + sbn.getKey());
+            throw mEulogizer.record(
+                    new IllegalStateException("No notification to remove with key "
+                            + sbn.getKey()));
         }
+
         entry.mCancellationReason = reason;
         tryRemoveNotification(entry);
         applyRanking(rankingMap);
@@ -390,11 +398,11 @@
         if (entry == null) {
             // A new notification!
             entry = new NotificationEntry(sbn, ranking, SystemClock.uptimeMillis());
+            mEventQueue.add(new InitEntryEvent(entry));
             mEventQueue.add(new BindEntryEvent(entry, sbn));
             mNotificationSet.put(sbn.getKey(), entry);
 
             mLogger.logNotifPosted(sbn.getKey());
-            mEventQueue.add(new InitEntryEvent(entry));
             mEventQueue.add(new EntryAddedEvent(entry));
 
         } else {
@@ -426,12 +434,15 @@
      */
     private boolean tryRemoveNotification(NotificationEntry entry) {
         if (mNotificationSet.get(entry.getKey()) != entry) {
-            throw new IllegalStateException("No notification to remove with key " + entry.getKey());
+            throw mEulogizer.record(
+                    new IllegalStateException("No notification to remove with key "
+                            + entry.getKey()));
         }
 
         if (!isCanceled(entry)) {
-            throw new IllegalStateException("Cannot remove notification " + entry.getKey()
-                        + ": has not been marked for removal");
+            throw mEulogizer.record(
+                    new IllegalStateException("Cannot remove notification " + entry.getKey()
+                            + ": has not been marked for removal"));
         }
 
         if (isDismissedByUser(entry)) {
@@ -501,11 +512,11 @@
         checkForReentrantCall();
 
         if (!entry.mLifetimeExtenders.remove(extender)) {
-            throw new IllegalStateException(
+            throw mEulogizer.record(new IllegalStateException(
                     String.format(
                             "Cannot end lifetime extension for extender \"%s\" (%s)",
                             extender.getName(),
-                            extender));
+                            extender)));
         }
 
         mLogger.logLifetimeExtensionEnded(
@@ -581,11 +592,11 @@
         checkForReentrantCall();
 
         if (!entry.mDismissInterceptors.remove(interceptor)) {
-            throw new IllegalStateException(
+            throw mEulogizer.record(new IllegalStateException(
                     String.format(
                             "Cannot end dismiss interceptor for interceptor \"%s\" (%s)",
                             interceptor.getName(),
-                            interceptor));
+                            interceptor)));
         }
 
         if (!isDismissIntercepted(entry)) {
@@ -608,7 +619,7 @@
 
     private void checkForReentrantCall() {
         if (mAmDispatchingToOtherCode) {
-            throw new IllegalStateException("Reentrant call detected");
+            throw mEulogizer.record(new IllegalStateException("Reentrant call detected"));
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index cb0c283..1eadd9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -31,7 +31,7 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
 
 import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_NOT_CANCELED;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_ALERTING;
 
 import static java.util.Objects.requireNonNull;
 
@@ -68,7 +68,7 @@
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController;
 import com.android.systemui.statusbar.notification.row.NotificationGuts;
-import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
+import com.android.systemui.statusbar.notification.stack.PriorityBucket;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -151,6 +151,8 @@
     public CharSequence headsUpStatusBarText;
     public CharSequence headsUpStatusBarTextPublic;
 
+    // indicates when this entry's view was first attached to a window
+    // this value will reset when the view is completely removed from the shade (ie: filtered out)
     private long initializationTime = -1;
 
     /**
@@ -209,7 +211,7 @@
     }
 
     /** The key for this notification. Guaranteed to be immutable and unique */
-    public String getKey() {
+    @NonNull public String getKey() {
         return mKey;
     }
 
@@ -217,7 +219,7 @@
      * The StatusBarNotification that represents one half of a NotificationEntry (the other half
      * being the Ranking). This object is swapped out whenever a notification is updated.
      */
-    public StatusBarNotification getSbn() {
+    @NonNull public StatusBarNotification getSbn() {
         return mSbn;
     }
 
@@ -409,12 +411,12 @@
         return wasBubble != isBubble();
     }
 
-    @NotificationSectionsManager.PriorityBucket
+    @PriorityBucket
     public int getBucket() {
         return mBucket;
     }
 
-    public void setBucket(@NotificationSectionsManager.PriorityBucket int bucket) {
+    public void setBucket(@PriorityBucket int bucket) {
         mBucket = bucket;
     }
 
@@ -473,8 +475,8 @@
     }
 
     public boolean hasFinishedInitialization() {
-        return initializationTime == -1
-                || SystemClock.elapsedRealtime() > initializationTime + INITIALIZATION_DELAY;
+        return initializationTime != -1
+                && SystemClock.elapsedRealtime() > initializationTime + INITIALIZATION_DELAY;
     }
 
     public int getContrastedColor(Context context, boolean isLowPriority,
@@ -565,6 +567,10 @@
         return false;
     }
 
+    public void resetInitializationTime() {
+        initializationTime = -1;
+    }
+
     public void setInitializationTime(long time) {
         if (initializationTime == -1) {
             initializationTime = time;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
index c78370e..bab2686 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
@@ -28,11 +28,11 @@
 import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON
-import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
-import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_HEADS_UP
-import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE
-import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT
-import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.PriorityBucket
+import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING
+import com.android.systemui.statusbar.notification.stack.BUCKET_FOREGROUND_SERVICE
+import com.android.systemui.statusbar.notification.stack.BUCKET_PEOPLE
+import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
+import com.android.systemui.statusbar.notification.stack.PriorityBucket
 import com.android.systemui.statusbar.phone.NotificationGroupManager
 import com.android.systemui.statusbar.policy.HeadsUpManager
 import dagger.Lazy
@@ -74,11 +74,14 @@
         val aRank = a.ranking.rank
         val bRank = b.ranking.rank
 
+        val aIsFsn = a.isColorizedForegroundService()
+        val bIsFsn = b.isColorizedForegroundService()
+
         val aPersonType = a.getPeopleNotificationType()
         val bPersonType = b.getPeopleNotificationType()
 
-        val aMedia = isImportantMedia(a)
-        val bMedia = isImportantMedia(b)
+        val aMedia = a.isImportantMedia()
+        val bMedia = b.isImportantMedia()
 
         val aSystemMax = a.isSystemMax()
         val bSystemMax = b.isSystemMax()
@@ -92,7 +95,7 @@
             aHeadsUp != bHeadsUp -> if (aHeadsUp) -1 else 1
             // Provide consistent ranking with headsUpManager
             aHeadsUp -> headsUpManager.compare(a, b)
-
+            aIsFsn != bIsFsn -> if (aIsFsn) -1 else 1
             usePeopleFiltering && aPersonType != bPersonType ->
                 peopleNotificationIdentifier.compareTo(aPersonType, bPersonType)
             // Upsort current media notification.
@@ -106,11 +109,6 @@
         }
     }
 
-    private fun isImportantMedia(entry: NotificationEntry): Boolean {
-        val importance = entry.ranking.importance
-        return entry.key == mediaManager.mediaNotificationKey && importance > IMPORTANCE_MIN
-    }
-
     fun updateRanking(
         newRankingMap: RankingMap?,
         entries: Collection<NotificationEntry>,
@@ -134,38 +132,31 @@
     ): List<NotificationEntry> {
         logger.logFilterAndSort(reason)
         val filtered = entries.asSequence()
-                .filterNot(notifFilter::shouldFilterOut)
+                .filterNot(this::filter)
                 .sortedWith(rankingComparator)
                 .toList()
-        assignBuckets(filtered)
+        entries.forEach { it.bucket = getBucketForEntry(it) }
         return filtered
     }
 
-    private fun assignBuckets(entries: List<NotificationEntry>) {
-        entries.forEach { it.bucket = getBucketForEntry(it) }
-        if (!usePeopleFiltering) {
-            // If we don't have a Conversation section, just assign buckets normally based on the
-            // content.
-            return
+    private fun filter(entry: NotificationEntry): Boolean {
+        val filtered = notifFilter.shouldFilterOut(entry)
+        if (filtered) {
+            // notification is removed from the list, so we reset its initialization time
+            entry.resetInitializationTime()
         }
-        // If HUNs are not continuous with the top section, break out into a new Incoming section.
-        entries.asReversed().asSequence().zipWithNext().forEach { (next, entry) ->
-            if (entry.isRowHeadsUp && entry.bucket > next.bucket) {
-                entry.bucket = BUCKET_HEADS_UP
-            }
-        }
+        return filtered
     }
 
     @PriorityBucket
     private fun getBucketForEntry(entry: NotificationEntry): Int {
         val isHeadsUp = entry.isRowHeadsUp
-        val isMedia = isImportantMedia(entry)
+        val isMedia = entry.isImportantMedia()
         val isSystemMax = entry.isSystemMax()
         return when {
-            usePeopleFiltering && entry.getPeopleNotificationType() != TYPE_NON_PERSON ->
-                BUCKET_PEOPLE
-            isHeadsUp || isMedia || isSystemMax || entry.isHighPriority() ->
-                BUCKET_ALERTING
+            entry.isColorizedForegroundService() -> BUCKET_FOREGROUND_SERVICE
+            usePeopleFiltering && entry.isConversation() -> BUCKET_PEOPLE
+            isHeadsUp || isMedia || isSystemMax || entry.isHighPriority() -> BUCKET_ALERTING
             else -> BUCKET_SILENT
         }
     }
@@ -194,6 +185,11 @@
         }
     }
 
+    private fun NotificationEntry.isImportantMedia() =
+            key == mediaManager.mediaNotificationKey && ranking.importance > IMPORTANCE_MIN
+
+    private fun NotificationEntry.isConversation() = getPeopleNotificationType() != TYPE_NON_PERSON
+
     private fun NotificationEntry.getPeopleNotificationType() =
             peopleNotificationIdentifier.getPeopleNotificationType(sbn, ranking)
 
@@ -202,10 +198,12 @@
 }
 
 // Convenience functions
-private fun NotificationEntry.isSystemMax(): Boolean {
-    return importance >= IMPORTANCE_HIGH && sbn.isSystemNotification()
-}
+private fun NotificationEntry.isSystemMax() =
+        importance >= IMPORTANCE_HIGH && sbn.isSystemNotification()
 
-private fun StatusBarNotification.isSystemNotification(): Boolean {
-    return "android" == packageName || "com.android.systemui" == packageName
+private fun StatusBarNotification.isSystemNotification() =
+        "android" == packageName || "com.android.systemui" == packageName
+
+private fun NotificationEntry.isColorizedForegroundService() = sbn.notification.run {
+    isForegroundService && isColorized && importance > IMPORTANCE_MIN
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index 0a3b02c..9d81d35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -36,6 +36,7 @@
 
 import com.android.systemui.Dumpable;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.statusbar.NotificationInteractionTracker;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener;
@@ -73,6 +74,7 @@
 public class ShadeListBuilder implements Dumpable {
     private final SystemClock mSystemClock;
     private final ShadeListBuilderLogger mLogger;
+    private final NotificationInteractionTracker mInteractionTracker;
 
     private List<ListEntry> mNotifList = new ArrayList<>();
     private List<ListEntry> mNewNotifList = new ArrayList<>();
@@ -105,10 +107,12 @@
     public ShadeListBuilder(
             SystemClock systemClock,
             ShadeListBuilderLogger logger,
-            DumpManager dumpManager) {
+            DumpManager dumpManager,
+            NotificationInteractionTracker interactionTracker) {
         Assert.isMainThread();
         mSystemClock = systemClock;
         mLogger = logger;
+        mInteractionTracker = interactionTracker;
         dumpManager.registerDumpable(TAG, this);
     }
 
@@ -713,6 +717,10 @@
     private boolean applyFilters(NotificationEntry entry, long now, List<NotifFilter> filters) {
         final NotifFilter filter = findRejectingFilter(entry, now, filters);
         entry.getAttachState().setExcludingFilter(filter);
+        if (filter != null) {
+            // notification is removed from the list, so we reset its initialization time
+            entry.resetInitializationTime();
+        }
         return filter != null;
     }
 
@@ -817,6 +825,7 @@
 
         pw.println(ListDumper.dumpTree(
                 getShadeList(),
+                mInteractionTracker,
                 true,
                 "\t\t"));
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
index 59f119e..75d772e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification.collection.notifcollection;
 
+import android.annotation.NonNull;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 
@@ -43,13 +44,13 @@
      * there is no guarantee of order and they may not have had a chance to initialize yet. Instead,
      * use {@link #onEntryAdded} which is called after all initialization.
      */
-    default void onEntryInit(NotificationEntry entry) {
+    default void onEntryInit(@NonNull NotificationEntry entry) {
     }
 
     /**
      * Called whenever a notification with a new key is posted.
      */
-    default void onEntryAdded(NotificationEntry entry) {
+    default void onEntryAdded(@NonNull NotificationEntry entry) {
     }
 
     /**
@@ -64,7 +65,7 @@
      * immediately after a user dismisses a notification: we wait until we receive confirmation from
      * system server before considering the notification removed.
      */
-    default void onEntryRemoved(NotificationEntry entry, @CancellationReason int reason) {
+    default void onEntryRemoved(@NonNull NotificationEntry entry, @CancellationReason int reason) {
     }
 
     /**
@@ -76,7 +77,7 @@
      * the entry during this call. Instead, use {@link #onEntryRemoved} which will be called before
      * deletion.
      */
-    default void onEntryCleanUp(NotificationEntry entry) {
+    default void onEntryCleanUp(@NonNull NotificationEntry entry) {
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/BypassHeadsUpNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/BypassHeadsUpNotifier.kt
index 88888d1..0fd865b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/BypassHeadsUpNotifier.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/BypassHeadsUpNotifier.kt
@@ -75,7 +75,7 @@
         mediaManager.addCallback(this)
     }
 
-    override fun onMetadataOrStateChanged(metadata: MediaMetadata?, state: Int) {
+    override fun onPrimaryMetadataOrStateChanged(metadata: MediaMetadata?, state: Int) {
         val previous = currentMediaEntry
         var newEntry = entryManager
                 .getActiveNotificationUnfiltered(mediaManager.mediaNotificationKey)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt
index 2fbd3ee..d32d09d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt
@@ -220,9 +220,9 @@
         }
         val clickRunnable = Runnable { notificationListener.unsnoozeNotification(key) }
         val extras = sbn.notification.extras
-        val name = ranking.shortcutInfo?.shortLabel
-                ?: extras.getString(Notification.EXTRA_CONVERSATION_TITLE)
-                ?: extras.getString(Notification.EXTRA_TITLE)
+        val name = ranking.shortcutInfo?.label
+                ?: extras.getCharSequence(Notification.EXTRA_CONVERSATION_TITLE)
+                ?: extras.getCharSequence(Notification.EXTRA_TITLE)
                 ?: return null
         val drawable = ranking.getIcon(iconFactory, sbn)
                 ?: iconFactory.getConversationDrawable(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 5797944..0831c0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -767,6 +767,10 @@
         return mContentTranslation;
     }
 
+    public boolean wantsAddAndRemoveAnimations() {
+        return true;
+    }
+
     /**
      * A listener notifying when {@link #getActualHeight} changes.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java
index 0ccebc13..56f8e08 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java
@@ -109,7 +109,7 @@
     }
 
     @Nullable
-    private CharSequence resolveText(Notification notification) {
+    public static CharSequence resolveText(Notification notification) {
         CharSequence contentText = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
         if (contentText == null) {
             contentText = notification.extras.getCharSequence(Notification.EXTRA_BIG_TEXT);
@@ -118,7 +118,7 @@
     }
 
     @Nullable
-    private CharSequence resolveTitle(Notification notification) {
+    public static CharSequence resolveTitle(Notification notification) {
         CharSequence titleText = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
         if (titleText == null) {
             titleText = notification.extras.getCharSequence(Notification.EXTRA_TITLE_BIG);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java
index 3ee2673..90d30dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipeline.java
@@ -154,12 +154,14 @@
      * the real work once rather than repeatedly start and cancel it.
      */
     private void requestPipelineRun(NotificationEntry entry) {
+        mLogger.logRequestPipelineRun(entry.getKey());
+
         final BindEntry bindEntry = getBindEntry(entry);
         if (bindEntry.row == null) {
             // Row is not managed yet but may be soon. Stop for now.
+            mLogger.logRequestPipelineRowNotSet(entry.getKey());
             return;
         }
-        mLogger.logRequestPipelineRun(entry.getKey());
 
         // Abort any existing pipeline run
         mStage.abortStage(entry, bindEntry.row);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt
index 1997304..f26598d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt
@@ -18,6 +18,7 @@
 
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.LogLevel.INFO
+import com.android.systemui.log.LogLevel.WARNING
 import com.android.systemui.log.dagger.NotificationLog
 import javax.inject.Inject
 
@@ -48,6 +49,14 @@
         })
     }
 
+    fun logRequestPipelineRowNotSet(notifKey: String) {
+        buffer.log(TAG, WARNING, {
+            str1 = notifKey
+        }, {
+            "Row is not set so pipeline will not run. notif = $str1"
+        })
+    }
+
     fun logStartPipeline(notifKey: String) {
         buffer.log(TAG, INFO, {
             str1 = notifKey
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index e9849ec..9925909 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -64,6 +64,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 
 /**
  * A frame layout containing the actual payload of the notification, including the contracted,
@@ -518,9 +519,12 @@
     protected void onVisibilityChanged(View changedView, int visibility) {
         super.onVisibilityChanged(changedView, visibility);
         updateVisibility();
-        if (visibility != VISIBLE) {
+        if (visibility != VISIBLE && !mOnContentViewInactiveListeners.isEmpty()) {
             // View is no longer visible so all content views are inactive.
-            for (Runnable r : mOnContentViewInactiveListeners.values()) {
+            // Clone list as runnables may modify the list of listeners
+            ArrayList<Runnable> listeners = new ArrayList<>(
+                    mOnContentViewInactiveListeners.values());
+            for (Runnable r : listeners) {
                 r.run();
             }
             mOnContentViewInactiveListeners.clear();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java
index cc5de65..1dc828b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java
@@ -135,10 +135,13 @@
     }
 
     private void bindActions() {
+        final OnClickListener settingsOnClickListener = getSettingsOnClickListener();
         final View settingsButton = findViewById(R.id.info);
-        settingsButton.setOnClickListener(getSettingsOnClickListener());
+        settingsButton.setOnClickListener(settingsOnClickListener);
         settingsButton.setVisibility(settingsButton.hasOnClickListeners() ? VISIBLE : GONE);
 
+        findViewById(R.id.settings_link).setOnClickListener(settingsOnClickListener);
+
         TextView msg = findViewById(R.id.non_configurable_text);
         msg.setText(getResources().getString(R.string.no_shortcut, mAppName));
     }
@@ -189,9 +192,9 @@
     private void bindName() {
         TextView name = findViewById(R.id.name);
         Bundle extras = mSbn.getNotification().extras;
-        String nameString = extras.getString(Notification.EXTRA_CONVERSATION_TITLE);
+        CharSequence nameString = extras.getCharSequence(Notification.EXTRA_CONVERSATION_TITLE, "");
         if (TextUtils.isEmpty(nameString)) {
-            nameString = extras.getString(Notification.EXTRA_TITLE);
+            nameString = extras.getCharSequence(Notification.EXTRA_TITLE, "");
         }
         name.setText(nameString);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index b96cff8..93d3f3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -178,38 +178,6 @@
         final MediaSession.Token token = mRow.getEntry().getSbn().getNotification().extras
                 .getParcelable(Notification.EXTRA_MEDIA_SESSION);
 
-        if (Utils.useQsMediaPlayer(mContext) && token != null) {
-            final int[] compactActions = mRow.getEntry().getSbn().getNotification().extras
-                    .getIntArray(Notification.EXTRA_COMPACT_ACTIONS);
-            int tintColor = getNotificationHeader().getOriginalIconColor();
-            NotificationShadeWindowController ctrl = Dependency.get(
-                    NotificationShadeWindowController.class);
-            QuickQSPanel panel = ctrl.getNotificationShadeView().findViewById(
-                    com.android.systemui.R.id.quick_qs_panel);
-            StatusBarNotification sbn = mRow.getEntry().getSbn();
-            Notification notif = sbn.getNotification();
-            Drawable iconDrawable = notif.getSmallIcon().loadDrawable(mContext);
-            panel.getMediaPlayer().setMediaSession(token,
-                    iconDrawable,
-                    notif.getLargeIcon(),
-                    tintColor,
-                    mBackgroundColor,
-                    mActions,
-                    compactActions,
-                    notif.contentIntent,
-                    sbn.getKey());
-            QSPanel bigPanel = ctrl.getNotificationShadeView().findViewById(
-                    com.android.systemui.R.id.quick_settings_panel);
-            bigPanel.addMediaSession(token,
-                    iconDrawable,
-                    notif.getLargeIcon(),
-                    tintColor,
-                    mBackgroundColor,
-                    mActions,
-                    sbn,
-                    sbn.getKey());
-        }
-
         boolean showCompactSeekbar = mMediaManager.getShowCompactMediaSeekbar();
         if (token == null || (COMPACT_MEDIA_TAG.equals(mView.getTag()) && !showCompactSeekbar)) {
             if (mSeekBarView != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java
index ab055e1..3ac322f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.ViewGroup;
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -37,7 +38,6 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mContentView = findViewById(R.id.keyguard_media_view);
     }
 
     @Override
@@ -52,4 +52,17 @@
     public void setBackgroundColor(int color) {
         setTintColor(color);
     }
+
+    public void setContentView(ViewGroup contentView) {
+        mContentView = contentView;
+        addView(contentView);
+        ViewGroup.LayoutParams layoutParams = contentView.getLayoutParams();
+        layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+        layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
+    }
+
+    @Override
+    public boolean wantsAddAndRemoveAnimations() {
+        return false;
+    }
 }
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 c9b1318..99691b7 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
@@ -463,7 +463,8 @@
                     mAttachedChildren.add(i, desiredChild);
                     result = true;
                 } else {
-                    visualStabilityManager.addReorderingAllowedCallback(callback);
+                    visualStabilityManager.addReorderingAllowedCallback(callback,
+                            false /* persistent */);
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java
index 9d456ef..bad36bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java
@@ -32,8 +32,8 @@
  * Represents the bounds of a section of the notification shade and handles animation when the
  * bounds change.
  */
-class NotificationSection {
-    private @NotificationSectionsManager.PriorityBucket int mBucket;
+public class NotificationSection {
+    private @PriorityBucket int mBucket;
     private View mOwningView;
     private Rect mBounds = new Rect();
     private Rect mCurrentBounds = new Rect(-1, -1, -1, -1);
@@ -44,7 +44,7 @@
     private ActivatableNotificationView mFirstVisibleChild;
     private ActivatableNotificationView mLastVisibleChild;
 
-    NotificationSection(View owningView, @NotificationSectionsManager.PriorityBucket int bucket) {
+    NotificationSection(View owningView, @PriorityBucket int bucket) {
         mOwningView = owningView;
         mBucket = bucket;
     }
@@ -74,7 +74,7 @@
         return mBottomAnimator != null || mTopAnimator != null;
     }
 
-    @NotificationSectionsManager.PriorityBucket
+    @PriorityBucket
     public int getBucket() {
         return mBucket;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt
new file mode 100644
index 0000000..17b4143
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.dagger.NotificationSectionLog
+import javax.inject.Inject
+import javax.inject.Singleton
+
+private const val TAG = "NotifSections"
+
+@Singleton
+class NotificationSectionsLogger @Inject constructor(
+    @NotificationSectionLog private val logBuffer: LogBuffer
+) {
+
+    fun logStartSectionUpdate(reason: String) = logBuffer.log(
+            TAG,
+            LogLevel.DEBUG,
+            { str1 = reason },
+            { "Updating section boundaries: $reason" }
+    )
+
+    fun logIncomingHeader(position: Int) = logPosition(position, "INCOMING HEADER")
+    fun logMediaControls(position: Int) = logPosition(position, "MEDIA CONTROLS")
+    fun logConversationsHeader(position: Int) = logPosition(position, "CONVERSATIONS HEADER")
+    fun logAlertingHeader(position: Int) = logPosition(position, "ALERTING HEADER")
+    fun logSilentHeader(position: Int) = logPosition(position, "SILENT HEADER")
+
+    fun logOther(position: Int, clazz: Class<*>) = logBuffer.log(
+            TAG,
+            LogLevel.DEBUG,
+            {
+                int1 = position
+                str1 = clazz.name
+            },
+            { "$int1: other ($str1)" }
+    )
+
+    fun logHeadsUp(position: Int, isHeadsUp: Boolean) =
+            logPosition(position, "Heads Up", isHeadsUp)
+    fun logConversation(position: Int, isHeadsUp: Boolean) =
+            logPosition(position, "Conversation", isHeadsUp)
+    fun logAlerting(position: Int, isHeadsUp: Boolean) =
+            logPosition(position, "Alerting", isHeadsUp)
+    fun logSilent(position: Int, isHeadsUp: Boolean) =
+            logPosition(position, "Silent", isHeadsUp)
+    fun logForegroundService(position: Int, isHeadsUp: Boolean) =
+            logPosition(position, "Foreground Service", isHeadsUp)
+
+    fun logStr(str: String) = logBuffer.log(TAG, LogLevel.DEBUG, { str1 = str }, { "$str1" })
+
+    private fun logPosition(position: Int, label: String, isHeadsUp: Boolean) {
+        val headsUpTag = if (isHeadsUp) " (HUN)" else ""
+        logBuffer.log(
+                TAG,
+                LogLevel.DEBUG,
+                {
+                    int1 = position
+                    str1 = label
+                    str2 = headsUpTag
+                },
+                {
+                    "$int1: $str1$str2"
+                }
+        )
+    }
+
+    private fun logPosition(position: Int, label: String) = logBuffer.log(
+            TAG,
+            LogLevel.DEBUG,
+            {
+                int1 = position
+                str1 = label
+            },
+            { "$int1: $str1" }
+    )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
deleted file mode 100644
index 6eec1ca..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.stack;
-
-import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
-
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.annotation.ColorInt;
-import android.annotation.IntDef;
-import android.annotation.LayoutRes;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Intent;
-import android.provider.Settings;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.keyguard.KeyguardMediaPlayer;
-import com.android.systemui.R;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
-import com.android.systemui.statusbar.notification.people.DataListener;
-import com.android.systemui.statusbar.notification.people.PeopleHubViewAdapter;
-import com.android.systemui.statusbar.notification.people.PeopleHubViewBoundary;
-import com.android.systemui.statusbar.notification.people.PersonViewModel;
-import com.android.systemui.statusbar.notification.people.Subscription;
-import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
-import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
-
-import java.lang.annotation.Retention;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-import javax.inject.Inject;
-
-import kotlin.sequences.Sequence;
-
-/**
- * Manages the boundaries of the two notification sections (high priority and low priority). Also
- * shows/hides the headers for those sections where appropriate.
- *
- * TODO: Move remaining sections logic from NSSL into this class.
- */
-public class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvider {
-
-    private static final String TAG = "NotifSectionsManager";
-    private static final boolean DEBUG = false;
-    private static final boolean ENABLE_SNOOZED_CONVERSATION_HUB = false;
-
-    private final ActivityStarter mActivityStarter;
-    private final StatusBarStateController mStatusBarStateController;
-    private final ConfigurationController mConfigurationController;
-    private final PeopleHubViewAdapter mPeopleHubViewAdapter;
-    private final KeyguardMediaPlayer mKeyguardMediaPlayer;
-    private final NotificationSectionsFeatureManager mSectionsFeatureManager;
-    private final int mNumberOfSections;
-
-    private final PeopleHubViewBoundary mPeopleHubViewBoundary = new PeopleHubViewBoundary() {
-        @Override
-        public void setVisible(boolean isVisible) {
-            if (mPeopleHubVisible != isVisible) {
-                mPeopleHubVisible = isVisible;
-                if (mInitialized) {
-                    updateSectionBoundaries();
-                }
-            }
-        }
-
-        @NonNull
-        @Override
-        public View getAssociatedViewForClickAnimation() {
-            return mPeopleHubView;
-        }
-
-        @NonNull
-        @Override
-        public Sequence<DataListener<PersonViewModel>> getPersonViewAdapters() {
-            return mPeopleHubView.getPersonViewAdapters();
-        }
-    };
-
-    private NotificationStackScrollLayout mParent;
-    private boolean mInitialized = false;
-
-    private SectionHeaderView mGentleHeader;
-    @Nullable private View.OnClickListener mOnClearGentleNotifsClickListener;
-
-    private SectionHeaderView mAlertingHeader;
-    private SectionHeaderView mIncomingHeader;
-
-    private PeopleHubView mPeopleHubView;
-    private boolean mPeopleHubVisible = false;
-    @Nullable private Subscription mPeopleHubSubscription;
-
-    private MediaHeaderView mMediaControlsView;
-
-    @Inject
-    NotificationSectionsManager(
-            ActivityStarter activityStarter,
-            StatusBarStateController statusBarStateController,
-            ConfigurationController configurationController,
-            PeopleHubViewAdapter peopleHubViewAdapter,
-            KeyguardMediaPlayer keyguardMediaPlayer,
-            NotificationSectionsFeatureManager sectionsFeatureManager) {
-        mActivityStarter = activityStarter;
-        mStatusBarStateController = statusBarStateController;
-        mConfigurationController = configurationController;
-        mPeopleHubViewAdapter = peopleHubViewAdapter;
-        mKeyguardMediaPlayer = keyguardMediaPlayer;
-        mSectionsFeatureManager = sectionsFeatureManager;
-        mNumberOfSections = mSectionsFeatureManager.getNumberOfBuckets();
-    }
-
-    NotificationSection[] createSectionsForBuckets() {
-        int[] buckets = mSectionsFeatureManager.getNotificationBuckets();
-        NotificationSection[] sections = new NotificationSection[buckets.length];
-        for (int i = 0; i < buckets.length; i++) {
-            sections[i] = new NotificationSection(mParent, buckets[i] /* bucket */);
-        }
-
-        return sections;
-    }
-
-    /** Must be called before use. */
-    void initialize(
-            NotificationStackScrollLayout parent, LayoutInflater layoutInflater) {
-        if (mInitialized) {
-            throw new IllegalStateException("NotificationSectionsManager already initialized");
-        }
-        mInitialized = true;
-        mParent = parent;
-        reinflateViews(layoutInflater);
-        mConfigurationController.addCallback(mConfigurationListener);
-    }
-
-    private <T extends ExpandableView> T reinflateView(
-            T view, LayoutInflater layoutInflater, @LayoutRes int layoutResId) {
-        int oldPos = -1;
-        if (view != null) {
-            if (view.getTransientContainer() != null) {
-                view.getTransientContainer().removeView(mGentleHeader);
-            } else if (view.getParent() != null) {
-                oldPos = mParent.indexOfChild(view);
-                mParent.removeView(view);
-            }
-        }
-
-        view = (T) layoutInflater.inflate(layoutResId, mParent, false);
-
-        if (oldPos != -1) {
-            mParent.addView(view, oldPos);
-        }
-
-        return view;
-    }
-
-    /**
-     * Reinflates the entire notification header, including all decoration views.
-     */
-    void reinflateViews(LayoutInflater layoutInflater) {
-        mGentleHeader = reinflateView(
-                mGentleHeader, layoutInflater, R.layout.status_bar_notification_section_header);
-        mGentleHeader.setHeaderText(R.string.notification_section_header_gentle);
-        mGentleHeader.setOnHeaderClickListener(this::onGentleHeaderClick);
-        mGentleHeader.setOnClearAllClickListener(this::onClearGentleNotifsClick);
-
-        mAlertingHeader = reinflateView(
-                mAlertingHeader, layoutInflater, R.layout.status_bar_notification_section_header);
-        mAlertingHeader.setHeaderText(R.string.notification_section_header_alerting);
-        mAlertingHeader.setOnHeaderClickListener(this::onGentleHeaderClick);
-
-        if (mPeopleHubSubscription != null) {
-            mPeopleHubSubscription.unsubscribe();
-        }
-        mPeopleHubView = reinflateView(mPeopleHubView, layoutInflater, R.layout.people_strip);
-        if (ENABLE_SNOOZED_CONVERSATION_HUB) {
-            mPeopleHubSubscription = mPeopleHubViewAdapter.bindView(mPeopleHubViewBoundary);
-        }
-
-        mIncomingHeader = reinflateView(
-                mIncomingHeader, layoutInflater, R.layout.status_bar_notification_section_header);
-        mIncomingHeader.setHeaderText(R.string.notification_section_header_incoming);
-        mIncomingHeader.setOnHeaderClickListener(this::onGentleHeaderClick);
-
-        if (mMediaControlsView != null) {
-            mKeyguardMediaPlayer.unbindView();
-        }
-        mMediaControlsView = reinflateView(mMediaControlsView, layoutInflater,
-                R.layout.keyguard_media_header);
-        mKeyguardMediaPlayer.bindView(mMediaControlsView);
-    }
-
-    /** Listener for when the "clear all" button is clicked on the gentle notification header. */
-    void setOnClearGentleNotifsClickListener(View.OnClickListener listener) {
-        mOnClearGentleNotifsClickListener = listener;
-    }
-
-    @Override
-    public boolean beginsSection(@NonNull View view, @Nullable View previous) {
-        return view == mGentleHeader
-                || view == mMediaControlsView
-                || view == mPeopleHubView
-                || view == mAlertingHeader
-                || view == mIncomingHeader
-                || !Objects.equals(getBucket(view), getBucket(previous));
-    }
-
-    private boolean isUsingMultipleSections() {
-        return mNumberOfSections > 1;
-    }
-
-    @Nullable
-    private Integer getBucket(View view) {
-        if (view == mGentleHeader) {
-            return BUCKET_SILENT;
-        } else if (view == mIncomingHeader) {
-            return BUCKET_HEADS_UP;
-        } else if (view == mMediaControlsView) {
-            return BUCKET_MEDIA_CONTROLS;
-        } else if (view == mPeopleHubView) {
-            return BUCKET_PEOPLE;
-        } else if (view == mAlertingHeader) {
-            return BUCKET_ALERTING;
-        } else if (view instanceof ExpandableNotificationRow) {
-            return ((ExpandableNotificationRow) view).getEntry().getBucket();
-        }
-        return null;
-    }
-
-    /**
-     * Should be called whenever notifs are added, removed, or updated. Updates section boundary
-     * bookkeeping and adds/moves/removes section headers if appropriate.
-     */
-    void updateSectionBoundaries() {
-        if (!isUsingMultipleSections()) {
-            return;
-        }
-
-        // The overall strategy here is to iterate over the current children of mParent, looking
-        // for where the sections headers are currently positioned, and where each section begins.
-        // Then, once we find the start of a new section, we track that position as the "target" for
-        // the section header, adjusted for the case where existing headers are in front of that
-        // target, but won't be once they are moved / removed after the pass has completed.
-
-        final boolean showHeaders = mStatusBarStateController.getState() != StatusBarState.KEYGUARD;
-        final boolean usingPeopleFiltering = mSectionsFeatureManager.isFilteringEnabled();
-        final boolean isKeyguard = mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
-        final boolean usingMediaControls = mSectionsFeatureManager.isMediaControlsEnabled();
-
-        boolean peopleNotifsPresent = false;
-
-        int currentMediaControlsIdx = -1;
-        // Currently, just putting media controls in the front and incrementing the position based
-        // on the number of heads-up notifs.
-        int mediaControlsTarget = isKeyguard && usingMediaControls ? 0 : -1;
-        int currentIncomingHeaderIdx = -1;
-        int incomingHeaderTarget = -1;
-        int currentPeopleHeaderIdx = -1;
-        int peopleHeaderTarget = -1;
-        int currentAlertingHeaderIdx = -1;
-        int alertingHeaderTarget = -1;
-        int currentGentleHeaderIdx = -1;
-        int gentleHeaderTarget = -1;
-
-        int lastNotifIndex = 0;
-
-        final int childCount = mParent.getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = mParent.getChildAt(i);
-
-            // Track the existing positions of the headers
-            if (child == mIncomingHeader) {
-                currentIncomingHeaderIdx = i;
-                continue;
-            }
-            if (child == mMediaControlsView) {
-                currentMediaControlsIdx = i;
-                continue;
-            }
-            if (child == mPeopleHubView) {
-                currentPeopleHeaderIdx = i;
-                continue;
-            }
-            if (child == mAlertingHeader) {
-                currentAlertingHeaderIdx = i;
-                continue;
-            }
-            if (child == mGentleHeader) {
-                currentGentleHeaderIdx = i;
-                continue;
-            }
-
-            if (!(child instanceof ExpandableNotificationRow)) {
-                continue;
-            }
-            lastNotifIndex = i;
-            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-            // Once we enter a new section, calculate the target position for the header.
-            switch (row.getEntry().getBucket()) {
-                case BUCKET_HEADS_UP:
-                    if (showHeaders && incomingHeaderTarget == -1) {
-                        incomingHeaderTarget = i;
-                        // Offset the target if there are other headers before this that will be
-                        // moved.
-                        if (currentIncomingHeaderIdx != -1) {
-                            incomingHeaderTarget--;
-                        }
-                        if (currentMediaControlsIdx != -1) {
-                            incomingHeaderTarget--;
-                        }
-                        if (currentPeopleHeaderIdx != -1) {
-                            incomingHeaderTarget--;
-                        }
-                        if (currentAlertingHeaderIdx != -1) {
-                            incomingHeaderTarget--;
-                        }
-                        if (currentGentleHeaderIdx != -1) {
-                            incomingHeaderTarget--;
-                        }
-                    }
-                    if (mediaControlsTarget != -1) {
-                        mediaControlsTarget++;
-                    }
-                    break;
-                case BUCKET_PEOPLE:
-                    peopleNotifsPresent = true;
-                    if (showHeaders && peopleHeaderTarget == -1) {
-                        peopleHeaderTarget = i;
-                        // Offset the target if there are other headers before this that will be
-                        // moved.
-                        if (currentPeopleHeaderIdx != -1) {
-                            peopleHeaderTarget--;
-                        }
-                        if (currentAlertingHeaderIdx != -1) {
-                            peopleHeaderTarget--;
-                        }
-                        if (currentGentleHeaderIdx != -1) {
-                            peopleHeaderTarget--;
-                        }
-                    }
-                    break;
-                case BUCKET_ALERTING:
-                    if (showHeaders && usingPeopleFiltering && alertingHeaderTarget == -1) {
-                        alertingHeaderTarget = i;
-                        // Offset the target if there are other headers before this that will be
-                        // moved.
-                        if (currentAlertingHeaderIdx != -1) {
-                            alertingHeaderTarget--;
-                        }
-                        if (currentGentleHeaderIdx != -1) {
-                            alertingHeaderTarget--;
-                        }
-                    }
-                    break;
-                case BUCKET_SILENT:
-                    if (showHeaders && gentleHeaderTarget == -1) {
-                        gentleHeaderTarget = i;
-                        // Offset the target if there are other headers before this that will be
-                        // moved.
-                        if (currentGentleHeaderIdx != -1) {
-                            gentleHeaderTarget--;
-                        }
-                    }
-                    break;
-                default:
-                    throw new IllegalStateException("Cannot find section bucket for view");
-            }
-        }
-        if (showHeaders && usingPeopleFiltering && mPeopleHubVisible && peopleHeaderTarget == -1) {
-            // Insert the people header even if there are no people visible, in order to show
-            // the hub. Put it directly above the next header.
-            if (alertingHeaderTarget != -1) {
-                peopleHeaderTarget = alertingHeaderTarget;
-            } else if (gentleHeaderTarget != -1) {
-                peopleHeaderTarget = gentleHeaderTarget;
-            } else {
-                // Put it at the end of the list.
-                peopleHeaderTarget = lastNotifIndex;
-            }
-            // Offset the target to account for the current position of the people header.
-            if (currentPeopleHeaderIdx != -1 && currentPeopleHeaderIdx < peopleHeaderTarget) {
-                peopleHeaderTarget--;
-            }
-        }
-
-        // Add headers in reverse order to preserve indices
-        adjustHeaderVisibilityAndPosition(
-                gentleHeaderTarget, mGentleHeader, currentGentleHeaderIdx);
-        adjustHeaderVisibilityAndPosition(
-                alertingHeaderTarget, mAlertingHeader, currentAlertingHeaderIdx);
-        adjustHeaderVisibilityAndPosition(
-                peopleHeaderTarget, mPeopleHubView, currentPeopleHeaderIdx);
-        adjustViewPosition(mediaControlsTarget, mMediaControlsView, currentMediaControlsIdx);
-        adjustViewPosition(incomingHeaderTarget, mIncomingHeader, currentIncomingHeaderIdx);
-
-        // Update headers to reflect state of section contents
-        mGentleHeader.setAreThereDismissableGentleNotifs(
-                mParent.hasActiveClearableNotifications(ROWS_GENTLE));
-        mPeopleHubView.setCanSwipe(showHeaders && mPeopleHubVisible && !peopleNotifsPresent);
-        if (peopleHeaderTarget != currentPeopleHeaderIdx) {
-            mPeopleHubView.resetTranslation();
-        }
-    }
-
-    private void adjustHeaderVisibilityAndPosition(
-            int targetPosition, StackScrollerDecorView header, int currentPosition) {
-        if (targetPosition == -1) {
-            if (currentPosition != -1) {
-                mParent.removeView(header);
-            }
-        } else {
-            if (currentPosition == -1) {
-                // If the header is animating away, it will still have a parent, so detach it first
-                // TODO: We should really cancel the active animations here. This will happen
-                // automatically when the view's intro animation starts, but it's a fragile link.
-                if (header.getTransientContainer() != null) {
-                    header.getTransientContainer().removeTransientView(header);
-                    header.setTransientContainer(null);
-                }
-                header.setContentVisible(true);
-                mParent.addView(header, targetPosition);
-            } else {
-                mParent.changeViewPosition(header, targetPosition);
-            }
-        }
-    }
-
-    private void adjustViewPosition(int targetPosition, ExpandableView header,
-            int currentPosition) {
-        if (targetPosition == -1) {
-            if (currentPosition != -1) {
-                mParent.removeView(header);
-            }
-        } else {
-            if (currentPosition == -1) {
-                // If the header is animating away, it will still have a parent, so detach it first
-                // TODO: We should really cancel the active animations here. This will happen
-                // automatically when the view's intro animation starts, but it's a fragile link.
-                if (header.getTransientContainer() != null) {
-                    header.getTransientContainer().removeTransientView(header);
-                    header.setTransientContainer(null);
-                }
-                mParent.addView(header, targetPosition);
-            } else {
-                mParent.changeViewPosition(header, targetPosition);
-            }
-        }
-    }
-
-    /**
-     * Updates the boundaries (as tracked by their first and last views) of the priority sections.
-     *
-     * @return {@code true} If the last view in the top section changed (so we need to animate).
-     */
-    boolean updateFirstAndLastViewsForAllSections(
-            NotificationSection[] sections,
-            List<ActivatableNotificationView> children) {
-
-        if (sections.length <= 0 || children.size() <= 0) {
-            for (NotificationSection s : sections) {
-                s.setFirstVisibleChild(null);
-                s.setLastVisibleChild(null);
-            }
-            return false;
-        }
-
-        boolean changed = false;
-        ArrayList<ActivatableNotificationView> viewsInBucket = new ArrayList<>();
-        for (NotificationSection s : sections) {
-            int filter = s.getBucket();
-            viewsInBucket.clear();
-
-            //TODO: do this in a single pass, and more better
-            for (ActivatableNotificationView v : children)  {
-                Integer bucket = getBucket(v);
-                if (bucket == null) {
-                    throw new IllegalArgumentException("Cannot find section bucket for view");
-                }
-
-                if (bucket == filter) {
-                    viewsInBucket.add(v);
-                }
-
-                if (viewsInBucket.size() >= 1) {
-                    changed |= s.setFirstVisibleChild(viewsInBucket.get(0));
-                    changed |= s.setLastVisibleChild(viewsInBucket.get(viewsInBucket.size() - 1));
-                } else {
-                    changed |= s.setFirstVisibleChild(null);
-                    changed |= s.setLastVisibleChild(null);
-                }
-            }
-        }
-
-        if (DEBUG) {
-            logSections(sections);
-        }
-
-        return changed;
-    }
-
-    private void logSections(NotificationSection[] sections) {
-        for (int i = 0; i < sections.length; i++) {
-            NotificationSection s = sections[i];
-            ActivatableNotificationView first = s.getFirstVisibleChild();
-            String fs = first == null ? "(null)"
-                    :  (first instanceof ExpandableNotificationRow)
-                            ? ((ExpandableNotificationRow) first).getEntry().getKey()
-                            : Integer.toHexString(System.identityHashCode(first));
-            ActivatableNotificationView last = s.getLastVisibleChild();
-            String ls = last == null ? "(null)"
-                    :  (last instanceof ExpandableNotificationRow)
-                            ? ((ExpandableNotificationRow) last).getEntry().getKey()
-                            : Integer.toHexString(System.identityHashCode(last));
-            android.util.Log.d(TAG, "updateSections: f=" + fs + " s=" + i);
-            android.util.Log.d(TAG, "updateSections: l=" + ls + " s=" + i);
-        }
-    }
-
-    @VisibleForTesting
-    ExpandableView getGentleHeaderView() {
-        return mGentleHeader;
-    }
-
-    @VisibleForTesting
-    ExpandableView getAlertingHeaderView() {
-        return mAlertingHeader;
-    }
-
-    @VisibleForTesting
-    ExpandableView getPeopleHeaderView() {
-        return mPeopleHubView;
-    }
-
-    @VisibleForTesting
-    ExpandableView getMediaControlsView() {
-        return mMediaControlsView;
-    }
-
-    @VisibleForTesting
-    void setPeopleHubVisible(boolean visible) {
-        mPeopleHubVisible = visible;
-    }
-
-    private final ConfigurationListener mConfigurationListener = new ConfigurationListener() {
-        @Override
-        public void onLocaleListChanged() {
-            reinflateViews(LayoutInflater.from(mParent.getContext()));
-        }
-    };
-
-    private void onGentleHeaderClick(View v) {
-        Intent intent = new Intent(Settings.ACTION_NOTIFICATION_SETTINGS);
-        mActivityStarter.startActivity(
-                intent,
-                true,
-                true,
-                Intent.FLAG_ACTIVITY_SINGLE_TOP);
-    }
-
-    private void onClearGentleNotifsClick(View v) {
-        if (mOnClearGentleNotifsClickListener != null) {
-            mOnClearGentleNotifsClickListener.onClick(v);
-        }
-    }
-
-    void hidePeopleRow() {
-        mPeopleHubVisible = false;
-        updateSectionBoundaries();
-    }
-
-    void setHeaderForegroundColor(@ColorInt int color) {
-        mPeopleHubView.setTextColor(color);
-        mGentleHeader.setForegroundColor(color);
-        mAlertingHeader.setForegroundColor(color);
-    }
-
-    /**
-     * For now, declare the available notification buckets (sections) here so that other
-     * presentation code can decide what to do based on an entry's buckets
-     */
-    @Retention(SOURCE)
-    @IntDef(prefix = { "BUCKET_" }, value = {
-            BUCKET_HEADS_UP,
-            BUCKET_MEDIA_CONTROLS,
-            BUCKET_PEOPLE,
-            BUCKET_ALERTING,
-            BUCKET_SILENT
-    })
-    public @interface PriorityBucket {}
-    public static final int BUCKET_HEADS_UP = 0;
-    public static final int BUCKET_MEDIA_CONTROLS = 1;
-    public static final int BUCKET_PEOPLE = 2;
-    public static final int BUCKET_ALERTING = 3;
-    public static final int BUCKET_SILENT = 4;
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
new file mode 100644
index 0000000..e39a4a0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
@@ -0,0 +1,595 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.notification.stack
+
+import android.annotation.ColorInt
+import android.annotation.IntDef
+import android.annotation.LayoutRes
+import android.content.Intent
+import android.provider.Settings
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import com.android.internal.annotations.VisibleForTesting
+import com.android.systemui.R
+import com.android.systemui.media.KeyguardMediaController
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
+import com.android.systemui.statusbar.notification.people.DataListener
+import com.android.systemui.statusbar.notification.people.PeopleHubViewAdapter
+import com.android.systemui.statusbar.notification.people.PeopleHubViewBoundary
+import com.android.systemui.statusbar.notification.people.PersonViewModel
+import com.android.systemui.statusbar.notification.people.Subscription
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.row.ExpandableView
+import com.android.systemui.statusbar.notification.row.StackScrollerDecorView
+import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.SectionProvider
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.util.children
+import com.android.systemui.util.foldToSparseArray
+import javax.inject.Inject
+
+/**
+ * Manages the boundaries of the two notification sections (high priority and low priority). Also
+ * shows/hides the headers for those sections where appropriate.
+ *
+ * TODO: Move remaining sections logic from NSSL into this class.
+ */
+class NotificationSectionsManager @Inject internal constructor(
+    private val activityStarter: ActivityStarter,
+    private val statusBarStateController: StatusBarStateController,
+    private val configurationController: ConfigurationController,
+    private val peopleHubViewAdapter: PeopleHubViewAdapter,
+    private val keyguardMediaController: KeyguardMediaController,
+    private val sectionsFeatureManager: NotificationSectionsFeatureManager,
+    private val logger: NotificationSectionsLogger
+) : SectionProvider {
+
+    private val configurationListener = object : ConfigurationController.ConfigurationListener {
+        override fun onLocaleListChanged() {
+            reinflateViews(LayoutInflater.from(parent.context))
+        }
+    }
+
+    private val peopleHubViewBoundary: PeopleHubViewBoundary = object : PeopleHubViewBoundary {
+        override fun setVisible(isVisible: Boolean) {
+            if (peopleHubVisible != isVisible) {
+                peopleHubVisible = isVisible
+                if (initialized) {
+                    updateSectionBoundaries("PeopleHub visibility changed")
+                }
+            }
+        }
+
+        override val associatedViewForClickAnimation: View
+            get() = peopleHeaderView!!
+
+        override val personViewAdapters: Sequence<DataListener<PersonViewModel?>>
+            get() = peopleHeaderView!!.personViewAdapters
+    }
+
+    private lateinit var parent: NotificationStackScrollLayout
+    private var initialized = false
+    private var onClearSilentNotifsClickListener: View.OnClickListener? = null
+
+    @get:VisibleForTesting
+    var silentHeaderView: SectionHeaderView? = null
+        private set
+
+    @get:VisibleForTesting
+    var alertingHeaderView: SectionHeaderView? = null
+        private set
+
+    @get:VisibleForTesting
+    var incomingHeaderView: SectionHeaderView? = null
+        private set
+
+    @get:VisibleForTesting
+    var peopleHeaderView: PeopleHubView? = null
+        private set
+
+    @set:VisibleForTesting
+    var peopleHubVisible = false
+    private var peopleHubSubscription: Subscription? = null
+
+    @get:VisibleForTesting
+    var mediaControlsView: MediaHeaderView? = null
+        private set
+
+    /** Must be called before use.  */
+    fun initialize(parent: NotificationStackScrollLayout, layoutInflater: LayoutInflater) {
+        check(!initialized) { "NotificationSectionsManager already initialized" }
+        initialized = true
+        this.parent = parent
+        reinflateViews(layoutInflater)
+        configurationController.addCallback(configurationListener)
+    }
+
+    private fun <T : ExpandableView> reinflateView(
+        view: T?,
+        layoutInflater: LayoutInflater,
+        @LayoutRes layoutResId: Int
+    ): T {
+        var oldPos = -1
+        view?.let {
+            view.transientContainer?.removeView(view)
+            if (view.parent === parent) {
+                oldPos = parent.indexOfChild(view)
+                parent.removeView(view)
+            }
+        }
+        val inflated = layoutInflater.inflate(layoutResId, parent, false) as T
+        if (oldPos != -1) {
+            parent.addView(inflated, oldPos)
+        }
+        return inflated
+    }
+
+    fun createSectionsForBuckets(): Array<NotificationSection> =
+            sectionsFeatureManager.getNotificationBuckets()
+                    .map { NotificationSection(parent, it) }
+                    .toTypedArray()
+
+    /**
+     * Reinflates the entire notification header, including all decoration views.
+     */
+    fun reinflateViews(layoutInflater: LayoutInflater) {
+        silentHeaderView = reinflateView(
+                silentHeaderView, layoutInflater, R.layout.status_bar_notification_section_header
+        ).apply {
+            setHeaderText(R.string.notification_section_header_gentle)
+            setOnHeaderClickListener { onGentleHeaderClick() }
+            setOnClearAllClickListener { onClearGentleNotifsClick(it) }
+        }
+        alertingHeaderView = reinflateView(
+                alertingHeaderView, layoutInflater, R.layout.status_bar_notification_section_header
+        ).apply {
+            setHeaderText(R.string.notification_section_header_alerting)
+            setOnHeaderClickListener { onGentleHeaderClick() }
+        }
+        peopleHubSubscription?.unsubscribe()
+        peopleHubSubscription = null
+        peopleHeaderView = reinflateView(peopleHeaderView, layoutInflater, R.layout.people_strip)
+        if (ENABLE_SNOOZED_CONVERSATION_HUB) {
+            peopleHubSubscription = peopleHubViewAdapter.bindView(peopleHubViewBoundary)
+        }
+        incomingHeaderView = reinflateView(
+                incomingHeaderView, layoutInflater, R.layout.status_bar_notification_section_header
+        ).apply {
+            setHeaderText(R.string.notification_section_header_incoming)
+            setOnHeaderClickListener { onGentleHeaderClick() }
+        }
+        mediaControlsView =
+                reinflateView(mediaControlsView, layoutInflater, R.layout.keyguard_media_header)
+                        .also(keyguardMediaController::attach)
+    }
+
+    override fun beginsSection(view: View, previous: View?): Boolean =
+            view === silentHeaderView ||
+            view === mediaControlsView ||
+            view === peopleHeaderView ||
+            view === alertingHeaderView ||
+            view === incomingHeaderView ||
+            getBucket(view) != getBucket(previous)
+
+    private fun getBucket(view: View?): Int? = when {
+        view === silentHeaderView -> BUCKET_SILENT
+        view === incomingHeaderView -> BUCKET_HEADS_UP
+        view === mediaControlsView -> BUCKET_MEDIA_CONTROLS
+        view === peopleHeaderView -> BUCKET_PEOPLE
+        view === alertingHeaderView -> BUCKET_ALERTING
+        view is ExpandableNotificationRow -> view.entry.bucket
+        else -> null
+    }
+
+    private fun logShadeContents() = parent.children.forEachIndexed { i, child ->
+        when {
+            child === incomingHeaderView -> logger.logIncomingHeader(i)
+            child === mediaControlsView -> logger.logMediaControls(i)
+            child === peopleHeaderView -> logger.logConversationsHeader(i)
+            child === alertingHeaderView -> logger.logAlertingHeader(i)
+            child === silentHeaderView -> logger.logSilentHeader(i)
+            child !is ExpandableNotificationRow -> logger.logOther(i, child.javaClass)
+            else -> {
+                val isHeadsUp = child.isHeadsUp
+                when (child.entry.bucket) {
+                    BUCKET_HEADS_UP -> logger.logHeadsUp(i, isHeadsUp)
+                    BUCKET_PEOPLE -> logger.logConversation(i, isHeadsUp)
+                    BUCKET_ALERTING -> logger.logAlerting(i, isHeadsUp)
+                    BUCKET_SILENT -> logger.logSilent(i, isHeadsUp)
+                }
+            }
+        }
+    }
+
+    private val isUsingMultipleSections: Boolean
+        get() = sectionsFeatureManager.getNumberOfBuckets() > 1
+
+    @VisibleForTesting
+    fun updateSectionBoundaries() = updateSectionBoundaries("test")
+
+    /**
+     * Should be called whenever notifs are added, removed, or updated. Updates section boundary
+     * bookkeeping and adds/moves/removes section headers if appropriate.
+     */
+    fun updateSectionBoundaries(reason: String) {
+        if (!isUsingMultipleSections) {
+            return
+        }
+        logger.logStartSectionUpdate(reason)
+
+        // The overall strategy here is to iterate over the current children of mParent, looking
+        // for where the sections headers are currently positioned, and where each section begins.
+        // Then, once we find the start of a new section, we track that position as the "target" for
+        // the section header, adjusted for the case where existing headers are in front of that
+        // target, but won't be once they are moved / removed after the pass has completed.
+        val showHeaders = statusBarStateController.state != StatusBarState.KEYGUARD
+        val usingPeopleFiltering = sectionsFeatureManager.isFilteringEnabled()
+        val usingMediaControls = sectionsFeatureManager.isMediaControlsEnabled()
+
+        var peopleNotifsPresent = false
+        var currentMediaControlsIdx = -1
+        val mediaControlsTarget = if (usingMediaControls) 0 else -1
+        var currentIncomingHeaderIdx = -1
+        var incomingHeaderTarget = -1
+        var currentPeopleHeaderIdx = -1
+        var peopleHeaderTarget = -1
+        var currentAlertingHeaderIdx = -1
+        var alertingHeaderTarget = -1
+        var currentGentleHeaderIdx = -1
+        var gentleHeaderTarget = -1
+
+        var lastNotifIndex = 0
+        var lastIncomingIndex = -1
+        var prev: ExpandableNotificationRow? = null
+
+        for ((i, child) in parent.children.withIndex()) {
+            when {
+                // Track the existing positions of the headers
+                child === incomingHeaderView -> {
+                    logger.logIncomingHeader(i)
+                    currentIncomingHeaderIdx = i
+                }
+                child === mediaControlsView -> {
+                    logger.logMediaControls(i)
+                    currentMediaControlsIdx = i
+                }
+                child === peopleHeaderView -> {
+                    logger.logConversationsHeader(i)
+                    currentPeopleHeaderIdx = i
+                }
+                child === alertingHeaderView -> {
+                    logger.logAlertingHeader(i)
+                    currentAlertingHeaderIdx = i
+                }
+                child === silentHeaderView -> {
+                    logger.logSilentHeader(i)
+                    currentGentleHeaderIdx = i
+                }
+                child !is ExpandableNotificationRow -> logger.logOther(i, child.javaClass)
+                else -> {
+                    lastNotifIndex = i
+                    // Is there a section discontinuity? This usually occurs due to HUNs
+                    if (prev?.entry?.bucket?.let { it > child.entry.bucket } == true) {
+                        // Remove existing headers, and move the Incoming header if necessary
+                        if (alertingHeaderTarget != -1) {
+                            if (showHeaders && incomingHeaderTarget != -1) {
+                                incomingHeaderTarget = alertingHeaderTarget
+                            }
+                            alertingHeaderTarget = -1
+                        }
+                        if (peopleHeaderTarget != -1) {
+                            if (showHeaders && incomingHeaderTarget != -1) {
+                                incomingHeaderTarget = peopleHeaderTarget
+                            }
+                            peopleHeaderTarget = -1
+                        }
+                        if (showHeaders && incomingHeaderTarget == -1) {
+                            incomingHeaderTarget = 0
+                        }
+                        // Walk backwards changing all previous notifications to the Incoming
+                        // section
+                        for (j in i - 1 downTo lastIncomingIndex + 1) {
+                            val prevChild = parent.getChildAt(j)
+                            if (prevChild is ExpandableNotificationRow) {
+                                prevChild.entry.bucket = BUCKET_HEADS_UP
+                            }
+                        }
+                        // Track the new bottom of the Incoming section
+                        lastIncomingIndex = i - 1
+                    }
+                    val isHeadsUp = child.isHeadsUp
+                    when (child.entry.bucket) {
+                        BUCKET_FOREGROUND_SERVICE -> logger.logForegroundService(i, isHeadsUp)
+                        BUCKET_PEOPLE -> {
+                            logger.logConversation(i, isHeadsUp)
+                            peopleNotifsPresent = true
+                            if (showHeaders && peopleHeaderTarget == -1) {
+                                peopleHeaderTarget = i
+                                // Offset the target if there are other headers before this that
+                                // will be moved.
+                                if (currentPeopleHeaderIdx != -1) {
+                                    peopleHeaderTarget--
+                                }
+                                if (currentAlertingHeaderIdx != -1) {
+                                    peopleHeaderTarget--
+                                }
+                                if (currentGentleHeaderIdx != -1) {
+                                    peopleHeaderTarget--
+                                }
+                            }
+                        }
+                        BUCKET_ALERTING -> {
+                            logger.logAlerting(i, isHeadsUp)
+                            if (showHeaders && usingPeopleFiltering && alertingHeaderTarget == -1) {
+                                alertingHeaderTarget = i
+                                // Offset the target if there are other headers before this that
+                                // will be moved.
+                                if (currentAlertingHeaderIdx != -1) {
+                                    alertingHeaderTarget--
+                                }
+                                if (currentGentleHeaderIdx != -1) {
+                                    alertingHeaderTarget--
+                                }
+                            }
+                        }
+                        BUCKET_SILENT -> {
+                            logger.logSilent(i, isHeadsUp)
+                            if (showHeaders && gentleHeaderTarget == -1) {
+                                gentleHeaderTarget = i
+                                // Offset the target if there are other headers before this that
+                                // will be moved.
+                                if (currentGentleHeaderIdx != -1) {
+                                    gentleHeaderTarget--
+                                }
+                            }
+                        }
+                    }
+
+                    prev = child
+                }
+            }
+        }
+
+        if (showHeaders && usingPeopleFiltering && peopleHubVisible && peopleHeaderTarget == -1) {
+            // Insert the people header even if there are no people visible, in order to show
+            // the hub. Put it directly above the next header.
+            peopleHeaderTarget = when {
+                alertingHeaderTarget != -1 -> alertingHeaderTarget
+                gentleHeaderTarget != -1 -> gentleHeaderTarget
+                else -> lastNotifIndex // Put it at the end of the list.
+            }
+            // Offset the target to account for the current position of the people header.
+            if (currentPeopleHeaderIdx != -1 && currentPeopleHeaderIdx < peopleHeaderTarget) {
+                peopleHeaderTarget--
+            }
+        }
+
+        logger.logStr("New header target positions:")
+        logger.logIncomingHeader(incomingHeaderTarget)
+        logger.logMediaControls(mediaControlsTarget)
+        logger.logConversationsHeader(peopleHeaderTarget)
+        logger.logAlertingHeader(alertingHeaderTarget)
+        logger.logSilentHeader(gentleHeaderTarget)
+
+        // Add headers in reverse order to preserve indices
+        silentHeaderView?.let {
+            adjustHeaderVisibilityAndPosition(gentleHeaderTarget, it, currentGentleHeaderIdx)
+        }
+        alertingHeaderView?.let {
+            adjustHeaderVisibilityAndPosition(alertingHeaderTarget, it, currentAlertingHeaderIdx)
+        }
+        peopleHeaderView?.let {
+            adjustHeaderVisibilityAndPosition(peopleHeaderTarget, it, currentPeopleHeaderIdx)
+        }
+        incomingHeaderView?.let {
+            adjustHeaderVisibilityAndPosition(incomingHeaderTarget, it, currentIncomingHeaderIdx)
+        }
+        mediaControlsView?.let {
+            adjustViewPosition(mediaControlsTarget, it, currentMediaControlsIdx)
+        }
+
+        logger.logStr("Final order:")
+        logShadeContents()
+        logger.logStr("Section boundary update complete")
+
+        // Update headers to reflect state of section contents
+        silentHeaderView?.setAreThereDismissableGentleNotifs(
+                parent.hasActiveClearableNotifications(NotificationStackScrollLayout.ROWS_GENTLE)
+        )
+        peopleHeaderView?.canSwipe = showHeaders && peopleHubVisible && !peopleNotifsPresent
+        if (peopleHeaderTarget != currentPeopleHeaderIdx) {
+            peopleHeaderView?.resetTranslation()
+        }
+    }
+
+    private fun adjustHeaderVisibilityAndPosition(
+        targetPosition: Int,
+        header: StackScrollerDecorView,
+        currentPosition: Int
+    ) {
+        adjustViewPosition(targetPosition, header, currentPosition)
+        if (targetPosition != -1 && currentPosition == -1) {
+            header.isContentVisible = true
+        }
+    }
+
+    private fun adjustViewPosition(
+        targetPosition: Int,
+        view: ExpandableView,
+        currentPosition: Int
+    ) {
+        if (targetPosition == -1) {
+            if (currentPosition != -1) {
+                parent.removeView(view)
+            }
+        } else {
+            if (currentPosition == -1) {
+                // If the header is animating away, it will still have a parent, so detach it first
+                // TODO: We should really cancel the active animations here. This will happen
+                // automatically when the view's intro animation starts, but it's a fragile link.
+                view.transientContainer?.removeTransientView(view)
+                view.transientContainer = null
+                parent.addView(view, targetPosition)
+            } else {
+                parent.changeViewPosition(view, targetPosition)
+            }
+        }
+    }
+
+    private sealed class SectionBounds {
+
+        data class Many(
+            val first: ActivatableNotificationView,
+            val last: ActivatableNotificationView
+        ) : SectionBounds()
+
+        data class One(val lone: ActivatableNotificationView) : SectionBounds()
+        object None : SectionBounds()
+
+        fun addNotif(notif: ActivatableNotificationView): SectionBounds = when (this) {
+            is None -> One(notif)
+            is One -> Many(lone, notif)
+            is Many -> copy(last = notif)
+        }
+
+        fun updateSection(section: NotificationSection): Boolean = when (this) {
+            is None -> section.setFirstAndLastVisibleChildren(null, null)
+            is One -> section.setFirstAndLastVisibleChildren(lone, lone)
+            is Many -> section.setFirstAndLastVisibleChildren(first, last)
+        }
+
+        private fun NotificationSection.setFirstAndLastVisibleChildren(
+            first: ActivatableNotificationView?,
+            last: ActivatableNotificationView?
+        ): Boolean {
+            val firstChanged = setFirstVisibleChild(first)
+            val lastChanged = setLastVisibleChild(last)
+            return firstChanged || lastChanged
+        }
+    }
+
+    /**
+     * Updates the boundaries (as tracked by their first and last views) of the priority sections.
+     *
+     * @return `true` If the last view in the top section changed (so we need to animate).
+     */
+    fun updateFirstAndLastViewsForAllSections(
+        sections: Array<NotificationSection>,
+        children: List<ActivatableNotificationView>
+    ): Boolean {
+        // Create mapping of bucket to section
+        val sectionBounds = children.asSequence()
+                // Group children by bucket
+                .groupingBy {
+                    getBucket(it)
+                            ?: throw IllegalArgumentException("Cannot find section bucket for view")
+                }
+                // Combine each bucket into a SectionBoundary
+                .foldToSparseArray(
+                        SectionBounds.None,
+                        size = sections.size,
+                        operation = SectionBounds::addNotif
+                )
+        // Update each section with the associated boundary, tracking if there was a change
+        val changed = sections.fold(false) { changed, section ->
+            val bounds = sectionBounds[section.bucket] ?: SectionBounds.None
+            bounds.updateSection(section) || changed
+        }
+        if (DEBUG) {
+            logSections(sections)
+        }
+        return changed
+    }
+
+    private fun logSections(sections: Array<NotificationSection>) {
+        for (i in sections.indices) {
+            val s = sections[i]
+            val fs = when (val first = s.firstVisibleChild) {
+                null -> "(null)"
+                is ExpandableNotificationRow -> first.entry.key
+                else -> Integer.toHexString(System.identityHashCode(first))
+            }
+            val ls = when (val last = s.lastVisibleChild) {
+                null -> "(null)"
+                is ExpandableNotificationRow -> last.entry.key
+                else -> Integer.toHexString(System.identityHashCode(last))
+            }
+            Log.d(TAG, "updateSections: f=$fs s=$i")
+            Log.d(TAG, "updateSections: l=$ls s=$i")
+        }
+    }
+
+    private fun onGentleHeaderClick() {
+        val intent = Intent(Settings.ACTION_NOTIFICATION_SETTINGS)
+        activityStarter.startActivity(
+                intent,
+                true,
+                true,
+                Intent.FLAG_ACTIVITY_SINGLE_TOP)
+    }
+
+    private fun onClearGentleNotifsClick(v: View) {
+        onClearSilentNotifsClickListener?.onClick(v)
+    }
+
+    /** Listener for when the "clear all" button is clicked on the gentle notification header. */
+    fun setOnClearSilentNotifsClickListener(listener: View.OnClickListener) {
+        onClearSilentNotifsClickListener = listener
+    }
+
+    fun hidePeopleRow() {
+        peopleHubVisible = false
+        updateSectionBoundaries("PeopleHub dismissed")
+    }
+
+    fun setHeaderForegroundColor(@ColorInt color: Int) {
+        peopleHeaderView?.setTextColor(color)
+        silentHeaderView?.setForegroundColor(color)
+        alertingHeaderView?.setForegroundColor(color)
+    }
+
+    companion object {
+        private const val TAG = "NotifSectionsManager"
+        private const val DEBUG = false
+        private const val ENABLE_SNOOZED_CONVERSATION_HUB = false
+    }
+}
+
+/**
+ * For now, declare the available notification buckets (sections) here so that other
+ * presentation code can decide what to do based on an entry's buckets
+ */
+@Retention(AnnotationRetention.SOURCE)
+@IntDef(
+        prefix = ["BUCKET_"],
+        value = [
+            BUCKET_UNKNOWN, BUCKET_MEDIA_CONTROLS, BUCKET_HEADS_UP, BUCKET_FOREGROUND_SERVICE,
+            BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT
+        ]
+)
+annotation class PriorityBucket
+
+const val BUCKET_UNKNOWN = 0
+const val BUCKET_MEDIA_CONTROLS = 1
+const val BUCKET_HEADS_UP = 2
+const val BUCKET_FOREGROUND_SERVICE = 3
+const val BUCKET_PEOPLE = 4
+const val BUCKET_ALERTING = 5
+const val BUCKET_SILENT = 6
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 7f32c00..e33cc60 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -21,7 +21,7 @@
 
 import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
 import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
 import static com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.ANCHOR_SCROLLING;
 import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE;
 import static com.android.systemui.statusbar.phone.NotificationIconAreaController.HIGH_PRIORITY;
@@ -29,7 +29,6 @@
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
-import android.app.TaskStackBuilder;
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.TimeAnimator;
@@ -51,7 +50,6 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
-import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -579,7 +577,7 @@
 
         mSectionsManager = notificationSectionsManager;
         mSectionsManager.initialize(this, LayoutInflater.from(context));
-        mSectionsManager.setOnClearGentleNotifsClickListener(v -> {
+        mSectionsManager.setOnClearSilentNotifsClickListener(v -> {
             // Leave the shade open if there will be other notifs left over to clear
             final boolean closeShade = !hasActiveClearableNotifications(ROWS_HIGH_PRIORITY);
             clearNotifications(ROWS_GENTLE, closeShade);
@@ -3074,6 +3072,9 @@
      */
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private boolean generateRemoveAnimation(ExpandableView child) {
+        if (!child.wantsAddAndRemoveAnimations()) {
+            return false;
+        }
         if (removeRemovedChildFromHeadsUpChangeAnimations(child)) {
             mAddedHeadsUpChildren.remove(child);
             return false;
@@ -3428,7 +3429,8 @@
     @Override
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     public void generateAddAnimation(ExpandableView child, boolean fromMoreCard) {
-        if (mIsExpanded && mAnimationsEnabled && !mChangePositionInProgress && !isFullyHidden()) {
+        if (mIsExpanded && mAnimationsEnabled && !mChangePositionInProgress && !isFullyHidden()
+                && child.wantsAddAndRemoveAnimations()) {
             // Generate Animations
             mChildrenToAddAnimated.add(child);
             if (fromMoreCard) {
@@ -5841,7 +5843,7 @@
         // Let's update the footer once the notifications have been updated (in the next frame)
         post(() -> {
             updateFooter();
-            updateSectionBoundaries();
+            updateSectionBoundaries("dynamic privacy changed");
         });
     }
 
@@ -5922,8 +5924,8 @@
 
     /** Updates the indices of the boundaries between sections. */
     @ShadeViewRefactor(RefactorComponent.INPUT)
-    public void updateSectionBoundaries() {
-        mSectionsManager.updateSectionBoundaries();
+    public void updateSectionBoundaries(String reason) {
+        mSectionsManager.updateSectionBoundaries(reason);
     }
 
     private void updateContinuousBackgroundDrawing() {
@@ -5981,6 +5983,7 @@
 
                 // ANIMATION_TYPE_ADD
                 new AnimationFilter()
+                        .animateAlpha()
                         .animateHeight()
                         .animateTopInset()
                         .animateY()
@@ -5989,6 +5992,7 @@
 
                 // ANIMATION_TYPE_REMOVE
                 new AnimationFilter()
+                        .animateAlpha()
                         .animateHeight()
                         .animateTopInset()
                         .animateY()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 0e8c1b7..8bcdbfe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -113,16 +113,6 @@
                 }
             };
 
-    private TaskStackChangeListener mTaskStackChangeListener = new TaskStackChangeListener() {
-        @Override
-        public void onRecentTaskListFrozenChanged(boolean frozen) {
-            if (!frozen) {
-                mStartingQuickstepRotation = -1;
-                mDisabledForQuickstep = false;
-            }
-        }
-    };
-
     private final ContentObserver mFixedRotationObserver = new ContentObserver(
             new Handler(Looper.getMainLooper())) {
         @Override
@@ -287,12 +277,8 @@
 
     private void setRotationCallbacks(boolean enable) {
         if (enable) {
-            ActivityManagerWrapper.getInstance().registerTaskStackListener(
-                    mTaskStackChangeListener);
             mOverviewProxyService.addCallback(mQuickSwitchListener);
         } else {
-            ActivityManagerWrapper.getInstance().unregisterTaskStackListener(
-                    mTaskStackChangeListener);
             mOverviewProxyService.removeCallback(mQuickSwitchListener);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 6b0df95..3dcf7ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -439,7 +439,8 @@
                         // time out anyway
                         && !entry.showingPulsing()) {
                     mEntriesToRemoveWhenReorderingAllowed.add(entry);
-                    mVisualStabilityManager.addReorderingAllowedCallback(HeadsUpManagerPhone.this);
+                    mVisualStabilityManager.addReorderingAllowedCallback(HeadsUpManagerPhone.this,
+                            false  /* persistent */);
                 } else if (mTrackingHeadsUp) {
                     mEntriesToRemoveAfterExpand.add(entry);
                 } else if (mIsAutoHeadsUp && mStatusBarState == StatusBarState.KEYGUARD) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index b2aa769..54511c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -305,14 +305,6 @@
         }
     };
 
-    private TaskStackChangeListener mTasksFrozenListener = new TaskStackChangeListener() {
-        @Override
-        public void onRecentTaskListFrozenChanged(boolean frozen) {
-            mFrozenTasks = frozen;
-            orientSecondaryHomeHandle();
-        }
-    };
-
     private NavigationBarTransitions.DarkIntensityListener mOrientationHandleIntensityListener =
             new NavigationBarTransitions.DarkIntensityListener() {
                 @Override
@@ -510,7 +502,6 @@
         }
 
         initSecondaryHomeHandleForRotation();
-        ActivityManagerWrapper.getInstance().registerTaskStackListener(mTasksFrozenListener);
     }
 
     @Override
@@ -527,7 +518,6 @@
         }
         mOverviewProxyService.removeCallback(mOverviewProxyListener);
         mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver);
-        ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTasksFrozenListener);
         if (mOrientationHandle != null) {
             resetSecondaryHandle();
             getContext().getSystemService(DisplayManager.class).unregisterDisplayListener(this);
@@ -594,7 +584,7 @@
             return;
         }
 
-        if (!mFrozenTasks) {
+        if (mStartingQuickSwitchRotation == -1) {
             resetSecondaryHandle();
         } else {
             int deltaRotation = deltaRotation(mCurrentRotation, mStartingQuickSwitchRotation);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index 84dd48b..80785db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.phone;
 
 import android.annotation.Nullable;
-import android.app.NotificationChannel;
 import android.service.notification.StatusBarNotification;
 import android.util.ArraySet;
 import android.util.Log;
@@ -28,6 +27,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
@@ -42,6 +42,8 @@
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
+import dagger.Lazy;
+
 /**
  * A class to handle notifications and their corresponding groups.
  */
@@ -51,6 +53,7 @@
     private static final String TAG = "NotificationGroupManager";
     private final HashMap<String, NotificationGroup> mGroupMap = new HashMap<>();
     private final ArraySet<OnGroupChangeListener> mListeners = new ArraySet<>();
+    private final Lazy<PeopleNotificationIdentifier> mPeopleNotificationIdentifier;
     private int mBarState = -1;
     private HashMap<String, StatusBarNotification> mIsolatedEntries = new HashMap<>();
     private HeadsUpManager mHeadsUpManager;
@@ -58,8 +61,11 @@
     @Nullable private BubbleController mBubbleController = null;
 
     @Inject
-    public NotificationGroupManager(StatusBarStateController statusBarStateController) {
+    public NotificationGroupManager(
+            StatusBarStateController statusBarStateController,
+            Lazy<PeopleNotificationIdentifier> peopleNotificationIdentifier) {
         statusBarStateController.addCallback(this);
+        mPeopleNotificationIdentifier = peopleNotificationIdentifier;
     }
 
     private BubbleController getBubbleController() {
@@ -536,8 +542,9 @@
         if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) {
             return false;
         }
-        NotificationChannel channel = entry.getChannel();
-        if (channel != null && channel.isImportantConversation()) {
+        int peopleNotificationType = mPeopleNotificationIdentifier.get().getPeopleNotificationType(
+                entry.getSbn(), entry.getRanking());
+        if (peopleNotificationType == PeopleNotificationIdentifier.TYPE_IMPORTANT_PERSON) {
             return true;
         }
         if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.getKey())) {
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 c9716d3..999e636 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -38,6 +38,7 @@
 import android.graphics.Region;
 import android.graphics.drawable.Drawable;
 import android.hardware.biometrics.BiometricSourceType;
+import android.os.Bundle;
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.util.Log;
@@ -51,6 +52,7 @@
 import android.view.ViewTreeObserver;
 import android.view.WindowInsets;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.FrameLayout;
 import android.widget.TextView;
 
@@ -69,6 +71,7 @@
 import com.android.systemui.doze.DozeLog;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
+import com.android.systemui.media.MediaHierarchyManager;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -242,6 +245,8 @@
     private final KeyguardBypassController mKeyguardBypassController;
     private final KeyguardUpdateMonitor mUpdateMonitor;
     private final ConversationNotificationManager mConversationNotificationManager;
+    private final MediaHierarchyManager mMediaHierarchyManager;
+    private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
     private KeyguardAffordanceHelper mAffordanceHelper;
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
@@ -437,6 +442,26 @@
 
     private int mOldLayoutDirection;
 
+    private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() {
+        @Override
+        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+            super.onInitializeAccessibilityNodeInfo(host, info);
+            info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD);
+            info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_UP);
+        }
+
+        @Override
+        public boolean performAccessibilityAction(View host, int action, Bundle args) {
+            if (action == AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD.getId()
+                    || action
+                    == AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_UP.getId()) {
+                mStatusBarKeyguardViewManager.showBouncer(true);
+                return true;
+            }
+            return super.performAccessibilityAction(host, action, args);
+        }
+    };
+
     @Inject
     public NotificationPanelViewController(NotificationPanelView view,
             InjectionInflationController injectionInflationController,
@@ -456,7 +481,9 @@
             ConfigurationController configurationController,
             FlingAnimationUtils.Builder flingAnimationUtilsBuilder,
             StatusBarTouchableRegionManager statusBarTouchableRegionManager,
-            ConversationNotificationManager conversationNotificationManager) {
+            ConversationNotificationManager conversationNotificationManager,
+            MediaHierarchyManager mediaHierarchyManager,
+            StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
         super(view, falsingManager, dozeLog, keyguardStateController,
                 (SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
                 latencyTracker, flingAnimationUtilsBuilder, statusBarTouchableRegionManager);
@@ -466,6 +493,8 @@
         mZenModeController = zenModeController;
         mConfigurationController = configurationController;
         mFlingAnimationUtilsBuilder = flingAnimationUtilsBuilder;
+        mMediaHierarchyManager = mediaHierarchyManager;
+        mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
         mView.setWillNotDraw(!DEBUG);
         mInjectionInflationController = injectionInflationController;
         mFalsingManager = falsingManager;
@@ -579,6 +608,8 @@
                 mOldLayoutDirection = layoutDirection;
             }
         });
+
+        mView.setAccessibilityDelegate(mAccessibilityDelegate);
     }
 
     @Override
@@ -1609,7 +1640,7 @@
         if (mQs == null) return;
         float qsExpansionFraction = getQsExpansionFraction();
         mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation());
-        int heightDiff = mQs.getDesiredHeight() - mQs.getQsMinExpansionHeight();
+        mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
         mNotificationStackScroller.setQsExpansionFraction(qsExpansionFraction);
     }
 
@@ -2880,8 +2911,8 @@
         return mNotificationStackScroller.createDelegate();
     }
 
-    public void updateNotificationViews() {
-        mNotificationStackScroller.updateSectionBoundaries();
+    void updateNotificationViews(String reason) {
+        mNotificationStackScroller.updateSectionBoundaries(reason);
         mNotificationStackScroller.updateSpeedBumpIndex();
         mNotificationStackScroller.updateFooter();
         updateShowEmptyShadeView();
@@ -3514,7 +3545,11 @@
             // Calculate quick setting heights.
             int oldMaxHeight = mQsMaxExpansionHeight;
             if (mQs != null) {
+                float previousMin = mQsMinExpansionHeight;
                 mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQs.getQsMinExpansionHeight();
+                if (mQsExpansionHeight == previousMin) {
+                    mQsExpansionHeight = mQsMinExpansionHeight;
+                }
                 mQsMaxExpansionHeight = mQs.getDesiredHeight();
                 mNotificationStackScroller.setMaxTopPadding(
                         mQsMaxExpansionHeight + mQsNotificationTopPadding);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
index 567ddb6..2e4a929d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
@@ -279,7 +279,7 @@
         } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
             mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
             // Make sure to remove FLAG_ALT_FOCUSABLE_IM when keyguard needs input.
-            if (state.mKeyguardNeedsInput) {
+            if (state.mKeyguardNeedsInput && state.isKeyguardShowingAndNotOccluded()) {
                 mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
             } else {
                 mLpChanged.flags |= LayoutParams.FLAG_ALT_FOCUSABLE_IM;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
index 0d25898..42222d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
@@ -430,15 +430,19 @@
     }
 
     public void setExpandAnimationPending(boolean pending) {
-        mExpandAnimationPending = pending;
-        mNotificationShadeWindowController
-                .setLaunchingActivity(mExpandAnimationPending | mExpandAnimationRunning);
+        if (mExpandAnimationPending != pending) {
+            mExpandAnimationPending = pending;
+            mNotificationShadeWindowController
+                    .setLaunchingActivity(mExpandAnimationPending | mExpandAnimationRunning);
+        }
     }
 
     public void setExpandAnimationRunning(boolean running) {
-        mExpandAnimationRunning = running;
-        mNotificationShadeWindowController
-                .setLaunchingActivity(mExpandAnimationPending | mExpandAnimationRunning);
+        if (mExpandAnimationRunning != running) {
+            mExpandAnimationRunning = running;
+            mNotificationShadeWindowController
+                    .setLaunchingActivity(mExpandAnimationPending | mExpandAnimationRunning);
+        }
     }
 
     public void cancelExpandHelper() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index d4f4d3b..2a4475b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -46,6 +46,8 @@
 import com.android.systemui.dagger.qualifiers.DisplayId;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
+import com.android.systemui.media.MediaData;
+import com.android.systemui.media.MediaDataManager;
 import com.android.systemui.qs.tiles.DndTile;
 import com.android.systemui.qs.tiles.RotationLockTile;
 import com.android.systemui.screenrecord.RecordingController;
@@ -80,14 +82,14 @@
  */
 public class PhoneStatusBarPolicy
         implements BluetoothController.Callback,
-                CommandQueue.Callbacks,
-                RotationLockControllerCallback,
-                Listener,
-                ZenModeController.Callback,
-                DeviceProvisionedListener,
-                KeyguardStateController.Callback,
-                LocationController.LocationChangeCallback,
-                RecordingController.RecordingStateChangeCallback {
+        CommandQueue.Callbacks,
+        RotationLockControllerCallback,
+        Listener,
+        ZenModeController.Callback,
+        DeviceProvisionedListener,
+        KeyguardStateController.Callback,
+        LocationController.LocationChangeCallback,
+        RecordingController.RecordingStateChangeCallback, MediaDataManager.Listener {
     private static final String TAG = "PhoneStatusBarPolicy";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -108,6 +110,7 @@
     private final String mSlotLocation;
     private final String mSlotSensorsOff;
     private final String mSlotScreenRecord;
+    private final String mSlotMedia;
     private final int mDisplayId;
     private final SharedPreferences mSharedPreferences;
     private final DateFormatUtil mDateFormatUtil;
@@ -135,6 +138,7 @@
     private final SensorPrivacyController mSensorPrivacyController;
     private final RecordingController mRecordingController;
     private final RingerModeTracker mRingerModeTracker;
+    private final MediaDataManager mMediaDataManager;
 
     private boolean mZenVisible;
     private boolean mVolumeVisible;
@@ -159,6 +163,7 @@
             SensorPrivacyController sensorPrivacyController, IActivityManager iActivityManager,
             AlarmManager alarmManager, UserManager userManager,
             RecordingController recordingController,
+            MediaDataManager mediaDataManager,
             @Nullable TelecomManager telecomManager, @DisplayId int displayId,
             @Main SharedPreferences sharedPreferences, DateFormatUtil dateFormatUtil,
             RingerModeTracker ringerModeTracker) {
@@ -185,6 +190,7 @@
         mUiBgExecutor = uiBgExecutor;
         mTelecomManager = telecomManager;
         mRingerModeTracker = ringerModeTracker;
+        mMediaDataManager = mediaDataManager;
 
         mSlotCast = resources.getString(com.android.internal.R.string.status_bar_cast);
         mSlotHotspot = resources.getString(com.android.internal.R.string.status_bar_hotspot);
@@ -202,6 +208,7 @@
         mSlotSensorsOff = resources.getString(com.android.internal.R.string.status_bar_sensors_off);
         mSlotScreenRecord = resources.getString(
                 com.android.internal.R.string.status_bar_screen_record);
+        mSlotMedia = resources.getString(com.android.internal.R.string.status_bar_media);
 
         mDisplayId = displayId;
         mSharedPreferences = sharedPreferences;
@@ -280,6 +287,11 @@
         mIconController.setIconVisibility(mSlotSensorsOff,
                 mSensorPrivacyController.isSensorPrivacyEnabled());
 
+        // play/pause icon when media is active
+        mIconController.setIcon(mSlotMedia, R.drawable.stat_sys_media,
+                mResources.getString(R.string.accessibility_media_active));
+        mIconController.setIconVisibility(mSlotMedia, mMediaDataManager.hasActiveMedia());
+
         // screen record
         mIconController.setIcon(mSlotScreenRecord, R.drawable.stat_sys_screen_record, null);
         mIconController.setIconVisibility(mSlotScreenRecord, false);
@@ -296,6 +308,7 @@
         mSensorPrivacyController.addCallback(mSensorPrivacyListener);
         mLocationController.addCallback(this);
         mRecordingController.addCallback(this);
+        mMediaDataManager.addListener(this);
 
         mCommandQueue.addCallback(this);
     }
@@ -663,6 +676,7 @@
         if (DEBUG) Log.d(TAG, "screenrecord: countdown " + millisUntilFinished);
         int countdown = (int) Math.floorDiv(millisUntilFinished + 500, 1000);
         int resourceId = R.drawable.stat_sys_screen_record;
+        String description = Integer.toString(countdown);
         switch (countdown) {
             case 1:
                 resourceId = R.drawable.stat_sys_screen_record_1;
@@ -674,7 +688,7 @@
                 resourceId = R.drawable.stat_sys_screen_record_3;
                 break;
         }
-        mIconController.setIcon(mSlotScreenRecord, resourceId, null);
+        mIconController.setIcon(mSlotScreenRecord, resourceId, description);
         mIconController.setIconVisibility(mSlotScreenRecord, true);
     }
 
@@ -688,7 +702,8 @@
     public void onRecordingStart() {
         if (DEBUG) Log.d(TAG, "screenrecord: showing icon");
         mIconController.setIcon(mSlotScreenRecord,
-                R.drawable.stat_sys_screen_record, null);
+                R.drawable.stat_sys_screen_record,
+                mResources.getString(R.string.screenrecord_ongoing_screen_only));
         mIconController.setIconVisibility(mSlotScreenRecord, true);
     }
 
@@ -698,4 +713,18 @@
         if (DEBUG) Log.d(TAG, "screenrecord: hiding icon");
         mHandler.post(() -> mIconController.setIconVisibility(mSlotScreenRecord, false));
     }
+
+    @Override
+    public void onMediaDataLoaded(String key, MediaData data) {
+        updateMediaIcon();
+    }
+
+    @Override
+    public void onMediaDataRemoved(String key) {
+        updateMediaIcon();
+    }
+
+    private void updateMediaIcon() {
+        mIconController.setIconVisibility(mSlotMedia, mMediaDataManager.hasActiveMedia());
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
index ba32327..de9c745 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
@@ -37,8 +37,9 @@
 import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityManager;
 
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
@@ -60,7 +61,7 @@
 
     private static final int NUM_ACCEPTED_ROTATION_SUGGESTIONS_FOR_INTRODUCTION = 3;
 
-    private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
+    private final UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
     private final ViewRippler mViewRippler = new ViewRippler();
 
     private @StyleRes int mStyleRes;
@@ -323,7 +324,7 @@
     }
 
     private void onRotateSuggestionClick(View v) {
-        mMetricsLogger.action(MetricsEvent.ACTION_ROTATION_SUGGESTION_ACCEPTED);
+        mUiEventLogger.log(RotationButtonEvent.ROTATION_SUGGESTION_ACCEPTED);
         incrementNumAcceptedRotationSuggestionsIfNeeded();
         setRotationLockedAtAngle(mLastRotationSuggestion);
     }
@@ -345,7 +346,7 @@
     private void showAndLogRotationSuggestion() {
         setRotateSuggestionButtonState(true /* visible */);
         rescheduleRotationTimeout(false /* reasonHover */);
-        mMetricsLogger.visible(MetricsEvent.ROTATION_SUGGESTION_SHOWN);
+        mUiEventLogger.log(RotationButtonEvent.ROTATION_SUGGESTION_SHOWN);
     }
 
     private boolean shouldOverrideUserLockPrefs(final int rotation) {
@@ -474,4 +475,19 @@
             }
         };
     }
+
+    enum RotationButtonEvent implements UiEventLogger.UiEventEnum {
+        @UiEvent(doc = "The rotation button was shown")
+        ROTATION_SUGGESTION_SHOWN(206),
+        @UiEvent(doc = "The rotation button was clicked")
+        ROTATION_SUGGESTION_ACCEPTED(207);
+
+        private final int mId;
+        RotationButtonEvent(int id) {
+            mId = id;
+        }
+        @Override public int getId() {
+            return mId;
+        }
+    }
 }
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 dd54a3d..19de191 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1488,7 +1488,7 @@
         if (mDividerOptional.isPresent()) {
             divider = mDividerOptional.get();
         }
-        if (divider == null || !divider.inSplitMode()) {
+        if (divider == null || !divider.isDividerVisible()) {
             final int navbarPos = WindowManagerWrapper.getInstance().getNavBarPosition(mDisplayId);
             if (navbarPos == NAV_BAR_POS_INVALID) {
                 return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 44ece35..64e5f0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -45,7 +45,6 @@
 import android.view.View;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.ActivityIntentHelper;
@@ -59,6 +58,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.statusbar.NotificationClickNotifier;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -103,7 +103,7 @@
     private final NotifCollection mNotifCollection;
     private final HeadsUpManagerPhone mHeadsUpManager;
     private final ActivityStarter mActivityStarter;
-    private final IStatusBarService mBarService;
+    private final NotificationClickNotifier mClickNotifier;
     private final StatusBarStateController mStatusBarStateController;
     private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
     private final KeyguardManager mKeyguardManager;
@@ -142,7 +142,7 @@
             NotifCollection notifCollection,
             HeadsUpManagerPhone headsUpManager,
             ActivityStarter activityStarter,
-            IStatusBarService statusBarService,
+            NotificationClickNotifier clickNotifier,
             StatusBarStateController statusBarStateController,
             StatusBarKeyguardViewManager statusBarKeyguardViewManager,
             KeyguardManager keyguardManager,
@@ -177,7 +177,7 @@
         mNotifCollection = notifCollection;
         mHeadsUpManager = headsUpManager;
         mActivityStarter = activityStarter;
-        mBarService = statusBarService;
+        mClickNotifier = clickNotifier;
         mStatusBarStateController = statusBarStateController;
         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
         mKeyguardManager = keyguardManager;
@@ -379,11 +379,7 @@
                 NotificationLogger.getNotificationLocation(entry);
         final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
                 rank, count, true, location);
-        try {
-            mBarService.onNotificationClick(notificationKey, nv);
-        } catch (RemoteException ex) {
-            // system process is dead if we're here.
-        }
+        mClickNotifier.onNotificationClick(notificationKey, nv);
 
         if (!isBubble) {
             if (parentToCancelFinal != null) {
@@ -429,7 +425,9 @@
             }
             int launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
                     null, null, getActivityOptions(adapter));
-            mActivityLaunchAnimator.setLaunchResult(launchResult, isActivityIntent);
+            mMainThreadHandler.post(() -> {
+                mActivityLaunchAnimator.setLaunchResult(launchResult, isActivityIntent);
+            });
         } catch (RemoteException | PendingIntent.CanceledException e) {
             // the stack trace isn't very helpful here.
             // Just log the exception message.
@@ -449,10 +447,11 @@
                                 mActivityLaunchAnimator.getLaunchAnimation(
                                         row, mStatusBar.isOccluded())),
                                 new UserHandle(UserHandle.getUserId(appUid)));
-                mActivityLaunchAnimator.setLaunchResult(launchResult, true /* isActivityIntent */);
 
                 // Putting it back on the main thread, since we're touching views
                 mMainThreadHandler.post(() -> {
+                    mActivityLaunchAnimator.setLaunchResult(launchResult,
+                            true /* isActivityIntent */);
                     removeHUN(row);
                 });
                 if (shouldCollapse()) {
@@ -648,7 +647,7 @@
         private final NotifCollection mNotifCollection;
         private final HeadsUpManagerPhone mHeadsUpManager;
         private final ActivityStarter mActivityStarter;
-        private final IStatusBarService mStatusBarService;
+        private final NotificationClickNotifier mClickNotifier;
         private final StatusBarStateController mStatusBarStateController;
         private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
         private final KeyguardManager mKeyguardManager;
@@ -686,7 +685,7 @@
                 NotifCollection notifCollection,
                 HeadsUpManagerPhone headsUpManager,
                 ActivityStarter activityStarter,
-                IStatusBarService statusBarService,
+                NotificationClickNotifier clickNotifier,
                 StatusBarStateController statusBarStateController,
                 StatusBarKeyguardViewManager statusBarKeyguardViewManager,
                 KeyguardManager keyguardManager,
@@ -717,7 +716,7 @@
             mNotifCollection = notifCollection;
             mHeadsUpManager = headsUpManager;
             mActivityStarter = activityStarter;
-            mStatusBarService = statusBarService;
+            mClickNotifier = clickNotifier;
             mStatusBarStateController = statusBarStateController;
             mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
             mKeyguardManager = keyguardManager;
@@ -774,7 +773,7 @@
                     mNotifCollection,
                     mHeadsUpManager,
                     mActivityStarter,
-                    mStatusBarService,
+                    mClickNotifier,
                     mStatusBarStateController,
                     mStatusBarKeyguardViewManager,
                     mKeyguardManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index aecbb90..84da35b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -296,20 +296,20 @@
     }
 
     @Override
-    public void updateNotificationViews() {
+    public void updateNotificationViews(final String reason) {
         // The function updateRowStates depends on both of these being non-null, so check them here.
         // We may be called before they are set from DeviceProvisionedController's callback.
         if (mScrimController == null) return;
 
         // Do not modify the notifications during collapse.
         if (isCollapsing()) {
-            mShadeController.addPostCollapseAction(this::updateNotificationViews);
+            mShadeController.addPostCollapseAction(() -> updateNotificationViews(reason));
             return;
         }
 
         mViewHierarchyManager.updateNotificationViews();
 
-        mNotificationPanel.updateNotificationViews();
+        mNotificationPanel.updateNotificationViews(reason);
     }
 
     public void onNotificationRemoved(String key, StatusBarNotification old) {
@@ -347,7 +347,7 @@
             updateNotificationOnUiModeChanged();
             mDispatchUiModeChangeOnUserSwitched = false;
         }
-        updateNotificationViews();
+        updateNotificationViews("user switched");
         mMediaManager.clearCurrentMediaNotification();
         mStatusBar.setLockscreenUser(newUserId);
         updateMediaMetaData(true, false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 428de9e..669e6a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -37,6 +37,7 @@
 import com.android.systemui.ActivityIntentHelper;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.ActionClickLogger;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -73,6 +74,7 @@
     private View mPendingRemoteInputView;
     private KeyguardManager mKeyguardManager;
     private final CommandQueue mCommandQueue;
+    private final ActionClickLogger mActionClickLogger;
     private int mDisabled2;
     protected BroadcastReceiver mChallengeReceiver = new ChallengeReceiver();
     private Handler mMainHandler = new Handler();
@@ -87,7 +89,8 @@
             StatusBarStateController statusBarStateController,
             StatusBarKeyguardViewManager statusBarKeyguardViewManager,
             ActivityStarter activityStarter, ShadeController shadeController,
-            CommandQueue commandQueue) {
+            CommandQueue commandQueue,
+            ActionClickLogger clickLogger) {
         mContext = context;
         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
         mShadeController = shadeController;
@@ -101,6 +104,7 @@
         mKeyguardManager = context.getSystemService(KeyguardManager.class);
         mCommandQueue = commandQueue;
         mCommandQueue.addCallback(this);
+        mActionClickLogger = clickLogger;
         mActivityIntentHelper = new ActivityIntentHelper(mContext);
         mGroupManager = groupManager;
         // Listen to onKeyguardShowingChanged in case a managed profile needs to be unlocked
@@ -304,9 +308,12 @@
             NotificationRemoteInputManager.ClickHandler defaultHandler) {
         final boolean isActivity = pendingIntent.isActivity();
         if (isActivity) {
+            mActionClickLogger.logWaitingToCloseKeyguard(pendingIntent);
             final boolean afterKeyguardGone = mActivityIntentHelper.wouldLaunchResolverActivity(
                     pendingIntent.getIntent(), mLockscreenUserManager.getCurrentUserId());
             mActivityStarter.dismissKeyguardThenExecute(() -> {
+                mActionClickLogger.logKeyguardGone(pendingIntent);
+
                 try {
                     ActivityManager.getService().resumeAppSwitches();
                 } catch (RemoteException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
index f8da03a..df3748a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
@@ -298,6 +298,7 @@
             convertView.setAlpha(
                     item.isCurrent || item.isSwitchToEnabled ? USER_SWITCH_ENABLED_ALPHA
                             : USER_SWITCH_DISABLED_ALPHA);
+            convertView.setEnabled(item.isSwitchToEnabled);
             return convertView;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index cb40d77..3bd33cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -38,6 +38,7 @@
 import com.android.systemui.BootCompleteCache;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.util.Utils;
 
 import java.util.ArrayList;
@@ -64,16 +65,16 @@
 
     private boolean mAreActiveLocationRequests;
 
-    private ArrayList<LocationChangeCallback> mSettingsChangeCallbacks =
-            new ArrayList<LocationChangeCallback>();
-    private final H mHandler = new H();
+    private final H mHandler;
 
     @Inject
-    public LocationControllerImpl(Context context, @Background Looper bgLooper,
-            BroadcastDispatcher broadcastDispatcher, BootCompleteCache bootCompleteCache) {
+    public LocationControllerImpl(Context context, @Main Looper mainLooper,
+            @Background Looper bgLooper, BroadcastDispatcher broadcastDispatcher,
+            BootCompleteCache bootCompleteCache) {
         mContext = context;
         mBroadcastDispatcher = broadcastDispatcher;
         mBootCompleteCache = bootCompleteCache;
+        mHandler = new H(mainLooper);
 
         // Register to listen for changes in location settings.
         IntentFilter filter = new IntentFilter();
@@ -94,12 +95,12 @@
      * Add a callback to listen for changes in location settings.
      */
     public void addCallback(LocationChangeCallback cb) {
-        mSettingsChangeCallbacks.add(cb);
+        mHandler.obtainMessage(H.MSG_ADD_CALLBACK, cb).sendToTarget();
         mHandler.sendEmptyMessage(H.MSG_LOCATION_SETTINGS_CHANGED);
     }
 
     public void removeCallback(LocationChangeCallback cb) {
-        mSettingsChangeCallbacks.remove(cb);
+        mHandler.obtainMessage(H.MSG_REMOVE_CALLBACK, cb).sendToTarget();
     }
 
     /**
@@ -208,6 +209,14 @@
     private final class H extends Handler {
         private static final int MSG_LOCATION_SETTINGS_CHANGED = 1;
         private static final int MSG_LOCATION_ACTIVE_CHANGED = 2;
+        private static final int MSG_ADD_CALLBACK = 3;
+        private static final int MSG_REMOVE_CALLBACK = 4;
+
+        private ArrayList<LocationChangeCallback> mSettingsChangeCallbacks = new ArrayList<>();
+
+        H(Looper looper) {
+            super(looper);
+        }
 
         @Override
         public void handleMessage(Message msg) {
@@ -218,6 +227,13 @@
                 case MSG_LOCATION_ACTIVE_CHANGED:
                     locationActiveChanged();
                     break;
+                case MSG_ADD_CALLBACK:
+                    mSettingsChangeCallbacks.add((LocationChangeCallback) msg.obj);
+                    break;
+                case MSG_REMOVE_CALLBACK:
+                    mSettingsChangeCallbacks.remove((LocationChangeCallback) msg.obj);
+                    break;
+
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 442c7ea..b6e72226 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -369,16 +369,24 @@
                     R.string.ext_media_new_notification_message, disk.getDescription());
 
             final PendingIntent initIntent = buildInitPendingIntent(vol);
-            return buildNotificationBuilder(vol, title, text)
-                    .addAction(new Action(R.drawable.ic_settings_24dp,
-                            mContext.getString(R.string.ext_media_init_action), initIntent))
-                    .addAction(new Action(R.drawable.ic_eject_24dp,
-                            mContext.getString(R.string.ext_media_unmount_action),
-                            buildUnmountPendingIntent(vol)))
-                    .setContentIntent(initIntent)
-                    .setDeleteIntent(buildSnoozeIntent(vol.getFsUuid()))
-                    .build();
+            final PendingIntent unmountIntent = buildUnmountPendingIntent(vol);
 
+            if (isAutomotive()) {
+                return buildNotificationBuilder(vol, title, text)
+                        .setContentIntent(unmountIntent)
+                        .setDeleteIntent(buildSnoozeIntent(vol.getFsUuid()))
+                        .build();
+            } else {
+                return buildNotificationBuilder(vol, title, text)
+                        .addAction(new Action(R.drawable.ic_settings_24dp,
+                                mContext.getString(R.string.ext_media_init_action), initIntent))
+                        .addAction(new Action(R.drawable.ic_eject_24dp,
+                                mContext.getString(R.string.ext_media_unmount_action),
+                                unmountIntent))
+                        .setContentIntent(initIntent)
+                        .setDeleteIntent(buildSnoozeIntent(vol.getFsUuid()))
+                        .build();
+            }
         } else {
             final CharSequence title = disk.getDescription();
             final CharSequence text = mContext.getString(
@@ -427,9 +435,15 @@
                 R.string.ext_media_unmountable_notification_title, disk.getDescription());
         final CharSequence text = mContext.getString(
                 R.string.ext_media_unmountable_notification_message, disk.getDescription());
+        PendingIntent action;
+        if (isAutomotive()) {
+            action = buildUnmountPendingIntent(vol);
+        } else {
+            action = buildInitPendingIntent(vol);
+        }
 
         return buildNotificationBuilder(vol, title, text)
-                .setContentIntent(buildInitPendingIntent(vol))
+                .setContentIntent(action)
                 .setCategory(Notification.CATEGORY_ERROR)
                 .build();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
index 367d4d2..2973e0a 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
@@ -23,15 +23,12 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.ServiceManager;
-import android.util.EventLog;
 import android.util.Log;
 import android.view.LayoutInflater;
-import android.view.MotionEvent;
 import android.view.View;
 import android.view.Window;
 import android.view.WindowManager;
 import android.widget.CheckBox;
-import android.widget.Toast;
 
 import com.android.internal.app.AlertActivity;
 import com.android.internal.app.AlertController;
@@ -79,25 +76,6 @@
         window.setCloseOnTouchOutside(false);
 
         setupAlert();
-
-        // adding touch listener on affirmative button - checks if window is obscured
-        // if obscured, do not let user give permissions (could be tapjacking involved)
-        final View.OnTouchListener filterTouchListener = (View v, MotionEvent event) -> {
-            // Filter obscured touches by consuming them.
-            if (((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0)
-                    || ((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) != 0)) {
-                if (event.getAction() == MotionEvent.ACTION_UP) {
-                    EventLog.writeEvent(0x534e4554, "62187985"); // safety net logging
-                    Toast.makeText(v.getContext(),
-                            R.string.touch_filtered_warning,
-                            Toast.LENGTH_SHORT).show();
-                }
-                return true;
-            }
-            return false;
-        };
-        mAlert.getButton(BUTTON_POSITIVE).setOnTouchListener(filterTouchListener);
-
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt b/packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt
similarity index 70%
copy from packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt
copy to packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt
index d0f7607..c91033e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlEntity.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt
@@ -13,12 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.systemui.bubbles.storage
 
-import android.annotation.UserIdInt
+package com.android.systemui.util
 
-data class BubbleXmlEntity(
-    @UserIdInt val userId: Int,
-    val packageName: String,
-    val shortcutId: String
-)
+import android.view.ViewGroup
+
+/** [Sequence] that yields all of the direct children of this [ViewGroup] */
+val ViewGroup.children
+    get() = sequence {
+        for (i in 0 until childCount) yield(getChildAt(i))
+    }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/util/SparseArrayUtils.kt b/packages/SystemUI/src/com/android/systemui/util/SparseArrayUtils.kt
new file mode 100644
index 0000000..accb81e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/SparseArrayUtils.kt
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util
+
+import android.util.SparseArray
+
+/**
+ * Transforms an [Array] into a [SparseArray], by applying each element to [keySelector] in order to
+ * generate the index at which it will be placed. If two elements produce the same index, the latter
+ * replaces the former in the final result.
+ *
+ * See [Array.associateBy].
+ */
+inline fun <T> Array<T>.associateByToSparseArray(
+    crossinline keySelector: (T) -> Int
+): SparseArray<T> {
+    val sparseArray = SparseArray<T>(size)
+    for (value in this) {
+        sparseArray.put(keySelector(value), value)
+    }
+    return sparseArray
+}
+
+/**
+ * Folds a [Grouping] into a [SparseArray]. See [Grouping.fold].
+ */
+inline fun <T, R> Grouping<T, Int>.foldToSparseArray(
+    initial: R,
+    size: Int = -1,
+    crossinline operation: (R, T) -> R
+): SparseArray<R> {
+    val sparseArray = when {
+        size < 0 -> SparseArray<R>()
+        else -> SparseArray<R>(size)
+    }
+    sourceIterator().forEach { elem ->
+        val key = keyOf(elem)
+        val acc = sparseArray.get(key) ?: initial
+        sparseArray.put(key, operation(acc, elem))
+    }
+    return sparseArray
+}
+
+/**
+ * Wraps this [SparseArray] into an immutable [Map], the methods of which forward to this
+ * [SparseArray].
+ */
+fun <T> SparseArray<T>.asMap(): Map<Int, T> = SparseArrayMapWrapper(this)
+
+private class SparseArrayMapWrapper<T>(
+    private val sparseArray: SparseArray<T>
+) : Map<Int, T> {
+
+    private data class Entry<T>(override val key: Int, override val value: T) : Map.Entry<Int, T>
+
+    private val entrySequence = sequence {
+        val size = sparseArray.size()
+        for (i in 0 until size) {
+            val key = sparseArray.keyAt(i)
+            val value = sparseArray.get(key)
+            yield(Entry(key, value))
+        }
+    }
+
+    override val entries: Set<Map.Entry<Int, T>>
+        get() = object : Set<Map.Entry<Int, T>> {
+            override val size: Int
+                get() = this@SparseArrayMapWrapper.size
+
+            override fun contains(element: Map.Entry<Int, T>): Boolean =
+                    sparseArray[element.key]?.let { it == element.value } == true
+
+            override fun containsAll(elements: Collection<Map.Entry<Int, T>>): Boolean =
+                    elements.all { contains(it) }
+
+            override fun isEmpty(): Boolean = size == 0
+
+            override fun iterator(): Iterator<Map.Entry<Int, T>> = entrySequence.iterator()
+        }
+
+    override val keys: Set<Int> = object : Set<Int> {
+        private val keySequence = entrySequence.map { it.key }
+
+        override val size: Int
+            get() = this@SparseArrayMapWrapper.size
+
+        override fun contains(element: Int): Boolean = containsKey(element)
+
+        override fun containsAll(elements: Collection<Int>): Boolean =
+                elements.all { contains(it) }
+
+        override fun isEmpty(): Boolean = size == 0
+
+        override fun iterator(): Iterator<Int> = keySequence.iterator()
+    }
+    override val size: Int
+        get() = sparseArray.size()
+    override val values: Collection<T>
+        get() = object : Collection<T> {
+            private val valueSequence = entrySequence.map { it.value }
+
+            override val size: Int
+                get() = this@SparseArrayMapWrapper.size
+
+            override fun contains(element: T): Boolean = containsValue(element)
+
+            override fun containsAll(elements: Collection<T>): Boolean =
+                    elements.all { contains(it) }
+
+            override fun isEmpty(): Boolean = this@SparseArrayMapWrapper.isEmpty()
+
+            override fun iterator(): Iterator<T> = valueSequence.iterator()
+        }
+
+    override fun containsKey(key: Int): Boolean = sparseArray.contains(key)
+
+    override fun containsValue(value: T): Boolean = sparseArray.indexOfValue(value) >= 0
+
+    override fun get(key: Int): T? = sparseArray.get(key)
+
+    override fun isEmpty(): Boolean = sparseArray.size() == 0
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java
index 6a9d9b6..b1792d0 100644
--- a/packages/SystemUI/src/com/android/systemui/util/Utils.java
+++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java
@@ -130,7 +130,7 @@
      */
     public static boolean useQsMediaPlayer(Context context) {
         int flag = Settings.Global.getInt(context.getContentResolver(),
-                Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS, 0);
+                Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS, 1);
         return flag > 0;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/MeasurementCache.kt b/packages/SystemUI/src/com/android/systemui/util/animation/MeasurementCache.kt
new file mode 100644
index 0000000..2be698b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/MeasurementCache.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.util.animation
+
+/**
+ * A class responsible for caching view Measurements which guarantees that we always obtain a value
+ */
+class GuaranteedMeasurementCache constructor(
+    private val baseCache : MeasurementCache,
+    private val inputMapper: (MeasurementInput) -> MeasurementInput,
+    private val measurementProvider: (MeasurementInput) -> MeasurementOutput?
+) : MeasurementCache {
+
+    override fun obtainMeasurement(input: MeasurementInput) : MeasurementOutput {
+        val mappedInput = inputMapper.invoke(input)
+        if (!baseCache.contains(mappedInput)) {
+            var measurement = measurementProvider.invoke(mappedInput)
+            if (measurement != null) {
+                // Only cache measurings that actually have a size
+                baseCache.putMeasurement(mappedInput, measurement)
+            } else {
+                measurement = MeasurementOutput(0, 0)
+            }
+            return measurement
+        } else {
+            return baseCache.obtainMeasurement(mappedInput)
+        }
+    }
+
+    override fun contains(input: MeasurementInput): Boolean {
+        return baseCache.contains(inputMapper.invoke(input))
+    }
+
+    override fun putMeasurement(input: MeasurementInput, output: MeasurementOutput) {
+        if (output.measuredWidth == 0 || output.measuredHeight == 0) {
+            // Only cache measurings that actually have a size
+            return;
+        }
+        val remappedInput = inputMapper.invoke(input)
+        baseCache.putMeasurement(remappedInput, output)
+    }
+}
+
+/**
+ * A base implementation class responsible for caching view Measurements
+ */
+class BaseMeasurementCache : MeasurementCache {
+    private val dataCache: MutableMap<MeasurementInput, MeasurementOutput> = mutableMapOf()
+
+    override fun obtainMeasurement(input: MeasurementInput) : MeasurementOutput {
+        val measurementOutput = dataCache[input]
+        if (measurementOutput == null) {
+            return MeasurementOutput(0, 0)
+        } else {
+            return measurementOutput
+        }
+    }
+
+    override fun contains(input: MeasurementInput) : Boolean {
+        return dataCache[input] != null
+    }
+
+    override fun putMeasurement(input: MeasurementInput, output: MeasurementOutput) {
+        dataCache[input] = output
+    }
+}
+
+interface MeasurementCache {
+    fun obtainMeasurement(input: MeasurementInput) : MeasurementOutput
+    fun contains(input: MeasurementInput) : Boolean
+    fun putMeasurement(input: MeasurementInput, output: MeasurementOutput)
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt b/packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
new file mode 100644
index 0000000..bf94c5d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.util.animation
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.view.View
+import android.widget.FrameLayout
+
+/**
+ * A special view that is designed to host a single "unique object". The unique object is
+ * dynamically added and removed from this view and may transition to other UniqueObjectHostViews
+ * available in the system.
+ * This is useful to share a singular instance of a view that can transition between completely
+ * independent parts of the view hierarchy.
+ * If the view currently hosts the unique object, it's measuring it normally,
+ * but if it's not attached, it will obtain the size by requesting a measure, as if it were
+ * always attached.
+ */
+class UniqueObjectHostView(
+    context: Context
+) : FrameLayout(context) {
+    lateinit var measurementCache : GuaranteedMeasurementCache
+    var onMeasureListener: ((MeasurementInput) -> Unit)? = null
+
+    @SuppressLint("DrawAllocation")
+    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        val paddingHorizontal = paddingStart + paddingEnd
+        val paddingVertical = paddingTop + paddingBottom
+        val width = MeasureSpec.getSize(widthMeasureSpec) - paddingHorizontal
+        val widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.getMode(widthMeasureSpec))
+        val height = MeasureSpec.getSize(heightMeasureSpec) - paddingVertical
+        val heightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.getMode(heightMeasureSpec))
+        val measurementInput = MeasurementInputData(widthSpec, heightSpec)
+        onMeasureListener?.apply {
+            invoke(measurementInput)
+        }
+        if (!isCurrentHost()) {
+            // We're not currently the host, let's get the dimension from our cache (this might
+            // perform a measuring if the cache doesn't have it yet)
+            // The goal here is that the view will always have a consistent measuring, regardless
+            // if it's attached or not.
+            // The behavior is therefore very similar to the view being persistently attached to
+            // this host, which can prevent flickers. It also makes sure that we always know
+            // the size of the view during transitions even if it has never been attached here
+            // before.
+            val (cachedWidth, cachedHeight) = measurementCache.obtainMeasurement(measurementInput)
+            setMeasuredDimension(cachedWidth + paddingHorizontal, cachedHeight + paddingVertical)
+        } else {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+            // Let's update our cache
+            val child = getChildAt(0)!!
+            val output = MeasurementOutput(child.measuredWidth, child.measuredHeight)
+            measurementCache.putMeasurement(measurementInput, output)
+        }
+    }
+
+    private fun isCurrentHost() = childCount != 0
+}
+
+/**
+ * A basic view measurement input
+ */
+interface MeasurementInput {
+    fun sameAs(input: MeasurementInput?): Boolean {
+        return equals(input)
+    }
+    val width : Int
+        get() {
+            return View.MeasureSpec.getSize(widthMeasureSpec)
+        }
+    val height : Int
+        get() {
+            return View.MeasureSpec.getSize(heightMeasureSpec)
+        }
+    var widthMeasureSpec: Int
+    var heightMeasureSpec: Int
+}
+
+/**
+ * The output of a view measurement
+ */
+data class MeasurementOutput(
+    val measuredWidth: Int,
+    val measuredHeight: Int
+)
+
+/**
+ * The data object holding a basic view measurement input
+ */
+data class MeasurementInputData(
+    override var widthMeasureSpec: Int,
+    override var heightMeasureSpec: Int
+) : MeasurementInput
diff --git a/packages/SystemUI/src/com/android/systemui/util/io/Files.java b/packages/SystemUI/src/com/android/systemui/util/io/Files.java
new file mode 100644
index 0000000..7d633a7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/io/Files.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.io;
+
+import androidx.annotation.NonNull;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.LinkOption;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.stream.Stream;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Wrapper around {@link java.nio.file.Files} that can be mocked in tests.
+ */
+@Singleton
+public class Files {
+    @Inject
+    public Files() { }
+
+    /** See {@link java.nio.file.Files#newBufferedWriter} */
+    public BufferedWriter newBufferedWriter(Path path, OpenOption... options) throws IOException {
+        return java.nio.file.Files.newBufferedWriter(path, StandardCharsets.UTF_8, options);
+    }
+
+    /** See {@link java.nio.file.Files#lines} */
+    public Stream<String> lines(Path path) throws IOException {
+        return java.nio.file.Files.lines(path);
+    }
+
+    /** See {@link java.nio.file.Files#readAttributes} */
+    public <A extends BasicFileAttributes> A readAttributes(
+            @NonNull Path path,
+            @NonNull Class<A> type,
+            @NonNull LinkOption... options) throws IOException {
+        return java.nio.file.Files.readAttributes(path, type, options);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
index 378dde2..708b5a7 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
@@ -21,16 +21,17 @@
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
-import android.os.Handler;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.R;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.util.concurrency.DelayableExecutor;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Consumer;
 
 import javax.inject.Inject;
@@ -49,8 +50,9 @@
     private String mTag = null;
     @VisibleForTesting ProximityEvent mLastEvent;
     private int mSensorDelay = SensorManager.SENSOR_DELAY_NORMAL;
-    private boolean mPaused;
+    @VisibleForTesting protected boolean mPaused;
     private boolean mRegistered;
+    private final AtomicBoolean mAlerting = new AtomicBoolean();
 
     private SensorEventListener mSensorEventListener = new SensorEventListener() {
         @Override
@@ -217,8 +219,12 @@
 
     /** Update all listeners with the last value this class received from the sensor. */
     public void alertListeners() {
+        if (mAlerting.getAndSet(true)) {
+            return;
+        }
         mListeners.forEach(proximitySensorListener ->
                 proximitySensorListener.onSensorEvent(mLastEvent));
+        mAlerting.set(false);
     }
 
     private void onSensorEvent(SensorEvent event) {
@@ -239,14 +245,14 @@
     public static class ProximityCheck implements Runnable {
 
         private final ProximitySensor mSensor;
-        private final Handler mHandler;
+        private final DelayableExecutor mDelayableExecutor;
         private List<Consumer<Boolean>> mCallbacks = new ArrayList<>();
 
         @Inject
-        public ProximityCheck(ProximitySensor sensor, Handler handler) {
+        public ProximityCheck(ProximitySensor sensor, DelayableExecutor delayableExecutor) {
             mSensor = sensor;
             mSensor.setTag("prox_check");
-            mHandler = handler;
+            mDelayableExecutor = delayableExecutor;
             mSensor.pause();
             ProximitySensorListener listener = proximityEvent -> {
                 mCallbacks.forEach(
@@ -280,7 +286,7 @@
             mCallbacks.add(callback);
             if (!mSensor.isRegistered()) {
                 mSensor.resume();
-                mHandler.postDelayed(this, timeoutMs);
+                mDelayableExecutor.executeDelayed(this, timeoutMs);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/util/time/SystemClock.java b/packages/SystemUI/src/com/android/systemui/util/time/SystemClock.java
index 6fef59f..6f32cc1 100644
--- a/packages/SystemUI/src/com/android/systemui/util/time/SystemClock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/time/SystemClock.java
@@ -37,4 +37,7 @@
 
     /** @see android.os.SystemClock#currentThreadTimeMillis() */
     long currentThreadTimeMillis();
+
+    /** @see System#currentTimeMillis()  */
+    long currentTimeMillis();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/util/time/SystemClockImpl.java b/packages/SystemUI/src/com/android/systemui/util/time/SystemClockImpl.java
index f0c7014..4e508cf 100644
--- a/packages/SystemUI/src/com/android/systemui/util/time/SystemClockImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/util/time/SystemClockImpl.java
@@ -42,4 +42,9 @@
     public long currentThreadTimeMillis() {
         return android.os.SystemClock.currentThreadTimeMillis();
     }
+
+    @Override
+    public long currentTimeMillis() {
+        return System.currentTimeMillis();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayController.java
index c66f07d..083c243 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/DisplayController.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayController.java
@@ -134,6 +134,39 @@
                         }
                     });
                 }
+
+                @Override
+                public void onFixedRotationStarted(int displayId, int newRotation) {
+                    mHandler.post(() -> {
+                        synchronized (mDisplays) {
+                            if (mDisplays.get(displayId) == null || getDisplay(displayId) == null) {
+                                Slog.w(TAG, "Skipping onFixedRotationStarted on unknown"
+                                        + " display, displayId=" + displayId);
+                                return;
+                            }
+                            for (int i = mDisplayChangedListeners.size() - 1; i >= 0; --i) {
+                                mDisplayChangedListeners.get(i).onFixedRotationStarted(
+                                        displayId, newRotation);
+                            }
+                        }
+                    });
+                }
+
+                @Override
+                public void onFixedRotationFinished(int displayId) {
+                    mHandler.post(() -> {
+                        synchronized (mDisplays) {
+                            if (mDisplays.get(displayId) == null || getDisplay(displayId) == null) {
+                                Slog.w(TAG, "Skipping onFixedRotationFinished on unknown"
+                                        + " display, displayId=" + displayId);
+                                return;
+                            }
+                            for (int i = mDisplayChangedListeners.size() - 1; i >= 0; --i) {
+                                mDisplayChangedListeners.get(i).onFixedRotationFinished(displayId);
+                            }
+                        }
+                    });
+                }
             };
 
     @Inject
@@ -232,5 +265,15 @@
          * Called when a display is removed.
          */
         default void onDisplayRemoved(int displayId) {}
+
+        /**
+         * Called when fixed rotation on a display is started.
+         */
+        default void onFixedRotationStarted(int displayId, int newRotation) {}
+
+        /**
+         * Called when fixed rotation on a display is finished.
+         */
+        default void onFixedRotationFinished(int displayId) {}
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java
index c7e9acc..2968b92 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java
@@ -178,6 +178,7 @@
         ValueAnimator mAnimation = null;
         int mRotation = Surface.ROTATION_0;
         boolean mImeShowing = false;
+        final Rect mImeFrame = new Rect();
 
         PerDisplay(int displayId, int initialRotation) {
             mDisplayId = displayId;
@@ -254,8 +255,8 @@
             }
         }
 
-        private int imeTop(InsetsSource imeSource, float surfaceOffset) {
-            return imeSource.getFrame().top + (int) surfaceOffset;
+        private int imeTop(float surfaceOffset) {
+            return mImeFrame.top + (int) surfaceOffset;
         }
 
         private void startAnimation(final boolean show, final boolean forceRestart) {
@@ -263,6 +264,11 @@
             if (imeSource == null || mImeSourceControl == null) {
                 return;
             }
+            // Set frame, but only if the new frame isn't empty -- this maintains continuity
+            final Rect newFrame = imeSource.getFrame();
+            if (newFrame.height() != 0) {
+                mImeFrame.set(newFrame);
+            }
             mHandler.post(() -> {
                 if (DEBUG) {
                     Slog.d(TAG, "Run startAnim  show:" + show + "  was:"
@@ -284,7 +290,7 @@
                 }
                 final float defaultY = mImeSourceControl.getSurfacePosition().y;
                 final float x = mImeSourceControl.getSurfacePosition().x;
-                final float hiddenY = defaultY + imeSource.getFrame().height();
+                final float hiddenY = defaultY + mImeFrame.height();
                 final float shownY = defaultY;
                 final float startY = show ? hiddenY : shownY;
                 final float endY = show ? shownY : hiddenY;
@@ -306,7 +312,7 @@
                     SurfaceControl.Transaction t = mTransactionPool.acquire();
                     float value = (float) animation.getAnimatedValue();
                     t.setPosition(mImeSourceControl.getLeash(), x, value);
-                    dispatchPositionChanged(mDisplayId, imeTop(imeSource, value), t);
+                    dispatchPositionChanged(mDisplayId, imeTop(value), t);
                     t.apply();
                     mTransactionPool.release(t);
                 });
@@ -319,11 +325,11 @@
                         t.setPosition(mImeSourceControl.getLeash(), x, startY);
                         if (DEBUG) {
                             Slog.d(TAG, "onAnimationStart d:" + mDisplayId + " top:"
-                                    + imeTop(imeSource, hiddenY) + "->" + imeTop(imeSource, shownY)
+                                    + imeTop(hiddenY) + "->" + imeTop(shownY)
                                     + " showing:" + (mAnimationDirection == DIRECTION_SHOW));
                         }
-                        dispatchStartPositioning(mDisplayId, imeTop(imeSource, hiddenY),
-                                imeTop(imeSource, shownY), mAnimationDirection == DIRECTION_SHOW,
+                        dispatchStartPositioning(mDisplayId, imeTop(hiddenY),
+                                imeTop(shownY), mAnimationDirection == DIRECTION_SHOW,
                                 t);
                         if (mAnimationDirection == DIRECTION_SHOW) {
                             t.show(mImeSourceControl.getLeash());
diff --git a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
index 93f45c5..21f67ae 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
@@ -125,7 +125,7 @@
      */
     public void removeView(View view) {
         SurfaceControlViewHost root = mViewRoots.remove(view);
-        root.die();
+        root.release();
     }
 
     /**
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index 870010a..aa4122f 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -134,6 +134,7 @@
         mDependency.injectMockDependency(WakefulnessLifecycle.class);
         mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
                 new Handler(mTestableLooper.getLooper()));
+        mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
         mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mKeyguardUpdateMonitor);
 
         doAnswer(this::checkMainThread).when(mKeyguardUpdateMonitor)
@@ -150,6 +151,7 @@
         // This should not start listening on any of the real dependencies but will test that
         // callbacks in mKeyguardUpdateMonitor are done in the mTestableLooper thread
         mCarrierTextController.setListening(mCarrierTextCallback);
+        mTestableLooper.processAllMessages();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMediaPlayerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMediaPlayerTest.kt
deleted file mode 100644
index 4bcf917..0000000
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMediaPlayerTest.kt
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard
-
-import android.app.Notification
-import android.graphics.drawable.Icon
-import android.media.MediaMetadata
-import android.media.session.MediaController
-import android.media.session.MediaSession
-import android.media.session.PlaybackState
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import android.view.View
-import android.widget.TextView
-import androidx.arch.core.executor.ArchTaskExecutor
-import androidx.arch.core.executor.TaskExecutor
-import androidx.test.filters.SmallTest
-
-import com.android.systemui.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
-import com.android.systemui.media.MediaControllerFactory
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.time.FakeSystemClock
-import com.google.common.truth.Truth.assertThat
-
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.any
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper
-public class KeyguardMediaPlayerTest : SysuiTestCase() {
-
-    private lateinit var keyguardMediaPlayer: KeyguardMediaPlayer
-    @Mock private lateinit var mockMediaFactory: MediaControllerFactory
-    @Mock private lateinit var mockMediaController: MediaController
-    private lateinit var playbackState: PlaybackState
-    private lateinit var fakeExecutor: FakeExecutor
-    private lateinit var mediaMetadata: MediaMetadata.Builder
-    private lateinit var entry: NotificationEntry
-    @Mock private lateinit var mockView: View
-    private lateinit var songView: TextView
-    private lateinit var artistView: TextView
-    @Mock private lateinit var mockIcon: Icon
-
-    private val taskExecutor: TaskExecutor = object : TaskExecutor() {
-        public override fun executeOnDiskIO(runnable: Runnable) {
-            runnable.run()
-        }
-        public override fun postToMainThread(runnable: Runnable) {
-            runnable.run()
-        }
-        public override fun isMainThread(): Boolean {
-            return true
-        }
-    }
-
-    @Before
-    public fun setup() {
-        playbackState = PlaybackState.Builder().run {
-            build()
-        }
-        mockMediaController = mock(MediaController::class.java)
-        whenever(mockMediaController.getPlaybackState()).thenReturn(playbackState)
-        mockMediaFactory = mock(MediaControllerFactory::class.java)
-        whenever(mockMediaFactory.create(any())).thenReturn(mockMediaController)
-
-        fakeExecutor = FakeExecutor(FakeSystemClock())
-        keyguardMediaPlayer = KeyguardMediaPlayer(context, mockMediaFactory, fakeExecutor)
-        mockIcon = mock(Icon::class.java)
-
-        mockView = mock(View::class.java)
-        songView = TextView(context)
-        artistView = TextView(context)
-        whenever<TextView>(mockView.findViewById(R.id.header_title)).thenReturn(songView)
-        whenever<TextView>(mockView.findViewById(R.id.header_artist)).thenReturn(artistView)
-
-        mediaMetadata = MediaMetadata.Builder()
-        entry = NotificationEntryBuilder().build()
-        entry.getSbn().getNotification().extras.putParcelable(Notification.EXTRA_MEDIA_SESSION,
-                MediaSession.Token(1, null))
-
-        ArchTaskExecutor.getInstance().setDelegate(taskExecutor)
-
-        keyguardMediaPlayer.bindView(mockView)
-    }
-
-    @After
-    public fun tearDown() {
-        keyguardMediaPlayer.unbindView()
-        ArchTaskExecutor.getInstance().setDelegate(null)
-    }
-
-    @Test
-    public fun testBind() {
-        keyguardMediaPlayer.unbindView()
-        keyguardMediaPlayer.bindView(mockView)
-    }
-
-    @Test
-    public fun testUnboundClearControls() {
-        keyguardMediaPlayer.unbindView()
-        keyguardMediaPlayer.clearControls()
-        keyguardMediaPlayer.bindView(mockView)
-    }
-
-    @Test
-    public fun testUpdateControls() {
-        keyguardMediaPlayer.updateControls(entry, mockIcon, mediaMetadata.build())
-        FakeExecutor.exhaustExecutors(fakeExecutor)
-        verify(mockView).setVisibility(View.VISIBLE)
-    }
-
-    @Test
-    public fun testClearControls() {
-        keyguardMediaPlayer.clearControls()
-        FakeExecutor.exhaustExecutors(fakeExecutor)
-        verify(mockView).setVisibility(View.GONE)
-    }
-
-    @Test
-    public fun testUpdateControlsNullPlaybackState() {
-        // GIVEN that the playback state is null (ie. the media session was destroyed)
-        whenever(mockMediaController.getPlaybackState()).thenReturn(null)
-        // WHEN updated
-        keyguardMediaPlayer.updateControls(entry, mockIcon, mediaMetadata.build())
-        FakeExecutor.exhaustExecutors(fakeExecutor)
-        // THEN the controls are cleared (ie. visibility is set to GONE)
-        verify(mockView).setVisibility(View.GONE)
-    }
-
-    @Test
-    public fun testSongName() {
-        val song: String = "Song"
-        mediaMetadata.putText(MediaMetadata.METADATA_KEY_TITLE, song)
-
-        keyguardMediaPlayer.updateControls(entry, mockIcon, mediaMetadata.build())
-
-        assertThat(fakeExecutor.runAllReady()).isEqualTo(1)
-        assertThat(songView.getText()).isEqualTo(song)
-    }
-
-    @Test
-    public fun testArtistName() {
-        val artist: String = "Artist"
-        mediaMetadata.putText(MediaMetadata.METADATA_KEY_ARTIST, artist)
-
-        keyguardMediaPlayer.updateControls(entry, mockIcon, mediaMetadata.build())
-
-        assertThat(fakeExecutor.runAllReady()).isEqualTo(1)
-        assertThat(artistView.getText()).isEqualTo(artist)
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index b5609dd..7bc453a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -38,6 +38,7 @@
 
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
+import android.app.trust.IStrongAuthTracker;
 import android.app.trust.TrustManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -72,6 +73,8 @@
 
 import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.widget.ILockSettings;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor.BiometricAuthenticated;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -120,6 +123,10 @@
     @Mock
     private TrustManager mTrustManager;
     @Mock
+    private LockPatternUtils mLockPatternUtils;
+    @Mock
+    private ILockSettings mLockSettings;
+    @Mock
     private FingerprintManager mFingerprintManager;
     @Mock
     private FaceManager mFaceManager;
@@ -169,12 +176,13 @@
         when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
         when(mUserManager.isUserUnlocked(anyInt())).thenReturn(true);
         when(mUserManager.isPrimaryUser()).thenReturn(true);
+        when(mStrongAuthTracker.getStub()).thenReturn(mock(IStrongAuthTracker.Stub.class));
         when(mStrongAuthTracker
                 .isUnlockingWithBiometricAllowed(anyBoolean() /* isStrongBiometric */))
                 .thenReturn(true);
-
         when(mTelephonyManager.getServiceStateForSubscriber(anyInt()))
                 .thenReturn(new ServiceState());
+        when(mLockPatternUtils.getLockSettings()).thenReturn(mLockSettings);
         mSpiedContext.addMockSystemService(TrustManager.class, mTrustManager);
         mSpiedContext.addMockSystemService(FingerprintManager.class, mFingerprintManager);
         mSpiedContext.addMockSystemService(BiometricManager.class, mBiometricManager);
@@ -729,8 +737,9 @@
             super(context,
                     TestableLooper.get(KeyguardUpdateMonitorTest.this).getLooper(),
                     mBroadcastDispatcher, mDumpManager,
-                    mRingerModeTracker, mBackgroundExecutor, mStatusBarStateController);
-            mStrongAuthTracker = KeyguardUpdateMonitorTest.this.mStrongAuthTracker;
+                    mRingerModeTracker, mBackgroundExecutor,
+                    mStatusBarStateController, mLockPatternUtils);
+            setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker);
         }
 
         public boolean hasSimStateJustChanged() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index 45f9437..805254c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -85,7 +85,8 @@
         mFsc = new ForegroundServiceController(
                 mEntryManager, mAppOpsController, mMainHandler);
         mListener = new ForegroundServiceNotificationListener(
-                mContext, mFsc, mEntryManager, mNotifPipeline, mClock);
+                mContext, mFsc, mEntryManager, mNotifPipeline,
+                mock(ForegroundServiceLifetimeExtender.class), mClock);
         ArgumentCaptor<NotificationEntryListener> entryListenerCaptor =
                 ArgumentCaptor.forClass(NotificationEntryListener.class);
         verify(mEntryManager).addNotificationEntryListener(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java
index bca8dee..050b553 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java
@@ -26,6 +26,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.systemui.statusbar.NotificationInteractionTracker;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
 import com.android.systemui.util.time.FakeSystemClock;
@@ -33,6 +34,8 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
@@ -42,9 +45,13 @@
     private Notification mNotif;
     private final FakeSystemClock mClock = new FakeSystemClock();
 
+    @Mock
+    private NotificationInteractionTracker mInteractionTracker;
+
     @Before
     public void setup() {
-        mExtender = new ForegroundServiceLifetimeExtender(mClock);
+        MockitoAnnotations.initMocks(this);
+        mExtender = new ForegroundServiceLifetimeExtender(mInteractionTracker, mClock);
 
         mNotif = new Notification.Builder(mContext, "")
                 .setSmallIcon(R.drawable.ic_person)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index 50b7af2..e0049d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -19,6 +19,7 @@
 import static junit.framework.TestCase.assertFalse;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -29,9 +30,8 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
-import static java.lang.Thread.sleep;
-
 import android.app.AppOpsManager;
+import android.os.Looper;
 import android.os.UserHandle;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -229,12 +229,7 @@
     @Test
     public void testActiveOpNotRemovedAfterNoted() throws InterruptedException {
         // Replaces the timeout delay with 5 ms
-        AppOpsControllerImpl.H testHandler = mController.new H(mTestableLooper.getLooper()) {
-            @Override
-            public void scheduleRemoval(AppOpItem item, long timeToRemoval) {
-                super.scheduleRemoval(item, 5L);
-            }
-        };
+        TestHandler testHandler = new TestHandler(mTestableLooper.getLooper());
 
         mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
         mController.setBGHandler(testHandler);
@@ -245,6 +240,10 @@
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
                 AppOpsManager.MODE_ALLOWED);
 
+        // Check that we "scheduled" the removal. Don't actually schedule until we are ready to
+        // process messages at a later time.
+        assertNotNull(testHandler.mDelayScheduled);
+
         mTestableLooper.processAllMessages();
         List<AppOpItem> list = mController.getActiveAppOps();
         verify(mCallback).onActiveStateChanged(
@@ -253,8 +252,8 @@
         // Duplicates are not removed between active and noted
         assertEquals(2, list.size());
 
-        sleep(10L);
-
+        // Now is later, so we can schedule delayed messages.
+        testHandler.scheduleDelayed();
         mTestableLooper.processAllMessages();
 
         verify(mCallback, never()).onActiveStateChanged(
@@ -321,4 +320,24 @@
         verify(mCallback).onActiveStateChanged(
                 AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
     }
+
+    private class TestHandler extends AppOpsControllerImpl.H {
+        TestHandler(Looper looper) {
+            mController.super(looper);
+        }
+
+        Runnable mDelayScheduled;
+
+        void scheduleDelayed() {
+            if (mDelayScheduled != null) {
+                mDelayScheduled.run();
+                mDelayScheduled = null;
+            }
+        }
+
+        @Override
+        public void scheduleRemoval(AppOpItem item, long timeToRemoval) {
+            mDelayScheduled = () -> super.scheduleRemoval(item, 0L);
+        }
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index e2f303e..96e868d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -279,7 +279,8 @@
                 mFloatingContentCoordinator,
                 mDataRepository,
                 mSysUiState,
-                mock(INotificationManager.class));
+                mock(INotificationManager.class),
+                mWindowManager);
         mBubbleController.setExpandListener(mBubbleExpandListener);
 
         // Get a reference to the BubbleController's entry listener
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
index 8a83b84..73b8760 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -254,7 +254,8 @@
                 mFloatingContentCoordinator,
                 mDataRepository,
                 mSysUiState,
-                mock(INotificationManager.class));
+                mock(INotificationManager.class),
+                mWindowManager);
         mBubbleController.addNotifCallback(mNotifCallback);
         mBubbleController.setExpandListener(mBubbleExpandListener);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
index 1542b86..bdb7944 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
@@ -18,6 +18,7 @@
 
 import android.app.INotificationManager;
 import android.content.Context;
+import android.view.WindowManager;
 
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.model.SysUiState;
@@ -57,13 +58,15 @@
             FloatingContentCoordinator floatingContentCoordinator,
             BubbleDataRepository dataRepository,
             SysUiState sysUiState,
-            INotificationManager notificationManager) {
+            INotificationManager notificationManager,
+            WindowManager windowManager) {
         super(context,
                 notificationShadeWindowController, statusBarStateController, shadeController,
                 data, Runnable::run, configurationController, interruptionStateProvider,
                 zenModeController, lockscreenUserManager, groupManager, entryManager,
                 notifPipeline, featureFlags, dumpManager, floatingContentCoordinator,
-                dataRepository, sysUiState, notificationManager);
+                dataRepository, sysUiState, notificationManager,
+                windowManager);
         setInflateSynchronously(true);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
index ec6d3e9..6a14863 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
@@ -49,11 +49,13 @@
     private int mOrientation = Configuration.ORIENTATION_PORTRAIT;
     private float mLauncherGridDiff = 30f;
 
+    private Runnable mOnBubbleAnimatedOutAction = Mockito.mock(Runnable.class);
+
     @Spy
     private ExpandedAnimationController mExpandedController =
             new ExpandedAnimationController(
                     new Point(mDisplayWidth, mDisplayHeight) /* displaySize */,
-                    mExpandedViewPadding, mOrientation);
+                    mExpandedViewPadding, mOrientation, mOnBubbleAnimatedOutAction);
 
     private int mStackOffset;
     private float mBubblePaddingTop;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
index b1ac022..cc62a2f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
@@ -40,6 +40,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -66,7 +67,7 @@
                     public int getAsInt() {
                         return mLayout.getChildCount();
                     }
-                }));
+                }, Mockito.mock(Runnable.class)));
         mLayout.setActiveController(mStackController);
         addOneMoreThanBubbleLimitBubbles();
         mStackOffset = mLayout.getResources().getDimensionPixelSize(R.dimen.bubble_stack_offset);
@@ -303,8 +304,9 @@
     private class TestableStackController extends StackAnimationController {
         TestableStackController(
                 FloatingContentCoordinator floatingContentCoordinator,
-                IntSupplier bubbleCountSupplier) {
-            super(floatingContentCoordinator, bubbleCountSupplier);
+                IntSupplier bubbleCountSupplier,
+                Runnable onBubbleAnimatedOutAction) {
+            super(floatingContentCoordinator, bubbleCountSupplier, onBubbleAnimatedOutAction);
         }
 
         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubblePersistentRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubblePersistentRepositoryTest.kt
new file mode 100644
index 0000000..d49d021
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubblePersistentRepositoryTest.kt
@@ -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 com.android.systemui.bubbles.storage
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import junit.framework.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class BubblePersistentRepositoryTest : SysuiTestCase() {
+
+    private val bubbles = listOf(
+            BubbleEntity(0, "com.example.messenger", "shortcut-1"),
+            BubbleEntity(10, "com.example.chat", "alice and bob"),
+            BubbleEntity(0, "com.example.messenger", "shortcut-2")
+    )
+    private lateinit var repository: BubblePersistentRepository
+
+    @Before
+    fun setup() {
+        repository = BubblePersistentRepository(mContext)
+    }
+
+    @Test
+    fun testReadWriteOperation() {
+        repository.persistsToDisk(bubbles)
+        assertEquals(bubbles, repository.readFromDisk())
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleVolatileRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleVolatileRepositoryTest.kt
new file mode 100644
index 0000000..7acc937
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleVolatileRepositoryTest.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bubbles.storage
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import junit.framework.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class BubbleVolatileRepositoryTest : SysuiTestCase() {
+
+    private val bubble1 = BubbleEntity(0, "com.example.messenger", "shortcut-1")
+    private val bubble2 = BubbleEntity(10, "com.example.chat", "alice and bob")
+    private val bubble3 = BubbleEntity(0, "com.example.messenger", "shortcut-2")
+    private val bubbles = listOf(bubble1, bubble2, bubble3)
+
+    private lateinit var repository: BubbleVolatileRepository
+
+    @Before
+    fun setup() {
+        repository = BubbleVolatileRepository()
+    }
+
+    @Test
+    fun testAddAndRemoveBubbles() {
+        repository.addBubbles(bubbles)
+        assertEquals(bubbles, repository.bubbles)
+        repository.addBubbles(listOf(bubble1))
+        assertEquals(listOf(bubble2, bubble3, bubble1), repository.bubbles)
+        repository.removeBubbles(listOf(bubble3))
+        assertEquals(listOf(bubble2, bubble1), repository.bubbles)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleXmlHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleXmlHelperTest.kt
new file mode 100644
index 0000000..ef4580c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleXmlHelperTest.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bubbles.storage
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import junit.framework.Assert.assertEquals
+import junit.framework.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class BubbleXmlHelperTest : SysuiTestCase() {
+
+    private val bubbles = listOf(
+        BubbleEntity(0, "com.example.messenger", "shortcut-1"),
+        BubbleEntity(10, "com.example.chat", "alice and bob"),
+        BubbleEntity(0, "com.example.messenger", "shortcut-2")
+    )
+
+    @Test
+    fun testWriteXml() {
+        val expectedEntries = """
+            <bb uid="0" pkg="com.example.messenger" sid="shortcut-1" />
+            <bb uid="10" pkg="com.example.chat" sid="alice and bob" />
+            <bb uid="0" pkg="com.example.messenger" sid="shortcut-2" />
+        """.trimIndent()
+        ByteArrayOutputStream().use {
+            writeXml(it, bubbles)
+            val actual = it.toString()
+            assertTrue("cannot find expected entry in \n$actual",
+                    actual.contains(expectedEntries))
+        }
+    }
+
+    @Test
+    fun testReadXml() {
+        val src = """
+            <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+            <bs>
+            <bb uid="0" pkg="com.example.messenger" sid="shortcut-1" />
+            <bb uid="10" pkg="com.example.chat" sid="alice and bob" />
+            <bb uid="0" pkg="com.example.messenger" sid="shortcut-2" />
+            </bs>
+        """.trimIndent()
+        val actual = readXml(ByteArrayInputStream(src.toByteArray(Charsets.UTF_8)))
+        assertEquals("failed parsing bubbles from xml\n$src", bubbles, actual)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt
index 9b40c5e..128a7e8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt
@@ -177,4 +177,31 @@
         inOrder.verify(mockSL).setListening(true)
         inOrder.verify(mockSL).reload()
     }
-}
\ No newline at end of file
+
+    @Test
+    fun testChangeUserResetsExistingCallbackServices() {
+        val list = listOf(serviceInfo)
+        controller.addCallback(mockCallback)
+
+        @Suppress("unchecked_cast")
+        val captor: ArgumentCaptor<List<ControlsServiceInfo>> =
+                ArgumentCaptor.forClass(List::class.java)
+                        as ArgumentCaptor<List<ControlsServiceInfo>>
+        executor.runAllReady()
+        reset(mockCallback)
+
+        serviceListingCallbackCaptor.value.onServicesReloaded(list)
+
+        executor.runAllReady()
+        verify(mockCallback).onServicesUpdated(capture(captor))
+        assertEquals(1, captor.value.size)
+
+        reset(mockCallback)
+        controller.changeUser(UserHandle.of(otherUser))
+        executor.runAllReady()
+        assertEquals(otherUser, controller.currentUserId)
+
+        verify(mockCallback).onServicesUpdated(capture(captor))
+        assertEquals(0, captor.value.size)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
index 317500c..a567536 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
@@ -18,6 +18,7 @@
 
 import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN;
 
+import static org.junit.Assert.assertFalse;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -46,6 +47,7 @@
 import com.android.systemui.plugins.SensorManagerPlugin;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.sensors.AsyncSensorManager;
+import com.android.systemui.util.sensors.ProximitySensor;
 import com.android.systemui.util.wakelock.WakeLock;
 
 import org.junit.Before;
@@ -82,7 +84,7 @@
     @Mock
     private DozeLog mDozeLog;
     @Mock
-    private Sensor mProximitySensor;
+    private ProximitySensor mProximitySensor;
     private SensorManagerPlugin.SensorEventListener mWakeLockScreenListener;
     private TestableLooper mTestableLooper;
     private DozeSensors mDozeSensors;
@@ -93,7 +95,6 @@
         mTestableLooper = TestableLooper.get(this);
         when(mAmbientDisplayConfiguration.getWakeLockScreenDebounce()).thenReturn(5000L);
         when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
-        when(mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)).thenReturn(mProximitySensor);
         doAnswer(invocation -> {
             ((Runnable) invocation.getArgument(0)).run();
             return null;
@@ -103,10 +104,9 @@
 
     @Test
     public void testRegisterProx() {
-        // We should not register with the sensor manager initially.
-        verify(mSensorManager, never()).registerListener(any(), any(Sensor.class), anyInt());
+        assertFalse(mProximitySensor.isRegistered());
         mDozeSensors.setProxListening(true);
-        verify(mSensorManager).registerListener(any(), any(Sensor.class), anyInt());
+        verify(mProximitySensor).resume();
     }
 
     @Test
@@ -169,7 +169,8 @@
 
         TestableDozeSensors() {
             super(getContext(), mAlarmManager, mSensorManager, mDozeParameters,
-                    mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog);
+                    mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog,
+                    mProximitySensor);
             for (TriggerSensor sensor : mSensors) {
                 if (sensor instanceof PluginSensor
                         && ((PluginSensor) sensor).mPluginSensor.getType()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index debc9d6..73aaeff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -31,7 +31,6 @@
 import android.hardware.Sensor;
 import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.Handler;
-import android.os.Looper;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -42,10 +41,12 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.sensors.AsyncSensorManager;
 import com.android.systemui.util.sensors.FakeProximitySensor;
 import com.android.systemui.util.sensors.FakeSensorManager;
 import com.android.systemui.util.sensors.ProximitySensor;
+import com.android.systemui.util.time.FakeSystemClock;
 import com.android.systemui.util.wakelock.WakeLock;
 import com.android.systemui.util.wakelock.WakeLockFake;
 
@@ -75,6 +76,7 @@
     private FakeSensorManager mSensors;
     private Sensor mTapSensor;
     private FakeProximitySensor mProximitySensor;
+    private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
 
     @Before
     public void setUp() throws Exception {
@@ -89,7 +91,7 @@
         mProximitySensor = new FakeProximitySensor(getContext().getResources(), asyncSensorManager);
 
         mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager, config, parameters,
-                asyncSensorManager, Handler.createAsync(Looper.myLooper()), wakeLock, true,
+                asyncSensorManager, mFakeExecutor, wakeLock, true,
                 mDockManager, mProximitySensor, mock(DozeLog.class), mBroadcastDispatcher);
         waitForSensorManager();
     }
@@ -111,9 +113,8 @@
         verify(mMachine, never()).requestState(any());
         verify(mMachine, never()).requestPulse(anyInt());
 
-        captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */);
-        waitForSensorManager();
         mProximitySensor.setLastEvent(new ProximitySensor.ProximityEvent(false, 2));
+        captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */);
         mProximitySensor.alertListeners();
 
         verify(mMachine).requestPulse(anyInt());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt
similarity index 90%
rename from packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt
index 8d530ec..9e67eda 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt
@@ -32,9 +32,12 @@
 import java.io.PrintWriter
 
 @SmallTest
-class DumpManagerTest : SysuiTestCase() {
+class DumpHandlerTest : SysuiTestCase() {
 
-    private lateinit var dumpManager: DumpManager
+    private lateinit var dumpHandler: DumpHandler
+
+    @Mock
+    private lateinit var logBufferEulogizer: LogBufferEulogizer
 
     @Mock
     private lateinit var fd: FileDescriptor
@@ -53,11 +56,13 @@
     @Mock
     private lateinit var buffer2: LogBuffer
 
+    private val dumpManager = DumpManager()
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
-        dumpManager = DumpManager(mContext)
+        dumpHandler = DumpHandler(mContext, dumpManager, logBufferEulogizer)
     }
 
     @Test
@@ -71,7 +76,7 @@
 
         // WHEN some of them are dumped explicitly
         val args = arrayOf("dumpable1", "dumpable3", "buffer2")
-        dumpManager.dump(fd, pw, args)
+        dumpHandler.dump(fd, pw, args)
 
         // THEN only the requested ones have their dump() method called
         verify(dumpable1).dump(fd, pw, args)
@@ -91,7 +96,7 @@
 
         // WHEN that module is dumped
         val args = arrayOf("dumpable1")
-        dumpManager.dump(fd, pw, args)
+        dumpHandler.dump(fd, pw, args)
 
         // THEN its dump() method is called
         verify(dumpable1).dump(fd, pw, args)
@@ -108,7 +113,7 @@
 
         // WHEN a critical dump is requested
         val args = arrayOf("--dump-priority", "CRITICAL")
-        dumpManager.dump(fd, pw, args)
+        dumpHandler.dump(fd, pw, args)
 
         // THEN all modules are dumped (but no buffers)
         verify(dumpable1).dump(fd, pw, args)
@@ -127,9 +132,9 @@
         dumpManager.registerBuffer("buffer1", buffer1)
         dumpManager.registerBuffer("buffer2", buffer2)
 
-        // WHEN a critical dump is requested
+        // WHEN a normal dump is requested
         val args = arrayOf("--dump-priority", "NORMAL")
-        dumpManager.dump(fd, pw, args)
+        dumpHandler.dump(fd, pw, args)
 
         // THEN all buffers are dumped (but no modules)
         verify(dumpable1, never()).dump(
@@ -147,4 +152,4 @@
         verify(buffer1).dump(pw, 0)
         verify(buffer2).dump(pw, 0)
     }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt
new file mode 100644
index 0000000..cb38846
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dump
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.io.FakeBasicFileAttributes
+import com.android.systemui.util.io.Files
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.time.FakeSystemClock
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import java.io.BufferedWriter
+import java.io.ByteArrayOutputStream
+import java.io.IOException
+import java.io.OutputStreamWriter
+import java.io.PrintWriter
+import java.nio.file.LinkOption
+import java.nio.file.OpenOption
+import java.nio.file.Paths
+import java.nio.file.attribute.BasicFileAttributes
+import java.util.Arrays
+
+@SmallTest
+class LogEulogizerTest : SysuiTestCase() {
+
+    lateinit var eulogizer: LogBufferEulogizer
+
+    @Mock
+    lateinit var dumpManager: DumpManager
+
+    @Mock
+    lateinit var files: Files
+
+    private val clock = FakeSystemClock()
+
+    private val path = Paths.get("/foo/bar/baz.txt")
+    private val fileAttrs = FakeBasicFileAttributes()
+    private val fileStream = ByteArrayOutputStream()
+    private val fileWriter = BufferedWriter(OutputStreamWriter(fileStream))
+
+    private val dumpStream = ByteArrayOutputStream()
+    private val dumpWriter = PrintWriter(OutputStreamWriter(dumpStream))
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        eulogizer =
+                LogBufferEulogizer(dumpManager, clock, files, path, MIN_WRITE_GAP, MAX_READ_AGE)
+
+        Mockito.`when`(files.newBufferedWriter(eq(path), any(OpenOption::class.java)))
+                .thenReturn(fileWriter)
+
+        Mockito.`when`(
+                files.readAttributes(eq(path),
+                eq(BasicFileAttributes::class.java),
+                any(LinkOption::class.java))
+        ).thenReturn(fileAttrs)
+
+        Mockito.`when`(files.lines(eq(path))).thenReturn(Arrays.stream(FAKE_LINES))
+    }
+
+    @Test
+    fun testFileIsCreated() {
+        // GIVEN that the log file doesn't already exist
+        Mockito.`when`(
+                files.readAttributes(eq(path),
+                        eq(BasicFileAttributes::class.java),
+                        any(LinkOption::class.java))
+        ).thenThrow(IOException("File not found"))
+
+        // WHEN .record() is called
+        val exception = RuntimeException("Something bad happened")
+        assertEquals(exception, eulogizer.record(exception))
+
+        // THEN the buffers are dumped to the file
+        verify(dumpManager).dumpBuffers(any(PrintWriter::class.java), Mockito.anyInt())
+        assertTrue(fileStream.toString().isNotEmpty())
+    }
+
+    @Test
+    fun testExistingFileIsOverwritten() {
+        // GIVEN that the log file already exists but hasn't been modified in a while
+        fileAttrs.setLastModifiedTime(clock.currentTimeMillis() - MIN_WRITE_GAP - 20)
+
+        // WHEN .record() is called
+        val exception = RuntimeException("Something bad happened")
+        assertEquals(exception, eulogizer.record(exception))
+
+        // THEN the buffers are dumped to the file
+        verify(dumpManager).dumpBuffers(any(PrintWriter::class.java), Mockito.anyInt())
+        assertTrue(fileStream.toString().isNotEmpty())
+    }
+
+    @Test
+    fun testYoungFileIsNotOverwritten() {
+        // GIVEN that the log file has been modified recently
+        fileAttrs.setLastModifiedTime(clock.currentTimeMillis() - MIN_WRITE_GAP + 7)
+
+        // WHEN .record() is called
+        val exception = RuntimeException("Something bad happened")
+        assertEquals(exception, eulogizer.record(exception))
+
+        // THEN the file isn't written to
+        verify(dumpManager, never()).dumpBuffers(any(PrintWriter::class.java), Mockito.anyInt())
+        assertTrue(fileStream.toString().isEmpty())
+    }
+
+    @Test
+    fun testRecentFileIsDumped() {
+        // GIVEN that the log file was written to "recently"
+        fileAttrs.setLastModifiedTime(clock.currentTimeMillis() - MAX_READ_AGE + 7)
+
+        // WHEN we're asked to eulogize the log
+        eulogizer.readEulogyIfPresent(dumpWriter)
+        dumpWriter.close()
+
+        // THEN the log file is written to the output stream
+        verify(files).lines(eq(path))
+        assertTrue(dumpStream.toString().isNotBlank())
+    }
+
+    @Test
+    fun testOldFileIsNotDumped() {
+        // GIVEN that the log file was written to a long time ago
+        fileAttrs.setLastModifiedTime(clock.currentTimeMillis() - MAX_READ_AGE - 7)
+
+        // WHEN we're asked to eulogize the log
+        eulogizer.readEulogyIfPresent(dumpWriter)
+        dumpWriter.close()
+
+        // THEN the log file is NOT written to the output stream
+        verify(files, never()).lines(eq(path))
+        assertTrue(dumpStream.toString().isEmpty())
+    }
+}
+
+private const val MIN_WRITE_GAP = 10L
+private const val MAX_READ_AGE = 100L
+
+private val FAKE_LINES =
+        arrayOf(
+                "First line",
+                "Second line",
+                "Third line"
+        )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
index 64acdcc..8db57cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
@@ -16,9 +16,13 @@
 
 package com.android.systemui.globalactions;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static junit.framework.Assert.assertEquals;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -30,6 +34,7 @@
 import android.app.trust.TrustManager;
 import android.content.ContentResolver;
 import android.content.res.Resources;
+import android.graphics.Color;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
 import android.os.Handler;
@@ -40,9 +45,12 @@
 import android.testing.TestableLooper;
 import android.util.FeatureFlagUtils;
 import android.view.IWindowManager;
+import android.view.View;
+import android.widget.FrameLayout;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.colorextraction.ColorExtractor;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.statusbar.IStatusBarService;
@@ -53,9 +61,10 @@
 import com.android.systemui.controls.controller.ControlsController;
 import com.android.systemui.controls.management.ControlsListingController;
 import com.android.systemui.controls.ui.ControlsUiController;
+import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.GlobalActions;
-import com.android.systemui.statusbar.BlurUtils;
+import com.android.systemui.plugins.GlobalActionsPanelPlugin;
 import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -97,7 +106,6 @@
     @Mock private NotificationShadeDepthController mDepthController;
     @Mock private SysuiColorExtractor mColorExtractor;
     @Mock private IStatusBarService mStatusBarService;
-    @Mock private BlurUtils mBlurUtils;
     @Mock private NotificationShadeWindowController mNotificationShadeWindowController;
     @Mock private ControlsUiController mControlsUiController;
     @Mock private IWindowManager mWindowManager;
@@ -107,6 +115,9 @@
     @Mock private UiEventLogger mUiEventLogger;
     @Mock private RingerModeTracker mRingerModeTracker;
     @Mock private RingerModeLiveData mRingerModeLiveData;
+    @Mock private SysUiState mSysUiState;
+    @Mock GlobalActionsPanelPlugin mWalletPlugin;
+    @Mock GlobalActionsPanelPlugin.PanelViewController mWalletController;
     @Mock private Handler mHandler;
 
     private TestableLooper mTestableLooper;
@@ -141,7 +152,6 @@
                 mDepthController,
                 mColorExtractor,
                 mStatusBarService,
-                mBlurUtils,
                 mNotificationShadeWindowController,
                 mControlsUiController,
                 mWindowManager,
@@ -150,19 +160,32 @@
                 mControlsController,
                 mUiEventLogger,
                 mRingerModeTracker,
+                mSysUiState,
                 mHandler
         );
         mGlobalActionsDialog.setZeroDialogPressDelayForTesting();
+
+        ColorExtractor.GradientColors backdropColors = new ColorExtractor.GradientColors();
+        backdropColors.setMainColor(Color.BLACK);
+        when(mColorExtractor.getNeutralColors()).thenReturn(backdropColors);
+        when(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState);
     }
 
     @Test
-    public void testShouldLogVisibility() {
+    public void testShouldLogShow() {
         mGlobalActionsDialog.onShow(null);
         mTestableLooper.processAllMessages();
         verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_POWER_MENU_OPEN);
     }
 
     @Test
+    public void testShouldLogDismiss() {
+        mGlobalActionsDialog.onDismiss(mGlobalActionsDialog.mDialog);
+        mTestableLooper.processAllMessages();
+        verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_POWER_MENU_CLOSE);
+    }
+
+    @Test
     public void testShouldLogBugreportPress() throws InterruptedException {
         GlobalActionsDialog.BugReportAction bugReportAction =
                 mGlobalActionsDialog.makeBugReportActionForTesting();
@@ -267,4 +290,65 @@
         assertEquals(3, mGlobalActionsDialog.mItems.size());
         assertEquals(0, mGlobalActionsDialog.mOverflowItems.size());
     }
+
+    @Test
+    public void testShouldShowLockScreenMessage() {
+        mGlobalActionsDialog = spy(mGlobalActionsDialog);
+        mGlobalActionsDialog.mDialog = null;
+        when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+        mGlobalActionsDialog.mShowLockScreenCardsAndControls = false;
+        setupDefaultActions();
+        when(mWalletPlugin.onPanelShown(any(), anyBoolean())).thenReturn(mWalletController);
+        when(mWalletController.getPanelContent()).thenReturn(new FrameLayout(mContext));
+
+        mGlobalActionsDialog.showOrHideDialog(false, true, mWalletPlugin);
+
+        GlobalActionsDialog.ActionsDialog dialog = mGlobalActionsDialog.mDialog;
+        assertThat(dialog).isNotNull();
+        assertThat(dialog.mLockMessageContainer.getVisibility()).isEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void testShouldNotShowLockScreenMessage_whenWalletOrControlsShownOnLockScreen() {
+        mGlobalActionsDialog = spy(mGlobalActionsDialog);
+        mGlobalActionsDialog.mDialog = null;
+        when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+        mGlobalActionsDialog.mShowLockScreenCardsAndControls = true;
+        setupDefaultActions();
+        when(mWalletPlugin.onPanelShown(any(), anyBoolean())).thenReturn(mWalletController);
+        when(mWalletController.getPanelContent()).thenReturn(new FrameLayout(mContext));
+
+        mGlobalActionsDialog.showOrHideDialog(false, true, mWalletPlugin);
+
+        GlobalActionsDialog.ActionsDialog dialog = mGlobalActionsDialog.mDialog;
+        assertThat(dialog).isNotNull();
+        assertThat(dialog.mLockMessageContainer.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void testShouldNotShowLockScreenMessage_whenControlsAndWalletBothDisabled() {
+        mGlobalActionsDialog = spy(mGlobalActionsDialog);
+        mGlobalActionsDialog.mDialog = null;
+        when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+        mGlobalActionsDialog.mShowLockScreenCardsAndControls = true;
+        setupDefaultActions();
+        when(mWalletPlugin.onPanelShown(any(), anyBoolean())).thenReturn(mWalletController);
+        when(mWalletController.getPanelContent()).thenReturn(null);
+        when(mControlsUiController.getAvailable()).thenReturn(false);
+
+        mGlobalActionsDialog.showOrHideDialog(false, true, mWalletPlugin);
+
+        GlobalActionsDialog.ActionsDialog dialog = mGlobalActionsDialog.mDialog;
+        assertThat(dialog).isNotNull();
+        assertThat(dialog.mLockMessageContainer.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    private void setupDefaultActions() {
+        String[] actions = {
+                GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
+                GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
+                GlobalActionsDialog.GLOBAL_ACTION_KEY_SCREENSHOT,
+        };
+        doReturn(actions).when(mGlobalActionsDialog).getDefaultActions();
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java
index 9629079..eb43b81 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java
@@ -34,6 +34,8 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.rule.ActivityTestRule;
 
+import com.android.systemui.SysuiTestCase;
+
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -41,7 +43,7 @@
 import java.util.function.BooleanSupplier;
 
 @LargeTest
-public class GlobalActionsImeTest {
+public class GlobalActionsImeTest extends SysuiTestCase {
 
     @Rule
     public ActivityTestRule<TestActivity> mActivityTestRule = new ActivityTestRule<>(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index 92c1d76..f70fb4f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -131,7 +131,7 @@
         MediaMetadata metadata = mock(MediaMetadata.class);
         when(metadata.getText(any())).thenReturn("metadata");
         mProvider.onDozingChanged(true);
-        mProvider.onMetadataOrStateChanged(metadata, PlaybackState.STATE_PLAYING);
+        mProvider.onPrimaryMetadataOrStateChanged(metadata, PlaybackState.STATE_PLAYING);
         mProvider.onBindSlice(mProvider.getUri());
         verify(metadata).getText(eq(MediaMetadata.METADATA_KEY_TITLE));
         verify(metadata).getText(eq(MediaMetadata.METADATA_KEY_ARTIST));
@@ -144,7 +144,7 @@
         when(metadata.getText(any())).thenReturn("metadata");
         when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
         when(mDozeParameters.getAlwaysOn()).thenReturn(true);
-        mProvider.onMetadataOrStateChanged(metadata, PlaybackState.STATE_PLAYING);
+        mProvider.onPrimaryMetadataOrStateChanged(metadata, PlaybackState.STATE_PLAYING);
         mProvider.onBindSlice(mProvider.getUri());
         verify(metadata).getText(eq(MediaMetadata.METADATA_KEY_TITLE));
         verify(metadata).getText(eq(MediaMetadata.METADATA_KEY_ARTIST));
@@ -210,7 +210,8 @@
         mProvider.onStateChanged(StatusBarState.KEYGUARD);
         mProvider.onDozingChanged(true);
         reset(mContentResolver);
-        mProvider.onMetadataOrStateChanged(mock(MediaMetadata.class), PlaybackState.STATE_PLAYING);
+        mProvider.onPrimaryMetadataOrStateChanged(mock(MediaMetadata.class),
+                PlaybackState.STATE_PLAYING);
         verify(mContentResolver).notifyChange(eq(mProvider.getUri()), eq(null));
 
         // Hides after waking up
@@ -222,7 +223,8 @@
     @Test
     public void onDozingChanged_updatesSliceIfMedia() {
         mProvider.onStateChanged(StatusBarState.KEYGUARD);
-        mProvider.onMetadataOrStateChanged(mock(MediaMetadata.class), PlaybackState.STATE_PLAYING);
+        mProvider.onPrimaryMetadataOrStateChanged(mock(MediaMetadata.class),
+                PlaybackState.STATE_PLAYING);
         reset(mContentResolver);
         // Show media when dozing
         mProvider.onDozingChanged(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
new file mode 100644
index 0000000..9aee11e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media
+
+import android.testing.AndroidTestingRunner
+import android.view.View.GONE
+import android.view.View.VISIBLE
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.notification.stack.MediaHeaderView
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class KeyguardMediaControllerTest : SysuiTestCase() {
+
+    @Mock
+    private lateinit var mediaHost: MediaHost
+    @Mock
+    private lateinit var bypassController: KeyguardBypassController
+    @Mock
+    private lateinit var statusBarStateController: SysuiStatusBarStateController
+    @Mock
+    private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager
+    @Mock
+    private lateinit var mediaHeaderView: MediaHeaderView
+    @Captor
+    private lateinit var visibilityListener: ArgumentCaptor<((Boolean) -> Unit)>
+    @JvmField @Rule
+    val mockito = MockitoJUnit.rule()
+    private lateinit var keyguardMediaController: KeyguardMediaController
+
+    @Before
+    fun setup() {
+        keyguardMediaController = KeyguardMediaController(mediaHost, bypassController,
+                statusBarStateController, notificationLockscreenUserManager)
+    }
+
+    @Test
+    fun testAttach_hiddenWhenHostIsHidden() {
+        `when`(mediaHost.visible).thenReturn(false)
+        triggerVisibilityListener()
+
+        verify(mediaHeaderView).visibility = eq(GONE)
+    }
+    @Test
+    fun testAttach_visibleOnKeyguard() {
+        `when`(mediaHost.visible).thenReturn(true)
+        `when`(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
+        `when`(notificationLockscreenUserManager.shouldShowLockscreenNotifications())
+                .thenReturn(true)
+        triggerVisibilityListener()
+
+        verify(mediaHeaderView).visibility = eq(VISIBLE)
+    }
+    @Test
+    fun testAttach_hiddenOnKeyguard_whenNotificationsAreHidden() {
+        `when`(mediaHost.visible).thenReturn(true)
+        `when`(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
+        `when`(notificationLockscreenUserManager.shouldShowLockscreenNotifications())
+                .thenReturn(false)
+        triggerVisibilityListener()
+
+        verify(mediaHeaderView).visibility = eq(GONE)
+    }
+
+    private fun triggerVisibilityListener() {
+        keyguardMediaController.attach(mediaHeaderView)
+        verify(mediaHost).visibleChangedListener = visibilityListener.capture()
+        visibilityListener.value.invoke(true)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
new file mode 100644
index 0000000..4d30500
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media
+
+import android.content.res.ColorStateList
+import android.graphics.Color
+import android.graphics.drawable.GradientDrawable
+import android.graphics.drawable.RippleDrawable
+import android.media.MediaMetadata
+import android.media.session.MediaSession
+import android.media.session.PlaybackState
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import android.widget.ImageButton
+import android.widget.ImageView
+import android.widget.SeekBar
+import android.widget.TextView
+
+import androidx.constraintlayout.motion.widget.MotionLayout
+import androidx.constraintlayout.motion.widget.MotionScene
+import androidx.constraintlayout.widget.ConstraintSet
+import androidx.test.filters.SmallTest
+
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.time.FakeSystemClock
+
+import com.google.common.truth.Truth.assertThat
+
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.`when` as whenever
+
+import java.util.ArrayList
+
+private const val KEY = "TEST_KEY"
+private const val APP = "APP"
+private const val BG_COLOR = Color.RED
+private const val PACKAGE = "PKG"
+private const val ARTIST = "ARTIST"
+private const val TITLE = "TITLE"
+private const val DEVICE_NAME = "DEVICE_NAME"
+private const val SESSION_KEY = "SESSION_KEY"
+private const val SESSION_ARTIST = "SESSION_ARTIST"
+private const val SESSION_TITLE = "SESSION_TITLE"
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class MediaControlPanelTest : SysuiTestCase() {
+
+    private lateinit var player: MediaControlPanel
+
+    private lateinit var fgExecutor: FakeExecutor
+    private lateinit var bgExecutor: FakeExecutor
+    @Mock private lateinit var activityStarter: ActivityStarter
+
+    @Mock private lateinit var holder: PlayerViewHolder
+    @Mock private lateinit var motion: MotionLayout
+    private lateinit var background: TextView
+    private lateinit var appIcon: ImageView
+    private lateinit var appName: TextView
+    private lateinit var albumView: ImageView
+    private lateinit var titleText: TextView
+    private lateinit var artistText: TextView
+    private lateinit var seamless: ViewGroup
+    private lateinit var seamlessIcon: ImageView
+    private lateinit var seamlessText: TextView
+    private lateinit var seekBar: SeekBar
+    private lateinit var elapsedTimeView: TextView
+    private lateinit var totalTimeView: TextView
+    private lateinit var action0: ImageButton
+    private lateinit var action1: ImageButton
+    private lateinit var action2: ImageButton
+    private lateinit var action3: ImageButton
+    private lateinit var action4: ImageButton
+
+    private lateinit var session: MediaSession
+    private val device = MediaDeviceData(true, null, DEVICE_NAME)
+    private val disabledDevice = MediaDeviceData(false, null, null)
+
+    @Before
+    fun setUp() {
+        fgExecutor = FakeExecutor(FakeSystemClock())
+        bgExecutor = FakeExecutor(FakeSystemClock())
+
+        activityStarter = mock(ActivityStarter::class.java)
+
+        player = MediaControlPanel(context, fgExecutor, bgExecutor, activityStarter)
+
+        // Mock out a view holder for the player to attach to.
+        holder = mock(PlayerViewHolder::class.java)
+        motion = mock(MotionLayout::class.java)
+        val trans: ArrayList<MotionScene.Transition> = ArrayList()
+        trans.add(mock(MotionScene.Transition::class.java))
+        whenever(motion.definedTransitions).thenReturn(trans)
+        val constraintSet = mock(ConstraintSet::class.java)
+        whenever(motion.getConstraintSet(R.id.expanded)).thenReturn(constraintSet)
+        whenever(motion.getConstraintSet(R.id.collapsed)).thenReturn(constraintSet)
+        whenever(holder.player).thenReturn(motion)
+        background = TextView(context)
+        whenever(holder.background).thenReturn(background)
+        appIcon = ImageView(context)
+        whenever(holder.appIcon).thenReturn(appIcon)
+        appName = TextView(context)
+        whenever(holder.appName).thenReturn(appName)
+        albumView = ImageView(context)
+        whenever(holder.albumView).thenReturn(albumView)
+        titleText = TextView(context)
+        whenever(holder.titleText).thenReturn(titleText)
+        artistText = TextView(context)
+        whenever(holder.artistText).thenReturn(artistText)
+        seamless = FrameLayout(context)
+        val seamlessBackground = mock(RippleDrawable::class.java)
+        seamless.setBackground(seamlessBackground)
+        whenever(seamlessBackground.getDrawable(0)).thenReturn(mock(GradientDrawable::class.java))
+        whenever(holder.seamless).thenReturn(seamless)
+        seamlessIcon = ImageView(context)
+        whenever(holder.seamlessIcon).thenReturn(seamlessIcon)
+        seamlessText = TextView(context)
+        whenever(holder.seamlessText).thenReturn(seamlessText)
+        seekBar = SeekBar(context)
+        whenever(holder.seekBar).thenReturn(seekBar)
+        elapsedTimeView = TextView(context)
+        whenever(holder.elapsedTimeView).thenReturn(elapsedTimeView)
+        totalTimeView = TextView(context)
+        whenever(holder.totalTimeView).thenReturn(totalTimeView)
+        action0 = ImageButton(context)
+        whenever(holder.action0).thenReturn(action0)
+        action1 = ImageButton(context)
+        whenever(holder.action1).thenReturn(action1)
+        action2 = ImageButton(context)
+        whenever(holder.action2).thenReturn(action2)
+        action3 = ImageButton(context)
+        whenever(holder.action3).thenReturn(action3)
+        action4 = ImageButton(context)
+        whenever(holder.action4).thenReturn(action4)
+
+        // Create media session
+        val metadataBuilder = MediaMetadata.Builder().apply {
+            putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
+            putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE)
+        }
+        val playbackBuilder = PlaybackState.Builder().apply {
+            setState(PlaybackState.STATE_PAUSED, 6000L, 1f)
+            setActions(PlaybackState.ACTION_PLAY)
+        }
+        session = MediaSession(context, SESSION_KEY).apply {
+            setMetadata(metadataBuilder.build())
+            setPlaybackState(playbackBuilder.build())
+        }
+        session.setActive(true)
+    }
+
+    @After
+    fun tearDown() {
+        session.release()
+        player.onDestroy()
+    }
+
+    @Test
+    fun bindWhenUnattached() {
+        val state = MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
+                emptyList(), PACKAGE, null, null, device)
+        player.bind(state)
+        assertThat(player.isPlaying()).isFalse()
+    }
+
+    @Test
+    fun bindText() {
+        player.attach(holder)
+        val state = MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
+                emptyList(), PACKAGE, session.getSessionToken(), null, device)
+        player.bind(state)
+        assertThat(appName.getText()).isEqualTo(APP)
+        assertThat(titleText.getText()).isEqualTo(TITLE)
+        assertThat(artistText.getText()).isEqualTo(ARTIST)
+    }
+
+    @Test
+    fun bindBackgroundColor() {
+        player.attach(holder)
+        val state = MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
+                emptyList(), PACKAGE, session.getSessionToken(), null, device)
+        player.bind(state)
+        assertThat(background.getBackgroundTintList()).isEqualTo(ColorStateList.valueOf(BG_COLOR))
+    }
+
+    @Test
+    fun bindDevice() {
+        player.attach(holder)
+        val state = MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
+                emptyList(), PACKAGE, session.getSessionToken(), null, device)
+        player.bind(state)
+        assertThat(seamlessText.getText()).isEqualTo(DEVICE_NAME)
+        assertThat(seamless.isEnabled()).isTrue()
+    }
+
+    @Test
+    fun bindDisabledDevice() {
+        player.attach(holder)
+        val state = MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
+                emptyList(), PACKAGE, session.getSessionToken(), null, disabledDevice)
+        player.bind(state)
+        assertThat(seamless.isEnabled()).isFalse()
+        assertThat(seamlessText.getText()).isEqualTo(context.getResources().getString(
+                R.string.media_seamless_remote_device))
+    }
+
+    @Test
+    fun bindNullDevice() {
+        player.attach(holder)
+        val state = MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
+                emptyList(), PACKAGE, session.getSessionToken(), null, null)
+        player.bind(state)
+        assertThat(seamless.isEnabled()).isTrue()
+        assertThat(seamlessText.getText()).isEqualTo(context.getResources().getString(
+                com.android.internal.R.string.ext_media_seamless_action))
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java
new file mode 100644
index 0000000..aa889a6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.graphics.Color;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class MediaDataCombineLatestTest extends SysuiTestCase {
+
+    private static final String KEY = "TEST_KEY";
+    private static final String APP = "APP";
+    private static final String PACKAGE = "PKG";
+    private static final int BG_COLOR = Color.RED;
+    private static final String ARTIST = "ARTIST";
+    private static final String TITLE = "TITLE";
+    private static final String DEVICE_NAME = "DEVICE_NAME";
+
+    private MediaDataCombineLatest mManager;
+
+    @Mock private MediaDataManager mDataSource;
+    @Mock private MediaDeviceManager mDeviceSource;
+    @Mock private MediaDataManager.Listener mListener;
+
+    private MediaDataManager.Listener mDataListener;
+    private MediaDeviceManager.Listener mDeviceListener;
+
+    private MediaData mMediaData;
+    private MediaDeviceData mDeviceData;
+
+    @Before
+    public void setUp() {
+        mDataSource = mock(MediaDataManager.class);
+        mDeviceSource = mock(MediaDeviceManager.class);
+        mListener = mock(MediaDataManager.Listener.class);
+
+        mManager = new MediaDataCombineLatest(mDataSource, mDeviceSource);
+
+        mDataListener = captureDataListener();
+        mDeviceListener = captureDeviceListener();
+
+        mManager.addListener(mListener);
+
+        mMediaData = new MediaData(true, BG_COLOR, APP, null, ARTIST, TITLE, null,
+                new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null);
+        mDeviceData = new MediaDeviceData(true, null, DEVICE_NAME);
+    }
+
+    @Test
+    public void eventNotEmittedWithoutDevice() {
+        // WHEN data source emits an event without device data
+        mDataListener.onMediaDataLoaded(KEY, mMediaData);
+        // THEN an event isn't emitted
+        verify(mListener, never()).onMediaDataLoaded(eq(KEY), any());
+    }
+
+    @Test
+    public void eventNotEmittedWithoutMedia() {
+        // WHEN device source emits an event without media data
+        mDeviceListener.onMediaDeviceChanged(KEY, mDeviceData);
+        // THEN an event isn't emitted
+        verify(mListener, never()).onMediaDataLoaded(eq(KEY), any());
+    }
+
+    @Test
+    public void emitEventAfterDeviceFirst() {
+        // GIVEN that a device event has already been received
+        mDeviceListener.onMediaDeviceChanged(KEY, mDeviceData);
+        // WHEN media event is received
+        mDataListener.onMediaDataLoaded(KEY, mMediaData);
+        // THEN the listener receives a combined event
+        ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class);
+        verify(mListener).onMediaDataLoaded(eq(KEY), captor.capture());
+        assertThat(captor.getValue().getDevice()).isNotNull();
+    }
+
+    @Test
+    public void emitEventAfterMediaFirst() {
+        // GIVEN that media event has already been received
+        mDataListener.onMediaDataLoaded(KEY, mMediaData);
+        // WHEN device event is received
+        mDeviceListener.onMediaDeviceChanged(KEY, mDeviceData);
+        // THEN the listener receives a combined event
+        ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class);
+        verify(mListener).onMediaDataLoaded(eq(KEY), captor.capture());
+        assertThat(captor.getValue().getDevice()).isNotNull();
+    }
+
+    @Test
+    public void mediaDataRemoved() {
+        // WHEN media data is removed without first receiving device or data
+        mDataListener.onMediaDataRemoved(KEY);
+        // THEN a removed event isn't emitted
+        verify(mListener, never()).onMediaDataRemoved(eq(KEY));
+    }
+
+    @Test
+    public void mediaDataRemovedAfterMediaEvent() {
+        mDataListener.onMediaDataLoaded(KEY, mMediaData);
+        mDataListener.onMediaDataRemoved(KEY);
+        verify(mListener).onMediaDataRemoved(eq(KEY));
+    }
+
+    @Test
+    public void mediaDataRemovedAfterDeviceEvent() {
+        mDeviceListener.onMediaDeviceChanged(KEY, mDeviceData);
+        mDataListener.onMediaDataRemoved(KEY);
+        verify(mListener).onMediaDataRemoved(eq(KEY));
+    }
+
+    private MediaDataManager.Listener captureDataListener() {
+        ArgumentCaptor<MediaDataManager.Listener> captor = ArgumentCaptor.forClass(
+                MediaDataManager.Listener.class);
+        verify(mDataSource).addListener(captor.capture());
+        return captor.getValue();
+    }
+
+    private MediaDeviceManager.Listener captureDeviceListener() {
+        ArgumentCaptor<MediaDeviceManager.Listener> captor = ArgumentCaptor.forClass(
+                MediaDeviceManager.Listener.class);
+        verify(mDeviceSource).addListener(captor.capture());
+        return captor.getValue();
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
new file mode 100644
index 0000000..7b80a6e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media
+
+import android.app.Notification
+import android.media.MediaMetadata
+import android.media.MediaRouter2Manager
+import android.media.RoutingSessionInfo
+import android.media.session.MediaSession
+import android.media.session.PlaybackState
+import android.os.Process
+import android.service.notification.StatusBarNotification
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+
+import com.android.settingslib.media.LocalMediaManager
+import com.android.settingslib.media.MediaDevice
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.time.FakeSystemClock
+
+import com.google.common.truth.Truth.assertThat
+
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.any
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.junit.MockitoJUnit
+
+private const val KEY = "TEST_KEY"
+private const val PACKAGE = "PKG"
+private const val SESSION_KEY = "SESSION_KEY"
+private const val SESSION_ARTIST = "SESSION_ARTIST"
+private const val SESSION_TITLE = "SESSION_TITLE"
+private const val DEVICE_NAME = "DEVICE_NAME"
+
+private fun <T> eq(value: T): T = Mockito.eq(value) ?: value
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+public class MediaDeviceManagerTest : SysuiTestCase() {
+
+    private lateinit var manager: MediaDeviceManager
+    @Mock private lateinit var lmmFactory: LocalMediaManagerFactory
+    @Mock private lateinit var lmm: LocalMediaManager
+    @Mock private lateinit var mr2: MediaRouter2Manager
+    @Mock private lateinit var featureFlag: MediaFeatureFlag
+    private lateinit var fakeExecutor: FakeExecutor
+    @Mock private lateinit var listener: MediaDeviceManager.Listener
+    @Mock private lateinit var device: MediaDevice
+    @Mock private lateinit var route: RoutingSessionInfo
+    private lateinit var session: MediaSession
+    private lateinit var metadataBuilder: MediaMetadata.Builder
+    private lateinit var playbackBuilder: PlaybackState.Builder
+    private lateinit var notifBuilder: Notification.Builder
+    private lateinit var sbn: StatusBarNotification
+    @JvmField @Rule val mockito = MockitoJUnit.rule()
+
+    @Before
+    fun setUp() {
+        fakeExecutor = FakeExecutor(FakeSystemClock())
+        manager = MediaDeviceManager(context, lmmFactory, mr2, featureFlag, fakeExecutor)
+        manager.addListener(listener)
+
+        // Configure mocks.
+        whenever(device.name).thenReturn(DEVICE_NAME)
+        whenever(lmmFactory.create(PACKAGE)).thenReturn(lmm)
+        whenever(lmm.getCurrentConnectedDevice()).thenReturn(device)
+        whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(route)
+        whenever(featureFlag.enabled).thenReturn(true)
+
+        // Create a media sesssion and notification for testing.
+        metadataBuilder = MediaMetadata.Builder().apply {
+            putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
+            putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE)
+        }
+        playbackBuilder = PlaybackState.Builder().apply {
+            setState(PlaybackState.STATE_PAUSED, 6000L, 1f)
+            setActions(PlaybackState.ACTION_PLAY)
+        }
+        session = MediaSession(context, SESSION_KEY).apply {
+            setMetadata(metadataBuilder.build())
+            setPlaybackState(playbackBuilder.build())
+        }
+        session.setActive(true)
+        notifBuilder = Notification.Builder(context, "NONE").apply {
+            setContentTitle(SESSION_TITLE)
+            setContentText(SESSION_ARTIST)
+            setSmallIcon(android.R.drawable.ic_media_pause)
+            setStyle(Notification.MediaStyle().setMediaSession(session.getSessionToken()))
+        }
+        sbn = StatusBarNotification(PACKAGE, PACKAGE, 0, "TAG", Process.myUid(), 0, 0,
+                notifBuilder.build(), Process.myUserHandle(), 0)
+    }
+
+    @After
+    fun tearDown() {
+        session.release()
+    }
+
+    @Test
+    fun removeUnknown() {
+        manager.onNotificationRemoved("unknown")
+    }
+
+    @Test
+    fun addNotification() {
+        manager.onNotificationAdded(KEY, sbn)
+        verify(lmmFactory).create(PACKAGE)
+    }
+
+    @Test
+    fun featureDisabled() {
+        whenever(featureFlag.enabled).thenReturn(false)
+        manager.onNotificationAdded(KEY, sbn)
+        verify(lmmFactory, never()).create(PACKAGE)
+    }
+
+    @Test
+    fun addAndRemoveNotification() {
+        manager.onNotificationAdded(KEY, sbn)
+        manager.onNotificationRemoved(KEY)
+        verify(lmm).unregisterCallback(any())
+    }
+
+    @Test
+    fun deviceEventOnAddNotification() {
+        // WHEN a notification is added
+        manager.onNotificationAdded(KEY, sbn)
+        val deviceCallback = captureCallback()
+        // THEN the update is dispatched to the listener
+        val data = captureDeviceData(KEY)
+        assertThat(data.enabled).isTrue()
+        assertThat(data.name).isEqualTo(DEVICE_NAME)
+    }
+
+    @Test
+    fun deviceListUpdate() {
+        manager.onNotificationAdded(KEY, sbn)
+        val deviceCallback = captureCallback()
+        // WHEN the device list changes
+        deviceCallback.onDeviceListUpdate(mutableListOf(device))
+        assertThat(fakeExecutor.runAllReady()).isEqualTo(1)
+        // THEN the update is dispatched to the listener
+        val data = captureDeviceData(KEY)
+        assertThat(data.enabled).isTrue()
+        assertThat(data.name).isEqualTo(DEVICE_NAME)
+    }
+
+    @Test
+    fun selectedDeviceStateChanged() {
+        manager.onNotificationAdded(KEY, sbn)
+        val deviceCallback = captureCallback()
+        // WHEN the selected device changes state
+        deviceCallback.onSelectedDeviceStateChanged(device, 1)
+        assertThat(fakeExecutor.runAllReady()).isEqualTo(1)
+        // THEN the update is dispatched to the listener
+        val data = captureDeviceData(KEY)
+        assertThat(data.enabled).isTrue()
+        assertThat(data.name).isEqualTo(DEVICE_NAME)
+    }
+
+    @Test
+    fun listenerReceivesKeyRemoved() {
+        manager.onNotificationAdded(KEY, sbn)
+        // WHEN the notification is removed
+        manager.onNotificationRemoved(KEY)
+        // THEN the listener receives key removed event
+        verify(listener).onKeyRemoved(eq(KEY))
+    }
+
+    @Test
+    fun deviceDisabledWhenMR2ReturnsNullRouteInfo() {
+        // GIVEN that MR2Manager returns null for routing session
+        whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null)
+        // WHEN a notification is added
+        manager.onNotificationAdded(KEY, sbn)
+        // THEN the device is disabled
+        val data = captureDeviceData(KEY)
+        assertThat(data.enabled).isFalse()
+        assertThat(data.name).isNull()
+    }
+
+    @Test
+    fun deviceDisabledWhenMR2ReturnsNullRouteInfoOnDeviceChanged() {
+        // GIVEN a notif is added
+        manager.onNotificationAdded(KEY, sbn)
+        reset(listener)
+        // AND MR2Manager returns null for routing session
+        whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null)
+        // WHEN the selected device changes state
+        val deviceCallback = captureCallback()
+        deviceCallback.onSelectedDeviceStateChanged(device, 1)
+        fakeExecutor.runAllReady()
+        // THEN the device is disabled
+        val data = captureDeviceData(KEY)
+        assertThat(data.enabled).isFalse()
+        assertThat(data.name).isNull()
+    }
+
+    @Test
+    fun deviceDisabledWhenMR2ReturnsNullRouteInfoOnDeviceListUpdate() {
+        // GIVEN a notif is added
+        manager.onNotificationAdded(KEY, sbn)
+        reset(listener)
+        // GIVEN that MR2Manager returns null for routing session
+        whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null)
+        // WHEN the selected device changes state
+        val deviceCallback = captureCallback()
+        deviceCallback.onDeviceListUpdate(mutableListOf(device))
+        fakeExecutor.runAllReady()
+        // THEN the device is disabled
+        val data = captureDeviceData(KEY)
+        assertThat(data.enabled).isFalse()
+        assertThat(data.name).isNull()
+    }
+
+    fun captureCallback(): LocalMediaManager.DeviceCallback {
+        val captor = ArgumentCaptor.forClass(LocalMediaManager.DeviceCallback::class.java)
+        verify(lmm).registerCallback(captor.capture())
+        return captor.getValue()
+    }
+
+    fun captureDeviceData(key: String): MediaDeviceData {
+        val captor = ArgumentCaptor.forClass(MediaDeviceData::class.java)
+        verify(listener).onMediaDeviceChanged(eq(key), captor.capture())
+        return captor.getValue()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/PlayerViewHolderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/PlayerViewHolderTest.kt
new file mode 100644
index 0000000..7678525
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/PlayerViewHolderTest.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import android.widget.FrameLayout
+
+import androidx.test.filters.SmallTest
+
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Tests for PlayerViewHolder.
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class PlayerViewHolderTest : SysuiTestCase() {
+
+    private lateinit var inflater: LayoutInflater
+    private lateinit var parent: ViewGroup
+
+    @Before
+    fun setUp() {
+        inflater = LayoutInflater.from(context)
+        parent = FrameLayout(context)
+    }
+
+    @Test
+    fun create() {
+        val holder = PlayerViewHolder.create(inflater, parent)
+        assertThat(holder.player).isNotNull()
+    }
+
+    @Test
+    fun backgroundIsIlluminationDrawable() {
+        val holder = PlayerViewHolder.create(inflater, parent)
+        assertThat(holder.background.background as IlluminationDrawable).isNotNull()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt
index d407b8a..75018df 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt
@@ -16,19 +16,14 @@
 
 package com.android.systemui.media
 
-import android.graphics.Color
-import android.content.res.ColorStateList
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.view.View
 import android.widget.SeekBar
 import android.widget.TextView
 import androidx.test.filters.SmallTest
-
-import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.google.common.truth.Truth.assertThat
-
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -42,30 +37,28 @@
 public class SeekBarObserverTest : SysuiTestCase() {
 
     private lateinit var observer: SeekBarObserver
-    @Mock private lateinit var mockView: View
+    @Mock private lateinit var mockHolder: PlayerViewHolder
     private lateinit var seekBarView: SeekBar
     private lateinit var elapsedTimeView: TextView
     private lateinit var totalTimeView: TextView
 
     @Before
     fun setUp() {
-        mockView = mock(View::class.java)
+        mockHolder = mock(PlayerViewHolder::class.java)
         seekBarView = SeekBar(context)
         elapsedTimeView = TextView(context)
         totalTimeView = TextView(context)
-        whenever<SeekBar>(
-                mockView.findViewById(R.id.media_progress_bar)).thenReturn(seekBarView)
-        whenever<TextView>(
-                mockView.findViewById(R.id.media_elapsed_time)).thenReturn(elapsedTimeView)
-        whenever<TextView>(mockView.findViewById(R.id.media_total_time)).thenReturn(totalTimeView)
-        observer = SeekBarObserver(mockView)
+        whenever(mockHolder.seekBar).thenReturn(seekBarView)
+        whenever(mockHolder.elapsedTimeView).thenReturn(elapsedTimeView)
+        whenever(mockHolder.totalTimeView).thenReturn(totalTimeView)
+        observer = SeekBarObserver(mockHolder)
     }
 
     @Test
     fun seekBarGone() {
         // WHEN seek bar is disabled
         val isEnabled = false
-        val data = SeekBarViewModel.Progress(isEnabled, false, null, null, null)
+        val data = SeekBarViewModel.Progress(isEnabled, false, null, null)
         observer.onChanged(data)
         // THEN seek bar shows just a line with no text
         assertThat(seekBarView.isEnabled()).isFalse()
@@ -78,7 +71,7 @@
     fun seekBarVisible() {
         // WHEN seek bar is enabled
         val isEnabled = true
-        val data = SeekBarViewModel.Progress(isEnabled, true, 3000, 12000, -1)
+        val data = SeekBarViewModel.Progress(isEnabled, true, 3000, 12000)
         observer.onChanged(data)
         // THEN seek bar is visible
         assertThat(seekBarView.getVisibility()).isEqualTo(View.VISIBLE)
@@ -89,7 +82,7 @@
     @Test
     fun seekBarProgress() {
         // WHEN seek bar progress is about half
-        val data = SeekBarViewModel.Progress(true, true, 3000, 120000, -1)
+        val data = SeekBarViewModel.Progress(true, true, 3000, 120000)
         observer.onChanged(data)
         // THEN seek bar is visible
         assertThat(seekBarView.progress).isEqualTo(100)
@@ -102,7 +95,7 @@
     fun seekBarDisabledWhenSeekNotAvailable() {
         // WHEN seek is not available
         val isSeekAvailable = false
-        val data = SeekBarViewModel.Progress(true, isSeekAvailable, 3000, 120000, -1)
+        val data = SeekBarViewModel.Progress(true, isSeekAvailable, 3000, 120000)
         observer.onChanged(data)
         // THEN seek bar is not enabled
         assertThat(seekBarView.isEnabled()).isFalse()
@@ -112,20 +105,9 @@
     fun seekBarEnabledWhenSeekNotAvailable() {
         // WHEN seek is available
         val isSeekAvailable = true
-        val data = SeekBarViewModel.Progress(true, isSeekAvailable, 3000, 120000, -1)
+        val data = SeekBarViewModel.Progress(true, isSeekAvailable, 3000, 120000)
         observer.onChanged(data)
         // THEN seek bar is not enabled
         assertThat(seekBarView.isEnabled()).isTrue()
     }
-
-    @Test
-    fun seekBarColor() {
-        // WHEN data included color
-        val data = SeekBarViewModel.Progress(true, true, 3000, 120000, Color.RED)
-        observer.onChanged(data)
-        // THEN seek bar is colored
-        val red = ColorStateList.valueOf(Color.RED)
-        assertThat(elapsedTimeView.getTextColors()).isEqualTo(red)
-        assertThat(totalTimeView.getTextColors()).isEqualTo(red)
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
index cde575d..19e15b3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
@@ -16,9 +16,9 @@
 
 package com.android.systemui.media
 
-import android.graphics.Color
 import android.media.MediaMetadata
 import android.media.session.MediaController
+import android.media.session.MediaSession
 import android.media.session.PlaybackState
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
@@ -36,9 +36,12 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
 import org.mockito.Mock
+import org.mockito.Mockito.any
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.never
+import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when` as whenever
 
@@ -62,12 +65,15 @@
     }
     @Mock private lateinit var mockController: MediaController
     @Mock private lateinit var mockTransport: MediaController.TransportControls
+    private val token1 = MediaSession.Token(1, null)
+    private val token2 = MediaSession.Token(2, null)
 
     @Before
     fun setUp() {
         fakeExecutor = FakeExecutor(FakeSystemClock())
         viewModel = SeekBarViewModel(fakeExecutor)
         mockController = mock(MediaController::class.java)
+        whenever(mockController.sessionToken).thenReturn(token1)
         mockTransport = mock(MediaController.TransportControls::class.java)
 
         // LiveData to run synchronously
@@ -80,9 +86,39 @@
     }
 
     @Test
-    fun updateColor() {
-        viewModel.updateController(mockController, Color.RED)
-        assertThat(viewModel.progress.value!!.color).isEqualTo(Color.RED)
+    fun updateRegistersCallback() {
+        viewModel.updateController(mockController)
+        verify(mockController).registerCallback(any())
+    }
+
+    @Test
+    fun updateSecondTimeDoesNotRepeatRegistration() {
+        viewModel.updateController(mockController)
+        viewModel.updateController(mockController)
+        verify(mockController, times(1)).registerCallback(any())
+    }
+
+    @Test
+    fun updateDifferentControllerUnregistersCallback() {
+        viewModel.updateController(mockController)
+        viewModel.updateController(mock(MediaController::class.java))
+        verify(mockController).unregisterCallback(any())
+    }
+
+    @Test
+    fun updateDifferentControllerRegistersCallback() {
+        viewModel.updateController(mockController)
+        val controller2 = mock(MediaController::class.java)
+        whenever(controller2.sessionToken).thenReturn(token2)
+        viewModel.updateController(controller2)
+        verify(controller2).registerCallback(any())
+    }
+
+    @Test
+    fun updateToNullUnregistersCallback() {
+        viewModel.updateController(mockController)
+        viewModel.updateController(null)
+        verify(mockController).unregisterCallback(any())
     }
 
     @Test
@@ -101,7 +137,7 @@
         }
         whenever(mockController.getPlaybackState()).thenReturn(state)
         // WHEN the controller is updated
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // THEN the duration is extracted
         assertThat(viewModel.progress.value!!.duration).isEqualTo(duration)
         assertThat(viewModel.progress.value!!.enabled).isTrue()
@@ -117,7 +153,7 @@
         }
         whenever(mockController.getMetadata()).thenReturn(metadata)
         // WHEN the controller is updated
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // THEN the duration is extracted
         assertThat(viewModel.progress.value!!.duration).isEqualTo(duration)
         assertThat(viewModel.progress.value!!.enabled).isFalse()
@@ -139,7 +175,7 @@
         }
         whenever(mockController.getPlaybackState()).thenReturn(state)
         // WHEN the controller is updated
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // THEN the seek bar is disabled
         assertThat(viewModel.progress.value!!.enabled).isFalse()
     }
@@ -160,7 +196,7 @@
         }
         whenever(mockController.getPlaybackState()).thenReturn(state)
         // WHEN the controller is updated
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // THEN the seek bar is disabled
         assertThat(viewModel.progress.value!!.enabled).isFalse()
     }
@@ -175,7 +211,7 @@
         }
         whenever(mockController.getPlaybackState()).thenReturn(state)
         // WHEN the controller is updated
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // THEN elapsed time is captured
         assertThat(viewModel.progress.value!!.elapsedTime).isEqualTo(200.toInt())
     }
@@ -189,7 +225,7 @@
         }
         whenever(mockController.getPlaybackState()).thenReturn(state)
         // WHEN the controller is updated
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // THEN seek is available
         assertThat(viewModel.progress.value!!.seekAvailable).isTrue()
     }
@@ -203,7 +239,7 @@
         }
         whenever(mockController.getPlaybackState()).thenReturn(state)
         // WHEN the controller is updated
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // THEN seek is not available
         assertThat(viewModel.progress.value!!.seekAvailable).isFalse()
     }
@@ -211,7 +247,7 @@
     @Test
     fun handleSeek() {
         whenever(mockController.getTransportControls()).thenReturn(mockTransport)
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // WHEN user input is dispatched
         val pos = 42L
         viewModel.onSeek(pos)
@@ -223,7 +259,7 @@
     @Test
     fun handleProgressChangedUser() {
         whenever(mockController.getTransportControls()).thenReturn(mockTransport)
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // WHEN user starts dragging the seek bar
         val pos = 42
         viewModel.seekBarListener.onProgressChanged(SeekBar(context), pos, true)
@@ -235,7 +271,7 @@
     @Test
     fun handleProgressChangedOther() {
         whenever(mockController.getTransportControls()).thenReturn(mockTransport)
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // WHEN user starts dragging the seek bar
         val pos = 42
         viewModel.seekBarListener.onProgressChanged(SeekBar(context), pos, false)
@@ -247,7 +283,7 @@
     @Test
     fun handleStartTrackingTouch() {
         whenever(mockController.getTransportControls()).thenReturn(mockTransport)
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // WHEN user starts dragging the seek bar
         val pos = 42
         val bar = SeekBar(context).apply {
@@ -262,7 +298,7 @@
     @Test
     fun handleStopTrackingTouch() {
         whenever(mockController.getTransportControls()).thenReturn(mockTransport)
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // WHEN user ends drag
         val pos = 42
         val bar = SeekBar(context).apply {
@@ -283,7 +319,7 @@
         }
         whenever(mockController.getPlaybackState()).thenReturn(state)
         // WHEN the controller is updated
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // THEN a task is queued
         assertThat(fakeExecutor.numPending()).isEqualTo(1)
     }
@@ -297,7 +333,7 @@
         }
         whenever(mockController.getPlaybackState()).thenReturn(state)
         // WHEN updated
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // THEN an update task is not queued
         assertThat(fakeExecutor.numPending()).isEqualTo(0)
     }
@@ -317,7 +353,7 @@
         }
         whenever(mockController.getPlaybackState()).thenReturn(state)
         // WHEN updated
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // THEN an update task is queued
         assertThat(fakeExecutor.numPending()).isEqualTo(1)
     }
@@ -337,7 +373,7 @@
         }
         whenever(mockController.getPlaybackState()).thenReturn(state)
         // WHEN updated
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // THEN an update task is not queued
         assertThat(fakeExecutor.numPending()).isEqualTo(0)
     }
@@ -350,7 +386,7 @@
             build()
         }
         whenever(mockController.getPlaybackState()).thenReturn(state)
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // WHEN the next task runs
         with(fakeExecutor) {
             advanceClockToNext()
@@ -361,25 +397,6 @@
     }
 
     @Test
-    fun taskUpdatesProgress() {
-        // GIVEN that the PlaybackState contins the initial position
-        val initialPosition = 0L
-        val state = PlaybackState.Builder().run {
-            setState(PlaybackState.STATE_PLAYING, initialPosition, 1f)
-            build()
-        }
-        whenever(mockController.getPlaybackState()).thenReturn(state)
-        viewModel.updateController(mockController, Color.RED)
-        // WHEN the task runs
-        with(fakeExecutor) {
-            advanceClockToNext()
-            runAllReady()
-        }
-        // THEN elapsed time has increased
-        assertThat(viewModel.progress.value!!.elapsedTime).isGreaterThan(initialPosition.toInt())
-    }
-
-    @Test
     fun startListeningQueuesPollTask() {
         // GIVEN not listening
         viewModel.listening = false
@@ -393,7 +410,7 @@
             build()
         }
         whenever(mockController.getPlaybackState()).thenReturn(state)
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // WHEN start listening
         viewModel.listening = true
         // THEN an update task is queued
@@ -401,6 +418,26 @@
     }
 
     @Test
+    fun playbackChangeQueuesPollTask() {
+        viewModel.updateController(mockController)
+        val captor = ArgumentCaptor.forClass(MediaController.Callback::class.java)
+        verify(mockController).registerCallback(captor.capture())
+        val callback = captor.value
+        // WHEN the callback receives an new state
+        val state = PlaybackState.Builder().run {
+            setState(PlaybackState.STATE_PLAYING, 100L, 1f)
+            build()
+        }
+        callback.onPlaybackStateChanged(state)
+        with(fakeExecutor) {
+            advanceClockToNext()
+            runAllReady()
+        }
+        // THEN an update task is queued
+        assertThat(fakeExecutor.numPending()).isEqualTo(1)
+    }
+
+    @Test
     fun clearSeekBar() {
         // GIVEN that the duration is contained within the metadata
         val metadata = MediaMetadata.Builder().run {
@@ -415,7 +452,7 @@
         }
         whenever(mockController.getPlaybackState()).thenReturn(state)
         // AND the controller has been updated
-        viewModel.updateController(mockController, Color.RED)
+        viewModel.updateController(mockController)
         // WHEN the controller is cleared on the event when the session is destroyed
         viewModel.clearController()
         with(fakeExecutor) {
@@ -425,4 +462,20 @@
         // THEN the seek bar is disabled
         assertThat(viewModel.progress.value!!.enabled).isFalse()
     }
+
+    @Test
+    fun clearSeekBarUnregistersCallback() {
+        viewModel.updateController(mockController)
+        viewModel.clearController()
+        fakeExecutor.runAllReady()
+        verify(mockController).unregisterCallback(any())
+    }
+
+    @Test
+    fun destroyUnregistersCallback() {
+        viewModel.updateController(mockController)
+        viewModel.onDestroy()
+        fakeExecutor.runAllReady()
+        verify(mockController).unregisterCallback(any())
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchHandlerTest.java
index 7211254..601fad6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchHandlerTest.java
@@ -65,9 +65,6 @@
     private IActivityManager mActivityManager;
 
     @Mock
-    private IActivityTaskManager mIActivityTaskManager;
-
-    @Mock
     private PipMenuActivityController mPipMenuActivityController;
 
     @Mock
@@ -101,7 +98,7 @@
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         mPipSnapAlgorithm = new PipSnapAlgorithm(mContext);
-        mPipTouchHandler = new PipTouchHandler(mContext, mActivityManager, mIActivityTaskManager,
+        mPipTouchHandler = new PipTouchHandler(mContext, mActivityManager,
                 mPipMenuActivityController, mInputConsumerController, mPipBoundsHandler,
                 mPipTaskOrganizer, mFloatingContentCoordinator, mDeviceConfigProxy,
                 mPipSnapAlgorithm);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
index 128d6e5..05b31c8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.media.MediaHost;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.qs.QSTileView;
 import com.android.systemui.qs.customize.QSCustomizer;
@@ -50,7 +51,6 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.policy.SecurityController;
-import com.android.systemui.util.concurrency.DelayableExecutor;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -62,7 +62,6 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.Collections;
-import java.util.concurrent.Executor;
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
@@ -90,9 +89,7 @@
     @Mock
     private QSTileView mQSTileView;
     @Mock
-    private Executor mForegroundExecutor;
-    @Mock
-    private DelayableExecutor mBackgroundExecutor;
+    private MediaHost mMediaHost;
     @Mock
     private LocalBluetoothManager mLocalBluetoothManager;
     @Mock
@@ -116,8 +113,7 @@
         mTestableLooper.runWithLooper(() -> {
             mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
             mQsPanel = new QSPanel(mContext, null, mDumpManager, mBroadcastDispatcher,
-                    mQSLogger, mForegroundExecutor, mBackgroundExecutor,
-                    mLocalBluetoothManager, mActivityStarter, mEntryManager, mUiEventLogger);
+                    mQSLogger, mMediaHost, mUiEventLogger);
             // Provides a parent with non-zero size for QSPanel
             mParentView = new FrameLayout(mContext);
             mParentView.addView(mQsPanel);
@@ -165,6 +161,9 @@
 
         mQsPanel.setListening(true);
         verify(mQSLogger).logAllTilesChangeListening(true, mQsPanel.getDumpableTag(), "dnd");
+
+        mQsPanel.setListening(false);
+        verify(mQSLogger).logAllTilesChangeListening(false, mQsPanel.getDumpableTag(), "dnd");
     }
 
 /*    @Test
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 d124bad..808f17b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -20,9 +20,9 @@
 import static android.content.Intent.ACTION_USER_SWITCHED;
 import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
 
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_MEDIA_CONTROLS;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_MEDIA_CONTROLS;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_PEOPLE;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
 
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
@@ -52,7 +52,6 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.Dependency;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -86,7 +85,7 @@
     @Mock
     private DevicePolicyManager mDevicePolicyManager;
     @Mock
-    private IStatusBarService mIStatusBarService;
+    private NotificationClickNotifier mClickNotifier;
     @Mock
     private KeyguardManager mKeyguardManager;
     @Mock
@@ -397,7 +396,7 @@
             extends NotificationLockscreenUserManagerImpl {
         public TestNotificationLockscreenUserManager(Context context) {
             super(context, mBroadcastDispatcher, mDevicePolicyManager, mUserManager,
-                    mIStatusBarService, NotificationLockscreenUserManagerTest.this.mKeyguardManager,
+                    mClickNotifier, NotificationLockscreenUserManagerTest.this.mKeyguardManager,
                     mStatusBarStateController, Handler.createAsync(Looper.myLooper()),
                     mDeviceProvisionedController, mKeyguardStateController);
         }
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 1117646..eaef43d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
@@ -62,6 +62,7 @@
     @Mock private ExpandableNotificationRow mRow;
     @Mock private StatusBarStateController mStateController;
     @Mock private RemoteInputUriController mRemoteInputUriController;
+    @Mock private NotificationClickNotifier mClickNotifier;
 
     // Dependency mocks:
     @Mock private NotificationEntryManager mEntryManager;
@@ -82,7 +83,9 @@
                 () -> mock(StatusBar.class),
                 mStateController,
                 Handler.createAsync(Looper.myLooper()),
-                mRemoteInputUriController);
+                mRemoteInputUriController,
+                mClickNotifier,
+                mock(ActionClickLogger.class));
         mEntry = new NotificationEntryBuilder()
                 .setPkg(TEST_PACKAGE_NAME)
                 .setOpPkg(TEST_PACKAGE_NAME)
@@ -256,17 +259,28 @@
 
     private class TestableNotificationRemoteInputManager extends NotificationRemoteInputManager {
 
-        TestableNotificationRemoteInputManager(Context context,
+        TestableNotificationRemoteInputManager(
+                Context context,
                 NotificationLockscreenUserManager lockscreenUserManager,
                 SmartReplyController smartReplyController,
                 NotificationEntryManager notificationEntryManager,
                 Lazy<StatusBar> statusBarLazy,
                 StatusBarStateController statusBarStateController,
                 Handler mainHandler,
-                RemoteInputUriController remoteInputUriController) {
-            super(context, lockscreenUserManager, smartReplyController, notificationEntryManager,
-                    statusBarLazy, statusBarStateController, mainHandler,
-                    remoteInputUriController);
+                RemoteInputUriController remoteInputUriController,
+                NotificationClickNotifier clickNotifier,
+                ActionClickLogger actionClickLogger) {
+            super(
+                    context,
+                    lockscreenUserManager,
+                    smartReplyController,
+                    notificationEntryManager,
+                    statusBarLazy,
+                    statusBarStateController,
+                    mainHandler,
+                    remoteInputUriController,
+                    clickNotifier,
+                    actionClickLogger);
         }
 
         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 c46ac47..e889dad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
@@ -28,6 +28,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator
 import com.android.systemui.statusbar.phone.BiometricUnlockController
+import com.android.systemui.statusbar.phone.DozeParameters
 import com.android.systemui.statusbar.phone.NotificationShadeWindowController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import org.junit.Before
@@ -67,6 +68,7 @@
     @Mock private lateinit var shadeAnimation: NotificationShadeDepthController.DepthAnimation
     @Mock private lateinit var globalActionsSpring: NotificationShadeDepthController.DepthAnimation
     @Mock private lateinit var brightnessSpring: NotificationShadeDepthController.DepthAnimation
+    @Mock private lateinit var dozeParameters: DozeParameters
     @JvmField @Rule val mockitoRule = MockitoJUnit.rule()
 
     private lateinit var statusBarStateListener: StatusBarStateController.StateListener
@@ -87,7 +89,7 @@
         notificationShadeDepthController = NotificationShadeDepthController(
                 statusBarStateController, blurUtils, biometricUnlockController,
                 keyguardStateController, choreographer, wallpaperManager,
-                notificationShadeWindowController, dumpManager)
+                notificationShadeWindowController, dozeParameters, dumpManager)
         notificationShadeDepthController.shadeSpring = shadeSpring
         notificationShadeDepthController.shadeAnimation = shadeAnimation
         notificationShadeDepthController.brightnessMirrorSpring = brightnessSpring
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 22dc080..7cbc4e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
@@ -75,6 +75,7 @@
     @Mock private IStatusBarService mIStatusBarService;
     @Mock private StatusBarStateController mStatusBarStateController;
     @Mock private RemoteInputUriController mRemoteInputUriController;
+    @Mock private NotificationClickNotifier mClickNotifier;
 
     @Before
     public void setUp() {
@@ -83,7 +84,7 @@
                 mNotificationEntryManager);
 
         mSmartReplyController = new SmartReplyController(mNotificationEntryManager,
-                mIStatusBarService);
+                mIStatusBarService, mClickNotifier);
         mDependency.injectTestDependency(SmartReplyController.class,
                 mSmartReplyController);
 
@@ -92,7 +93,9 @@
                 mNotificationEntryManager, () -> mock(StatusBar.class),
                 mStatusBarStateController,
                 Handler.createAsync(Looper.myLooper()),
-                mRemoteInputUriController);
+                mRemoteInputUriController,
+                mClickNotifier,
+                mock(ActionClickLogger.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/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index bb7f73a..a5a5f81 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
@@ -210,6 +210,28 @@
     }
 
     @Test
+    public void testAddNotification_noDuplicateEntriesCreated() {
+        // GIVEN a notification has been added
+        mEntryManager.addNotification(mSbn, mRankingMap);
+
+        // WHEN the same notification is added multiple times before the previous entry (with
+        // the same key) didn't finish inflating
+        mEntryManager.addNotification(mSbn, mRankingMap);
+        mEntryManager.addNotification(mSbn, mRankingMap);
+        mEntryManager.addNotification(mSbn, mRankingMap);
+
+        // THEN getAllNotifs() only contains exactly one notification with this key
+        int count = 0;
+        for (NotificationEntry entry : mEntryManager.getAllNotifs()) {
+            if (entry.getKey().equals(mSbn.getKey())) {
+                count++;
+            }
+        }
+        assertEquals("Should only be one entry with key=" + mSbn.getKey() + " in mAllNotifs. "
+                        + "Instead there are " + count, 1, count);
+    }
+
+    @Test
     public void testAddNotification_setsUserSentiment() {
         mEntryManager.addNotification(mSbn, mRankingMap);
 
@@ -243,7 +265,7 @@
         // Ensure that update callbacks happen in correct order
         InOrder order = inOrder(mEntryListener, mPresenter, mEntryListener);
         order.verify(mEntryListener).onPreEntryUpdated(mEntry);
-        order.verify(mPresenter).updateNotificationViews();
+        order.verify(mPresenter).updateNotificationViews(any());
         order.verify(mEntryListener).onPostEntryUpdated(mEntry);
     }
 
@@ -254,7 +276,7 @@
 
         mEntryManager.removeNotification(mSbn.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
 
-        verify(mPresenter).updateNotificationViews();
+        verify(mPresenter).updateNotificationViews(any());
         verify(mEntryListener).onEntryRemoved(
                 eq(mEntry), any(), eq(false) /* removedByUser */, eq(UNDEFINED_DISMISS_REASON));
         verify(mRow).setRemoved();
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 277ac24..595ba89 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
@@ -45,6 +45,7 @@
 import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -93,7 +94,9 @@
                 .thenReturn(PackageManager.PERMISSION_GRANTED);
         mDependency.injectTestDependency(ForegroundServiceController.class, mFsc);
         mDependency.injectTestDependency(NotificationGroupManager.class,
-                new NotificationGroupManager(mock(StatusBarStateController.class)));
+                new NotificationGroupManager(
+                        mock(StatusBarStateController.class),
+                        () -> mock(PeopleNotificationIdentifier.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/NotificationSectionsFeatureManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
index ca7a5db..8948fd0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
@@ -74,7 +74,7 @@
                 DeviceConfig.NAMESPACE_SYSTEMUI, NOTIFICATIONS_USE_PEOPLE_FILTERING, "true", false)
 
         assertTrue("People filtering should be enabled", manager!!.isFilteringEnabled())
-        assertTrue("Expecting 4 buckets when people filtering is enabled",
-                manager!!.getNumberOfBuckets() == 4)
+        assertTrue("Expecting 5 buckets when people filtering is enabled",
+                manager!!.getNumberOfBuckets() == 5)
     }
 }
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 3d06c57..ea1b498 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
@@ -21,6 +21,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -108,7 +109,7 @@
     public void testCallBackCalledScreenOn() {
         mVisualStabilityManager.setPanelExpanded(true);
         mVisualStabilityManager.setScreenOn(true);
-        mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
+        mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false  /* persistent */);
         mVisualStabilityManager.setScreenOn(false);
         verify(mCallback).onChangeAllowed();
     }
@@ -117,7 +118,7 @@
     public void testCallBackCalledPanelExpanded() {
         mVisualStabilityManager.setPanelExpanded(true);
         mVisualStabilityManager.setScreenOn(true);
-        mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
+        mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false  /* persistent */);
         mVisualStabilityManager.setPanelExpanded(false);
         verify(mCallback).onChangeAllowed();
     }
@@ -126,7 +127,7 @@
     public void testCallBackExactlyOnce() {
         mVisualStabilityManager.setPanelExpanded(true);
         mVisualStabilityManager.setScreenOn(true);
-        mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
+        mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false  /* persistent */);
         mVisualStabilityManager.setScreenOn(false);
         mVisualStabilityManager.setScreenOn(true);
         mVisualStabilityManager.setScreenOn(false);
@@ -134,6 +135,17 @@
     }
 
     @Test
+    public void testCallBackCalledContinuouslyWhenRequested() {
+        mVisualStabilityManager.setPanelExpanded(true);
+        mVisualStabilityManager.setScreenOn(true);
+        mVisualStabilityManager.addReorderingAllowedCallback(mCallback, true  /* persistent */);
+        mVisualStabilityManager.setScreenOn(false);
+        mVisualStabilityManager.setScreenOn(true);
+        mVisualStabilityManager.setScreenOn(false);
+        verify(mCallback, times(2)).onChangeAllowed();
+    }
+
+    @Test
     public void testAddedCanReorder() {
         mVisualStabilityManager.setPanelExpanded(true);
         mVisualStabilityManager.setScreenOn(true);
@@ -188,7 +200,7 @@
     @Test
     public void testCallBackCalled_Pulsing() {
         mVisualStabilityManager.setPulsing(true);
-        mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
+        mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false  /* persistent */);
         mVisualStabilityManager.setPulsing(false);
         verify(mCallback).onChangeAllowed();
     }
@@ -198,7 +210,7 @@
         // GIVEN having the panel open (which would block reordering)
         mVisualStabilityManager.setScreenOn(true);
         mVisualStabilityManager.setPanelExpanded(true);
-        mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
+        mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false  /* persistent */);
 
         // WHEN we temprarily allow reordering
         mVisualStabilityManager.temporarilyAllowReordering();
@@ -212,7 +224,7 @@
     public void testTemporarilyAllowReorderingDoesntOverridePulsing() {
         // GIVEN we are in a pulsing state
         mVisualStabilityManager.setPulsing(true);
-        mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
+        mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false  /* persistent */);
 
         // WHEN we temprarily allow reordering
         mVisualStabilityManager.temporarilyAllowReordering();
@@ -227,7 +239,7 @@
         // GIVEN having the panel open (which would block reordering)
         mVisualStabilityManager.setScreenOn(true);
         mVisualStabilityManager.setPanelExpanded(true);
-        mVisualStabilityManager.addReorderingAllowedCallback(mCallback);
+        mVisualStabilityManager.addReorderingAllowedCallback(mCallback, false  /* persistent */);
 
         // WHEN we temprarily allow reordering and then wait until the window expires
         mVisualStabilityManager.temporarilyAllowReordering();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index 82de4a3..ca9cc29 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -34,6 +34,7 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
@@ -65,6 +66,7 @@
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.dump.LogBufferEulogizer;
 import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.RankingBuilder;
 import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent;
@@ -100,11 +102,13 @@
 public class NotifCollectionTest extends SysuiTestCase {
 
     @Mock private IStatusBarService mStatusBarService;
+    @Mock private FeatureFlags mFeatureFlags;
     @Mock private NotifCollectionLogger mLogger;
+    @Mock private LogBufferEulogizer mEulogizer;
+
     @Mock private GroupCoalescer mGroupCoalescer;
     @Spy private RecordingCollectionListener mCollectionListener;
     @Mock private CollectionReadyForBuildListener mBuildListener;
-    @Mock private FeatureFlags mFeatureFlags;
 
     @Spy private RecordingLifetimeExtender mExtender1 = new RecordingLifetimeExtender("Extender1");
     @Spy private RecordingLifetimeExtender mExtender2 = new RecordingLifetimeExtender("Extender2");
@@ -136,13 +140,16 @@
         when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(true);
         when(mFeatureFlags.isNewNotifPipelineEnabled()).thenReturn(true);
 
+        when(mEulogizer.record(any(Exception.class))).thenAnswer(i -> i.getArguments()[0]);
+
         mListenerInOrder = inOrder(mCollectionListener);
 
         mCollection = new NotifCollection(
                 mStatusBarService,
                 mock(DumpManager.class),
                 mFeatureFlags,
-                mLogger);
+                mLogger,
+                mEulogizer);
         mCollection.attach(mGroupCoalescer);
         mCollection.addCollectionListener(mCollectionListener);
         mCollection.setBuildListener(mBuildListener);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
index b4cabfd..1c47131 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
@@ -21,6 +21,7 @@
 import android.app.NotificationManager.IMPORTANCE_DEFAULT
 import android.app.NotificationManager.IMPORTANCE_HIGH
 import android.app.NotificationManager.IMPORTANCE_LOW
+import android.os.SystemClock
 import android.service.notification.NotificationListenerService.RankingMap
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
@@ -36,10 +37,12 @@
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_IMPORTANT_PERSON
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_PERSON
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
-import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
-import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT
+import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING
+import com.android.systemui.statusbar.notification.stack.BUCKET_FOREGROUND_SERVICE
+import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
 import com.android.systemui.statusbar.phone.NotificationGroupManager
 import com.android.systemui.statusbar.policy.HeadsUpManager
+import com.google.common.truth.Truth.assertThat
 import dagger.Lazy
 import junit.framework.Assert.assertEquals
 import org.junit.Before
@@ -58,17 +61,19 @@
     private lateinit var personNotificationIdentifier: PeopleNotificationIdentifier
     private lateinit var rankingManager: TestableNotificationRankingManager
     private lateinit var sectionsManager: NotificationSectionsFeatureManager
+    private lateinit var notificationFilter: NotificationFilter
 
     @Before
     fun setup() {
         personNotificationIdentifier =
                 mock(PeopleNotificationIdentifier::class.java)
         sectionsManager = mock(NotificationSectionsFeatureManager::class.java)
+        notificationFilter = mock(NotificationFilter::class.java)
         rankingManager = TestableNotificationRankingManager(
                 lazyMedia,
                 mock(NotificationGroupManager::class.java),
                 mock(HeadsUpManager::class.java),
-                mock(NotificationFilter::class.java),
+                notificationFilter,
                 mock(NotificationEntryManagerLogger::class.java),
                 sectionsManager,
                 personNotificationIdentifier,
@@ -324,6 +329,84 @@
         assertEquals(e.bucket, BUCKET_SILENT)
     }
 
+    @Test
+    fun testFilter_resetsInitalizationTime() {
+        // GIVEN an entry that was initialized 1 second ago
+        val notif = Notification.Builder(mContext, "test") .build()
+
+        val e = NotificationEntryBuilder()
+            .setPkg("pkg")
+            .setOpPkg("pkg")
+            .setTag("tag")
+            .setNotification(notif)
+            .setUser(mContext.user)
+            .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT))
+            .setOverrideGroupKey("")
+            .build()
+
+        e.setInitializationTime(SystemClock.elapsedRealtime() - 1000)
+        assertEquals(true, e.hasFinishedInitialization())
+
+        // WHEN we update ranking and filter out the notification entry
+        whenever(notificationFilter.shouldFilterOut(e)).thenReturn(true)
+        rankingManager.updateRanking(RankingMap(arrayOf(e.ranking)), listOf(e), "test")
+
+        // THEN the initialization time for the entry is reset
+        assertEquals(false, e.hasFinishedInitialization())
+    }
+
+    @Test
+    fun testSort_colorizedForegroundService() {
+        whenever(sectionsManager.isFilteringEnabled()).thenReturn(true)
+
+        val a = NotificationEntryBuilder()
+                .setImportance(IMPORTANCE_HIGH)
+                .setPkg("pkg")
+                .setOpPkg("pkg")
+                .setTag("tag")
+                .setNotification(
+                        Notification.Builder(mContext, "test")
+                                .build())
+                .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT))
+                .setUser(mContext.getUser())
+                .setOverrideGroupKey("")
+                .build()
+
+        val b = NotificationEntryBuilder()
+                .setImportance(IMPORTANCE_DEFAULT) // high priority
+                .setPkg("pkg2")
+                .setOpPkg("pkg2")
+                .setTag("tag")
+                .setNotification(mock(Notification::class.java).also { notif ->
+                    whenever(notif.isForegroundService).thenReturn(true)
+                    whenever(notif.isColorized).thenReturn(true)
+                })
+                .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT))
+                .setUser(mContext.getUser())
+                .setOverrideGroupKey("")
+                .build()
+
+        val cN = Notification.Builder(mContext, "test")
+                .setStyle(Notification.MessagingStyle(""))
+                .build()
+        val c = NotificationEntryBuilder()
+                .setImportance(IMPORTANCE_HIGH)
+                .setPkg("pkg")
+                .setOpPkg("pkg")
+                .setTag("tag")
+                .setNotification(cN)
+                .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT))
+                .setUser(mContext.user)
+                .setOverrideGroupKey("")
+                .build()
+        whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking))
+                .thenReturn(TYPE_IMPORTANT_PERSON)
+
+        assertThat(rankingManager.updateRanking(null, listOf(a, b, c), "test"))
+                .containsExactly(b, c, a)
+        assertThat(b.bucket).isEqualTo(BUCKET_FOREGROUND_SERVICE)
+    }
+
     internal class TestableNotificationRankingManager(
         mediaManager: Lazy<NotificationMediaManager>,
         groupManager: NotificationGroupManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
index 3adc3d0..6fa5055 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
@@ -19,8 +19,10 @@
 import static com.android.systemui.statusbar.notification.collection.ListDumper.dumpTree;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyList;
 import static org.mockito.ArgumentMatchers.anyLong;
@@ -33,6 +35,7 @@
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
+import android.os.SystemClock;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.util.ArrayMap;
@@ -41,6 +44,7 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.statusbar.NotificationInteractionTracker;
 import com.android.systemui.statusbar.notification.collection.ShadeListBuilder.OnRenderListListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
@@ -83,6 +87,7 @@
 
     @Mock private ShadeListBuilderLogger mLogger;
     @Mock private NotifCollection mNotifCollection;
+    @Mock private NotificationInteractionTracker mInteractionTracker;
     @Spy private OnBeforeTransformGroupsListener mOnBeforeTransformGroupsListener;
     @Spy private OnBeforeSortListener mOnBeforeSortListener;
     @Spy private OnBeforeFinalizeFilterListener mOnBeforeFinalizeFilterListener;
@@ -104,7 +109,8 @@
         MockitoAnnotations.initMocks(this);
         allowTestableLooperAsMainThread();
 
-        mListBuilder = new ShadeListBuilder(mSystemClock, mLogger, mock(DumpManager.class));
+        mListBuilder = new ShadeListBuilder(
+                mSystemClock, mLogger, mock(DumpManager.class), mInteractionTracker);
         mListBuilder.setOnRenderListListener(mOnRenderListListener);
 
         mListBuilder.attach(mNotifCollection);
@@ -475,6 +481,28 @@
     }
 
     @Test
+    public void testFilter_resetsInitalizationTime() {
+        // GIVEN a NotifFilter that filters out a specific package
+        NotifFilter filter1 = spy(new PackageFilter(PACKAGE_1));
+        mListBuilder.addFinalizeFilter(filter1);
+
+        // GIVEN a notification that was initialized 1 second ago that will be filtered out
+        final NotificationEntry entry = new NotificationEntryBuilder()
+                .setPkg(PACKAGE_1)
+                .setId(nextId(PACKAGE_1))
+                .setRank(nextRank())
+                .build();
+        entry.setInitializationTime(SystemClock.elapsedRealtime() - 1000);
+        assertTrue(entry.hasFinishedInitialization());
+
+        // WHEN the pipeline is kicked off
+        mReadyForBuildListener.onBuildList(Arrays.asList(entry));
+
+        // THEN the entry's initialization time is reset
+        assertFalse(entry.hasFinishedInitialization());
+    }
+
+    @Test
     public void testNotifFiltersCanBePreempted() {
         // GIVEN two notif filters
         NotifFilter filter1 = spy(new PackageFilter(PACKAGE_2));
@@ -1255,7 +1283,7 @@
         } catch (AssertionError err) {
             throw new AssertionError(
                     "List under test failed verification:\n" + dumpTree(mBuiltList,
-                            true, ""), err);
+                            mInteractionTracker, true, ""), err);
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index d39b2c2..a3a46f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.statusbar.notification.logging;
 
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_ALERTING;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
index dbf40e4..4b21ef2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
@@ -193,7 +193,7 @@
         when(mMockPackageManager.getPackageInfo(eq("android"), anyInt()))
                 .thenReturn(packageInfo);
 
-        when(mShortcutInfo.getShortLabel()).thenReturn("Convo name");
+        when(mShortcutInfo.getLabel()).thenReturn("Convo name");
         List<ShortcutInfo> shortcuts = Arrays.asList(mShortcutInfo);
         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(shortcuts);
         when(mIconFactory.getConversationDrawable(
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 2894abb8..7dfead7 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
@@ -335,7 +335,7 @@
         assertNotNull(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey()));
 
         // THEN we update the presenter
-        verify(mPresenter).updateNotificationViews();
+        verify(mPresenter).updateNotificationViews(any());
     }
 
     @Test
@@ -364,7 +364,7 @@
         verify(mEntryListener).onEntryReinflated(entry);
 
         // THEN we update the presenter
-        verify(mPresenter).updateNotificationViews();
+        verify(mPresenter).updateNotificationViews(any());
     }
 
     @Test
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 07f2085..b9eb4d1 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
@@ -115,7 +115,9 @@
         dependency.injectMockDependency(BubbleController.class);
         dependency.injectMockDependency(NotificationShadeWindowController.class);
         mStatusBarStateController = mock(StatusBarStateController.class);
-        mGroupManager = new NotificationGroupManager(mStatusBarStateController);
+        mGroupManager = new NotificationGroupManager(
+                mStatusBarStateController,
+                () -> mock(PeopleNotificationIdentifier.class));
         mHeadsUpManager = new HeadsUpManagerPhone(mContext, mStatusBarStateController,
                 mock(KeyguardBypassController.class), mock(NotificationGroupManager.class),
                 mock(ConfigurationControllerImpl.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java
index 1bfebfb..545b59a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java
@@ -47,6 +47,7 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.text.SpannableString;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.ImageView;
@@ -151,8 +152,11 @@
                 NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME,
                 IMPORTANCE_LOW);
         mDefaultNotificationChannelSet.add(mDefaultNotificationChannel);
+        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
+                .setContentTitle(new SpannableString("title"))
+                .build();
         mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
-                new Notification(), UserHandle.CURRENT, null, 0);
+                n, UserHandle.CURRENT, null, 0);
         mEntry = new NotificationEntryBuilder().setSbn(mSbn).build();
     }
 
@@ -176,6 +180,23 @@
     }
 
     @Test
+    public void testBindNotification_SetsName() {
+        mInfo.bindNotification(
+                mMockPackageManager,
+                mMockINotificationManager,
+                mChannelEditorDialogController,
+                TEST_PACKAGE_NAME,
+                mNotificationChannel,
+                mNotificationChannelSet,
+                mEntry,
+                null,
+                true,
+                false);
+        final TextView textView = mInfo.findViewById(R.id.name);
+        assertTrue(textView.getText().toString().contains("title"));
+    }
+
+    @Test
     public void testBindNotification_groupSetsPackageIcon() {
         mEntry.getSbn().getNotification().extras.putBoolean(EXTRA_IS_GROUP_CONVERSATION, true);
         final Drawable iconDrawable = mock(Drawable.class);
@@ -356,6 +377,30 @@
     }
 
     @Test
+    public void testBindNotification_SetsOnClickListenerForSettings_mainText() {
+        final CountDownLatch latch = new CountDownLatch(1);
+        mInfo.bindNotification(
+                mMockPackageManager,
+                mMockINotificationManager,
+                mChannelEditorDialogController,
+                TEST_PACKAGE_NAME,
+                mNotificationChannel,
+                mNotificationChannelSet,
+                mEntry,
+                (View v, NotificationChannel c, int appUid) -> {
+                    assertEquals(mNotificationChannel, c);
+                    latch.countDown();
+                },
+                true,
+                false);
+
+        final View settingsButton = mInfo.findViewById(R.id.settings_link);
+        settingsButton.performClick();
+        // Verify that listener was triggered.
+        assertEquals(0, latch.getCount());
+    }
+
+    @Test
     public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() {
         mInfo.bindNotification(
                 mMockPackageManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
index 646bc96..3dc941a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
@@ -18,16 +18,20 @@
 
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_HEADS_UP;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_ALERTING;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_FOREGROUND_SERVICE;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_HEADS_UP;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_PEOPLE;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
+
+import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -42,12 +46,13 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.keyguard.KeyguardMediaPlayer;
 import com.android.systemui.ActivityStarterDelegate;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.media.KeyguardMediaController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.people.PeopleHubViewAdapter;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -62,6 +67,9 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
@@ -74,27 +82,42 @@
     @Mock private StatusBarStateController mStatusBarStateController;
     @Mock private ConfigurationController mConfigurationController;
     @Mock private PeopleHubViewAdapter mPeopleHubAdapter;
-    @Mock private KeyguardMediaPlayer mKeyguardMediaPlayer;
+    @Mock private KeyguardMediaController mKeyguardMediaController;
     @Mock private NotificationSectionsFeatureManager mSectionsFeatureManager;
     @Mock private NotificationRowComponent mNotificationRowComponent;
     @Mock private ActivatableNotificationViewController mActivatableNotificationViewController;
+    @Mock private NotificationSectionsLogger mLogger;
 
     private NotificationSectionsManager mSectionsManager;
 
     @Before
     public void setUp() {
-        when(mSectionsFeatureManager.getNumberOfBuckets()).thenReturn(2);
-        when(mNotificationRowComponent.getActivatableNotificationViewController()).thenReturn(
-                mActivatableNotificationViewController
-        );
+        when(mSectionsFeatureManager.getNumberOfBuckets()).thenAnswer(
+                invocation -> {
+                    int count = 2;
+                    if (mSectionsFeatureManager.isFilteringEnabled()) {
+                        count = 5;
+                    }
+                    if (mSectionsFeatureManager.isMediaControlsEnabled()) {
+                        if (!mSectionsFeatureManager.isFilteringEnabled()) {
+                            count = 5;
+                        } else {
+                            count += 1;
+                        }
+                    }
+                    return count;
+                });
+        when(mNotificationRowComponent.getActivatableNotificationViewController())
+                .thenReturn(mActivatableNotificationViewController);
         mSectionsManager =
                 new NotificationSectionsManager(
                         mActivityStarterDelegate,
                         mStatusBarStateController,
                         mConfigurationController,
                         mPeopleHubAdapter,
-                        mKeyguardMediaPlayer,
-                        mSectionsFeatureManager
+                        mKeyguardMediaController,
+                        mSectionsFeatureManager,
+                        mLogger
                 );
         // Required in order for the header inflation to work properly
         when(mNssl.generateLayoutParams(any(AttributeSet.class)))
@@ -102,6 +125,7 @@
         mSectionsManager.initialize(mNssl, LayoutInflater.from(mContext));
         when(mNssl.indexOfChild(any(View.class))).thenReturn(-1);
         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
+
     }
 
     @Test(expected =  IllegalStateException.class)
@@ -112,140 +136,152 @@
     @Test
     public void testInsertHeader() {
         // GIVEN a stack with HI and LO rows but no section headers
-        setStackState(ChildType.ALERTING, ChildType.ALERTING, ChildType.ALERTING, ChildType.GENTLE);
+        setStackState(
+                ALERTING,
+                ALERTING,
+                ALERTING,
+                GENTLE);
 
         // WHEN we update the section headers
         mSectionsManager.updateSectionBoundaries();
 
         // THEN a LO section header is added
-        verify(mNssl).addView(mSectionsManager.getGentleHeaderView(), 3);
+        verify(mNssl).addView(mSectionsManager.getSilentHeaderView(), 3);
     }
 
     @Test
     public void testRemoveHeader() {
         // GIVEN a stack that originally had a header between the HI and LO sections
-        setStackState(ChildType.ALERTING, ChildType.ALERTING, ChildType.GENTLE);
+        setStackState(
+                ALERTING,
+                ALERTING,
+                GENTLE);
         mSectionsManager.updateSectionBoundaries();
 
         // WHEN the last LO row is replaced with a HI row
         setStackState(
-                ChildType.ALERTING,
-                ChildType.ALERTING,
-                ChildType.GENTLE_HEADER,
-                ChildType.ALERTING);
+                ALERTING,
+                ALERTING,
+                GENTLE_HEADER,
+                ALERTING);
         clearInvocations(mNssl);
         mSectionsManager.updateSectionBoundaries();
 
         // THEN the LO section header is removed
-        verify(mNssl).removeView(mSectionsManager.getGentleHeaderView());
+        verify(mNssl).removeView(mSectionsManager.getSilentHeaderView());
     }
 
     @Test
     public void testDoNothingIfHeaderAlreadyRemoved() {
         // GIVEN a stack with only HI rows
-        setStackState(ChildType.ALERTING, ChildType.ALERTING, ChildType.ALERTING);
+        setStackState(
+                ALERTING,
+                ALERTING,
+                ALERTING);
 
         // WHEN we update the sections headers
         mSectionsManager.updateSectionBoundaries();
 
         // THEN we don't add any section headers
-        verify(mNssl, never()).addView(eq(mSectionsManager.getGentleHeaderView()), anyInt());
+        verify(mNssl, never()).addView(eq(mSectionsManager.getSilentHeaderView()), anyInt());
     }
 
     @Test
     public void testMoveHeaderForward() {
         // GIVEN a stack that originally had a header between the HI and LO sections
         setStackState(
-                ChildType.ALERTING,
-                ChildType.ALERTING,
-                ChildType.ALERTING,
-                ChildType.GENTLE);
+                ALERTING,
+                ALERTING,
+                ALERTING,
+                GENTLE);
         mSectionsManager.updateSectionBoundaries();
 
         // WHEN the LO section moves forward
         setStackState(
-                ChildType.ALERTING,
-                ChildType.ALERTING,
-                ChildType.GENTLE,
-                ChildType.GENTLE_HEADER,
-                ChildType.GENTLE);
+                ALERTING,
+                ALERTING,
+                GENTLE,
+                GENTLE_HEADER,
+                GENTLE);
         mSectionsManager.updateSectionBoundaries();
 
         // THEN the LO section header is also moved forward
-        verify(mNssl).changeViewPosition(mSectionsManager.getGentleHeaderView(), 2);
+        verify(mNssl).changeViewPosition(mSectionsManager.getSilentHeaderView(), 2);
     }
 
     @Test
     public void testMoveHeaderBackward() {
         // GIVEN a stack that originally had a header between the HI and LO sections
         setStackState(
-                ChildType.ALERTING,
-                ChildType.GENTLE,
-                ChildType.GENTLE,
-                ChildType.GENTLE);
+                ALERTING,
+                GENTLE,
+                GENTLE,
+                GENTLE);
         mSectionsManager.updateSectionBoundaries();
 
         // WHEN the LO section moves backward
         setStackState(
-                ChildType.ALERTING,
-                ChildType.GENTLE_HEADER,
-                ChildType.ALERTING,
-                ChildType.ALERTING,
-                ChildType.GENTLE);
+                ALERTING,
+                GENTLE_HEADER,
+                ALERTING,
+                ALERTING,
+                GENTLE);
         mSectionsManager.updateSectionBoundaries();
 
         // THEN the LO section header is also moved backward (with appropriate index shifting)
-        verify(mNssl).changeViewPosition(mSectionsManager.getGentleHeaderView(), 3);
+        verify(mNssl).changeViewPosition(mSectionsManager.getSilentHeaderView(), 3);
     }
 
     @Test
     public void testHeaderRemovedFromTransientParent() {
         // GIVEN a stack where the header is animating away
         setStackState(
-                ChildType.ALERTING,
-                ChildType.GENTLE,
-                ChildType.GENTLE,
-                ChildType.GENTLE);
-        mSectionsManager.updateSectionBoundaries();
-        setStackState(
-                ChildType.ALERTING,
-                ChildType.GENTLE_HEADER);
+                ALERTING,
+                GENTLE_HEADER);
         mSectionsManager.updateSectionBoundaries();
         clearInvocations(mNssl);
 
         ViewGroup transientParent = mock(ViewGroup.class);
-        mSectionsManager.getGentleHeaderView().setTransientContainer(transientParent);
+        mSectionsManager.getSilentHeaderView().setTransientContainer(transientParent);
 
         // WHEN the LO section reappears
         setStackState(
-                ChildType.ALERTING,
-                ChildType.GENTLE);
+                ALERTING,
+                GENTLE);
         mSectionsManager.updateSectionBoundaries();
 
         // THEN the header is first removed from the transient parent before being added to the
         // NSSL.
-        verify(transientParent).removeTransientView(mSectionsManager.getGentleHeaderView());
-        verify(mNssl).addView(mSectionsManager.getGentleHeaderView(), 1);
+        verify(transientParent).removeTransientView(mSectionsManager.getSilentHeaderView());
+        verify(mNssl).addView(mSectionsManager.getSilentHeaderView(), 1);
     }
 
     @Test
     public void testHeaderNotShownOnLockscreen() {
         // GIVEN a stack of HI and LO notifs on the lockscreen
         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
-        setStackState(ChildType.ALERTING, ChildType.ALERTING, ChildType.ALERTING, ChildType.GENTLE);
+        setStackState(
+                ALERTING,
+                ALERTING,
+                ALERTING,
+                GENTLE);
 
         // WHEN we update the section headers
         mSectionsManager.updateSectionBoundaries();
 
         // Then the section header is not added
-        verify(mNssl, never()).addView(eq(mSectionsManager.getGentleHeaderView()), anyInt());
+        verify(mNssl, never()).addView(eq(mSectionsManager.getSilentHeaderView()), anyInt());
     }
 
     @Test
     public void testHeaderShownWhenEnterLockscreen() {
         // GIVEN a stack of HI and LO notifs on the lockscreen
         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
-        setStackState(ChildType.ALERTING, ChildType.ALERTING, ChildType.ALERTING, ChildType.GENTLE);
+        setStackState(
+                ALERTING,
+                ALERTING,
+                ALERTING,
+                GENTLE);
         mSectionsManager.updateSectionBoundaries();
 
         // WHEN we unlock
@@ -253,20 +289,23 @@
         mSectionsManager.updateSectionBoundaries();
 
         // Then the section header is added
-        verify(mNssl).addView(mSectionsManager.getGentleHeaderView(), 3);
+        verify(mNssl).addView(mSectionsManager.getSilentHeaderView(), 3);
     }
 
     @Test
     public void testHeaderHiddenWhenEnterLockscreen() {
         // GIVEN a stack of HI and LO notifs on the shade
-        setStackState(ChildType.ALERTING, ChildType.GENTLE_HEADER, ChildType.GENTLE);
+        setStackState(
+                ALERTING,
+                GENTLE_HEADER,
+                GENTLE);
 
         // WHEN we go back to the keyguard
         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
         mSectionsManager.updateSectionBoundaries();
 
         // Then the section header is removed
-        verify(mNssl).removeView(mSectionsManager.getGentleHeaderView());
+        verify(mNssl).removeView(mSectionsManager.getSilentHeaderView());
     }
 
     @Test
@@ -274,13 +313,13 @@
         enablePeopleFiltering();
 
         setStackState(
-                ChildType.GENTLE_HEADER,
-                ChildType.PERSON,
-                ChildType.ALERTING,
-                ChildType.GENTLE);
+                GENTLE_HEADER,
+                PERSON,
+                ALERTING,
+                GENTLE);
         mSectionsManager.updateSectionBoundaries();
 
-        verify(mNssl).changeViewPosition(mSectionsManager.getGentleHeaderView(), 2);
+        verify(mNssl).changeViewPosition(mSectionsManager.getSilentHeaderView(), 2);
         verify(mNssl).addView(mSectionsManager.getAlertingHeaderView(), 1);
         verify(mNssl).addView(mSectionsManager.getPeopleHeaderView(), 0);
     }
@@ -290,12 +329,12 @@
         enablePeopleFiltering();
 
         setStackState(
-                ChildType.PERSON,
-                ChildType.ALERTING,
-                ChildType.GENTLE);
+                PERSON,
+                ALERTING,
+                GENTLE);
         mSectionsManager.updateSectionBoundaries();
 
-        verify(mNssl).addView(mSectionsManager.getGentleHeaderView(), 2);
+        verify(mNssl).addView(mSectionsManager.getSilentHeaderView(), 2);
         verify(mNssl).addView(mSectionsManager.getAlertingHeaderView(), 1);
         verify(mNssl).addView(mSectionsManager.getPeopleHeaderView(), 0);
     }
@@ -305,15 +344,15 @@
         enablePeopleFiltering();
 
         setStackState(
-                ChildType.PEOPLE_HEADER,
-                ChildType.ALERTING_HEADER,
-                ChildType.GENTLE_HEADER,
-                ChildType.PERSON,
-                ChildType.ALERTING,
-                ChildType.GENTLE);
+                PEOPLE_HEADER,
+                ALERTING_HEADER,
+                GENTLE_HEADER,
+                PERSON,
+                ALERTING,
+                GENTLE);
         mSectionsManager.updateSectionBoundaries();
 
-        verify(mNssl).changeViewPosition(mSectionsManager.getGentleHeaderView(), 4);
+        verify(mNssl).changeViewPosition(mSectionsManager.getSilentHeaderView(), 4);
         verify(mNssl).changeViewPosition(mSectionsManager.getAlertingHeaderView(), 2);
         verify(mNssl).changeViewPosition(mSectionsManager.getPeopleHeaderView(), 0);
     }
@@ -324,12 +363,11 @@
         enablePeopleFiltering();
 
         setStackState(
-                ChildType.PEOPLE_HEADER,
-                ChildType.ALERTING_HEADER,
-                ChildType.ALERTING,
-                ChildType.GENTLE_HEADER,
-                ChildType.GENTLE
-        );
+                PEOPLE_HEADER,
+                ALERTING_HEADER,
+                ALERTING,
+                GENTLE_HEADER,
+                GENTLE);
         mSectionsManager.updateSectionBoundaries();
 
         verify(mNssl, never()).removeView(mSectionsManager.getPeopleHeaderView());
@@ -337,11 +375,120 @@
     }
 
     @Test
+    public void testPeopleFiltering_AlertingHunWhilePeopleVisible() {
+        enablePeopleFiltering();
+
+        setupMockStack(
+                PEOPLE_HEADER,
+                ALERTING.headsUp(),
+                PERSON,
+                ALERTING_HEADER,
+                GENTLE_HEADER,
+                GENTLE
+        );
+        mSectionsManager.updateSectionBoundaries();
+
+        verifyMockStack(
+                ChildType.INCOMING_HEADER,
+                ChildType.HEADS_UP,
+                ChildType.PEOPLE_HEADER,
+                ChildType.PERSON,
+                ChildType.GENTLE_HEADER,
+                ChildType.GENTLE
+        );
+    }
+
+    @Test
+    public void testPeopleFiltering_PersonHunWhileAlertingHunVisible() {
+        enablePeopleFiltering();
+
+        setupMockStack(
+                PERSON.headsUp(),
+                INCOMING_HEADER,
+                ALERTING.headsUp(),
+                PEOPLE_HEADER,
+                PERSON
+        );
+        mSectionsManager.updateSectionBoundaries();
+
+        verifyMockStack(
+                ChildType.INCOMING_HEADER,
+                ChildType.HEADS_UP,
+                ChildType.HEADS_UP,
+                ChildType.PEOPLE_HEADER,
+                ChildType.PERSON
+        );
+    }
+
+    @Test
+    public void testPeopleFiltering_PersonHun() {
+        enablePeopleFiltering();
+
+        setupMockStack(
+                PERSON.headsUp(),
+                PEOPLE_HEADER,
+                PERSON
+        );
+        mSectionsManager.updateSectionBoundaries();
+
+        verifyMockStack(
+                ChildType.PEOPLE_HEADER,
+                ChildType.PERSON,
+                ChildType.PERSON
+        );
+    }
+
+    @Test
+    public void testPeopleFiltering_AlertingHunWhilePersonHunning() {
+        enablePeopleFiltering();
+
+        setupMockStack(
+                ALERTING.headsUp(),
+                PERSON.headsUp()
+        );
+        mSectionsManager.updateSectionBoundaries();
+        verifyMockStack(
+                ChildType.INCOMING_HEADER,
+                ChildType.HEADS_UP,
+                ChildType.PEOPLE_HEADER,
+                ChildType.PERSON
+        );
+    }
+
+    @Test
+    public void testPeopleFiltering_Fsn() {
+        enablePeopleFiltering();
+
+        setupMockStack(
+                INCOMING_HEADER,
+                ALERTING.headsUp(),
+                PEOPLE_HEADER,
+                FSN,
+                PERSON,
+                ALERTING,
+                GENTLE
+        );
+        mSectionsManager.updateSectionBoundaries();
+
+        verifyMockStack(
+                ChildType.INCOMING_HEADER,
+                ChildType.HEADS_UP,
+                ChildType.FSN,
+                ChildType.PEOPLE_HEADER,
+                ChildType.PERSON,
+                ChildType.ALERTING_HEADER,
+                ChildType.ALERTING,
+                ChildType.GENTLE_HEADER,
+                ChildType.GENTLE
+        );
+    }
+
+    @Test
     public void testMediaControls_AddWhenEnterKeyguard() {
         enableMediaControls();
 
         // GIVEN a stack that doesn't include media controls
-        setStackState(ChildType.ALERTING, ChildType.GENTLE_HEADER, ChildType.GENTLE);
+        setStackState(ALERTING, GENTLE_HEADER, GENTLE);
 
         // WHEN we go back to the keyguard
         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
@@ -356,69 +503,45 @@
         enableMediaControls();
 
         // GIVEN a stack that doesn't include media controls but includes HEADS_UP
-        setStackState(ChildType.HEADS_UP, ChildType.ALERTING, ChildType.GENTLE_HEADER,
-                ChildType.GENTLE);
+        setupMockStack(
+                ALERTING.headsUp(),
+                ALERTING,
+                GENTLE_HEADER,
+                GENTLE);
 
         // WHEN we go back to the keyguard
         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
         mSectionsManager.updateSectionBoundaries();
 
-        // Then the media controls are added after HEADS_UP
-        verify(mNssl).addView(mSectionsManager.getMediaControlsView(), 1);
-    }
-
-    @Test
-    public void testMediaControls_RemoveWhenExitKeyguard() {
-        enableMediaControls();
-
-        // GIVEN a stack with media controls
-        setStackState(ChildType.MEDIA_CONTROLS, ChildType.ALERTING, ChildType.GENTLE_HEADER,
+        verifyMockStack(
+                ChildType.MEDIA_CONTROLS,
+                ChildType.ALERTING,
+                ChildType.ALERTING,
                 ChildType.GENTLE);
-
-        // WHEN we leave the keyguard
-        when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
-        mSectionsManager.updateSectionBoundaries();
-
-        // Then the media controls is removed
-        verify(mNssl).removeView(mSectionsManager.getMediaControlsView());
-    }
-
-    @Test
-    public void testMediaControls_RemoveWhenPullDownShade() {
-        enableMediaControls();
-
-        // GIVEN a stack with media controls
-        setStackState(ChildType.MEDIA_CONTROLS, ChildType.ALERTING, ChildType.GENTLE_HEADER,
-                ChildType.GENTLE);
-
-        // WHEN we pull down the shade on the keyguard
-        when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED);
-        mSectionsManager.updateSectionBoundaries();
-
-        // Then the media controls is removed
-        verify(mNssl).removeView(mSectionsManager.getMediaControlsView());
     }
 
     private void enablePeopleFiltering() {
         when(mSectionsFeatureManager.isFilteringEnabled()).thenReturn(true);
-        when(mSectionsFeatureManager.getNumberOfBuckets()).thenReturn(4);
     }
 
     private void enableMediaControls() {
         when(mSectionsFeatureManager.isMediaControlsEnabled()).thenReturn(true);
-        when(mSectionsFeatureManager.getNumberOfBuckets()).thenReturn(4);
     }
 
     private enum ChildType {
-        MEDIA_CONTROLS, PEOPLE_HEADER, ALERTING_HEADER, GENTLE_HEADER, HEADS_UP, PERSON, ALERTING,
-            GENTLE, OTHER
+        INCOMING_HEADER, MEDIA_CONTROLS, PEOPLE_HEADER, ALERTING_HEADER, GENTLE_HEADER, HEADS_UP,
+        FSN, PERSON, ALERTING, GENTLE, OTHER
     }
 
-    private void setStackState(ChildType... children) {
+    private void setStackState(StackEntry... children) {
         when(mNssl.getChildCount()).thenReturn(children.length);
         for (int i = 0; i < children.length; i++) {
             View child;
-            switch (children[i]) {
+            StackEntry entry = children[i];
+            switch (entry.mChildType) {
+                case INCOMING_HEADER:
+                    child = mSectionsManager.getIncomingHeaderView();
+                    break;
                 case MEDIA_CONTROLS:
                     child = mSectionsManager.getMediaControlsView();
                     break;
@@ -429,19 +552,19 @@
                     child = mSectionsManager.getAlertingHeaderView();
                     break;
                 case GENTLE_HEADER:
-                    child = mSectionsManager.getGentleHeaderView();
+                    child = mSectionsManager.getSilentHeaderView();
                     break;
-                case HEADS_UP:
-                    child = mockNotification(BUCKET_HEADS_UP);
+                case FSN:
+                    child = mockNotification(BUCKET_FOREGROUND_SERVICE, entry.mIsHeadsUp);
                     break;
                 case PERSON:
-                    child = mockNotification(BUCKET_PEOPLE);
+                    child = mockNotification(BUCKET_PEOPLE, entry.mIsHeadsUp);
                     break;
                 case ALERTING:
-                    child = mockNotification(BUCKET_ALERTING);
+                    child = mockNotification(BUCKET_ALERTING, entry.mIsHeadsUp);
                     break;
                 case GENTLE:
-                    child = mockNotification(BUCKET_SILENT);
+                    child = mockNotification(BUCKET_SILENT, entry.mIsHeadsUp);
                     break;
                 case OTHER:
                     child = mock(View.class);
@@ -456,12 +579,183 @@
         }
     }
 
-    private View mockNotification(int bucket) {
-        ExpandableNotificationRow notifRow = mock(ExpandableNotificationRow.class,
-                RETURNS_DEEP_STUBS);
+    private View mockNotification(int bucket, boolean headsUp) {
+        ExpandableNotificationRow notifRow =
+                mock(ExpandableNotificationRow.class, RETURNS_DEEP_STUBS);
         when(notifRow.getVisibility()).thenReturn(View.VISIBLE);
-        when(notifRow.getEntry().getBucket()).thenReturn(bucket);
         when(notifRow.getParent()).thenReturn(mNssl);
+
+        NotificationEntry mockEntry = mock(NotificationEntry.class);
+        when(notifRow.getEntry()).thenReturn(mockEntry);
+
+        int[] bucketRef = new int[] { bucket };
+        when(mockEntry.getBucket()).thenAnswer(invocation -> bucketRef[0]);
+        doAnswer(invocation -> {
+            bucketRef[0] = invocation.getArgument(0);
+            return null;
+        }).when(mockEntry).setBucket(anyInt());
+
+        when(notifRow.isHeadsUp()).thenReturn(headsUp);
+        when(mockEntry.isRowHeadsUp()).thenReturn(headsUp);
         return notifRow;
     }
+
+    private void verifyMockStack(ChildType... expected) {
+        final List<ChildType> actual = new ArrayList<>();
+        int childCount = mNssl.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = mNssl.getChildAt(i);
+            if (child == mSectionsManager.getIncomingHeaderView()) {
+                actual.add(ChildType.INCOMING_HEADER);
+                continue;
+            }
+            if (child == mSectionsManager.getMediaControlsView()) {
+                actual.add(ChildType.MEDIA_CONTROLS);
+                continue;
+            }
+            if (child == mSectionsManager.getPeopleHeaderView()) {
+                actual.add(ChildType.PEOPLE_HEADER);
+                continue;
+            }
+            if (child == mSectionsManager.getAlertingHeaderView()) {
+                actual.add(ChildType.ALERTING_HEADER);
+                continue;
+            }
+            if (child == mSectionsManager.getSilentHeaderView()) {
+                actual.add(ChildType.GENTLE_HEADER);
+                continue;
+            }
+            if (child instanceof ExpandableNotificationRow) {
+                switch (((ExpandableNotificationRow) child).getEntry().getBucket()) {
+                    case BUCKET_HEADS_UP:
+                        actual.add(ChildType.HEADS_UP);
+                        break;
+                    case BUCKET_FOREGROUND_SERVICE:
+                        actual.add(ChildType.FSN);
+                        break;
+                    case BUCKET_PEOPLE:
+                        actual.add(ChildType.PERSON);
+                        break;
+                    case BUCKET_ALERTING:
+                        actual.add(ChildType.ALERTING);
+                        break;
+                    case BUCKET_SILENT:
+                        actual.add(ChildType.GENTLE);
+                        break;
+                    default:
+                        actual.add(ChildType.OTHER);
+                        break;
+                }
+                continue;
+            }
+            actual.add(ChildType.OTHER);
+        }
+        assertThat(actual).containsExactly((Object[]) expected).inOrder();
+    }
+
+    private void setupMockStack(StackEntry... entries) {
+        final List<View> children = new ArrayList<>();
+        when(mNssl.getChildCount()).thenAnswer(invocation -> children.size());
+        when(mNssl.getChildAt(anyInt()))
+                .thenAnswer(invocation -> children.get(invocation.getArgument(0)));
+        when(mNssl.indexOfChild(any()))
+                .thenAnswer(invocation -> children.indexOf(invocation.getArgument(0)));
+        doAnswer(invocation -> {
+            View child = invocation.getArgument(0);
+            int index = invocation.getArgument(1);
+            children.add(index, child);
+            return null;
+        }).when(mNssl).addView(any(), anyInt());
+        doAnswer(invocation -> {
+            View child = invocation.getArgument(0);
+            children.remove(child);
+            return null;
+        }).when(mNssl).removeView(any());
+        doAnswer(invocation -> {
+            View child = invocation.getArgument(0);
+            int newIndex = invocation.getArgument(1);
+            children.remove(child);
+            children.add(newIndex, child);
+            return null;
+        }).when(mNssl).changeViewPosition(any(), anyInt());
+        for (StackEntry entry : entries) {
+            View child;
+            switch (entry.mChildType) {
+                case INCOMING_HEADER:
+                    child = mSectionsManager.getIncomingHeaderView();
+                    break;
+                case MEDIA_CONTROLS:
+                    child = mSectionsManager.getMediaControlsView();
+                    break;
+                case PEOPLE_HEADER:
+                    child = mSectionsManager.getPeopleHeaderView();
+                    break;
+                case ALERTING_HEADER:
+                    child = mSectionsManager.getAlertingHeaderView();
+                    break;
+                case GENTLE_HEADER:
+                    child = mSectionsManager.getSilentHeaderView();
+                    break;
+                case FSN:
+                    child = mockNotification(BUCKET_FOREGROUND_SERVICE, entry.mIsHeadsUp);
+                    break;
+                case PERSON:
+                    child = mockNotification(BUCKET_PEOPLE, entry.mIsHeadsUp);
+                    break;
+                case ALERTING:
+                    child = mockNotification(BUCKET_ALERTING, entry.mIsHeadsUp);
+                    break;
+                case GENTLE:
+                    child = mockNotification(BUCKET_SILENT, entry.mIsHeadsUp);
+                    break;
+                case OTHER:
+                    child = mock(View.class);
+                    when(child.getVisibility()).thenReturn(View.VISIBLE);
+                    when(child.getParent()).thenReturn(mNssl);
+                    break;
+                default:
+                    throw new RuntimeException("Unknown ChildType: " + entry.mChildType);
+            }
+            children.add(child);
+        }
+    }
+
+    private static final StackEntry INCOMING_HEADER = new StackEntry(ChildType.INCOMING_HEADER);
+    private static final StackEntry MEDIA_CONTROLS = new StackEntry(ChildType.MEDIA_CONTROLS);
+    private static final StackEntry PEOPLE_HEADER = new StackEntry(ChildType.PEOPLE_HEADER);
+    private static final StackEntry ALERTING_HEADER = new StackEntry(ChildType.ALERTING_HEADER);
+    private static final StackEntry GENTLE_HEADER = new StackEntry(ChildType.GENTLE_HEADER);
+    private static final StackEntry FSN = new StackEntry(ChildType.FSN);
+    private static final StackEntry.Hunnable PERSON = new StackEntry.Hunnable(ChildType.PERSON);
+    private static final StackEntry.Hunnable ALERTING = new StackEntry.Hunnable(ChildType.ALERTING);
+    private static final StackEntry GENTLE = new StackEntry(ChildType.GENTLE);
+
+    private static class StackEntry {
+        final ChildType mChildType;
+        final boolean mIsHeadsUp;
+
+        StackEntry(ChildType childType) {
+            this(childType, false);
+        }
+
+        StackEntry(ChildType childType, boolean isHeadsUp) {
+            mChildType = childType;
+            mIsHeadsUp = isHeadsUp;
+        }
+
+        static class Hunnable extends StackEntry {
+
+            Hunnable(ChildType childType) {
+                super(childType, false);
+            }
+
+            Hunnable(ChildType childType, boolean isHeadsUp) {
+                super(childType, isHeadsUp);
+            }
+
+            public Hunnable headsUp() {
+                return new Hunnable(mChildType, true);
+            }
+        }
+    }
 }
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 67f94130..885dff3 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
@@ -42,6 +42,7 @@
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.row.NotifBindPipeline.BindCallback;
 import com.android.systemui.statusbar.notification.row.RowContentBindParams;
 import com.android.systemui.statusbar.notification.row.RowContentBindStage;
@@ -87,7 +88,9 @@
         when(mNotificationEntryManager.getPendingNotificationsIterator())
                 .thenReturn(mPendingEntries.values());
 
-        mGroupManager = new NotificationGroupManager(mock(StatusBarStateController.class));
+        mGroupManager = new NotificationGroupManager(
+                mock(StatusBarStateController.class),
+                () -> mock(PeopleNotificationIdentifier.class));
         mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager);
         mGroupManager.setHeadsUpManager(mHeadsUpManager);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java
index 19ce1ea..5a6f74a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java
@@ -33,6 +33,7 @@
 import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 
 import org.junit.Before;
@@ -63,7 +64,9 @@
     }
 
     private void initializeGroupManager() {
-        mGroupManager = new NotificationGroupManager(mock(StatusBarStateController.class));
+        mGroupManager = new NotificationGroupManager(
+                mock(StatusBarStateController.class),
+                () -> mock(PeopleNotificationIdentifier.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/NotificationPanelViewTest.java
index 57ef055..c2d2181 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -43,6 +43,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 import androidx.test.filters.SmallTest;
 
@@ -55,6 +56,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.doze.DozeLog;
+import com.android.systemui.media.MediaHierarchyManager;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -79,11 +81,13 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.mockito.stubbing.Answer;
 
+import java.util.List;
 import java.util.function.Consumer;
 
 @SmallTest
@@ -172,10 +176,15 @@
     @Mock
     private ConfigurationController mConfigurationController;
     @Mock
+    private MediaHierarchyManager mMediaHiearchyManager;
+    @Mock
     private ConversationNotificationManager mConversationNotificationManager;
+    @Mock
+    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
     private FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder;
 
     private NotificationPanelViewController mNotificationPanelViewController;
+    private View.AccessibilityDelegate mAccessibiltyDelegate;
 
     @Before
     public void setup() {
@@ -228,11 +237,18 @@
                 mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
                 mMetricsLogger, mActivityManager, mZenModeController, mConfigurationController,
                 mFlingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
-                mConversationNotificationManager);
+                mConversationNotificationManager, mMediaHiearchyManager,
+                mStatusBarKeyguardViewManager);
         mNotificationPanelViewController.initDependencies(mStatusBar, mGroupManager,
                 mNotificationShelf, mNotificationAreaController, mScrimController);
         mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
         mNotificationPanelViewController.setBar(mPanelBar);
+
+        ArgumentCaptor<View.AccessibilityDelegate> accessibilityDelegateArgumentCaptor =
+                ArgumentCaptor.forClass(View.AccessibilityDelegate.class);
+        verify(mView)
+                .setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture());
+        mAccessibiltyDelegate = accessibilityDelegateArgumentCaptor.getValue();
     }
 
     @Test
@@ -302,6 +318,39 @@
         verify(mKeyguardStatusBar, never()).setVisibility(View.VISIBLE);
     }
 
+    @Test
+    public void testA11y_initializeNode() {
+        AccessibilityNodeInfo nodeInfo = new AccessibilityNodeInfo();
+        mAccessibiltyDelegate.onInitializeAccessibilityNodeInfo(mView, nodeInfo);
+
+        List<AccessibilityNodeInfo.AccessibilityAction> actionList = nodeInfo.getActionList();
+        assertThat(actionList).containsAllIn(
+                new AccessibilityNodeInfo.AccessibilityAction[] {
+                        AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD,
+                        AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_UP}
+        );
+    }
+
+    @Test
+    public void testA11y_scrollForward() {
+        mAccessibiltyDelegate.performAccessibilityAction(
+                mView,
+                AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD.getId(),
+                null);
+
+        verify(mStatusBarKeyguardViewManager).showBouncer(true);
+    }
+
+    @Test
+    public void testA11y_scrollUp() {
+        mAccessibiltyDelegate.performAccessibilityAction(
+                mView,
+                AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_UP.getId(),
+                null);
+
+        verify(mStatusBarKeyguardViewManager).showBouncer(true);
+    }
+
     private void onTouchEvent(MotionEvent ev) {
         mTouchHandler.onTouch(mView, ev);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java
index 5320ecd..ca6c16f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java
@@ -16,11 +16,15 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -44,6 +48,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -62,6 +67,7 @@
     @Mock private SysuiColorExtractor mColorExtractor;
     @Mock ColorExtractor.GradientColors mGradientColors;
     @Mock private DumpManager mDumpManager;
+    @Captor private ArgumentCaptor<WindowManager.LayoutParams> mLayoutParameters;
 
     private NotificationShadeWindowController mNotificationShadeWindowController;
 
@@ -121,4 +127,46 @@
         mNotificationShadeWindowController.setBackgroundBlurRadius(0);
         verify(mNotificationShadeWindowView).setVisibility(eq(View.INVISIBLE));
     }
+
+    @Test
+    public void setBouncerShowing_isFocusable_whenNeedsInput() {
+        mNotificationShadeWindowController.setKeyguardNeedsInput(true);
+        clearInvocations(mWindowManager);
+        mNotificationShadeWindowController.setBouncerShowing(true);
+
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat((mLayoutParameters.getValue().flags & FLAG_NOT_FOCUSABLE) == 0).isTrue();
+        assertThat((mLayoutParameters.getValue().flags & FLAG_ALT_FOCUSABLE_IM) == 0).isTrue();
+    }
+
+    @Test
+    public void setKeyguardShowing_focusable_notAltFocusable_whenNeedsInput() {
+        mNotificationShadeWindowController.setKeyguardShowing(true);
+        clearInvocations(mWindowManager);
+        mNotificationShadeWindowController.setKeyguardNeedsInput(true);
+
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat((mLayoutParameters.getValue().flags & FLAG_NOT_FOCUSABLE) == 0).isTrue();
+        assertThat((mLayoutParameters.getValue().flags & FLAG_ALT_FOCUSABLE_IM) == 0).isTrue();
+    }
+
+    @Test
+    public void setPanelExpanded_notFocusable_altFocusable_whenPanelIsOpen() {
+        mNotificationShadeWindowController.setPanelExpanded(true);
+        clearInvocations(mWindowManager);
+        mNotificationShadeWindowController.setNotificationShadeFocusable(true);
+
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat((mLayoutParameters.getValue().flags & FLAG_NOT_FOCUSABLE) == 0).isTrue();
+        assertThat((mLayoutParameters.getValue().flags & FLAG_ALT_FOCUSABLE_IM) != 0).isTrue();
+    }
+
+    @Test
+    public void setKeyguardShowing_notFocusable_byDefault() {
+        mNotificationShadeWindowController.setKeyguardShowing(false);
+
+        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+        assertThat((mLayoutParameters.getValue().flags & FLAG_NOT_FOCUSABLE) != 0).isTrue();
+        assertThat((mLayoutParameters.getValue().flags & FLAG_ALT_FOCUSABLE_IM) == 0).isTrue();
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.java
new file mode 100644
index 0000000..a14d575
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.AlarmManager;
+import android.app.IActivityManager;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.os.UserManager;
+import android.telecom.TelecomManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.media.MediaDataManager;
+import com.android.systemui.screenrecord.RecordingController;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.policy.BluetoothController;
+import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.DataSaverController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.LocationController;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.policy.SensorPrivacyController;
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.RingerModeLiveData;
+import com.android.systemui.util.RingerModeTracker;
+import com.android.systemui.util.time.DateFormatUtil;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.concurrent.Executor;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class PhoneStatusBarPolicyTest extends SysuiTestCase {
+
+    private static final int DISPLAY_ID = 0;
+    @Mock
+    private StatusBarIconController mIconController;
+    @Mock
+    private CommandQueue mCommandQueue;
+    @Mock
+    private BroadcastDispatcher mBroadcastDispatcher;
+    @Mock
+    private Executor mBackgroundExecutor;
+    @Mock
+    private CastController mCastController;
+    @Mock
+    private HotspotController mHotSpotController;
+    @Mock
+    private BluetoothController mBluetoothController;
+    @Mock
+    private NextAlarmController mNextAlarmController;
+    @Mock
+    private UserInfoController mUserInfoController;
+    @Mock
+    private RotationLockController mRotationLockController;
+    @Mock
+    private DataSaverController mDataSaverController;
+    @Mock
+    private ZenModeController mZenModeController;
+    @Mock
+    private DeviceProvisionedController mDeviceProvisionerController;
+    @Mock
+    private KeyguardStateController mKeyguardStateController;
+    @Mock
+    private LocationController mLocationController;
+    @Mock
+    private SensorPrivacyController mSensorPrivacyController;
+    @Mock
+    private IActivityManager mIActivityManager;
+    @Mock
+    private AlarmManager mAlarmManager;
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private RecordingController mRecordingController;
+    @Mock
+    private MediaDataManager mMediaDataManager;
+    @Mock
+    private TelecomManager mTelecomManager;
+    @Mock
+    private SharedPreferences mSharedPreferences;
+    @Mock
+    private DateFormatUtil mDateFormatUtil;
+    @Mock
+    private RingerModeTracker mRingerModeTracker;
+    @Mock
+    private RingerModeLiveData mRingerModeLiveData;
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+    private Resources mResources;
+    private PhoneStatusBarPolicy mPhoneStatusBarPolicy;
+
+    @Before
+    public void setup() {
+        mResources = spy(getContext().getResources());
+        mPhoneStatusBarPolicy = new PhoneStatusBarPolicy(mIconController, mCommandQueue,
+                mBroadcastDispatcher, mBackgroundExecutor, mResources, mCastController,
+                mHotSpotController, mBluetoothController, mNextAlarmController, mUserInfoController,
+                mRotationLockController, mDataSaverController, mZenModeController,
+                mDeviceProvisionerController, mKeyguardStateController, mLocationController,
+                mSensorPrivacyController, mIActivityManager, mAlarmManager, mUserManager,
+                mRecordingController, mMediaDataManager, mTelecomManager, DISPLAY_ID,
+                mSharedPreferences, mDateFormatUtil, mRingerModeTracker);
+        when(mRingerModeTracker.getRingerMode()).thenReturn(mRingerModeLiveData);
+        when(mRingerModeTracker.getRingerModeInternal()).thenReturn(mRingerModeLiveData);
+        clearInvocations(mIconController);
+    }
+
+    @Test
+    public void testInit_registerMediaCallback() {
+        mPhoneStatusBarPolicy.init();
+        verify(mMediaDataManager).addListener(eq(mPhoneStatusBarPolicy));
+    }
+
+    @Test
+    public void testOnMediaDataLoaded_updatesIcon_hasMedia() {
+        String mediaSlot = mResources.getString(com.android.internal.R.string.status_bar_media);
+        when(mMediaDataManager.hasActiveMedia()).thenReturn(true);
+        mPhoneStatusBarPolicy.onMediaDataLoaded(null, null);
+        verify(mMediaDataManager).hasActiveMedia();
+        verify(mIconController).setIconVisibility(eq(mediaSlot), eq(true));
+    }
+
+    @Test
+    public void testOnMediaDataRemoved_updatesIcon_noMedia() {
+        String mediaSlot = mResources.getString(com.android.internal.R.string.status_bar_media);
+        mPhoneStatusBarPolicy.onMediaDataRemoved(null);
+        verify(mMediaDataManager).hasActiveMedia();
+        verify(mIconController).setIconVisibility(eq(mediaSlot), eq(false));
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 1afe132..53a1773 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -48,7 +48,6 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.ActivityIntentHelper;
@@ -59,6 +58,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.statusbar.NotificationClickNotifier;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -98,7 +98,7 @@
     @Mock
     private ActivityStarter mActivityStarter;
     @Mock
-    private IStatusBarService mStatusBarService;
+    private NotificationClickNotifier mClickNotifier;
     @Mock
     private StatusBarStateController mStatusBarStateController;
     @Mock
@@ -188,7 +188,7 @@
                         mNotifCollection,
                         mock(HeadsUpManagerPhone.class),
                         mActivityStarter,
-                        mStatusBarService,
+                        mClickNotifier,
                         mock(StatusBarStateController.class),
                         mStatusBarKeyguardViewManager,
                         mock(KeyguardManager.class),
@@ -263,7 +263,7 @@
 
         verify(mAssistManager).hideAssist();
 
-        verify(mStatusBarService).onNotificationClick(
+        verify(mClickNotifier).onNotificationClick(
                 eq(sbn.getKey()), any(NotificationVisibility.class));
 
         // Notification is removed due to FLAG_AUTO_CANCEL
@@ -289,7 +289,7 @@
 
         verify(mAssistManager).hideAssist();
 
-        verify(mStatusBarService).onNotificationClick(
+        verify(mClickNotifier).onNotificationClick(
                 eq(sbn.getKey()), any(NotificationVisibility.class));
 
         // The content intent should NOT be sent on click.
@@ -319,7 +319,7 @@
 
         verify(mAssistManager).hideAssist();
 
-        verify(mStatusBarService).onNotificationClick(
+        verify(mClickNotifier).onNotificationClick(
                 eq(sbn.getKey()), any(NotificationVisibility.class));
 
         // The content intent should NOT be sent on click.
@@ -349,7 +349,7 @@
 
         verify(mAssistManager).hideAssist();
 
-        verify(mStatusBarService).onNotificationClick(
+        verify(mClickNotifier).onNotificationClick(
                 eq(sbn.getKey()), any(NotificationVisibility.class));
 
         // The content intent should NOT be sent on click.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
index cd2c349..bf2bd38 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
@@ -31,6 +31,7 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.ActionClickLogger;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -73,7 +74,8 @@
         mRemoteInputCallback = spy(new StatusBarRemoteInputCallback(mContext,
                 mock(NotificationGroupManager.class), mNotificationLockscreenUserManager,
                 mKeyguardStateController, mStatusBarStateController, mStatusBarKeyguardViewManager,
-                mActivityStarter, mShadeController, new CommandQueue(mContext)));
+                mActivityStarter, mShadeController, new CommandQueue(mContext),
+                mock(ActionClickLogger.class)));
         mRemoteInputCallback.mChallengeReceiver = mRemoteInputCallback.new ChallengeReceiver();
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
index 81c375a..5ce209b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
@@ -14,8 +14,11 @@
 
 package com.android.systemui.statusbar.policy;
 
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.Intent;
@@ -32,7 +35,6 @@
 import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -42,17 +44,19 @@
 public class LocationControllerImplTest extends SysuiTestCase {
 
     private LocationControllerImpl mLocationController;
+    private TestableLooper mTestableLooper;
 
     @Before
     public void setup() {
+        mTestableLooper = TestableLooper.get(this);
         mLocationController = spy(new LocationControllerImpl(mContext,
-                TestableLooper.get(this).getLooper(),
+                mTestableLooper.getLooper(),
+                mTestableLooper.getLooper(),
                 mock(BroadcastDispatcher.class),
                 mock(BootCompleteCache.class)));
     }
 
     @Test
-    @Ignore("flaky")
     public void testRemoveSelfActive_DoesNotCrash() {
         LocationController.LocationChangeCallback callback = new LocationChangeCallback() {
             @Override
@@ -70,11 +74,10 @@
         mLocationController.onReceive(mContext, new Intent(
                 LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION));
 
-        TestableLooper.get(this).processAllMessages();
+        mTestableLooper.processAllMessages();
     }
 
     @Test
-    @Ignore("flaky")
     public void testRemoveSelfSettings_DoesNotCrash() {
         LocationController.LocationChangeCallback callback = new LocationChangeCallback() {
             @Override
@@ -85,6 +88,47 @@
         mLocationController.addCallback(callback);
         mLocationController.addCallback(mock(LocationChangeCallback.class));
 
-        TestableLooper.get(this).processAllMessages();
+        mTestableLooper.processAllMessages();
+    }
+
+    @Test
+    public void testAddCallback_notifiedImmediately() {
+        LocationChangeCallback callback = mock(LocationChangeCallback.class);
+
+        mLocationController.addCallback(callback);
+
+        mTestableLooper.processAllMessages();
+
+        verify(callback).onLocationSettingsChanged(anyBoolean());
+    }
+
+    @Test
+    public void testCallbackNotified() {
+        LocationChangeCallback callback = mock(LocationChangeCallback.class);
+
+        mLocationController.addCallback(callback);
+        mLocationController.onReceive(mContext, new Intent(LocationManager.MODE_CHANGED_ACTION));
+
+        mTestableLooper.processAllMessages();
+
+        verify(callback, times(2)).onLocationSettingsChanged(anyBoolean());
+    }
+
+    @Test
+    public void testCallbackRemoved() {
+        LocationChangeCallback callback = mock(LocationChangeCallback.class);
+
+        mLocationController.addCallback(callback);
+        mTestableLooper.processAllMessages();
+
+        verify(callback).onLocationSettingsChanged(anyBoolean());
+        mLocationController.removeCallback(callback);
+
+        mLocationController.onReceive(mContext, new Intent(LocationManager.MODE_CHANGED_ACTION));
+
+        mTestableLooper.processAllMessages();
+
+        // No new callbacks
+        verify(callback).onLocationSettingsChanged(anyBoolean());
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/io/FakeBasicFileAttributes.java b/packages/SystemUI/tests/src/com/android/systemui/util/io/FakeBasicFileAttributes.java
new file mode 100644
index 0000000..f7a04dc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/io/FakeBasicFileAttributes.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.io;
+
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Fake implementation of {@link BasicFileAttributes} (for use in tests)
+ */
+public class FakeBasicFileAttributes implements BasicFileAttributes {
+    private FileTime mLastModifiedTime = FileTime.from(0, TimeUnit.MILLISECONDS);
+    private FileTime mLastAccessTime = FileTime.from(0, TimeUnit.MILLISECONDS);
+    private FileTime mCreationTime = FileTime.from(0, TimeUnit.MILLISECONDS);
+    private boolean mIsRegularFile = true;
+    private boolean mIsDirectory = false;
+    private boolean mIsSymbolicLink = false;
+    private boolean mIsOther = false;
+    private long mSize = 0;
+    private Object mFileKey = null;
+
+    @Override
+    public FileTime lastModifiedTime() {
+        return mLastModifiedTime;
+    }
+
+    @Override
+    public FileTime lastAccessTime() {
+        return mLastAccessTime;
+    }
+
+    @Override
+    public FileTime creationTime() {
+        return mCreationTime;
+    }
+
+    @Override
+    public boolean isRegularFile() {
+        return mIsRegularFile;
+    }
+
+    @Override
+    public boolean isDirectory() {
+        return mIsDirectory;
+    }
+
+    @Override
+    public boolean isSymbolicLink() {
+        return mIsSymbolicLink;
+    }
+
+    @Override
+    public boolean isOther() {
+        return mIsOther;
+    }
+
+    @Override
+    public long size() {
+        return mSize;
+    }
+
+    @Override
+    public Object fileKey() {
+        return mFileKey;
+    }
+
+    public FakeBasicFileAttributes setLastModifiedTime(long millis) {
+        mLastModifiedTime = FileTime.from(millis, TimeUnit.MILLISECONDS);
+        return this;
+    }
+
+    public FakeBasicFileAttributes setLastAccessTime(long millis) {
+        mLastAccessTime = FileTime.from(millis, TimeUnit.MILLISECONDS);
+        return this;
+    }
+
+    public FakeBasicFileAttributes setCreationTime(long millis) {
+        mCreationTime = FileTime.from(millis, TimeUnit.MILLISECONDS);
+        return this;
+    }
+
+    public FakeBasicFileAttributes setRegularFile(boolean regularFile) {
+        mIsRegularFile = regularFile;
+        return this;
+    }
+
+    public FakeBasicFileAttributes setDirectory(boolean directory) {
+        mIsDirectory = directory;
+        return this;
+    }
+
+    public FakeBasicFileAttributes setSymbolicLink(boolean symbolicLink) {
+        mIsSymbolicLink = symbolicLink;
+        return this;
+    }
+
+    public FakeBasicFileAttributes setOther(boolean other) {
+        mIsOther = other;
+        return this;
+    }
+
+    public FakeBasicFileAttributes setSize(long size) {
+        mSize = size;
+        return this;
+    }
+
+    public FakeBasicFileAttributes setFileKey(Object fileKey) {
+        mFileKey = fileKey;
+        return this;
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java
index 31d884c..bd697fe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java
@@ -20,6 +20,7 @@
 
 public class FakeProximitySensor extends ProximitySensor {
     private boolean mAvailable;
+    private boolean mRegistered;
 
     public FakeProximitySensor(Resources resources, AsyncSensorManager sensorManager) {
         super(resources, sensorManager);
@@ -35,17 +36,22 @@
     }
 
     @Override
+    public boolean isRegistered() {
+        return mRegistered;
+    }
+
+    @Override
     public boolean getSensorAvailable() {
         return mAvailable;
     }
 
     @Override
     protected void registerInternal() {
-        // no-op
+        mRegistered = !mPaused;
     }
 
     @Override
     protected void unregisterInternal() {
-        // no-op
+        mRegistered = false;
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java
new file mode 100644
index 0000000..7221095
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.sensors;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Handler;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+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 java.util.function.Consumer;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class ProximityCheckTest extends SysuiTestCase {
+
+    private FakeProximitySensor mFakeProximitySensor;
+    private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
+
+    private TestableCallback mTestableCallback = new TestableCallback();
+
+    private ProximitySensor.ProximityCheck mProximityCheck;
+
+    @Before
+    public void setUp() throws Exception {
+        AsyncSensorManager asyncSensorManager =
+                new AsyncSensorManager(new FakeSensorManager(mContext), null, new Handler());
+        mFakeProximitySensor = new FakeProximitySensor(mContext.getResources(), asyncSensorManager);
+
+        mProximityCheck = new ProximitySensor.ProximityCheck(mFakeProximitySensor, mFakeExecutor);
+    }
+
+    @Test
+    public void testCheck() {
+        mProximityCheck.check(100, mTestableCallback);
+
+        assertNull(mTestableCallback.mLastResult);
+
+        mFakeProximitySensor.setLastEvent(new ProximitySensor.ProximityEvent(true, 0));
+        mFakeProximitySensor.alertListeners();
+
+        assertTrue(mTestableCallback.mLastResult);
+    }
+
+    @Test
+    public void testTimeout() {
+        mProximityCheck.check(100, mTestableCallback);
+
+        assertTrue(mFakeProximitySensor.isRegistered());
+
+        mFakeExecutor.advanceClockToNext();
+        mFakeExecutor.runAllReady();
+
+        assertFalse(mFakeProximitySensor.isRegistered());
+    }
+
+    private static class TestableCallback implements Consumer<Boolean> {
+        Boolean mLastResult;
+        @Override
+        public void accept(Boolean result) {
+            mLastResult = result;
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java
index 526fba7..914790b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java
@@ -219,6 +219,26 @@
         waitForSensorManager();
     }
 
+    @Test
+    public void testPreventRecursiveAlert() {
+        TestableListener listenerA = new TestableListener() {
+            @Override
+            public void onSensorEvent(ProximitySensor.ProximityEvent proximityEvent) {
+                super.onSensorEvent(proximityEvent);
+                if (mCallCount < 2) {
+                    mProximitySensor.alertListeners();
+                }
+            }
+        };
+
+        mProximitySensor.register(listenerA);
+
+        mProximitySensor.alertListeners();
+
+        assertEquals(1, listenerA.mCallCount);
+    }
+
+
     class TestableListener implements ProximitySensor.ProximitySensorListener {
         ProximitySensor.ProximityEvent mLastEvent;
         int mCallCount = 0;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java b/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java
index 601f88e..ecfb357 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java
@@ -36,8 +36,9 @@
     private long mElapsedRealtime = 10000;
     private long mCurrentThreadTimeMillis = 10000;
 
-    private final List<ClockTickListener> mListeners = new ArrayList<>();
+    private long mCurrentTimeMillis = 1555555500000L;
 
+    private final List<ClockTickListener> mListeners = new ArrayList<>();
     @Override
     public long uptimeMillis() {
         return mUptimeMillis;
@@ -58,10 +59,19 @@
         return mCurrentThreadTimeMillis;
     }
 
+    @Override
+    public long currentTimeMillis() {
+        return mCurrentTimeMillis;
+    }
+
     public void setUptimeMillis(long uptime) {
         advanceTime(uptime - mUptimeMillis);
     }
 
+    public void setCurrentTimeMillis(long millis) {
+        mCurrentTimeMillis = millis;
+    }
+
     public void advanceTime(long uptime) {
         advanceTime(uptime, 0);
     }
@@ -74,6 +84,7 @@
         if (uptime > 0 || sleepTime > 0) {
             mUptimeMillis += uptime;
             mElapsedRealtime += uptime + sleepTime;
+            mCurrentTimeMillis += uptime + sleepTime;
 
             mCurrentThreadTimeMillis += Math.ceil(uptime * 0.5);
 
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index cbc5e14..1ee017b 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -51,6 +51,11 @@
 cc_library {
     name: "libtetherutilsjni",
     sdk_version: "current",
+    apex_available: [
+        "//apex_available:platform", // Used by InProcessTethering
+        "com.android.tethering",
+    ],
+    min_sdk_version: "current",
     srcs: [
         "jni/android_net_util_TetheringUtils.cpp",
     ],
@@ -110,6 +115,7 @@
     // InProcessTethering is a replacement for Tethering
     overrides: ["Tethering"],
     apex_available: ["com.android.tethering"],
+    min_sdk_version: "current",
 }
 
 // Updatable tethering packaged as an application
@@ -123,4 +129,5 @@
     // The permission configuration *must* be included to ensure security of the device
     required: ["NetworkPermissionConfig"],
     apex_available: ["com.android.tethering"],
+    min_sdk_version: "current",
 }
diff --git a/packages/Tethering/apex/Android.bp b/packages/Tethering/apex/Android.bp
index 20ccd2a..67097a7 100644
--- a/packages/Tethering/apex/Android.bp
+++ b/packages/Tethering/apex/Android.bp
@@ -17,7 +17,7 @@
 apex {
     name: "com.android.tethering",
     updatable: true,
-    min_sdk_version: "R",
+    min_sdk_version: "current",
     java_libs: ["framework-tethering"],
     apps: ["Tethering"],
     manifest: "manifest.json",
diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp
index d029d2b..ae4bb3e 100644
--- a/packages/Tethering/common/TetheringLib/Android.bp
+++ b/packages/Tethering/common/TetheringLib/Android.bp
@@ -13,43 +13,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// AIDL interfaces between the core system and the tethering mainline module.
-aidl_interface {
-    name: "tethering-aidl-interfaces",
-    unstable: true,
-    local_include_dir: "src",
-    include_dirs: ["frameworks/base/core/java"], // For framework parcelables.
-    srcs: [
-        // @JavaOnlyStableParcelable aidl declarations must not be listed here, as this would cause
-        // compilation to fail (b/148001843).
-        "src/android/net/IIntResultListener.aidl",
-        "src/android/net/ITetheringConnector.aidl",
-        "src/android/net/ITetheringEventCallback.aidl",
-        "src/android/net/TetheringCallbackStartedParcel.aidl",
-        "src/android/net/TetheringConfigurationParcel.aidl",
-        "src/android/net/TetheringRequestParcel.aidl",
-        "src/android/net/TetherStatesParcel.aidl",
-    ],
-    backend: {
-        ndk: {
-            enabled: false,
-        },
-        cpp: {
-            enabled: false,
-        },
-    },
-}
-
 java_library {
     name: "framework-tethering",
     sdk_version: "module_current",
     srcs: [
-        "src/android/net/TetheredClient.java",
-        "src/android/net/TetheringManager.java",
-        "src/android/net/TetheringConstants.java",
-    ],
-    static_libs: [
-        "tethering-aidl-interfaces-java",
+        ":framework-tethering-srcs",
     ],
     jarjar_rules: "jarjar-rules.txt",
     installable: true,
diff --git a/packages/Tethering/res/values/config.xml b/packages/Tethering/res/values/config.xml
index 9dda716..9269c6f 100644
--- a/packages/Tethering/res/values/config.xml
+++ b/packages/Tethering/res/values/config.xml
@@ -57,6 +57,12 @@
         <item>"bt-pan"</item>
     </string-array>
 
+    <!-- Use the BPF offload for tethering when the kernel has support. True by default.
+         If the device doesn't want to support tether BPF offload, this should be false.
+         Note that this setting could be overridden by device config.
+    -->
+    <bool translatable="false" name="config_tether_enable_bpf_offload">true</bool>
+
     <!-- Use the old dnsmasq DHCP server for tethering instead of the framework implementation. -->
     <bool translatable="false" name="config_tether_enable_legacy_dhcp_server">false</bool>
 
diff --git a/packages/Tethering/res/values/overlayable.xml b/packages/Tethering/res/values/overlayable.xml
index 4c78a74..4e2bb1e 100644
--- a/packages/Tethering/res/values/overlayable.xml
+++ b/packages/Tethering/res/values/overlayable.xml
@@ -23,6 +23,11 @@
             <item type="array" name="config_tether_wifi_p2p_regexs"/>
             <item type="array" name="config_tether_bluetooth_regexs"/>
             <item type="array" name="config_tether_dhcp_range"/>
+            <!-- Use the BPF offload for tethering when the kernel has support. True by default.
+                 If the device doesn't want to support tether BPF offload, this should be false.
+                 Note that this setting could be overridden by device config.
+            -->
+            <item type="bool" name="config_tether_enable_bpf_offload"/>
             <item type="bool" name="config_tether_enable_legacy_dhcp_server"/>
             <item type="integer" name="config_tether_offload_poll_interval"/>
             <item type="array" name="config_tether_upstream_types"/>
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index 83727bc..d993306 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -227,6 +227,7 @@
     private final int mInterfaceType;
     private final LinkProperties mLinkProperties;
     private final boolean mUsingLegacyDhcp;
+    private final boolean mUsingBpfOffload;
 
     private final Dependencies mDeps;
 
@@ -302,9 +303,12 @@
 
     private final IpNeighborMonitor mIpNeighborMonitor;
 
+    // TODO: Add a dependency object to pass the data members or variables from the tethering
+    // object. It helps to reduce the arguments of the constructor.
     public IpServer(
             String ifaceName, Looper looper, int interfaceType, SharedLog log,
-            INetd netd, Callback callback, boolean usingLegacyDhcp, Dependencies deps) {
+            INetd netd, Callback callback, boolean usingLegacyDhcp, boolean usingBpfOffload,
+            Dependencies deps) {
         super(ifaceName, looper);
         mLog = log.forSubComponent(ifaceName);
         mNetd = netd;
@@ -314,6 +318,7 @@
         mInterfaceType = interfaceType;
         mLinkProperties = new LinkProperties();
         mUsingLegacyDhcp = usingLegacyDhcp;
+        mUsingBpfOffload = usingBpfOffload;
         mDeps = deps;
         resetLinkProperties();
         mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
@@ -321,7 +326,12 @@
 
         mIpNeighborMonitor = mDeps.getIpNeighborMonitor(getHandler(), mLog,
                 new MyNeighborEventConsumer());
-        if (!mIpNeighborMonitor.start()) {
+
+        // IP neighbor monitor monitors the neighbor events for adding/removing offload
+        // forwarding rules per client. If BPF offload is not supported, don't start listening
+        // for neighbor events. See updateIpv6ForwardingRules, addIpv6ForwardingRule,
+        // removeIpv6ForwardingRule.
+        if (mUsingBpfOffload && !mIpNeighborMonitor.start()) {
             mLog.e("Failed to create IpNeighborMonitor on " + mIfaceName);
         }
 
@@ -715,12 +725,12 @@
             final String upstreamIface = v6only.getInterfaceName();
 
             params = new RaParams();
-            // We advertise an mtu lower by 16, which is the closest multiple of 8 >= 14,
-            // the ethernet header size.  This makes kernel ebpf tethering offload happy.
-            // This hack should be reverted once we have the kernel fixed up.
+            // When BPF offload is enabled, we advertise an mtu lower by 16, which is the closest
+            // multiple of 8 >= 14, the ethernet header size. This makes kernel ebpf tethering
+            // offload happy. This hack should be reverted once we have the kernel fixed up.
             // Note: this will automatically clamp to at least 1280 (ipv6 minimum mtu)
             // see RouterAdvertisementDaemon.java putMtu()
-            params.mtu = v6only.getMtu() - 16;
+            params.mtu = mUsingBpfOffload ? v6only.getMtu() - 16 : v6only.getMtu();
             params.hasDefaultRoute = v6only.hasIpv6DefaultRoute();
 
             if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface);
@@ -844,6 +854,11 @@
     }
 
     private void addIpv6ForwardingRule(Ipv6ForwardingRule rule) {
+        // Theoretically, we don't need this check because IP neighbor monitor doesn't start if BPF
+        // offload is disabled. Add this check just in case.
+        // TODO: Perhaps remove this protection check.
+        if (!mUsingBpfOffload) return;
+
         try {
             mNetd.tetherOffloadRuleAdd(rule.toTetherOffloadRuleParcel());
             mIpv6ForwardingRules.put(rule.address, rule);
@@ -853,6 +868,11 @@
     }
 
     private void removeIpv6ForwardingRule(Ipv6ForwardingRule rule, boolean removeFromMap) {
+        // Theoretically, we don't need this check because IP neighbor monitor doesn't start if BPF
+        // offload is disabled. Add this check just in case.
+        // TODO: Perhaps remove this protection check.
+        if (!mUsingBpfOffload) return;
+
         try {
             mNetd.tetherOffloadRuleRemove(rule.toTetherOffloadRuleParcel());
             if (removeFromMap) {
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java b/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
index 293f8ea..fe92204 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
@@ -66,6 +66,7 @@
 
     private final Handler mHandler;
     private final SharedLog mLog;
+    private final Dependencies mDeps;
     private IOffloadControl mOffloadControl;
     private TetheringOffloadCallback mTetheringOffloadCallback;
     private ControlCallback mControlCallback;
@@ -126,8 +127,76 @@
     }
 
     public OffloadHardwareInterface(Handler h, SharedLog log) {
+        this(h, log, new Dependencies(log));
+    }
+
+    OffloadHardwareInterface(Handler h, SharedLog log, Dependencies deps) {
         mHandler = h;
         mLog = log.forSubComponent(TAG);
+        mDeps = deps;
+    }
+
+    /** Capture OffloadHardwareInterface dependencies, for injection. */
+    static class Dependencies {
+        private final SharedLog mLog;
+
+        Dependencies(SharedLog log) {
+            mLog = log;
+        }
+
+        public IOffloadConfig getOffloadConfig() {
+            try {
+                return IOffloadConfig.getService(true /*retry*/);
+            } catch (RemoteException | NoSuchElementException e) {
+                mLog.e("getIOffloadConfig error " + e);
+                return null;
+            }
+        }
+
+        public IOffloadControl getOffloadControl() {
+            try {
+                return IOffloadControl.getService(true /*retry*/);
+            } catch (RemoteException | NoSuchElementException e) {
+                mLog.e("tethering offload control not supported: " + e);
+                return null;
+            }
+        }
+
+        public NativeHandle createConntrackSocket(final int groups) {
+            final FileDescriptor fd;
+            try {
+                fd = NetlinkSocket.forProto(OsConstants.NETLINK_NETFILTER);
+            } catch (ErrnoException e) {
+                mLog.e("Unable to create conntrack socket " + e);
+                return null;
+            }
+
+            final SocketAddress sockAddr = SocketUtils.makeNetlinkSocketAddress(0, groups);
+            try {
+                Os.bind(fd, sockAddr);
+            } catch (ErrnoException | SocketException e) {
+                mLog.e("Unable to bind conntrack socket for groups " + groups + " error: " + e);
+                try {
+                    SocketUtils.closeSocket(fd);
+                } catch (IOException ie) {
+                    // Nothing we can do here
+                }
+                return null;
+            }
+            try {
+                Os.connect(fd, sockAddr);
+            } catch (ErrnoException | SocketException e) {
+                mLog.e("connect to kernel fail for groups " + groups + " error: " + e);
+                try {
+                    SocketUtils.closeSocket(fd);
+                } catch (IOException ie) {
+                    // Nothing we can do here
+                }
+                return null;
+            }
+
+            return new NativeHandle(fd, true);
+        }
     }
 
     /** Get default value indicating whether offload is supported. */
@@ -141,13 +210,7 @@
      * share them with offload management process.
      */
     public boolean initOffloadConfig() {
-        IOffloadConfig offloadConfig;
-        try {
-            offloadConfig = IOffloadConfig.getService(true /*retry*/);
-        } catch (RemoteException | NoSuchElementException e) {
-            mLog.e("getIOffloadConfig error " + e);
-            return false;
-        }
+        final IOffloadConfig offloadConfig = mDeps.getOffloadConfig();
         if (offloadConfig == null) {
             mLog.e("Could not find IOffloadConfig service");
             return false;
@@ -159,11 +222,11 @@
         //
         // h2    provides a file descriptor bound to the following netlink groups
         //       (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY).
-        final NativeHandle h1 = createConntrackSocket(
+        final NativeHandle h1 = mDeps.createConntrackSocket(
                 NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY);
         if (h1 == null) return false;
 
-        final NativeHandle h2 = createConntrackSocket(
+        final NativeHandle h2 = mDeps.createConntrackSocket(
                 NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY);
         if (h2 == null) {
             closeFdInNativeHandle(h1);
@@ -198,53 +261,12 @@
         }
     }
 
-    private NativeHandle createConntrackSocket(final int groups) {
-        FileDescriptor fd;
-        try {
-            fd = NetlinkSocket.forProto(OsConstants.NETLINK_NETFILTER);
-        } catch (ErrnoException e) {
-            mLog.e("Unable to create conntrack socket " + e);
-            return null;
-        }
-
-        final SocketAddress sockAddr = SocketUtils.makeNetlinkSocketAddress(0, groups);
-        try {
-            Os.bind(fd, sockAddr);
-        } catch (ErrnoException | SocketException e) {
-            mLog.e("Unable to bind conntrack socket for groups " + groups + " error: " + e);
-            try {
-                SocketUtils.closeSocket(fd);
-            } catch (IOException ie) {
-                // Nothing we can do here
-            }
-            return null;
-        }
-        try {
-            Os.connect(fd, sockAddr);
-        } catch (ErrnoException | SocketException e) {
-            mLog.e("connect to kernel fail for groups " + groups + " error: " + e);
-            try {
-                SocketUtils.closeSocket(fd);
-            } catch (IOException ie) {
-                // Nothing we can do here
-            }
-            return null;
-        }
-
-        return new NativeHandle(fd, true);
-    }
-
     /** Initialize the tethering offload HAL. */
     public boolean initOffloadControl(ControlCallback controlCb) {
         mControlCallback = controlCb;
 
         if (mOffloadControl == null) {
-            try {
-                mOffloadControl = IOffloadControl.getService(true /*retry*/);
-            } catch (RemoteException | NoSuchElementException e) {
-                mLog.e("tethering offload control not supported: " + e);
-                return false;
-            }
+            mOffloadControl = mDeps.getOffloadControl();
             if (mOffloadControl == null) {
                 mLog.e("tethering IOffloadControl.getService() returned null");
                 return false;
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
index ae6119f2..04ad43f 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -109,8 +109,10 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceSpecificException;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -228,6 +230,7 @@
     private final ConnectedClientsTracker mConnectedClientsTracker;
     private final TetheringThreadExecutor mExecutor;
     private final TetheringNotificationUpdater mNotificationUpdater;
+    private final UserManager mUserManager;
     private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID;
     // All the usage of mTetheringEventCallback should run in the same thread.
     private ITetheringEventCallback mTetheringEventCallback = null;
@@ -305,23 +308,24 @@
 
         mStateReceiver = new StateReceiver();
 
-        final UserManager userManager = (UserManager) mContext.getSystemService(
-                Context.USER_SERVICE);
+        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         mTetheringRestriction = new UserRestrictionActionListener(
-                userManager, this, mNotificationUpdater);
+                mUserManager, this, mNotificationUpdater);
         mExecutor = new TetheringThreadExecutor(mHandler);
         mActiveDataSubIdListener = new ActiveDataSubIdListener(mExecutor);
         mNetdCallback = new NetdCallback();
 
         // Load tethering configuration.
         updateConfiguration();
+
+        startStateMachineUpdaters();
     }
 
     /**
      * Start to register callbacks.
      * Call this function when tethering is ready to handle callback events.
      */
-    public void startStateMachineUpdaters() {
+    private void startStateMachineUpdaters() {
         try {
             mNetd.registerUnsolicitedEventListener(mNetdCallback);
         } catch (RemoteException e) {
@@ -779,7 +783,7 @@
 
     // TODO: Figure out how to update for local hotspot mode interfaces.
     private void sendTetherStateChangedBroadcast() {
-        if (!mDeps.isTetheringSupported()) return;
+        if (!isTetheringSupported()) return;
 
         final ArrayList<String> availableList = new ArrayList<>();
         final ArrayList<String> tetherList = new ArrayList<>();
@@ -1020,14 +1024,14 @@
 
     @VisibleForTesting
     protected static class UserRestrictionActionListener {
-        private final UserManager mUserManager;
+        private final UserManager mUserMgr;
         private final Tethering mWrapper;
         private final TetheringNotificationUpdater mNotificationUpdater;
         public boolean mDisallowTethering;
 
         public UserRestrictionActionListener(@NonNull UserManager um, @NonNull Tethering wrapper,
                 @NonNull TetheringNotificationUpdater updater) {
-            mUserManager = um;
+            mUserMgr = um;
             mWrapper = wrapper;
             mNotificationUpdater = updater;
             mDisallowTethering = false;
@@ -1037,7 +1041,7 @@
             // getUserRestrictions gets restriction for this process' user, which is the primary
             // user. This is fine because DISALLOW_CONFIG_TETHERING can only be set on the primary
             // user. See UserManager.DISALLOW_CONFIG_TETHERING.
-            final Bundle restrictions = mUserManager.getUserRestrictions();
+            final Bundle restrictions = mUserMgr.getUserRestrictions();
             final boolean newlyDisallowed =
                     restrictions.getBoolean(UserManager.DISALLOW_CONFIG_TETHERING);
             final boolean prevDisallowed = mDisallowTethering;
@@ -1988,7 +1992,7 @@
         mHandler.post(() -> {
             mTetheringEventCallbacks.register(callback, new CallbackCookie(hasListPermission));
             final TetheringCallbackStartedParcel parcel = new TetheringCallbackStartedParcel();
-            parcel.tetheringSupported = mDeps.isTetheringSupported();
+            parcel.tetheringSupported = isTetheringSupported();
             parcel.upstreamNetwork = mTetherUpstream;
             parcel.config = mConfig.toStableParcelable();
             parcel.states =
@@ -2111,6 +2115,20 @@
         }
     }
 
+    // if ro.tether.denied = true we default to no tethering
+    // gservices could set the secure setting to 1 though to enable it on a build where it
+    // had previously been turned off.
+    boolean isTetheringSupported() {
+        final int defaultVal =
+                SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1;
+        final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
+        final boolean tetherEnabledInSettings = tetherSupported
+                && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
+
+        return tetherEnabledInSettings && hasTetherableConfiguration();
+    }
+
     void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) {
         // Binder.java closes the resource for us.
         @SuppressWarnings("resource")
@@ -2296,7 +2314,7 @@
         final TetherState tetherState = new TetherState(
                 new IpServer(iface, mLooper, interfaceType, mLog, mNetd,
                              makeControlCallback(), mConfig.enableLegacyDhcpServer,
-                             mDeps.getIpServerDependencies()));
+                             mConfig.enableBpfOffload, mDeps.getIpServerDependencies()));
         mTetherStates.put(iface, tetherState);
         tetherState.ipServer.start();
     }
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
index 9d4e747..48a600d 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
@@ -73,6 +73,12 @@
     private static final String[] DEFAULT_IPV4_DNS = {"8.8.4.4", "8.8.8.8"};
 
     /**
+     * Override enabling BPF offload configuration for tethering.
+     */
+    public static final String OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD =
+            "override_tether_enable_bpf_offload";
+
+    /**
      * Use the old dnsmasq DHCP server for tethering instead of the framework implementation.
      */
     public static final String TETHER_ENABLE_LEGACY_DHCP_SERVER =
@@ -95,6 +101,8 @@
     public final String[] legacyDhcpRanges;
     public final String[] defaultIPv4DNS;
     public final boolean enableLegacyDhcpServer;
+    // TODO: Add to TetheringConfigurationParcel if required.
+    public final boolean enableBpfOffload;
 
     public final String[] provisioningApp;
     public final String provisioningAppNoUi;
@@ -124,11 +132,12 @@
         isDunRequired = checkDunRequired(ctx);
 
         chooseUpstreamAutomatically = getResourceBoolean(
-                res, R.bool.config_tether_upstream_automatic);
+                res, R.bool.config_tether_upstream_automatic, false /** defaultValue */);
         preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired);
 
         legacyDhcpRanges = getLegacyDhcpRanges(res);
         defaultIPv4DNS = copy(DEFAULT_IPV4_DNS);
+        enableBpfOffload = getEnableBpfOffload(res);
         enableLegacyDhcpServer = getEnableLegacyDhcpServer(res);
 
         provisioningApp = getResourceStringArray(res, R.array.config_mobile_hotspot_provision_app);
@@ -208,6 +217,9 @@
         pw.print("provisioningAppNoUi: ");
         pw.println(provisioningAppNoUi);
 
+        pw.print("enableBpfOffload: ");
+        pw.println(enableBpfOffload);
+
         pw.print("enableLegacyDhcpServer: ");
         pw.println(enableLegacyDhcpServer);
     }
@@ -228,6 +240,7 @@
                 toIntArray(preferredUpstreamIfaceTypes)));
         sj.add(String.format("provisioningApp:%s", makeString(provisioningApp)));
         sj.add(String.format("provisioningAppNoUi:%s", provisioningAppNoUi));
+        sj.add(String.format("enableBpfOffload:%s", enableBpfOffload));
         sj.add(String.format("enableLegacyDhcpServer:%s", enableLegacyDhcpServer));
         return String.format("TetheringConfiguration{%s}", sj.toString());
     }
@@ -332,11 +345,11 @@
         }
     }
 
-    private static boolean getResourceBoolean(Resources res, int resId) {
+    private static boolean getResourceBoolean(Resources res, int resId, boolean defaultValue) {
         try {
             return res.getBoolean(resId);
         } catch (Resources.NotFoundException e404) {
-            return false;
+            return defaultValue;
         }
     }
 
@@ -357,14 +370,36 @@
         }
     }
 
+    private boolean getEnableBpfOffload(final Resources res) {
+        // Get BPF offload config
+        // Priority 1: Device config
+        // Priority 2: Resource config
+        // Priority 3: Default value
+        final boolean defaultValue = getResourceBoolean(
+                res, R.bool.config_tether_enable_bpf_offload, true /** default value */);
+
+        return getDeviceConfigBoolean(OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD, defaultValue);
+    }
+
     private boolean getEnableLegacyDhcpServer(final Resources res) {
-        return getResourceBoolean(res, R.bool.config_tether_enable_legacy_dhcp_server)
-                || getDeviceConfigBoolean(TETHER_ENABLE_LEGACY_DHCP_SERVER);
+        return getResourceBoolean(
+                res, R.bool.config_tether_enable_legacy_dhcp_server, false /** defaultValue */)
+                || getDeviceConfigBoolean(
+                TETHER_ENABLE_LEGACY_DHCP_SERVER, false /** defaultValue */);
+    }
+
+    private boolean getDeviceConfigBoolean(final String name, final boolean defaultValue) {
+        // Due to the limitation of static mock for testing, using #getDeviceConfigProperty instead
+        // of DeviceConfig#getBoolean. If using #getBoolean here, the test can't know that the
+        // returned boolean value comes from device config or default value (because of null
+        // property string). See the test case testBpfOffload{*} in TetheringConfigurationTest.java.
+        final String value = getDeviceConfigProperty(name);
+        return value != null ? Boolean.parseBoolean(value) : defaultValue;
     }
 
     @VisibleForTesting
-    protected boolean getDeviceConfigBoolean(final String name) {
-        return DeviceConfig.getBoolean(NAMESPACE_CONNECTIVITY, name, false /** defaultValue */);
+    protected String getDeviceConfigProperty(String name) {
+        return DeviceConfig.getProperty(NAMESPACE_CONNECTIVITY, name);
     }
 
     private Resources getResources(Context ctx, int subId) {
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java
index d07c555f..bf7fb04 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java
@@ -40,15 +40,12 @@
 import android.net.dhcp.DhcpServerCallbacks;
 import android.net.dhcp.DhcpServingParamsParcel;
 import android.net.ip.IpServer;
-import android.net.util.SharedLog;
 import android.os.Binder;
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
-import android.os.SystemProperties;
-import android.os.UserManager;
 import android.provider.Settings;
 import android.util.Log;
 
@@ -68,21 +65,14 @@
 public class TetheringService extends Service {
     private static final String TAG = TetheringService.class.getSimpleName();
 
-    private final SharedLog mLog = new SharedLog(TAG);
     private TetheringConnector mConnector;
-    private Context mContext;
-    private TetheringDependencies mDeps;
-    private Tethering mTethering;
-    private UserManager mUserManager;
 
     @Override
     public void onCreate() {
-        mLog.mark("onCreate");
-        mDeps = getTetheringDependencies();
-        mContext = mDeps.getContext();
-        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-        mTethering = makeTethering(mDeps);
-        mTethering.startStateMachineUpdaters();
+        final TetheringDependencies deps = makeTetheringDependencies();
+        // The Tethering object needs a fully functional context to start, so this can't be done
+        // in the constructor.
+        mConnector = new TetheringConnector(makeTethering(deps), TetheringService.this);
     }
 
     /**
@@ -94,21 +84,10 @@
         return new Tethering(deps);
     }
 
-    /**
-     * Create a binder connector for the system server to communicate with the tethering.
-     */
-    private synchronized IBinder makeConnector() {
-        if (mConnector == null) {
-            mConnector = new TetheringConnector(mTethering, TetheringService.this);
-        }
-        return mConnector;
-    }
-
     @NonNull
     @Override
     public IBinder onBind(Intent intent) {
-        mLog.mark("onBind");
-        return makeConnector();
+        return mConnector;
     }
 
     private static class TetheringConnector extends ITetheringConnector.Stub {
@@ -237,7 +216,7 @@
                     listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
                     return true;
                 }
-                if (!mService.isTetheringSupported()) {
+                if (!mTethering.isTetheringSupported()) {
                     listener.onResult(TETHER_ERROR_UNSUPPORTED);
                     return true;
                 }
@@ -253,7 +232,7 @@
                 receiver.send(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, null);
                 return true;
             }
-            if (!mService.isTetheringSupported()) {
+            if (!mTethering.isTetheringSupported()) {
                 receiver.send(TETHER_ERROR_UNSUPPORTED, null);
                 return true;
             }
@@ -287,105 +266,83 @@
         }
     }
 
-    // if ro.tether.denied = true we default to no tethering
-    // gservices could set the secure setting to 1 though to enable it on a build where it
-    // had previously been turned off.
-    private boolean isTetheringSupported() {
-        final int defaultVal =
-                SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1;
-        final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
-        final boolean tetherEnabledInSettings = tetherSupported
-                && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
-
-        return tetherEnabledInSettings && mTethering.hasTetherableConfiguration();
-    }
-
     /**
      * An injection method for testing.
      */
     @VisibleForTesting
-    public TetheringDependencies getTetheringDependencies() {
-        if (mDeps == null) {
-            mDeps = new TetheringDependencies() {
-                @Override
-                public NetworkRequest getDefaultNetworkRequest() {
-                    // TODO: b/147280869, add a proper system API to replace this.
-                    final NetworkRequest trackDefaultRequest = new NetworkRequest.Builder()
-                            .clearCapabilities()
-                            .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
-                            .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
-                            .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
-                            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
-                            .build();
-                    return trackDefaultRequest;
-                }
+    public TetheringDependencies makeTetheringDependencies() {
+        return new TetheringDependencies() {
+            @Override
+            public NetworkRequest getDefaultNetworkRequest() {
+                // TODO: b/147280869, add a proper system API to replace this.
+                final NetworkRequest trackDefaultRequest = new NetworkRequest.Builder()
+                        .clearCapabilities()
+                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+                        .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
+                        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                        .build();
+                return trackDefaultRequest;
+            }
 
-                @Override
-                public Looper getTetheringLooper() {
-                    final HandlerThread tetherThread = new HandlerThread("android.tethering");
-                    tetherThread.start();
-                    return tetherThread.getLooper();
-                }
+            @Override
+            public Looper getTetheringLooper() {
+                final HandlerThread tetherThread = new HandlerThread("android.tethering");
+                tetherThread.start();
+                return tetherThread.getLooper();
+            }
 
-                @Override
-                public boolean isTetheringSupported() {
-                    return TetheringService.this.isTetheringSupported();
-                }
+            @Override
+            public Context getContext() {
+                return TetheringService.this;
+            }
 
-                @Override
-                public Context getContext() {
-                    return TetheringService.this;
-                }
+            @Override
+            public IpServer.Dependencies getIpServerDependencies() {
+                return new IpServer.Dependencies() {
+                    @Override
+                    public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
+                            DhcpServerCallbacks cb) {
+                        try {
+                            final INetworkStackConnector service = getNetworkStackConnector();
+                            if (service == null) return;
 
-                @Override
-                public IpServer.Dependencies getIpServerDependencies() {
-                    return new IpServer.Dependencies() {
-                        @Override
-                        public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
-                                DhcpServerCallbacks cb) {
+                            service.makeDhcpServer(ifName, params, cb);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "Fail to make dhcp server");
                             try {
-                                final INetworkStackConnector service = getNetworkStackConnector();
-                                if (service == null) return;
-
-                                service.makeDhcpServer(ifName, params, cb);
-                            } catch (RemoteException e) {
-                                Log.e(TAG, "Fail to make dhcp server");
-                                try {
-                                    cb.onDhcpServerCreated(STATUS_UNKNOWN_ERROR, null);
-                                } catch (RemoteException re) { }
-                            }
+                                cb.onDhcpServerCreated(STATUS_UNKNOWN_ERROR, null);
+                            } catch (RemoteException re) { }
                         }
-                    };
-                }
-
-                // TODO: replace this by NetworkStackClient#getRemoteConnector after refactoring
-                // networkStackClient.
-                static final int NETWORKSTACK_TIMEOUT_MS = 60_000;
-                private INetworkStackConnector getNetworkStackConnector() {
-                    IBinder connector;
-                    try {
-                        final long before = System.currentTimeMillis();
-                        while ((connector = NetworkStack.getService()) == null) {
-                            if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) {
-                                Log.wtf(TAG, "Timeout, fail to get INetworkStackConnector");
-                                return null;
-                            }
-                            Thread.sleep(200);
-                        }
-                    } catch (InterruptedException e) {
-                        Log.wtf(TAG, "Interrupted, fail to get INetworkStackConnector");
-                        return null;
                     }
-                    return INetworkStackConnector.Stub.asInterface(connector);
-                }
+                };
+            }
 
-                @Override
-                public BluetoothAdapter getBluetoothAdapter() {
-                    return BluetoothAdapter.getDefaultAdapter();
+            // TODO: replace this by NetworkStackClient#getRemoteConnector after refactoring
+            // networkStackClient.
+            static final int NETWORKSTACK_TIMEOUT_MS = 60_000;
+            private INetworkStackConnector getNetworkStackConnector() {
+                IBinder connector;
+                try {
+                    final long before = System.currentTimeMillis();
+                    while ((connector = NetworkStack.getService()) == null) {
+                        if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) {
+                            Log.wtf(TAG, "Timeout, fail to get INetworkStackConnector");
+                            return null;
+                        }
+                        Thread.sleep(200);
+                    }
+                } catch (InterruptedException e) {
+                    Log.wtf(TAG, "Interrupted, fail to get INetworkStackConnector");
+                    return null;
                 }
-            };
-        }
-        return mDeps;
+                return INetworkStackConnector.Stub.asInterface(connector);
+            }
+
+            @Override
+            public BluetoothAdapter getBluetoothAdapter() {
+                return BluetoothAdapter.getDefaultAdapter();
+            }
+        };
     }
 }
diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index f9be7b9..b9622da 100644
--- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -106,6 +106,7 @@
     private static final String BLUETOOTH_IFACE_ADDR = "192.168.42.1";
     private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24;
     private static final int DHCP_LEASE_TIME_SECS = 3600;
+    private static final boolean DEFAULT_USING_BPF_OFFLOAD = true;
 
     private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams(
             IFACE_NAME, 42 /* index */, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */);
@@ -130,10 +131,11 @@
     private NeighborEventConsumer mNeighborEventConsumer;
 
     private void initStateMachine(int interfaceType) throws Exception {
-        initStateMachine(interfaceType, false /* usingLegacyDhcp */);
+        initStateMachine(interfaceType, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD);
     }
 
-    private void initStateMachine(int interfaceType, boolean usingLegacyDhcp) throws Exception {
+    private void initStateMachine(int interfaceType, boolean usingLegacyDhcp,
+            boolean usingBpfOffload) throws Exception {
         doAnswer(inv -> {
             final IDhcpServerCallbacks cb = inv.getArgument(2);
             new Thread(() -> {
@@ -165,7 +167,7 @@
 
         mIpServer = new IpServer(
                 IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, mNetd,
-                mCallback, usingLegacyDhcp, mDependencies);
+                mCallback, usingLegacyDhcp, usingBpfOffload, mDependencies);
         mIpServer.start();
         mNeighborEventConsumer = neighborCaptor.getValue();
 
@@ -179,12 +181,13 @@
 
     private void initTetheredStateMachine(int interfaceType, String upstreamIface)
             throws Exception {
-        initTetheredStateMachine(interfaceType, upstreamIface, false);
+        initTetheredStateMachine(interfaceType, upstreamIface, false,
+                DEFAULT_USING_BPF_OFFLOAD);
     }
 
     private void initTetheredStateMachine(int interfaceType, String upstreamIface,
-            boolean usingLegacyDhcp) throws Exception {
-        initStateMachine(interfaceType, usingLegacyDhcp);
+            boolean usingLegacyDhcp, boolean usingBpfOffload) throws Exception {
+        initStateMachine(interfaceType, usingLegacyDhcp, usingBpfOffload);
         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
         if (upstreamIface != null) {
             LinkProperties lp = new LinkProperties();
@@ -204,7 +207,8 @@
         when(mDependencies.getIpNeighborMonitor(any(), any(), any()))
                 .thenReturn(mIpNeighborMonitor);
         mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(), TETHERING_BLUETOOTH, mSharedLog,
-                mNetd, mCallback, false /* usingLegacyDhcp */, mDependencies);
+                mNetd, mCallback, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD,
+                mDependencies);
         mIpServer.start();
         mLooper.dispatchAll();
         verify(mCallback).updateInterfaceState(
@@ -494,7 +498,8 @@
 
     @Test
     public void doesNotStartDhcpServerIfDisabled() throws Exception {
-        initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */);
+        initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */,
+                DEFAULT_USING_BPF_OFFLOAD);
         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
 
         verify(mDependencies, never()).makeDhcpServer(any(), any(), any());
@@ -577,7 +582,8 @@
 
     @Test
     public void addRemoveipv6ForwardingRules() throws Exception {
-        initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */);
+        initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */,
+                DEFAULT_USING_BPF_OFFLOAD);
 
         final int myIfindex = TEST_IFACE_PARAMS.index;
         final int notMyIfindex = myIfindex - 1;
@@ -678,6 +684,53 @@
         reset(mNetd);
     }
 
+    @Test
+    public void enableDisableUsingBpfOffload() throws Exception {
+        final int myIfindex = TEST_IFACE_PARAMS.index;
+        final InetAddress neigh = InetAddresses.parseNumericAddress("2001:db8::1");
+        final MacAddress macA = MacAddress.fromString("00:00:00:00:00:0a");
+        final MacAddress macNull = MacAddress.fromString("00:00:00:00:00:00");
+
+        reset(mNetd);
+
+        // Expect that rules can be only added/removed when the BPF offload config is enabled.
+        // Note that the usingBpfOffload false case is not a realistic test case. Because IP
+        // neighbor monitor doesn't start if BPF offload is disabled, there should have no
+        // neighbor event listening. This is used for testing the protection check just in case.
+        // TODO: Perhaps remove this test once we don't need this check anymore.
+        for (boolean usingBpfOffload : new boolean[]{true, false}) {
+            initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */,
+                    usingBpfOffload);
+
+            // A neighbor is added.
+            recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, macA);
+            if (usingBpfOffload) {
+                verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neigh, macA));
+            } else {
+                verify(mNetd, never()).tetherOffloadRuleAdd(any());
+            }
+            reset(mNetd);
+
+            // A neighbor is deleted.
+            recvDelNeigh(myIfindex, neigh, NUD_STALE, macA);
+            if (usingBpfOffload) {
+                verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neigh, macNull));
+            } else {
+                verify(mNetd, never()).tetherOffloadRuleRemove(any());
+            }
+            reset(mNetd);
+        }
+    }
+
+    @Test
+    public void doesNotStartIpNeighborMonitorIfBpfOffloadDisabled() throws Exception {
+        initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */,
+                false /* usingBpfOffload */);
+
+        // IP neighbor monitor doesn't start if BPF offload is disabled.
+        verify(mIpNeighborMonitor, never()).start();
+    }
+
     private void assertDhcpStarted(IpPrefix expectedPrefix) throws Exception {
         verify(mDependencies, times(1)).makeDhcpServer(eq(IFACE_NAME), any(), any());
         verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks(
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java
index cdd0e24..72fa916 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java
@@ -147,9 +147,8 @@
         doReturn(false).when(
                 () -> SystemProperties.getBoolean(
                 eq(EntitlementManager.DISABLE_PROVISIONING_SYSPROP_KEY), anyBoolean()));
-        doReturn(false).when(
-                () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY),
-                eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean()));
+        doReturn(null).when(
+                () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY), anyString()));
 
         when(mResources.getStringArray(R.array.config_tether_dhcp_range))
                 .thenReturn(new String[0]);
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
new file mode 100644
index 0000000..f8ff1cb
--- /dev/null
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.tethering;
+
+import static android.net.util.TetheringUtils.uint16;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
+import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
+import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
+import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
+import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
+import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
+import android.net.util.SharedLog;
+import android.os.Handler;
+import android.os.NativeHandle;
+import android.os.test.TestLooper;
+import android.system.OsConstants;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+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.ArrayList;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public final class OffloadHardwareInterfaceTest {
+    private static final String RMNET0 = "test_rmnet_data0";
+
+    private final TestLooper mTestLooper = new TestLooper();
+
+    private OffloadHardwareInterface mOffloadHw;
+    private ITetheringOffloadCallback mTetheringOffloadCallback;
+    private OffloadHardwareInterface.ControlCallback mControlCallback;
+
+    @Mock private IOffloadConfig mIOffloadConfig;
+    @Mock private IOffloadControl mIOffloadControl;
+    @Mock private NativeHandle mNativeHandle;
+
+    class MyDependencies extends OffloadHardwareInterface.Dependencies {
+        MyDependencies(SharedLog log) {
+            super(log);
+        }
+
+        @Override
+        public IOffloadConfig getOffloadConfig() {
+            return mIOffloadConfig;
+        }
+
+        @Override
+        public IOffloadControl getOffloadControl() {
+            return mIOffloadControl;
+        }
+
+        @Override
+        public NativeHandle createConntrackSocket(final int groups) {
+            return mNativeHandle;
+        }
+    }
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        final SharedLog log = new SharedLog("test");
+        mOffloadHw = new OffloadHardwareInterface(new Handler(mTestLooper.getLooper()), log,
+                new MyDependencies(log));
+        mControlCallback = spy(new OffloadHardwareInterface.ControlCallback());
+    }
+
+    private void startOffloadHardwareInterface() throws Exception {
+        mOffloadHw.initOffloadConfig();
+        mOffloadHw.initOffloadControl(mControlCallback);
+        final ArgumentCaptor<ITetheringOffloadCallback> mOffloadCallbackCaptor =
+                ArgumentCaptor.forClass(ITetheringOffloadCallback.class);
+        verify(mIOffloadControl).initOffload(mOffloadCallbackCaptor.capture(), any());
+        mTetheringOffloadCallback = mOffloadCallbackCaptor.getValue();
+    }
+
+    @Test
+    public void testGetForwardedStats() throws Exception {
+        startOffloadHardwareInterface();
+        final OffloadHardwareInterface.ForwardedStats stats = mOffloadHw.getForwardedStats(RMNET0);
+        verify(mIOffloadControl).getForwardedStats(eq(RMNET0), any());
+        assertNotNull(stats);
+    }
+
+    @Test
+    public void testSetLocalPrefixes() throws Exception {
+        startOffloadHardwareInterface();
+        final ArrayList<String> localPrefixes = new ArrayList<>();
+        localPrefixes.add("127.0.0.0/8");
+        localPrefixes.add("fe80::/64");
+        mOffloadHw.setLocalPrefixes(localPrefixes);
+        verify(mIOffloadControl).setLocalPrefixes(eq(localPrefixes), any());
+    }
+
+    @Test
+    public void testSetDataLimit() throws Exception {
+        startOffloadHardwareInterface();
+        final long limit = 12345;
+        mOffloadHw.setDataLimit(RMNET0, limit);
+        verify(mIOffloadControl).setDataLimit(eq(RMNET0), eq(limit), any());
+    }
+
+    @Test
+    public void testSetUpstreamParameters() throws Exception {
+        startOffloadHardwareInterface();
+        final String v4addr = "192.168.10.1";
+        final String v4gateway = "192.168.10.255";
+        final ArrayList<String> v6gws = new ArrayList<>(0);
+        v6gws.add("2001:db8::1");
+        mOffloadHw.setUpstreamParameters(RMNET0, v4addr, v4gateway, v6gws);
+        verify(mIOffloadControl).setUpstreamParameters(eq(RMNET0), eq(v4addr), eq(v4gateway),
+                eq(v6gws), any());
+
+        final ArgumentCaptor<ArrayList<String>> mArrayListCaptor =
+                ArgumentCaptor.forClass(ArrayList.class);
+        mOffloadHw.setUpstreamParameters(null, null, null, null);
+        verify(mIOffloadControl).setUpstreamParameters(eq(""), eq(""), eq(""),
+                mArrayListCaptor.capture(), any());
+        assertEquals(mArrayListCaptor.getValue().size(), 0);
+    }
+
+    @Test
+    public void testUpdateDownstreamPrefix() throws Exception {
+        startOffloadHardwareInterface();
+        final String ifName = "wlan1";
+        final String prefix = "192.168.43.0/24";
+        mOffloadHw.addDownstreamPrefix(ifName, prefix);
+        verify(mIOffloadControl).addDownstream(eq(ifName), eq(prefix), any());
+
+        mOffloadHw.removeDownstreamPrefix(ifName, prefix);
+        verify(mIOffloadControl).removeDownstream(eq(ifName), eq(prefix), any());
+    }
+
+    @Test
+    public void testTetheringOffloadCallback() throws Exception {
+        startOffloadHardwareInterface();
+
+        mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STARTED);
+        mTestLooper.dispatchAll();
+        verify(mControlCallback).onStarted();
+
+        mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_ERROR);
+        mTestLooper.dispatchAll();
+        verify(mControlCallback).onStoppedError();
+
+        mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_UNSUPPORTED);
+        mTestLooper.dispatchAll();
+        verify(mControlCallback).onStoppedUnsupported();
+
+        mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_SUPPORT_AVAILABLE);
+        mTestLooper.dispatchAll();
+        verify(mControlCallback).onSupportAvailable();
+
+        mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_LIMIT_REACHED);
+        mTestLooper.dispatchAll();
+        verify(mControlCallback).onStoppedLimitReached();
+
+        final NatTimeoutUpdate tcpParams = buildNatTimeoutUpdate(NetworkProtocol.TCP);
+        mTetheringOffloadCallback.updateTimeout(tcpParams);
+        mTestLooper.dispatchAll();
+        verify(mControlCallback).onNatTimeoutUpdate(eq(OsConstants.IPPROTO_TCP),
+                eq(tcpParams.src.addr),
+                eq(uint16(tcpParams.src.port)),
+                eq(tcpParams.dst.addr),
+                eq(uint16(tcpParams.dst.port)));
+
+        final NatTimeoutUpdate udpParams = buildNatTimeoutUpdate(NetworkProtocol.UDP);
+        mTetheringOffloadCallback.updateTimeout(udpParams);
+        mTestLooper.dispatchAll();
+        verify(mControlCallback).onNatTimeoutUpdate(eq(OsConstants.IPPROTO_UDP),
+                eq(udpParams.src.addr),
+                eq(uint16(udpParams.src.port)),
+                eq(udpParams.dst.addr),
+                eq(uint16(udpParams.dst.port)));
+    }
+
+    private NatTimeoutUpdate buildNatTimeoutUpdate(final int proto) {
+        final NatTimeoutUpdate params = new NatTimeoutUpdate();
+        params.proto = proto;
+        params.src.addr = "192.168.43.200";
+        params.src.port = 100;
+        params.dst.addr = "172.50.46.169";
+        params.dst.port = 150;
+        return params;
+    }
+}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
index e8ba5b8..1999ad7 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
@@ -30,7 +30,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.when;
 
@@ -109,9 +108,9 @@
                 .mockStatic(DeviceConfig.class)
                 .strictness(Strictness.WARN)
                 .startMocking();
-        doReturn(false).when(
-                () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY),
-                eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean()));
+        doReturn(null).when(
+                () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
+                eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER)));
 
         when(mResources.getStringArray(R.array.config_tether_dhcp_range)).thenReturn(
                 new String[0]);
@@ -127,6 +126,8 @@
                 .thenReturn(new String[0]);
         when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
                 false);
+        initializeBpfOffloadConfiguration(true, null /* unset */);
+
         mHasTelephonyManager = true;
         mMockContext = new MockContext(mContext);
         mEnableLegacyDhcpServer = false;
@@ -278,13 +279,57 @@
         assertFalse(upstreamIterator.hasNext());
     }
 
+    private void initializeBpfOffloadConfiguration(
+            final boolean fromRes, final String fromDevConfig) {
+        when(mResources.getBoolean(R.bool.config_tether_enable_bpf_offload)).thenReturn(fromRes);
+        doReturn(fromDevConfig).when(
+                () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
+                eq(TetheringConfiguration.OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD)));
+    }
+
+    @Test
+    public void testBpfOffloadEnabledByResource() {
+        initializeBpfOffloadConfiguration(true, null /* unset */);
+        final TetheringConfiguration enableByRes =
+                new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+        assertTrue(enableByRes.enableBpfOffload);
+    }
+
+    @Test
+    public void testBpfOffloadEnabledByDeviceConfigOverride() {
+        for (boolean res : new boolean[]{true, false}) {
+            initializeBpfOffloadConfiguration(res, "true");
+            final TetheringConfiguration enableByDevConOverride =
+                    new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+            assertTrue(enableByDevConOverride.enableBpfOffload);
+        }
+    }
+
+    @Test
+    public void testBpfOffloadDisabledByResource() {
+        initializeBpfOffloadConfiguration(false, null /* unset */);
+        final TetheringConfiguration disableByRes =
+                new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+        assertFalse(disableByRes.enableBpfOffload);
+    }
+
+    @Test
+    public void testBpfOffloadDisabledByDeviceConfigOverride() {
+        for (boolean res : new boolean[]{true, false}) {
+            initializeBpfOffloadConfiguration(res, "false");
+            final TetheringConfiguration disableByDevConOverride =
+                    new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+            assertFalse(disableByDevConOverride.enableBpfOffload);
+        }
+    }
+
     @Test
     public void testNewDhcpServerDisabled() {
         when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
                 true);
-        doReturn(false).when(
-                () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY),
-                eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean()));
+        doReturn("false").when(
+                () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
+                eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER)));
 
         final TetheringConfiguration enableByRes =
                 new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -292,9 +337,9 @@
 
         when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
                 false);
-        doReturn(true).when(
-                () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY),
-                eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean()));
+        doReturn("true").when(
+                () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
+                eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER)));
 
         final TetheringConfiguration enableByDevConfig =
                 new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -305,9 +350,9 @@
     public void testNewDhcpServerEnabled() {
         when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
                 false);
-        doReturn(false).when(
-                () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY),
-                eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean()));
+        doReturn("false").when(
+                () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
+                eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER)));
 
         final TetheringConfiguration cfg =
                 new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java
index 51bad9a..4a667b1 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java
@@ -82,8 +82,7 @@
         mTetheringConnector = mockConnector.getTetheringConnector();
         final MockTetheringService service = mockConnector.getService();
         mTethering = service.getTethering();
-        verify(mTethering).startStateMachineUpdaters();
-        when(mTethering.hasTetherableConfiguration()).thenReturn(true);
+        when(mTethering.isTetheringSupported()).thenReturn(true);
     }
 
     @After
@@ -96,7 +95,7 @@
         when(mTethering.tether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR);
         final TestTetheringResult result = new TestTetheringResult();
         mTetheringConnector.tether(TEST_IFACE_NAME, TEST_CALLER_PKG, result);
-        verify(mTethering).hasTetherableConfiguration();
+        verify(mTethering).isTetheringSupported();
         verify(mTethering).tether(TEST_IFACE_NAME);
         verifyNoMoreInteractions(mTethering);
         result.assertResult(TETHER_ERROR_NO_ERROR);
@@ -107,7 +106,7 @@
         when(mTethering.untether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR);
         final TestTetheringResult result = new TestTetheringResult();
         mTetheringConnector.untether(TEST_IFACE_NAME, TEST_CALLER_PKG, result);
-        verify(mTethering).hasTetherableConfiguration();
+        verify(mTethering).isTetheringSupported();
         verify(mTethering).untether(TEST_IFACE_NAME);
         verifyNoMoreInteractions(mTethering);
         result.assertResult(TETHER_ERROR_NO_ERROR);
@@ -118,7 +117,7 @@
         when(mTethering.setUsbTethering(true /* enable */)).thenReturn(TETHER_ERROR_NO_ERROR);
         final TestTetheringResult result = new TestTetheringResult();
         mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG, result);
-        verify(mTethering).hasTetherableConfiguration();
+        verify(mTethering).isTetheringSupported();
         verify(mTethering).setUsbTethering(true /* enable */);
         verifyNoMoreInteractions(mTethering);
         result.assertResult(TETHER_ERROR_NO_ERROR);
@@ -130,7 +129,7 @@
         final TetheringRequestParcel request = new TetheringRequestParcel();
         request.tetheringType = TETHERING_WIFI;
         mTetheringConnector.startTethering(request, TEST_CALLER_PKG, result);
-        verify(mTethering).hasTetherableConfiguration();
+        verify(mTethering).isTetheringSupported();
         verify(mTethering).startTethering(eq(request), eq(result));
         verifyNoMoreInteractions(mTethering);
     }
@@ -139,7 +138,7 @@
     public void testStopTethering() throws Exception {
         final TestTetheringResult result = new TestTetheringResult();
         mTetheringConnector.stopTethering(TETHERING_WIFI, TEST_CALLER_PKG, result);
-        verify(mTethering).hasTetherableConfiguration();
+        verify(mTethering).isTetheringSupported();
         verify(mTethering).stopTethering(TETHERING_WIFI);
         verifyNoMoreInteractions(mTethering);
         result.assertResult(TETHER_ERROR_NO_ERROR);
@@ -150,7 +149,7 @@
         final ResultReceiver result = new ResultReceiver(null);
         mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result,
                 true /* showEntitlementUi */, TEST_CALLER_PKG);
-        verify(mTethering).hasTetherableConfiguration();
+        verify(mTethering).isTetheringSupported();
         verify(mTethering).requestLatestTetheringEntitlementResult(eq(TETHERING_WIFI),
                 eq(result), eq(true) /* showEntitlementUi */);
         verifyNoMoreInteractions(mTethering);
@@ -177,7 +176,7 @@
     public void testStopAllTethering() throws Exception {
         final TestTetheringResult result = new TestTetheringResult();
         mTetheringConnector.stopAllTethering(TEST_CALLER_PKG, result);
-        verify(mTethering).hasTetherableConfiguration();
+        verify(mTethering).isTetheringSupported();
         verify(mTethering).untetherAll();
         verifyNoMoreInteractions(mTethering);
         result.assertResult(TETHER_ERROR_NO_ERROR);
@@ -187,7 +186,7 @@
     public void testIsTetheringSupported() throws Exception {
         final TestTetheringResult result = new TestTetheringResult();
         mTetheringConnector.isTetheringSupported(TEST_CALLER_PKG, result);
-        verify(mTethering).hasTetherableConfiguration();
+        verify(mTethering).isTetheringSupported();
         verifyNoMoreInteractions(mTethering);
         result.assertResult(TETHER_ERROR_NO_ERROR);
     }
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index 2bd8ae0..0132aba 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -312,8 +312,8 @@
         }
 
         @Override
-        protected boolean getDeviceConfigBoolean(final String name) {
-            return false;
+        protected String getDeviceConfigProperty(final String name) {
+            return null;
         }
 
         @Override
@@ -485,18 +485,6 @@
         MockitoAnnotations.initMocks(this);
         when(mResources.getStringArray(R.array.config_tether_dhcp_range))
                 .thenReturn(new String[0]);
-        when(mResources.getStringArray(R.array.config_tether_usb_regexs))
-                .thenReturn(new String[] { "test_rndis\\d" });
-        when(mResources.getStringArray(R.array.config_tether_wifi_regexs))
-                .thenReturn(new String[]{ "test_wlan\\d" });
-        when(mResources.getStringArray(R.array.config_tether_wifi_p2p_regexs))
-                .thenReturn(new String[]{ "test_p2p-p2p\\d-.*" });
-        when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs))
-                .thenReturn(new String[0]);
-        when(mResources.getStringArray(R.array.config_tether_ncm_regexs))
-                .thenReturn(new String[] { "test_ncm\\d" });
-        when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[0]);
-        when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(false);
         when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
                 false);
         when(mNetd.interfaceGetList())
@@ -515,6 +503,7 @@
         mServiceContext = new TestContext(mContext);
         mContentResolver = new MockContentResolver(mServiceContext);
         mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+        setTetheringSupported(true /* supported */);
         mIntents = new Vector<>();
         mBroadcastReceiver = new BroadcastReceiver() {
             @Override
@@ -525,7 +514,6 @@
         mServiceContext.registerReceiver(mBroadcastReceiver,
                 new IntentFilter(ACTION_TETHER_STATE_CHANGED));
         mTethering = makeTethering();
-        mTethering.startStateMachineUpdaters();
         verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any());
         verify(mNetd).registerUnsolicitedEventListener(any());
         final ArgumentCaptor<PhoneStateListener> phoneListenerCaptor =
@@ -536,6 +524,31 @@
         mPhoneStateListener = phoneListenerCaptor.getValue();
     }
 
+    private void setTetheringSupported(final boolean supported) {
+        Settings.Global.putInt(mContentResolver, Settings.Global.TETHER_SUPPORTED,
+                supported ? 1 : 0);
+        when(mUserManager.hasUserRestriction(
+                UserManager.DISALLOW_CONFIG_TETHERING)).thenReturn(!supported);
+        // Setup tetherable configuration.
+        when(mResources.getStringArray(R.array.config_tether_usb_regexs))
+                .thenReturn(new String[] { "test_rndis\\d" });
+        when(mResources.getStringArray(R.array.config_tether_wifi_regexs))
+                .thenReturn(new String[]{ "test_wlan\\d" });
+        when(mResources.getStringArray(R.array.config_tether_wifi_p2p_regexs))
+                .thenReturn(new String[]{ "test_p2p-p2p\\d-.*" });
+        when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs))
+                .thenReturn(new String[0]);
+        when(mResources.getStringArray(R.array.config_tether_ncm_regexs))
+                .thenReturn(new String[] { "test_ncm\\d" });
+        when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[0]);
+        when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(true);
+    }
+
+    private void initTetheringUpstream(UpstreamNetworkState upstreamState) {
+        when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
+        when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())).thenReturn(upstreamState);
+    }
+
     private Tethering makeTethering() {
         mTetheringDependencies.reset();
         return new Tethering(mTetheringDependencies);
@@ -672,9 +685,7 @@
     }
 
     private void prepareUsbTethering(UpstreamNetworkState upstreamState) {
-        when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
-        when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
-                .thenReturn(upstreamState);
+        initTetheringUpstream(upstreamState);
 
         // Emulate pressing the USB tethering button in Settings UI.
         mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB), null);
@@ -700,7 +711,7 @@
         verify(mNetd, times(1)).interfaceGetList();
 
         // UpstreamNetworkMonitor should receive selected upstream
-        verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any());
+        verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream();
         verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
     }
 
@@ -872,8 +883,7 @@
 
         // Then 464xlat comes up
         upstreamState = buildMobile464xlatUpstreamState();
-        when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
-                .thenReturn(upstreamState);
+        initTetheringUpstream(upstreamState);
 
         // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES.
         mTetheringDependencies.mUpstreamNetworkMonitorMasterSM.sendMessage(
@@ -1344,9 +1354,7 @@
         callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
         // 2. Enable wifi tethering.
         UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
-        when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
-        when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
-                .thenReturn(upstreamState);
+        initTetheringUpstream(upstreamState);
         when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
         mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
         mLooper.dispatchAll();
@@ -1723,7 +1731,7 @@
         final Tethering.TetherMasterSM stateMachine = (Tethering.TetherMasterSM)
                 mTetheringDependencies.mUpstreamNetworkMonitorMasterSM;
         final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
-        when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())).thenReturn(upstreamState);
+        initTetheringUpstream(upstreamState);
         stateMachine.chooseUpstreamType(true);
 
         verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(eq(upstreamState.network));
@@ -1735,7 +1743,7 @@
         final Tethering.TetherMasterSM stateMachine = (Tethering.TetherMasterSM)
                 mTetheringDependencies.mUpstreamNetworkMonitorMasterSM;
         final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
-        when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())).thenReturn(upstreamState);
+        initTetheringUpstream(upstreamState);
         stateMachine.chooseUpstreamType(true);
 
         stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 6d848d1..07bb335 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -51,6 +51,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.database.ContentObserver;
@@ -132,6 +133,7 @@
 import java.util.Set;
 import java.util.function.Consumer;
 import java.util.function.Function;
+import java.util.function.Predicate;
 
 /**
  * This class is instantiated by the system as a system level service and can be
@@ -391,7 +393,7 @@
                         return;
                     }
                     // We will update when the automation service dies.
-                    AccessibilityUserState userState = getCurrentUserStateLocked();
+                    final AccessibilityUserState userState = getCurrentUserStateLocked();
                     // We have to reload the installed services since some services may
                     // have different attributes, resolve info (does not support equals),
                     // etc. Remove them then to force reload.
@@ -440,15 +442,18 @@
                     if (userId != mCurrentUserId) {
                         return;
                     }
-                    AccessibilityUserState userState = getUserStateLocked(userId);
-                    Iterator<ComponentName> it = userState.mEnabledServices.iterator();
+                    final AccessibilityUserState userState = getUserStateLocked(userId);
+                    final Predicate<ComponentName> filter =
+                            component -> component != null && component.getPackageName().equals(
+                                    packageName);
+                    userState.mBindingServices.removeIf(filter);
+                    userState.mCrashedServices.removeIf(filter);
+                    final Iterator<ComponentName> it = userState.mEnabledServices.iterator();
                     while (it.hasNext()) {
-                        ComponentName comp = it.next();
-                        String compPkg = comp.getPackageName();
+                        final ComponentName comp = it.next();
+                        final String compPkg = comp.getPackageName();
                         if (compPkg.equals(packageName)) {
                             it.remove();
-                            userState.getBindingServicesLocked().remove(comp);
-                            userState.getCrashedServicesLocked().remove(comp);
                             // Update the enabled services setting.
                             persistComponentNamesToSettingLocked(
                                     Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
@@ -476,11 +481,11 @@
                     if (userId != mCurrentUserId) {
                         return false;
                     }
-                    AccessibilityUserState userState = getUserStateLocked(userId);
-                    Iterator<ComponentName> it = userState.mEnabledServices.iterator();
+                    final AccessibilityUserState userState = getUserStateLocked(userId);
+                    final Iterator<ComponentName> it = userState.mEnabledServices.iterator();
                     while (it.hasNext()) {
-                        ComponentName comp = it.next();
-                        String compPkg = comp.getPackageName();
+                        final ComponentName comp = it.next();
+                        final String compPkg = comp.getPackageName();
                         for (String pkg : packages) {
                             if (compPkg.equals(pkg)) {
                                 if (!doit) {
@@ -1208,7 +1213,7 @@
         final Intent intent = new Intent();
         final Bundle bundle = ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle();
         intent.setComponent(name);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         try {
             mContext.startActivityAsUser(intent, bundle, UserHandle.of(mCurrentUserId));
         } catch (ActivityNotFoundException ignore) {
@@ -1540,6 +1545,7 @@
             } else {
                 if (service != null) {
                     service.unbindLocked();
+                    removeShortcutTargetForUnboundServiceLocked(userState, service);
                 }
             }
         }
@@ -2314,6 +2320,36 @@
         scheduleNotifyClientsOfServicesStateChangeLocked(userState);
     }
 
+    /**
+     * Remove the shortcut target for the unbound service which is requesting accessibility button
+     * and targeting sdk > Q from the accessibility button and shortcut.
+     *
+     * @param userState The accessibility user state.
+     * @param service The unbound service.
+     */
+    private void removeShortcutTargetForUnboundServiceLocked(AccessibilityUserState userState,
+            AccessibilityServiceConnection service) {
+        if (!service.mRequestAccessibilityButton
+                || service.getServiceInfo().getResolveInfo().serviceInfo.applicationInfo
+                .targetSdkVersion <= Build.VERSION_CODES.Q) {
+            return;
+        }
+        final ComponentName serviceName = service.getComponentName();
+        if (userState.removeShortcutTargetLocked(ACCESSIBILITY_SHORTCUT_KEY, serviceName)) {
+            final Set<String> currentTargets = userState.getShortcutTargetsLocked(
+                    ACCESSIBILITY_SHORTCUT_KEY);
+            persistColonDelimitedSetToSettingLocked(
+                    Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
+                    userState.mUserId, currentTargets, str -> str);
+        }
+        if (userState.removeShortcutTargetLocked(ACCESSIBILITY_BUTTON, serviceName)) {
+            final Set<String> currentTargets = userState.getShortcutTargetsLocked(
+                    ACCESSIBILITY_BUTTON);
+            persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
+                    userState.mUserId, currentTargets, str -> str);
+        }
+    }
+
     private void updateRecommendedUiTimeoutLocked(AccessibilityUserState userState) {
         int newNonInteractiveUiTimeout = userState.getUserNonInteractiveUiTimeoutLocked();
         int newInteractiveUiTimeout = userState.getUserInteractiveUiTimeoutLocked();
@@ -2899,11 +2935,19 @@
     public class AccessibilityDisplayListener implements DisplayManager.DisplayListener {
         private final DisplayManager mDisplayManager;
         private final ArrayList<Display> mDisplaysList = new ArrayList<>();
+        private int mSystemUiUid = 0;
 
         AccessibilityDisplayListener(Context context, MainHandler handler) {
             mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
             mDisplayManager.registerDisplayListener(this, handler);
             initializeDisplayList();
+
+            final PackageManagerInternal pm =
+                    LocalServices.getService(PackageManagerInternal.class);
+            if (pm != null) {
+                mSystemUiUid = pm.getPackageUid(pm.getSystemUiServiceComponent().getPackageName(),
+                        PackageManager.MATCH_SYSTEM_ONLY, mCurrentUserId);
+            }
         }
 
         ArrayList<Display> getValidDisplayList() {
@@ -2999,8 +3043,13 @@
             }
             // Private virtual displays are created by the ap and is not allowed to access by other
             // aps. We assume we could ignore them.
+            // The exceptional case is for bubbles. Because the bubbles use the activityView, and
+            // the virtual display of the activityView is private, so if the owner UID of the
+            // private virtual display is the one of system ui which creates the virtual display of
+            // bubbles, then this private virtual display should track the windows.
             if (display.getType() == Display.TYPE_VIRTUAL
-                    && (display.getFlags() & Display.FLAG_PRIVATE) != 0) {
+                    && (display.getFlags() & Display.FLAG_PRIVATE) != 0
+                    && display.getOwnerUid() != mSystemUiUid) {
                 return false;
             }
             return true;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index bad649a..43bb4b3 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -631,6 +631,25 @@
     }
 
     /**
+     * Removes given shortcut target in the list.
+     *
+     * @param shortcutType The shortcut type.
+     * @param target The component name of the shortcut target.
+     * @return true if the shortcut target is removed.
+     */
+    public boolean removeShortcutTargetLocked(@ShortcutType int shortcutType,
+            ComponentName target) {
+        return getShortcutTargetsLocked(shortcutType).removeIf(name -> {
+            ComponentName componentName;
+            if (name == null
+                    || (componentName = ComponentName.unflattenFromString(name)) == null) {
+                return false;
+            }
+            return componentName.equals(target);
+        });
+    }
+
+    /**
      * Returns installed accessibility service info by the given service component name.
      */
     public AccessibilityServiceInfo getInstalledServiceInfoLocked(ComponentName componentName) {
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
index a3b5a3e..6d0f069 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
@@ -295,7 +295,7 @@
                 mListener.onGestureStarted();
             }
         } else if (state == GestureMatcher.STATE_GESTURE_COMPLETED) {
-            onGestureCompleted(gestureId);
+            onGestureCompleted(gestureId, event, rawEvent, policyFlags);
         } else if (state == GestureMatcher.STATE_GESTURE_CANCELED && mState.isGestureDetecting()) {
             // We only want to call the cancelation callback if there are no other pending
             // detectors.
@@ -311,8 +311,8 @@
         }
     }
 
-    private void onGestureCompleted(int gestureId) {
-        MotionEvent event = mState.getLastReceivedEvent();
+    private void onGestureCompleted(
+            int gestureId, MotionEvent event, MotionEvent rawEvent, int policyFlags) {
         // Note that gestures that complete immediately call clear() from onMotionEvent.
         // Gestures that complete on a delay call clear() here.
         switch (gestureId) {
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerMultiTap.java b/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerMultiTap.java
index e5340f1..642a841 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerMultiTap.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerMultiTap.java
@@ -197,6 +197,7 @@
         if (getState() == STATE_GESTURE_STARTED || getState() == STATE_CLEAR) {
             // Needs more fingers lifted within the tap timeout
             // after reaching the target number of fingers are down.
+            cancelAfterTapTimeout(event, rawEvent, policyFlags);
         } else {
             cancelGesture(event, rawEvent, policyFlags);
         }
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java b/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java
index a14584a..4b89731 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java
@@ -20,9 +20,9 @@
 
 import static com.android.server.accessibility.gestures.GestureUtils.MM_PER_CM;
 import static com.android.server.accessibility.gestures.GestureUtils.getActionIndex;
-import static com.android.server.accessibility.gestures.Swipe.CANCEL_ON_PAUSE_THRESHOLD_NOT_STARTED_MS;
-import static com.android.server.accessibility.gestures.Swipe.CANCEL_ON_PAUSE_THRESHOLD_STARTED_MS;
 import static com.android.server.accessibility.gestures.Swipe.GESTURE_CONFIRM_CM;
+import static com.android.server.accessibility.gestures.Swipe.MAX_TIME_TO_CONTINUE_SWIPE_MS;
+import static com.android.server.accessibility.gestures.Swipe.MAX_TIME_TO_START_SWIPE_MS;
 import static com.android.server.accessibility.gestures.TouchExplorer.DEBUG;
 
 import android.content.Context;
@@ -387,10 +387,10 @@
         cancelPendingTransitions();
         switch (getState()) {
             case STATE_CLEAR:
-                cancelAfter(CANCEL_ON_PAUSE_THRESHOLD_NOT_STARTED_MS, event, rawEvent, policyFlags);
+                cancelAfter(MAX_TIME_TO_START_SWIPE_MS, event, rawEvent, policyFlags);
                 break;
             case STATE_GESTURE_STARTED:
-                cancelAfter(CANCEL_ON_PAUSE_THRESHOLD_STARTED_MS, event, rawEvent, policyFlags);
+                cancelAfter(MAX_TIME_TO_CONTINUE_SWIPE_MS, event, rawEvent, policyFlags);
                 break;
             default:
                 break;
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/Swipe.java b/services/accessibility/java/com/android/server/accessibility/gestures/Swipe.java
index 9108c69..041b424 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/Swipe.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/Swipe.java
@@ -49,11 +49,10 @@
     // Buffer for storing points for gesture detection.
     private final ArrayList<PointF> mStrokeBuffer = new ArrayList<>(100);
 
-    // The minimal delta between moves to add a gesture point.
-    private static final int TOUCH_TOLERANCE_PIX = 3;
-
-    // The minimal score for accepting a predicted gesture.
-    private static final float MIN_PREDICTION_SCORE = 2.0f;
+    // Constants for sampling motion event points.
+    // We sample based on a minimum distance between points, primarily to improve accuracy by
+    // reducing noisy minor changes in direction.
+    private static final float MIN_CM_BETWEEN_SAMPLES = 0.25f;
 
     // Distance a finger must travel before we decide if it is a gesture or not.
     public static final int GESTURE_CONFIRM_CM = 1;
@@ -67,22 +66,19 @@
     // all gestures started with the initial movement taking less than 100ms.
     // When touch exploring, the first movement almost always takes longer than
     // 200ms.
-    public static final long CANCEL_ON_PAUSE_THRESHOLD_NOT_STARTED_MS = 150;
+    public static final long MAX_TIME_TO_START_SWIPE_MS = 150 * GESTURE_CONFIRM_CM;
 
     // Time threshold used to determine if a gesture should be cancelled.  If
-    // the finger takes more than this time to move 1cm, the ongoing gesture is
-    // cancelled.
-    public static final long CANCEL_ON_PAUSE_THRESHOLD_STARTED_MS = 300;
+    // the finger takes more than this time to move  to the next sample point, the ongoing gesture
+    // is cancelled.
+    public static final long MAX_TIME_TO_CONTINUE_SWIPE_MS = 350 * GESTURE_CONFIRM_CM;
 
     private int[] mDirections;
     private float mBaseX;
     private float mBaseY;
+    private long mBaseTime;
     private float mPreviousGestureX;
     private float mPreviousGestureY;
-    // Constants for sampling motion event points.
-    // We sample based on a minimum distance between points, primarily to improve accuracy by
-    // reducing noisy minor changes in direction.
-    private static final float MIN_CM_BETWEEN_SAMPLES = 0.25f;
     private final float mMinPixelsBetweenSamplesX;
     private final float mMinPixelsBetweenSamplesY;
     // The minmimum distance the finger must travel before we evaluate the initial direction of the
@@ -134,16 +130,19 @@
     protected void clear() {
         mBaseX = Float.NaN;
         mBaseY = Float.NaN;
+        mBaseTime = 0;
+        mPreviousGestureX = Float.NaN;
+        mPreviousGestureY = Float.NaN;
         mStrokeBuffer.clear();
         super.clear();
     }
 
     @Override
     protected void onDown(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
-        cancelAfterPauseThreshold(event, rawEvent, policyFlags);
         if (Float.isNaN(mBaseX) && Float.isNaN(mBaseY)) {
             mBaseX = rawEvent.getX();
             mBaseY = rawEvent.getY();
+            mBaseTime = rawEvent.getEventTime();
             mPreviousGestureX = mBaseX;
             mPreviousGestureY = mBaseY;
         }
@@ -154,9 +153,11 @@
     protected void onMove(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
         final float x = rawEvent.getX();
         final float y = rawEvent.getY();
+        final long time = rawEvent.getEventTime();
         final float dX = Math.abs(x - mPreviousGestureX);
         final float dY = Math.abs(y - mPreviousGestureY);
         final double moveDelta = Math.hypot(Math.abs(x - mBaseX), Math.abs(y - mBaseY));
+        final long timeDelta = time - mBaseTime;
         if (DEBUG) {
             Slog.d(
                     getGestureName(),
@@ -171,34 +172,38 @@
                 return;
             } else if (mStrokeBuffer.size() == 0) {
                 // First, make sure the pointer is going in the right direction.
-                cancelAfterPauseThreshold(event, rawEvent, policyFlags);
                 int direction = toDirection(x - mBaseX, y - mBaseY);
                 if (direction != mDirections[0]) {
                     cancelGesture(event, rawEvent, policyFlags);
                     return;
-                } else {
-                    // This is confirmed to be some kind of swipe so start tracking points.
-                    mStrokeBuffer.add(new PointF(mBaseX, mBaseY));
                 }
-            }
-            if (moveDelta > mGestureDetectionThresholdPixels) {
-                // If the pointer has moved more than the threshold,
-                // update the stored values.
-                mBaseX = x;
-                mBaseY = y;
-                if (getState() == STATE_CLEAR) {
-                    startGesture(event, rawEvent, policyFlags);
-                    cancelAfterPauseThreshold(event, rawEvent, policyFlags);
-                }
+                // This is confirmed to be some kind of swipe so start tracking points.
+                mStrokeBuffer.add(new PointF(mBaseX, mBaseY));
             }
         }
-        if (getState() == STATE_GESTURE_STARTED) {
-            if (dX >= mMinPixelsBetweenSamplesX || dY >= mMinPixelsBetweenSamplesY) {
-                mPreviousGestureX = x;
-                mPreviousGestureY = y;
-                mStrokeBuffer.add(new PointF(x, y));
-                cancelAfterPauseThreshold(event, rawEvent, policyFlags);
+        if (moveDelta > mGestureDetectionThresholdPixels) {
+            // This is a gesture, not touch exploration.
+            mBaseX = x;
+            mBaseY = y;
+            mBaseTime = time;
+            startGesture(event, rawEvent, policyFlags);
+        } else if (getState() == STATE_CLEAR) {
+            if (timeDelta > MAX_TIME_TO_START_SWIPE_MS) {
+                // The user isn't moving fast enough.
+                cancelGesture(event, rawEvent, policyFlags);
+                return;
             }
+        } else if (getState() == STATE_GESTURE_STARTED) {
+            if (timeDelta > MAX_TIME_TO_CONTINUE_SWIPE_MS) {
+                cancelGesture(event, rawEvent, policyFlags);
+                return;
+            }
+        }
+        if (dX >= mMinPixelsBetweenSamplesX || dY >= mMinPixelsBetweenSamplesY) {
+            // At this point gesture detection has started and we are sampling points.
+            mPreviousGestureX = x;
+            mPreviousGestureY = y;
+            mStrokeBuffer.add(new PointF(x, y));
         }
     }
 
@@ -230,25 +235,6 @@
     }
 
     /**
-     * queues a transition to STATE_GESTURE_CANCEL based on the current state. If we have
-     * transitioned to STATE_GESTURE_STARTED the delay is longer.
-     */
-    private void cancelAfterPauseThreshold(
-            MotionEvent event, MotionEvent rawEvent, int policyFlags) {
-        cancelPendingTransitions();
-        switch (getState()) {
-            case STATE_CLEAR:
-                cancelAfter(CANCEL_ON_PAUSE_THRESHOLD_NOT_STARTED_MS, event, rawEvent, policyFlags);
-                break;
-            case STATE_GESTURE_STARTED:
-                cancelAfter(CANCEL_ON_PAUSE_THRESHOLD_STARTED_MS, event, rawEvent, policyFlags);
-                break;
-            default:
-                break;
-        }
-    }
-
-    /**
      * Looks at the sequence of motions in mStrokeBuffer, classifies the gesture, then calls
      * Listener callbacks for success or failure.
      *
diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
index fdc5f81..103151d 100644
--- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
+++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
@@ -267,6 +267,9 @@
         mRemoteService.destroy();
         mRemoteService = null;
 
+        synchronized (mLock) {
+            mZombie = true;
+        }
         mRemoteService = getRemoteServiceLocked();
         if (mRemoteService != null) {
             if (isDebug()) {
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 74e4e4a..d7a3a32 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -19,7 +19,6 @@
 import static android.content.Context.KEYGUARD_SERVICE;
 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
 
 import android.annotation.UserIdInt;
@@ -101,7 +100,6 @@
 import android.view.Display;
 import android.view.View;
 import android.widget.RemoteViews;
-
 import com.android.internal.R;
 import com.android.internal.app.SuspendedAppActivity;
 import com.android.internal.app.UnlaunchableAppActivity;
@@ -116,11 +114,6 @@
 import com.android.server.LocalServices;
 import com.android.server.WidgetBackupProvider;
 import com.android.server.policy.IconUtilities;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -142,6 +135,9 @@
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
 
 class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBackupProvider,
         OnCrossProfileWidgetProvidersChangeListener {
@@ -4887,7 +4883,7 @@
                 final int widgetCount = mWidgets.size();
                 for (int i = 0; i < widgetCount; i++) {
                     final Widget widget = mWidgets.get(i);
-                    if  (widget.host.id.uid == uid) {
+                    if  (widget.host.id.uid == uid && widget.provider != null) {
                         if (widgetPackages == null) {
                             widgetPackages = new ArraySet<>();
                         }
diff --git a/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java b/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java
index 3282870..23bb9d6 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java
@@ -67,8 +67,8 @@
      * Requests the IME to create an {@link InlineSuggestionsRequest} for {@code autofillId}.
      *
      * @param autofillId      the Id of the field for which the request is for.
-     * @param requestConsumer the callback which will be invoked when IME responded or if it times
-     *                        out waiting for IME response.
+     * @param requestConsumer the callback to be invoked when the IME responds. Note that this is
+     *                        never invoked if the IME doesn't respond.
      */
     @GuardedBy("mLock")
     void onCreateInlineSuggestionsRequestLocked(@NonNull AutofillId autofillId,
@@ -127,6 +127,22 @@
     }
 
     /**
+     * Clear the locally cached inline fill UI, but don't clear the suggestion in the IME.
+     *
+     * <p>This is called to invalid the locally cached inline suggestions so we don't resend them
+     * to the IME, while assuming that the IME will clean up suggestion on their own when the input
+     * connection is finished. We don't send an empty response to IME so that it doesn't cause UI
+     * flicker on the IME side if it arrives before the input view is finished on the IME.
+     */
+    @GuardedBy("mLock")
+    void resetInlineFillUiLocked() {
+        mInlineFillUi = null;
+        if (mSession != null) {
+            mSession.resetInlineFillUiLocked();
+        }
+    }
+
+    /**
      * Updates the inline fill UI with the filter text. It'll send updated inline suggestions to
      * the IME.
      */
diff --git a/services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java b/services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java
index 0bf8993..687b75a 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillInlineSuggestionsRequestSession.java
@@ -55,16 +55,6 @@
 
     private static final String TAG = AutofillInlineSuggestionsRequestSession.class.getSimpleName();
 
-    // This timeout controls how long Autofill should wait for the IME to respond either
-    // unsupported or an {@link InlineSuggestionsRequest}. The timeout is needed to take into
-    // account the latency between the two events after a field is focused, 1) an Autofill
-    // request is triggered on framework; 2) the InputMethodService#onStartInput() event is
-    // triggered on the IME side. When 1) happens, Autofill may call the IME to return an {@link
-    // InlineSuggestionsRequest}, but the IME will only return it after 2) happens (or return
-    // immediately if the IME doesn't support inline suggestions). Also there is IPC latency
-    // between the framework and the IME but that should be small compare to that.
-    private static final int CREATE_INLINE_SUGGESTIONS_REQUEST_TIMEOUT_MS = 1000;
-
     @NonNull
     private final InputMethodManagerInternal mInputMethodManagerInternal;
     private final int mUserId;
@@ -92,9 +82,6 @@
     @GuardedBy("mLock")
     @Nullable
     private IInlineSuggestionsResponseCallback mResponseCallback;
-    @GuardedBy("mLock")
-    @Nullable
-    private Runnable mTimeoutCallback;
 
     @GuardedBy("mLock")
     @Nullable
@@ -174,12 +161,17 @@
     }
 
     /**
-     * This method must be called when the session is destroyed, to avoid further callbacks from/to
-     * the IME.
+     * Prevents further interaction with the IME. Must be called before starting a new request
+     * session to avoid unwanted behavior from two overlapping requests.
      */
     @GuardedBy("mLock")
     void destroySessionLocked() {
         mDestroyed = true;
+
+        if (!mImeRequestReceived) {
+            Slog.w(TAG,
+                    "Never received an InlineSuggestionsRequest from the IME for " + mAutofillId);
+        }
     }
 
     /**
@@ -196,11 +188,16 @@
         mInputMethodManagerInternal.onCreateInlineSuggestionsRequest(mUserId,
                 new InlineSuggestionsRequestInfo(mComponentName, mAutofillId, mUiExtras),
                 new InlineSuggestionsRequestCallbackImpl(this));
-        mTimeoutCallback = () -> {
-            Slog.w(TAG, "Timed out waiting for IME callback InlineSuggestionsRequest.");
-            handleOnReceiveImeRequest(null, null);
-        };
-        mHandler.postDelayed(mTimeoutCallback, CREATE_INLINE_SUGGESTIONS_REQUEST_TIMEOUT_MS);
+    }
+
+    /**
+     * Clear the locally cached inline fill UI, but don't clear the suggestion in IME.
+     *
+     * See also {@link AutofillInlineSessionController#resetInlineFillUiLocked()}
+     */
+    @GuardedBy("mLock")
+    void resetInlineFillUiLocked() {
+        mInlineFillUi = null;
     }
 
     /**
@@ -212,12 +209,12 @@
         if (mDestroyed || mResponseCallback == null) {
             return;
         }
-        if (!mImeInputViewStarted && mPreviousResponseIsNotEmpty) {
-            // 1. if previous response is not empty, and IME just become invisible, then send
-            // empty response to make sure existing responses don't stick around on the IME.
+        if (!mImeInputStarted && mPreviousResponseIsNotEmpty) {
+            // 1. if previous response is not empty, and IME is just disconnected from the view,
+            // then send empty response to make sure existing responses don't stick around.
             // Although the inline suggestions should disappear when IME hides which removes them
-            // from the view hierarchy, but we still send an empty response to be extra safe.
-
+            // from the view hierarchy, but we still send an empty response to indicate that the
+            // previous suggestions are invalid now.
             if (sVerbose) Slog.v(TAG, "Send empty inline response");
             updateResponseToImeUncheckLocked(new InlineSuggestionsResponse(Collections.EMPTY_LIST));
             mPreviousResponseIsNotEmpty = false;
@@ -264,11 +261,6 @@
             }
             mImeRequestReceived = true;
 
-            if (mTimeoutCallback != null) {
-                if (sVerbose) Slog.v(TAG, "removing timeout callback");
-                mHandler.removeCallbacks(mTimeoutCallback);
-                mTimeoutCallback = null;
-            }
             if (request != null && callback != null) {
                 mImeRequest = request;
                 mResponseCallback = callback;
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 086a8be..558acfa 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -19,6 +19,7 @@
 import static android.service.autofill.AutofillFieldClassificationService.EXTRA_SCORES;
 import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
 import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE;
+import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED;
 import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
 import static android.view.autofill.AutofillManager.ACTION_RESPONSE_EXPIRED;
 import static android.view.autofill.AutofillManager.ACTION_START_SESSION;
@@ -653,6 +654,10 @@
         return mService.isInlineSuggestionsEnabled();
     }
 
+    private boolean isViewFocusedLocked(int flags) {
+        return (flags & FLAG_VIEW_NOT_FOCUSED) == 0;
+    }
+
     /**
      * Clears the existing response for the partition, reads a new structure, and then requests a
      * new fill response from the fill service.
@@ -711,10 +716,13 @@
         cancelCurrentRequestLocked();
 
         // Only ask IME to create inline suggestions request if Autofill provider supports it and
-        // the render service is available.
+        // the render service is available except the autofill is triggered manually and the view
+        // is also not focused.
         final RemoteInlineSuggestionRenderService remoteRenderService =
                 mService.getRemoteInlineSuggestionRenderServiceLocked();
-        if (isInlineSuggestionsEnabledByAutofillProviderLocked() && remoteRenderService != null) {
+        if (isInlineSuggestionsEnabledByAutofillProviderLocked()
+                && remoteRenderService != null
+                && isViewFocusedLocked(flags)) {
             Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer =
                     mAssistReceiver.newAutofillRequestLocked(viewState,
                             /*isInlineRequest=*/ true);
@@ -2573,7 +2581,9 @@
                     if (sVerbose) Slog.v(TAG, "Exiting view " + id);
                     mUi.hideFillUi(this);
                     hideAugmentedAutofillLocked(viewState);
-                    mInlineSessionController.hideInlineSuggestionsUiLocked(mCurrentViewId);
+                    // We don't send an empty response to IME so that it doesn't cause UI flicker
+                    // on the IME side if it arrives before the input view is finished on the IME.
+                    mInlineSessionController.resetInlineFillUiLocked();
                     mCurrentViewId = null;
                 }
                 break;
@@ -2647,6 +2657,9 @@
                 if (sVerbose) {
                     Slog.v(TAG, "ignoring autofilled change on id " + id);
                 }
+                // TODO(b/156099633): remove this once framework gets out of business of resending
+                // inline suggestions when IME visibility changes.
+                mInlineSessionController.hideInlineSuggestionsUiLocked(viewState.id);
                 viewState.resetState(ViewState.STATE_CHANGED);
                 return;
             } else if ((viewState.id.equals(this.mCurrentViewId))
@@ -3139,9 +3152,9 @@
                     }
                 };
 
-        // When the inline suggestion render service is available, there are 2 cases when
-        // augmented autofill should ask IME for inline suggestion request, because standard
-        // autofill flow didn't:
+        // When the inline suggestion render service is available and the view is focused, there
+        // are 2 cases when augmented autofill should ask IME for inline suggestion request,
+        // because standard autofill flow didn't:
         // 1. the field is augmented autofill only (when standard autofill provider is None or
         // when it returns null response)
         // 2. standard autofill provider doesn't support inline suggestion
@@ -3149,7 +3162,8 @@
                 mService.getRemoteInlineSuggestionRenderServiceLocked();
         if (remoteRenderService != null
                 && (mForAugmentedAutofillOnly
-                || !isInlineSuggestionsEnabledByAutofillProviderLocked())) {
+                || !isInlineSuggestionsEnabledByAutofillProviderLocked())
+                && isViewFocusedLocked(flags)) {
             if (sDebug) Slog.d(TAG, "Create inline request for augmented autofill");
             remoteRenderService.getInlineSuggestionsRendererInfo(new RemoteCallback(
                     (extras) -> {
@@ -3339,7 +3353,9 @@
                 if (generateEvent) {
                     mService.logDatasetSelected(dataset.getId(), id, mClientState);
                 }
-
+                if (mCurrentViewId != null) {
+                    mInlineSessionController.hideInlineSuggestionsUiLocked(mCurrentViewId);
+                }
                 autoFillApp(dataset);
                 return;
             }
diff --git a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
index 089eeb2..c8485b7 100644
--- a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
+++ b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
@@ -57,7 +57,6 @@
             @NonNull AutoFillUI.AutoFillUiCallback client, @NonNull Runnable onErrorCallback,
             @Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
         final BiConsumer<Dataset, Integer> onClickFactory = (dataset, datasetIndex) -> {
-            client.requestHideFillUi(autofillId);
             client.authenticate(response.getRequestId(),
                     datasetIndex, response.getAuthentication(), response.getClientState(),
                     /* authenticateInline= */ true);
@@ -65,7 +64,8 @@
         final Consumer<IntentSender> intentSenderConsumer = (intentSender) ->
                 client.startIntentSender(intentSender, new Intent());
         InlinePresentation inlineAuthentication = response.getInlinePresentation();
-        return createInlineAuthSuggestion(inlineAuthentication,
+        return createInlineAuthSuggestion(
+                mergedInlinePresentation(request, 0, inlineAuthentication),
                 remoteRenderService, onClickFactory, onErrorCallback, intentSenderConsumer,
                 request.getHostInputToken(), request.getHostDisplayId());
     }
@@ -85,7 +85,6 @@
         final Consumer<IntentSender> intentSenderConsumer = (intentSender) ->
                 client.startIntentSender(intentSender, new Intent());
         final BiConsumer<Dataset, Integer> onClickFactory = (dataset, datasetIndex) -> {
-            client.requestHideFillUi(autofillId);
             client.fill(requestId, datasetIndex, dataset);
         };
 
diff --git a/services/core/Android.bp b/services/core/Android.bp
index cf85b1d..a95a0c2 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -97,7 +97,7 @@
         "android.hardware.power-V1.0-java",
         "android.hardware.tv.cec-V1.0-java",
         "android.hardware.vibrator-java",
-        "android.net.ipsec.ike.stubs.module_libs_api",
+        "android.net.ipsec.ike.stubs.module_lib",
         "app-compat-annotations",
         "framework-tethering-stubs-module_libs_api",
         "service-permission-stubs",
diff --git a/services/core/java/android/app/usage/UsageStatsManagerInternal.java b/services/core/java/android/app/usage/UsageStatsManagerInternal.java
index f688759..fa84427 100644
--- a/services/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/services/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -315,4 +315,15 @@
      * @return {@code true} if the pruning was successful, {@code false} otherwise
      */
     public abstract boolean pruneUninstalledPackagesData(@UserIdInt int userId);
+
+    /**
+     * Called by {@link com.android.server.usage.UsageStatsIdleService} between 24 to 48 hours of
+     * when the user is first unlocked to update the usage stats package mappings data that might
+     * be stale or have existed from a restore and belongs to packages that are not installed for
+     * this user anymore.
+     * Note: this is only executed for the system user.
+     *
+     * @return {@code true} if the updating was successful, {@code false} otherwise
+     */
+    public abstract boolean updatePackageMappingsData();
 }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 2c63c6f..7c61ba2 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2740,7 +2740,7 @@
                         // the Messenger, but if this ever changes, not making a defensive copy
                         // here will give attack vectors to clients using this code path.
                         networkCapabilities = new NetworkCapabilities(networkCapabilities);
-                        networkCapabilities.restrictCapabilitesForTestNetwork();
+                        networkCapabilities.restrictCapabilitesForTestNetwork(nai.creatorUid);
                     }
                     updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities);
                     break;
@@ -3087,30 +3087,7 @@
 
         @Override
         public void notifyDataStallSuspected(DataStallReportParcelable p) {
-            final Message msg = mConnectivityDiagnosticsHandler.obtainMessage(
-                    ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED,
-                    p.detectionMethod, mNetId, p.timestampMillis);
-
-            final PersistableBundle extras = new PersistableBundle();
-            switch (p.detectionMethod) {
-                case DETECTION_METHOD_DNS_EVENTS:
-                    extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, p.dnsConsecutiveTimeouts);
-                    break;
-                case DETECTION_METHOD_TCP_METRICS:
-                    extras.putInt(KEY_TCP_PACKET_FAIL_RATE, p.tcpPacketFailRate);
-                    extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS,
-                            p.tcpMetricsCollectionPeriodMillis);
-                    break;
-                default:
-                    log("Unknown data stall detection method, ignoring: " + p.detectionMethod);
-                    return;
-            }
-            msg.setData(new Bundle(extras));
-
-            // NetworkStateTrackerHandler currently doesn't take any actions based on data
-            // stalls so send the message directly to ConnectivityDiagnosticsHandler and avoid
-            // the cost of going through two handlers.
-            mConnectivityDiagnosticsHandler.sendMessage(msg);
+            ConnectivityService.this.notifyDataStallSuspected(p, mNetId);
         }
 
         @Override
@@ -3124,6 +3101,39 @@
         }
     }
 
+    private void notifyDataStallSuspected(DataStallReportParcelable p, int netId) {
+        final PersistableBundle extras = new PersistableBundle();
+        switch (p.detectionMethod) {
+            case DETECTION_METHOD_DNS_EVENTS:
+                extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, p.dnsConsecutiveTimeouts);
+                break;
+            case DETECTION_METHOD_TCP_METRICS:
+                extras.putInt(KEY_TCP_PACKET_FAIL_RATE, p.tcpPacketFailRate);
+                extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS,
+                        p.tcpMetricsCollectionPeriodMillis);
+                break;
+            default:
+                // TODO(b/156294356): update for new data stall detection methods
+                log("Unknown data stall detection method, ignoring: " + p.detectionMethod);
+                return;
+        }
+
+        notifyDataStallSuspected(p.detectionMethod, netId, p.timestampMillis, extras);
+    }
+
+    private void notifyDataStallSuspected(int detectionMethod, int netId, long timestampMillis,
+            @NonNull PersistableBundle extras) {
+        final Message msg = mConnectivityDiagnosticsHandler.obtainMessage(
+                ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, detectionMethod, netId,
+                timestampMillis);
+        msg.setData(new Bundle(extras));
+
+        // NetworkStateTrackerHandler currently doesn't take any actions based on data
+        // stalls so send the message directly to ConnectivityDiagnosticsHandler and avoid
+        // the cost of going through two handlers.
+        mConnectivityDiagnosticsHandler.sendMessage(msg);
+    }
+
     private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) {
         return isPrivateDnsValidationRequired(nai.networkCapabilities);
     }
@@ -5859,7 +5869,7 @@
             // the call to mixInCapabilities below anyway, but sanitizing here means the NAI never
             // sees capabilities that may be malicious, which might prevent mistakes in the future.
             networkCapabilities = new NetworkCapabilities(networkCapabilities);
-            networkCapabilities.restrictCapabilitesForTestNetwork();
+            networkCapabilities.restrictCapabilitesForTestNetwork(Binder.getCallingUid());
         } else {
             enforceNetworkFactoryPermission();
         }
@@ -5872,7 +5882,7 @@
         final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
                 new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
                 currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig),
-                this, mNetd, mDnsResolver, mNMS, providerId);
+                this, mNetd, mDnsResolver, mNMS, providerId, Binder.getCallingUid());
 
         // Make sure the LinkProperties and NetworkCapabilities reflect what the agent info says.
         nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc));
@@ -5973,7 +5983,8 @@
             // Start or stop DNS64 detection and 464xlat according to network state.
             networkAgent.clatd.update();
             notifyIfacesChangedForNetworkStats();
-            networkAgent.networkMonitor().notifyLinkPropertiesChanged(newLp);
+            networkAgent.networkMonitor().notifyLinkPropertiesChanged(
+                    new LinkProperties(newLp, true /* parcelSensitiveFields */));
             if (networkAgent.everConnected) {
                 notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
             }
@@ -7127,6 +7138,14 @@
             networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
 
             if (!createNativeNetwork(networkAgent)) return;
+            if (networkAgent.isVPN()) {
+                // Initialize the VPN capabilities to their starting values according to the
+                // underlying networks. This will avoid a spurious callback to
+                // onCapabilitiesUpdated being sent in updateAllVpnCapabilities below as
+                // the VPN would switch from its default, blank capabilities to those
+                // that reflect the capabilities of its underlying networks.
+                updateAllVpnsCapabilities();
+            }
             networkAgent.created = true;
         }
 
@@ -7153,7 +7172,9 @@
                 networkAgent.networkMonitor().setAcceptPartialConnectivity();
             }
             networkAgent.networkMonitor().notifyNetworkConnected(
-                    networkAgent.linkProperties, networkAgent.networkCapabilities);
+                    new LinkProperties(networkAgent.linkProperties,
+                            true /* parcelSensitiveFields */),
+                    networkAgent.networkCapabilities);
             scheduleUnvalidatedPrompt(networkAgent);
 
             // Whether a particular NetworkRequest listen should cause signal strength thresholds to
@@ -8151,4 +8172,23 @@
                         0,
                         callback));
     }
+
+    @Override
+    public void simulateDataStall(int detectionMethod, long timestampMillis,
+            @NonNull Network network, @NonNull PersistableBundle extras) {
+        enforceAnyPermissionOf(android.Manifest.permission.MANAGE_TEST_NETWORKS,
+                android.Manifest.permission.NETWORK_STACK);
+        final NetworkCapabilities nc = getNetworkCapabilitiesInternal(network);
+        if (!nc.hasTransport(TRANSPORT_TEST)) {
+            throw new SecurityException("Data Stall simluation is only possible for test networks");
+        }
+
+        final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
+        if (nai == null || nai.creatorUid != Binder.getCallingUid()) {
+            throw new SecurityException("Data Stall simulation is only possible for network "
+                + "creators");
+        }
+
+        notifyDataStallSuspected(detectionMethod, network.netId, timestampMillis, extras);
+    }
 }
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 905c489..6402e07 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -1776,7 +1776,7 @@
             socketRecord =
                     userRecord.mEncapSocketRecords.getResourceOrThrow(c.getEncapSocketResourceId());
         }
-        SpiRecord spiRecord = userRecord.mSpiRecords.getResourceOrThrow(c.getSpiResourceId());
+        SpiRecord spiRecord = transformInfo.getSpiRecord();
 
         int mark =
                 (direction == IpSecManager.DIRECTION_OUT)
@@ -1809,7 +1809,7 @@
 
                 // Set outbound SPI only. We want inbound to use any valid SA (old, new) on rekeys,
                 // but want to guarantee outbound packets are sent over the new SA.
-                spi = transformInfo.getSpiRecord().getSpi();
+                spi = spiRecord.getSpi();
             }
 
             // Always update the policy with the relevant XFRM_IF_ID
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index be53945..ee0f71b 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -42,8 +42,8 @@
 import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED;
 import static android.os.storage.OnObbStateChangeListener.MOUNTED;
 import static android.os.storage.OnObbStateChangeListener.UNMOUNTED;
+import static android.os.storage.StorageManager.PROP_FORCED_SCOPED_STORAGE_WHITELIST;
 import static android.os.storage.StorageManager.PROP_FUSE;
-import static android.os.storage.StorageManager.PROP_LEGACY_OP_STICKY;
 import static android.os.storage.StorageManager.PROP_SETTINGS_FUSE;
 
 import static com.android.internal.util.XmlUtils.readIntAttribute;
@@ -121,6 +121,7 @@
 import android.os.storage.VolumeInfo;
 import android.os.storage.VolumeRecord;
 import android.provider.DeviceConfig;
+import android.provider.DocumentsContract;
 import android.provider.Downloads;
 import android.provider.MediaStore;
 import android.provider.Settings;
@@ -432,6 +433,8 @@
 
     private volatile int mDownloadsAuthorityAppId = -1;
 
+    private volatile int mExternalStorageAuthorityAppId = -1;
+
     private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
 
     private final Installer mInstaller;
@@ -911,7 +914,6 @@
                     refreshIsolatedStorageSettings();
                 }
             });
-        updateLegacyStorageOpSticky();
         // For now, simply clone property when it changes
         DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
                 mContext.getMainExecutor(), (properties) -> {
@@ -1833,13 +1835,6 @@
         }
     }
 
-    private void updateLegacyStorageOpSticky() {
-        final boolean propertyValue = DeviceConfig.getBoolean(
-                DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
-                "legacy_storage_op_sticky", true);
-        SystemProperties.set(PROP_LEGACY_OP_STICKY, propertyValue ? "true" : "false");
-    }
-
     private void start() {
         connectStoraged();
         connectVold();
@@ -1923,29 +1918,37 @@
         mIAppOpsService = IAppOpsService.Stub.asInterface(
                 ServiceManager.getService(Context.APP_OPS_SERVICE));
 
-        ProviderInfo provider = mPmInternal.resolveContentProvider(
-                MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
-                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                UserHandle.getUserId(UserHandle.USER_SYSTEM));
+        ProviderInfo provider = getProviderInfo(MediaStore.AUTHORITY);
         if (provider != null) {
             mMediaStoreAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
             sMediaStoreAuthorityProcessName = provider.applicationInfo.processName;
         }
 
-        provider = mPmInternal.resolveContentProvider(
-                Downloads.Impl.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
-                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                UserHandle.getUserId(UserHandle.USER_SYSTEM));
-
+        provider = getProviderInfo(Downloads.Impl.AUTHORITY);
         if (provider != null) {
             mDownloadsAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
         }
 
-        try {
-            mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
-            mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback);
-        } catch (RemoteException e) {
+        provider = getProviderInfo(DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY);
+        if (provider != null) {
+            mExternalStorageAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
         }
+
+        if (!mIsFuseEnabled) {
+            try {
+                mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null,
+                        mAppOpsCallback);
+                mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    private ProviderInfo getProviderInfo(String authority) {
+        return mPmInternal.resolveContentProvider(
+                authority, PackageManager.MATCH_DIRECT_BOOT_AWARE
+                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                UserHandle.getUserId(UserHandle.USER_SYSTEM));
     }
 
     private void updateLegacyStorageApps(String packageName, int uid, boolean hasLegacy) {
@@ -4188,9 +4191,11 @@
                 return Zygote.MOUNT_EXTERNAL_PASS_THROUGH;
             }
 
-            if (mIsFuseEnabled && mDownloadsAuthorityAppId == UserHandle.getAppId(uid)) {
+            if (mIsFuseEnabled && (mDownloadsAuthorityAppId == UserHandle.getAppId(uid)
+                    || mExternalStorageAuthorityAppId == UserHandle.getAppId(uid))) {
                 // DownloadManager can write in app-private directories on behalf of apps;
                 // give it write access to Android/
+                // ExternalStorageProvider can access Android/{data,obb} dirs in managed mode
                 return Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE;
             }
 
@@ -4429,6 +4434,9 @@
             pw.println("Isolated storage, remote feature flag: "
                     + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_REMOTE, 0));
             pw.println("Isolated storage, resolved: " + StorageManager.hasIsolatedStorage());
+            pw.println("Forced scoped storage app list: "
+                    + DeviceConfig.getProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+                    PROP_FORCED_SCOPED_STORAGE_WHITELIST));
         }
 
         synchronized (mObbMounts) {
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index 0ea7346..d6bd5a1 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -317,39 +317,34 @@
                     "Cannot create network for non ipsec, non-testtun interface");
         }
 
-        // Setup needs to be done with NETWORK_STACK privileges.
-        int callingUid = Binder.getCallingUid();
-        Binder.withCleanCallingIdentity(
-                () -> {
-                    try {
-                        mNMS.setInterfaceUp(iface);
+        try {
+            // This requires NETWORK_STACK privileges.
+            Binder.withCleanCallingIdentity(() -> mNMS.setInterfaceUp(iface));
 
-                        // Synchronize all accesses to mTestNetworkTracker to prevent the case
-                        // where:
-                        // 1. TestNetworkAgent successfully binds to death of binder
-                        // 2. Before it is added to the mTestNetworkTracker, binder dies,
-                        // binderDied() is called (on a different thread)
-                        // 3. This thread is pre-empted, put() is called after remove()
-                        synchronized (mTestNetworkTracker) {
-                            TestNetworkAgent agent =
-                                    registerTestNetworkAgent(
-                                            mHandler.getLooper(),
-                                            mContext,
-                                            iface,
-                                            lp,
-                                            isMetered,
-                                            callingUid,
-                                            administratorUids,
-                                            binder);
+            // Synchronize all accesses to mTestNetworkTracker to prevent the case where:
+            // 1. TestNetworkAgent successfully binds to death of binder
+            // 2. Before it is added to the mTestNetworkTracker, binder dies, binderDied() is called
+            // (on a different thread)
+            // 3. This thread is pre-empted, put() is called after remove()
+            synchronized (mTestNetworkTracker) {
+                TestNetworkAgent agent =
+                        registerTestNetworkAgent(
+                                mHandler.getLooper(),
+                                mContext,
+                                iface,
+                                lp,
+                                isMetered,
+                                Binder.getCallingUid(),
+                                administratorUids,
+                                binder);
 
-                            mTestNetworkTracker.put(agent.getNetwork().netId, agent);
-                        }
-                    } catch (SocketException e) {
-                        throw new UncheckedIOException(e);
-                    } catch (RemoteException e) {
-                        throw e.rethrowFromSystemServer();
-                    }
-                });
+                mTestNetworkTracker.put(agent.getNetwork().netId, agent);
+            }
+        } catch (SocketException e) {
+            throw new UncheckedIOException(e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /** Teardown a test network */
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index f42e32d..35936ba 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -337,6 +337,8 @@
                 mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
                 mWindowManager = LocalServices.getService(WindowManagerInternal.class);
                 mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
+                TwilightManager twilightManager = getLocalService(TwilightManager.class);
+                if (twilightManager != null) mTwilightManager = twilightManager;
                 mLocalPowerManager =
                         LocalServices.getService(PowerManagerInternal.class);
                 initPowerSave();
@@ -381,7 +383,6 @@
                 com.android.internal.R.bool.config_enableCarDockHomeLaunch);
         mUiModeLocked = res.getBoolean(com.android.internal.R.bool.config_lockUiMode);
         mNightModeLocked = res.getBoolean(com.android.internal.R.bool.config_lockDayNightMode);
-        mTwilightManager = getLocalService(TwilightManager.class);
         final PackageManager pm = context.getPackageManager();
         mTelevision = pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
                 || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
@@ -391,6 +392,8 @@
         // Update the initial, static configurations.
         SystemServerInitThreadPool.submit(() -> {
             synchronized (mLock) {
+                TwilightManager twilightManager = getLocalService(TwilightManager.class);
+                if (twilightManager != null) mTwilightManager = twilightManager;
                 updateNightModeFromSettingsLocked(context, res, UserHandle.getCallingUserId());
                 updateSystemProperties();
             }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d914bda..671733b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -299,6 +299,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
+import android.util.SparseLongArray;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 import android.util.proto.ProtoUtils;
@@ -822,6 +823,46 @@
     }
 
     /**
+     * While starting activity, WindowManager posts a runnable to DisplayThread to updateOomAdj.
+     * The latency of the thread switch could cause client app failure when the app is checking
+     * {@link #isUidActive} before updateOomAdj is done.
+     *
+     * Use PendingStartActivityUids to save uid after WindowManager start activity and before
+     * updateOomAdj is done.
+     *
+     * <p>NOTE: This object is protected by its own lock, NOT the global activity manager lock!
+     */
+    final PendingStartActivityUids mPendingStartActivityUidsLocked = new PendingStartActivityUids();
+    final class PendingStartActivityUids {
+        // Key is uid, value is SystemClock.elapsedRealtime() when the key is added.
+        private final SparseLongArray mPendingUids = new SparseLongArray();
+
+        void add(int uid) {
+            if (mPendingUids.indexOfKey(uid) < 0) {
+                mPendingUids.put(uid, SystemClock.elapsedRealtime());
+            }
+        }
+
+        void delete(int uid) {
+            if (mPendingUids.indexOfKey(uid) >= 0) {
+                long delay = SystemClock.elapsedRealtime() - mPendingUids.get(uid);
+                if (delay >= 1000) {
+                    Slog.wtf(TAG,
+                            "PendingStartActivityUids startActivity to updateOomAdj delay:"
+                            + delay + "ms,"
+                            + " uid:" + uid
+                            + " packageName:" + Settings.getPackageNameForUid(mContext, uid));
+                }
+                mPendingUids.delete(uid);
+            }
+        }
+
+        boolean isPendingTopUid(int uid) {
+            return mPendingUids.indexOfKey(uid) >= 0;
+        }
+    }
+
+    /**
      * Puts the process record in the map.
      * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
      * method.
@@ -2098,6 +2139,7 @@
             }
             ServiceManager.addService("permission", new PermissionController(this));
             ServiceManager.addService("processinfo", new ProcessInfoService(this));
+            ServiceManager.addService("cacheinfo", new CacheBinder(this));
 
             ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
                     "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
@@ -2191,16 +2233,18 @@
 
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
-                Process.enableFreezer(false);
-            }
+            try {
+                if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
+                    Process.enableFreezer(false);
+                }
 
-            if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
-                    "meminfo", pw)) return;
-            PriorityDump.dump(mPriorityDumper, fd, pw, args);
-
-            if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
-                Process.enableFreezer(true);
+                if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
+                        "meminfo", pw)) return;
+                PriorityDump.dump(mPriorityDumper, fd, pw, args);
+            } finally {
+                if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
+                    Process.enableFreezer(true);
+                }
             }
         }
     }
@@ -2213,16 +2257,18 @@
 
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
-                Process.enableFreezer(false);
-            }
+            try {
+                if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
+                    Process.enableFreezer(false);
+                }
 
-            if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
-                    "gfxinfo", pw)) return;
-            mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
-
-            if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
-                Process.enableFreezer(true);
+                if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
+                        "gfxinfo", pw)) return;
+                mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
+            } finally {
+                if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
+                    Process.enableFreezer(true);
+                }
             }
         }
     }
@@ -2235,16 +2281,18 @@
 
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
-                Process.enableFreezer(false);
-            }
+            try {
+                if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
+                    Process.enableFreezer(false);
+                }
 
-            if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
-                    "dbinfo", pw)) return;
-            mActivityManagerService.dumpDbInfo(fd, pw, args);
-
-            if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
-                Process.enableFreezer(true);
+                if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
+                        "dbinfo", pw)) return;
+                mActivityManagerService.dumpDbInfo(fd, pw, args);
+            } finally {
+                if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
+                    Process.enableFreezer(true);
+                }
             }
         }
     }
@@ -2280,6 +2328,34 @@
         }
     }
 
+    static class CacheBinder extends Binder {
+        ActivityManagerService mActivityManagerService;
+
+        CacheBinder(ActivityManagerService activityManagerService) {
+            mActivityManagerService = activityManagerService;
+        }
+
+        @Override
+        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            try {
+                if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
+                    Process.enableFreezer(false);
+                }
+
+                if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
+                        "cacheinfo", pw)) {
+                    return;
+                }
+
+                mActivityManagerService.dumpBinderCacheContents(fd, pw, args);
+            } finally {
+                if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
+                    Process.enableFreezer(true);
+                }
+            }
+        }
+    }
+
     public static final class Lifecycle extends SystemService {
         private final ActivityManagerService mService;
         private static ActivityTaskManagerService sAtm;
@@ -8756,7 +8832,18 @@
                     "isUidActive");
         }
         synchronized (this) {
-            return isUidActiveLocked(uid);
+            if (isUidActiveLocked(uid)) {
+                return true;
+            }
+        }
+
+        if (mInternal.isPendingTopUid(uid)) {
+            Slog.wtf(TAG, "PendingStartActivityUids isUidActive false but"
+                    + " isPendingTopUid true, uid:" + uid
+                    + " callingPackage:" + callingPackage);
+            return true;
+        } else {
+            return false;
         }
     }
 
@@ -11083,18 +11170,22 @@
 
     void dumpLruEntryLocked(PrintWriter pw, int index, ProcessRecord proc, String prefix) {
         pw.print(prefix);
-        pw.print("#");
+        pw.print('#');
+        if (index < 10) {
+            pw.print(' ');
+        }
         pw.print(index);
         pw.print(": ");
         pw.print(ProcessList.makeOomAdjString(proc.setAdj, false));
-        pw.print(" ");
+        pw.print(' ');
         pw.print(ProcessList.makeProcStateString(proc.getCurProcState()));
-        pw.print(" ");
+        pw.print(' ');
+        ActivityManager.printCapabilitiesSummary(pw, proc.curCapability);
+        pw.print(' ');
         pw.print(proc.toShortString());
-        pw.print(" ");
         if (proc.hasActivitiesOrRecentTasks() || proc.hasClientActivities()
                 || proc.treatLikeActivity) {
-            pw.print(" activity=");
+            pw.print(" act:");
             boolean printed = false;
             if (proc.hasActivities()) {
                 pw.print("activities");
@@ -12559,7 +12650,7 @@
             char schedGroup;
             switch (r.setSchedGroup) {
                 case ProcessList.SCHED_GROUP_BACKGROUND:
-                    schedGroup = 'B';
+                    schedGroup = 'b';
                     break;
                 case ProcessList.SCHED_GROUP_DEFAULT:
                     schedGroup = 'F';
@@ -12570,6 +12661,9 @@
                 case ProcessList.SCHED_GROUP_RESTRICTED:
                     schedGroup = 'R';
                     break;
+                case ProcessList.SCHED_GROUP_TOP_APP_BOUND:
+                    schedGroup = 'B';
+                    break;
                 default:
                     schedGroup = '?';
                     break;
@@ -12597,7 +12691,10 @@
             pw.print(foreground);
             pw.print('/');
             pw.print(procState);
-            pw.print(" trm:");
+            pw.print(' ');
+            ActivityManager.printCapabilitiesSummary(pw, r.curCapability);
+            pw.print(' ');
+            pw.print(" t:");
             if (r.trimMemoryLevel < 10) pw.print(' ');
             pw.print(r.trimMemoryLevel);
             pw.print(' ');
@@ -12712,6 +12809,39 @@
         }
     }
 
+    final void dumpBinderCacheContents(FileDescriptor fd, PrintWriter pw, String[] args) {
+        ArrayList<ProcessRecord> procs = collectProcesses(pw, 0, false, args);
+        if (procs == null) {
+            pw.println("No process found for: " + args[0]);
+            return;
+        }
+
+        pw.println("Per-process Binder Cache Contents");
+
+        for (int i = procs.size() - 1; i >= 0; i--) {
+            ProcessRecord r = procs.get(i);
+            if (r.thread != null) {
+                pw.println("\n\n** Cache info for pid " + r.pid + " [" + r.processName + "] **");
+                pw.flush();
+                try {
+                    TransferPipe tp = new TransferPipe();
+                    try {
+                        r.thread.dumpCacheInfo(tp.getWriteFd(), args);
+                        tp.go(fd);
+                    } finally {
+                        tp.kill();
+                    }
+                } catch (IOException e) {
+                    pw.println("Failure while dumping the app " + r);
+                    pw.flush();
+                } catch (RemoteException e) {
+                    pw.println("Got a RemoteException while dumping the app " + r);
+                    pw.flush();
+                }
+            }
+        }
+    }
+
     final void dumpDbInfo(FileDescriptor fd, PrintWriter pw, String[] args) {
         ArrayList<ProcessRecord> procs = collectProcesses(pw, 0, false, args);
         if (procs == null) {
@@ -13597,7 +13727,9 @@
                         pw.print(" unmapped + ");
                         pw.print(stringifyKBSize(ionPool));
                         pw.println(" pools)");
-                kernelUsed += ionUnmapped;
+                // Note: mapped ION memory is not accounted in PSS due to VM_PFNMAP flag being
+                // set on ION VMAs, therefore consider the entire ION heap as used kernel memory
+                kernelUsed += ionHeap;
             }
             final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
                     - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
@@ -14403,7 +14535,9 @@
             memInfoBuilder.append("       ION: ");
             memInfoBuilder.append(stringifyKBSize(ionHeap + ionPool));
             memInfoBuilder.append("\n");
-            kernelUsed += ionUnmapped;
+            // Note: mapped ION memory is not accounted in PSS due to VM_PFNMAP flag being
+            // set on ION VMAs, therefore consider the entire ION heap as used kernel memory
+            kernelUsed += ionHeap;
         }
         memInfoBuilder.append("  Used RAM: ");
         memInfoBuilder.append(stringifyKBSize(
@@ -19600,6 +19734,25 @@
                 return uid >= 0 && mDeviceOwnerUid == uid;
             }
         }
+
+        @Override
+        public void updatePendingTopUid(int uid, boolean pending) {
+            synchronized (mPendingStartActivityUidsLocked) {
+                if (pending) {
+                    mPendingStartActivityUidsLocked.add(uid);
+                } else {
+                    mPendingStartActivityUidsLocked.delete(uid);
+                }
+            }
+
+        }
+
+        @Override
+        public boolean isPendingTopUid(int uid) {
+            synchronized (mPendingStartActivityUidsLocked) {
+                return mPendingStartActivityUidsLocked.isPendingTopUid(uid);
+            }
+        }
     }
 
     long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index f9d204f..43e3a04 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -45,6 +45,7 @@
 
 import java.io.FileOutputStream;
 import java.io.FileReader;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -114,6 +115,14 @@
     }
     private PropertyChangedCallbackForTest mTestCallback;
 
+    // This interface is for functions related to the Process object that need a different
+    // implementation in the tests as we are not creating real processes when testing compaction.
+    @VisibleForTesting
+    interface ProcessDependencies {
+        long[] getRss(int pid);
+        void performCompaction(String action, int pid) throws IOException;
+    }
+
     // Handler constants.
     static final int COMPACT_PROCESS_SOME = 1;
     static final int COMPACT_PROCESS_FULL = 2;
@@ -215,13 +224,16 @@
     @VisibleForTesting final Set<Integer> mProcStateThrottle;
 
     // Handler on which compaction runs.
-    private Handler mCompactionHandler;
+    @VisibleForTesting
+    Handler mCompactionHandler;
     private Handler mFreezeHandler;
 
     // Maps process ID to last compaction statistics for processes that we've fully compacted. Used
     // when evaluating throttles that we only consider for "full" compaction, so we don't store
-    // data for "some" compactions.
-    private Map<Integer, LastCompactionStats> mLastCompactionStats =
+    // data for "some" compactions. Uses LinkedHashMap to ensure insertion order is kept and
+    // facilitate removal of the oldest entry.
+    @VisibleForTesting
+    LinkedHashMap<Integer, LastCompactionStats> mLastCompactionStats =
             new LinkedHashMap<Integer, LastCompactionStats>() {
                 @Override
                 protected boolean removeEldestEntry(Map.Entry eldest) {
@@ -233,17 +245,20 @@
     private int mFullCompactionCount;
     private int mPersistentCompactionCount;
     private int mBfgsCompactionCount;
+    private final ProcessDependencies mProcessDependencies;
 
     public CachedAppOptimizer(ActivityManagerService am) {
-        mAm = am;
-        mCachedAppOptimizerThread = new ServiceThread("CachedAppOptimizerThread",
-                THREAD_PRIORITY_FOREGROUND, true);
-        mProcStateThrottle = new HashSet<>();
+        this(am, null, new DefaultProcessDependencies());
     }
 
     @VisibleForTesting
-    CachedAppOptimizer(ActivityManagerService am, PropertyChangedCallbackForTest callback) {
-        this(am);
+    CachedAppOptimizer(ActivityManagerService am, PropertyChangedCallbackForTest callback,
+            ProcessDependencies processDependencies) {
+        mAm = am;
+        mCachedAppOptimizerThread = new ServiceThread("CachedAppOptimizerThread",
+            THREAD_PRIORITY_FOREGROUND, true);
+        mProcStateThrottle = new HashSet<>();
+        mProcessDependencies = processDependencies;
         mTestCallback = callback;
     }
 
@@ -659,7 +674,8 @@
         }
     }
 
-    private static final class LastCompactionStats {
+    @VisibleForTesting
+    static final class LastCompactionStats {
         private final long[] mRssAfterCompaction;
 
         LastCompactionStats(long[] rss) {
@@ -712,9 +728,7 @@
 
                         lastCompactAction = proc.lastCompactAction;
                         lastCompactTime = proc.lastCompactTime;
-                        // remove rather than get so that insertion order will be updated when we
-                        // put the post-compaction stats back into the map.
-                        lastCompactionStats = mLastCompactionStats.remove(pid);
+                        lastCompactionStats = mLastCompactionStats.get(pid);
                     }
 
                     if (pid == 0) {
@@ -806,7 +820,7 @@
                         return;
                     }
 
-                    long[] rssBefore = Process.getRss(pid);
+                    long[] rssBefore = mProcessDependencies.getRss(pid);
                     long anonRssBefore = rssBefore[2];
 
                     if (rssBefore[0] == 0 && rssBefore[1] == 0 && rssBefore[2] == 0
@@ -863,16 +877,13 @@
                         default:
                             break;
                     }
-
                     try {
                         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Compact "
                                 + ((pendingAction == COMPACT_PROCESS_SOME) ? "some" : "full")
                                 + ": " + name);
                         long zramFreeKbBefore = Debug.getZramFreeKb();
-                        FileOutputStream fos = new FileOutputStream("/proc/" + pid + "/reclaim");
-                        fos.write(action.getBytes());
-                        fos.close();
-                        long[] rssAfter = Process.getRss(pid);
+                        mProcessDependencies.performCompaction(action, pid);
+                        long[] rssAfter = mProcessDependencies.getRss(pid);
                         long end = SystemClock.uptimeMillis();
                         long time = end - start;
                         long zramFreeKbAfter = Debug.getZramFreeKb();
@@ -882,7 +893,6 @@
                                 rssAfter[2] - rssBefore[2], rssAfter[3] - rssBefore[3], time,
                                 lastCompactAction, lastCompactTime, lastOomAdj, procState,
                                 zramFreeKbBefore, zramFreeKbAfter - zramFreeKbBefore);
-
                         // Note that as above not taking mPhenoTypeFlagLock here to avoid locking
                         // on every single compaction for a flag that will seldom change and the
                         // impact of reading the wrong value here is low.
@@ -894,14 +904,14 @@
                                     lastOomAdj, ActivityManager.processStateAmToProto(procState),
                                     zramFreeKbBefore, zramFreeKbAfter);
                         }
-
                         synchronized (mAm) {
                             proc.lastCompactTime = end;
                             proc.lastCompactAction = pendingAction;
                         }
-
                         if (action.equals(COMPACT_ACTION_FULL)
                                 || action.equals(COMPACT_ACTION_ANON)) {
+                            // Remove entry and insert again to update insertion order.
+                            mLastCompactionStats.remove(pid);
                             mLastCompactionStats.put(pid, new LastCompactionStats(rssAfter));
                         }
                     } catch (Exception e) {
@@ -1018,4 +1028,23 @@
             }
         }
     }
+
+    /**
+     * Default implementation for ProcessDependencies, public vor visibility to OomAdjuster class.
+     */
+    private static final class DefaultProcessDependencies implements ProcessDependencies {
+        // Get memory RSS from process.
+        @Override
+        public long[] getRss(int pid) {
+            return Process.getRss(pid);
+        }
+
+        // Compact process.
+        @Override
+        public void performCompaction(String action, int pid) throws IOException {
+            try (FileOutputStream fos = new FileOutputStream("/proc/" + pid + "/reclaim")) {
+                fos.write(action.getBytes());
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
deleted file mode 100644
index 0e34801..0000000
--- a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
+++ /dev/null
@@ -1,193 +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.server.am;
-
-import android.content.Context;
-import android.content.pm.UserInfo;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.WindowInsets;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.internal.R;
-
-
-/**
- * Dialog to show when a user switch it about to happen for the car. The intent is to snapshot the
- * screen immediately after the dialog shows so that the user is informed that something is
- * happening in the background rather than just freeze the screen and not know if the user-switch
- * affordance was being handled.
- */
-final class CarUserSwitchingDialog extends UserSwitchingDialog {
-
-    private static final String TAG = "ActivityManagerCarUserSwitchingDialog";
-    private View mView;
-
-    public CarUserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser,
-            UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
-            String switchingToSystemUserMessage) {
-        super(service, context, oldUser, newUser, aboveSystem, switchingFromSystemUserMessage,
-                switchingToSystemUserMessage);
-    }
-
-    @Override
-    void inflateContent() {
-        // Set up the dialog contents
-        setCancelable(false);
-        Resources res = getContext().getResources();
-        // Custom view due to alignment and font size requirements
-        getContext().setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert_UserSwitchingDialog);
-        mView = LayoutInflater.from(getContext()).inflate(
-                R.layout.car_user_switching_dialog,
-                null);
-
-        UserManager userManager =
-                (UserManager) getContext().getSystemService(Context.USER_SERVICE);
-        Bitmap bitmap = userManager.getUserIcon(mNewUser.id);
-        if (bitmap != null) {
-            CircleFramedDrawable drawable = CircleFramedDrawable.getInstance(bitmap,
-                    res.getDimension(R.dimen.car_fullscreen_user_pod_image_avatar_height));
-            ((ImageView) mView.findViewById(R.id.user_loading_avatar))
-                    .setImageDrawable(drawable);
-        }
-
-        TextView msgView = mView.findViewById(R.id.user_loading);
-
-        // TODO(b/145132885): use constant from CarSettings
-        boolean showInfo = "true".equals(Settings.Global.getString(
-                getContext().getContentResolver(),
-                "android.car.ENABLE_USER_SWITCH_DEVELOPER_MESSAGE"));
-
-        if (showInfo) {
-            msgView.setText(res.getString(R.string.car_loading_profile) + " user\n(from "
-                    + mOldUser.id + " to " + mNewUser.id + ")");
-        } else {
-            msgView.setText(res.getString(R.string.car_loading_profile));
-        }
-        setView(mView);
-    }
-
-    @Override
-    public void show() {
-        super.show();
-        hideNavigationBar();
-    }
-
-    private void hideNavigationBar() {
-        mView.getWindowInsetsController().hide(WindowInsets.Type.navigationBars());
-    }
-
-    /**
-     * Converts the user icon to a circularly clipped one.  This is used in the User Picker and
-     * Settings.
-     */
-    static class CircleFramedDrawable extends Drawable {
-
-        private final Bitmap mBitmap;
-        private final int mSize;
-        private final Paint mPaint;
-
-        private float mScale;
-        private Rect mSrcRect;
-        private RectF mDstRect;
-
-        public static CircleFramedDrawable getInstance(Bitmap icon, float iconSize) {
-            CircleFramedDrawable instance = new CircleFramedDrawable(icon, (int) iconSize);
-            return instance;
-        }
-
-        public CircleFramedDrawable(Bitmap icon, int size) {
-            super();
-            mSize = size;
-
-            mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888);
-            final Canvas canvas = new Canvas(mBitmap);
-
-            final int width = icon.getWidth();
-            final int height = icon.getHeight();
-            final int square = Math.min(width, height);
-
-            final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2,
-                    square, square);
-            final RectF circleRect = new RectF(0f, 0f, mSize, mSize);
-
-            final Path fillPath = new Path();
-            fillPath.addArc(circleRect, 0f, 360f);
-
-            canvas.drawColor(0, PorterDuff.Mode.CLEAR);
-
-            // opaque circle
-            mPaint = new Paint();
-            mPaint.setAntiAlias(true);
-            mPaint.setColor(Color.BLACK);
-            mPaint.setStyle(Paint.Style.FILL);
-            canvas.drawPath(fillPath, mPaint);
-
-            // mask in the icon where the bitmap is opaque
-            mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
-            canvas.drawBitmap(icon, cropRect, circleRect, mPaint);
-
-            // prepare paint for frame drawing
-            mPaint.setXfermode(null);
-
-            mScale = 1f;
-
-            mSrcRect = new Rect(0, 0, mSize, mSize);
-            mDstRect = new RectF(0, 0, mSize, mSize);
-        }
-
-        @Override
-        public void draw(Canvas canvas) {
-            final float inside = mScale * mSize;
-            final float pad = (mSize - inside) / 2f;
-
-            mDstRect.set(pad, pad, mSize - pad, mSize - pad);
-            canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null);
-        }
-
-        @Override
-        public int getOpacity() {
-            return PixelFormat.TRANSLUCENT;
-        }
-
-        @Override
-        public void setAlpha(int alpha) {
-            // Needed to implement abstract method.  Do nothing.
-        }
-
-        @Override
-        public void setColorFilter(ColorFilter colorFilter) {
-            // Needed to implement abstract method.  Do nothing.
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index ad85853..f7a158a 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -151,15 +151,6 @@
     @EnabledAfter(targetSdkVersion=android.os.Build.VERSION_CODES.Q)
     static final long CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID = 136219221L;
 
-    // TODO: remove this when development is done.
-    // These are debug flags used between OomAdjuster and AppOpsService to detect and report absence
-    // of the real flags.
-    public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q = 1 << 27;
-    public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q = 1 << 28;
-    public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 29;
-    public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA = 1 << 30;
-    public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 31;
-
     /**
      * For some direct access we need to power manager.
      */
@@ -947,6 +938,7 @@
                     mService.mServices.foregroundServiceProcStateChangedLocked(uidRec);
                 }
             }
+            mService.mInternal.updatePendingTopUid(uidRec.uid, false);
         }
         if (mLocalPowerManager != null) {
             mLocalPowerManager.finishUidChanges();
@@ -1506,8 +1498,9 @@
                     //lost the capability, use temp location capability to mark this case.
                     //TODO: remove this block when development is done.
                     capabilityFromFGS |=
-                            (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
-                                    != 0 ? DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
+                            (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION) != 0
+                                    ? ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION
+                                    : 0;
                 }
                 if (s.mAllowWhileInUsePermissionInFgs) {
                     boolean enabled = false;
@@ -1520,22 +1513,22 @@
                         capabilityFromFGS |=
                                 (fgsType & FOREGROUND_SERVICE_TYPE_CAMERA)
                                         != 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA
-                                        : DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA;
+                                        : ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA;
                         capabilityFromFGS |=
                                 (fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE)
                                         != 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
-                                        : DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+                                        : ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
                     } else {
                         // Remove fgsType check and assign PROCESS_CAPABILITY_FOREGROUND_CAMERA
                         // and MICROPHONE when finish debugging.
                         capabilityFromFGS |=
                                 (fgsType & FOREGROUND_SERVICE_TYPE_CAMERA)
                                         != 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA
-                                        : DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q;
+                                        : ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q;
                         capabilityFromFGS |=
                                 (fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE)
                                         != 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
-                                        : DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q;
+                                        : ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q;
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index b753de9..108fb7d 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -972,7 +972,7 @@
             return buildOomTag("vis", "vis", "   ", setAdj,
                     ProcessList.VISIBLE_APP_ADJ, compact);
         } else if (setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
-            return buildOomTag("fore  ", "fore", null, setAdj,
+            return buildOomTag("fg ", "fg ", "   ", setAdj,
                     ProcessList.FOREGROUND_APP_ADJ, compact);
         } else if (setAdj >= ProcessList.PERSISTENT_SERVICE_ADJ) {
             return buildOomTag("psvc  ", "psvc", null, setAdj,
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index fc6931d..c5152c0 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -431,16 +431,46 @@
                 pw.print(" nextPssTime=");
                 TimeUtils.formatDuration(nextPssTime, nowUptime, pw);
                 pw.println();
-        pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq);
-                pw.print(" lruSeq="); pw.print(lruSeq);
-                pw.print(" lastPss="); DebugUtils.printSizeValue(pw, lastPss*1024);
-                pw.print(" lastSwapPss="); DebugUtils.printSizeValue(pw, lastSwapPss*1024);
-                pw.print(" lastCachedPss="); DebugUtils.printSizeValue(pw, lastCachedPss*1024);
-                pw.print(" lastCachedSwapPss="); DebugUtils.printSizeValue(pw, lastCachedSwapPss*1024);
-        pw.print(" lastRss="); DebugUtils.printSizeValue(pw, mLastRss * 1024);
+        pw.print(prefix); pw.print("lastPss="); DebugUtils.printSizeValue(pw, lastPss * 1024);
+                pw.print(" lastSwapPss="); DebugUtils.printSizeValue(pw, lastSwapPss * 1024);
+                pw.print(" lastCachedPss="); DebugUtils.printSizeValue(pw, lastCachedPss * 1024);
+                pw.print(" lastCachedSwapPss="); DebugUtils.printSizeValue(pw,
+                        lastCachedSwapPss * 1024);
+                pw.print(" lastRss="); DebugUtils.printSizeValue(pw, mLastRss * 1024);
                 pw.println();
         pw.print(prefix); pw.print("procStateMemTracker: ");
         procStateMemTracker.dumpLine(pw);
+        pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq);
+                pw.print(" lruSeq="); pw.println(lruSeq);
+        pw.print(prefix); pw.print("oom adj: max="); pw.print(maxAdj);
+                pw.print(" curRaw="); pw.print(mCurRawAdj);
+                pw.print(" setRaw="); pw.print(setRawAdj);
+                pw.print(" cur="); pw.print(curAdj);
+                pw.print(" set="); pw.println(setAdj);
+        pw.print(prefix); pw.print("lastCompactTime="); pw.print(lastCompactTime);
+                pw.print(" lastCompactAction="); pw.println(lastCompactAction);
+        pw.print(prefix); pw.print("mCurSchedGroup="); pw.print(mCurSchedGroup);
+                pw.print(" setSchedGroup="); pw.print(setSchedGroup);
+                pw.print(" systemNoUi="); pw.print(systemNoUi);
+                pw.print(" trimMemoryLevel="); pw.println(trimMemoryLevel);
+        pw.print(prefix); pw.print("curProcState="); pw.print(getCurProcState());
+                pw.print(" mRepProcState="); pw.print(mRepProcState);
+                pw.print(" pssProcState="); pw.print(pssProcState);
+                pw.print(" setProcState="); pw.print(setProcState);
+                pw.print(" lastStateTime=");
+                TimeUtils.formatDuration(lastStateTime, nowUptime, pw);
+                pw.println();
+        pw.print(prefix); pw.print("curCapability=");
+                ActivityManager.printCapabilitiesFull(pw, curCapability);
+                pw.print(" setCapability=");
+                ActivityManager.printCapabilitiesFull(pw, setCapability);
+                pw.println();
+        if (hasShownUi || mPendingUiClean || hasAboveClient || treatLikeActivity) {
+            pw.print(prefix); pw.print("hasShownUi="); pw.print(hasShownUi);
+                    pw.print(" pendingUiClean="); pw.print(mPendingUiClean);
+                    pw.print(" hasAboveClient="); pw.print(hasAboveClient);
+                    pw.print(" treatLikeActivity="); pw.println(treatLikeActivity);
+        }
         pw.print(prefix); pw.print("cached="); pw.print(mCached);
                 pw.print(" empty="); pw.println(empty);
         if (serviceb) {
@@ -451,32 +481,6 @@
             pw.print(prefix); pw.print("notCachedSinceIdle="); pw.print(notCachedSinceIdle);
                     pw.print(" initialIdlePss="); pw.println(initialIdlePss);
         }
-        pw.print(prefix); pw.print("oom: max="); pw.print(maxAdj);
-                pw.print(" curRaw="); pw.print(mCurRawAdj);
-                pw.print(" setRaw="); pw.print(setRawAdj);
-                pw.print(" cur="); pw.print(curAdj);
-                pw.print(" set="); pw.println(setAdj);
-        pw.print(prefix); pw.print("lastCompactTime="); pw.print(lastCompactTime);
-                pw.print(" lastCompactAction="); pw.print(lastCompactAction);
-        pw.print(prefix); pw.print("mCurSchedGroup="); pw.print(mCurSchedGroup);
-                pw.print(" setSchedGroup="); pw.print(setSchedGroup);
-                pw.print(" systemNoUi="); pw.print(systemNoUi);
-                pw.print(" trimMemoryLevel="); pw.println(trimMemoryLevel);
-        pw.print(prefix); pw.print("curProcState="); pw.print(getCurProcState());
-                pw.print(" mRepProcState="); pw.print(mRepProcState);
-                pw.print(" pssProcState="); pw.print(pssProcState);
-                pw.print(" setProcState="); pw.print(setProcState);
-                pw.print(" curCapability="); pw.print(curCapability);
-                pw.print(" setCapability="); pw.print(setCapability);
-                pw.print(" lastStateTime=");
-                TimeUtils.formatDuration(lastStateTime, nowUptime, pw);
-                pw.println();
-        if (hasShownUi || mPendingUiClean || hasAboveClient || treatLikeActivity) {
-            pw.print(prefix); pw.print("hasShownUi="); pw.print(hasShownUi);
-                    pw.print(" pendingUiClean="); pw.print(mPendingUiClean);
-                    pw.print(" hasAboveClient="); pw.print(hasAboveClient);
-                    pw.print(" treatLikeActivity="); pw.println(treatLikeActivity);
-        }
         if (connectionService != null || connectionGroup != 0) {
             pw.print(prefix); pw.print("connectionGroup="); pw.print(connectionGroup);
             pw.print(" Importance="); pw.print(connectionImportance);
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 5b12933..ea70598 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -90,7 +90,6 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
-import android.util.SparseLongArray;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.R;
@@ -154,6 +153,15 @@
     static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 110;
     static final int START_USER_SWITCH_FG_MSG = 120;
 
+    // Message constant to clear {@link UserJourneySession} from {@link mUserIdToUserJourneyMap} if
+    // the user journey, defined in the UserLifecycleJourneyReported atom for statsd, is not
+    // complete within {@link USER_JOURNEY_TIMEOUT}.
+    private static final int CLEAR_USER_JOURNEY_SESSION_MSG = 200;
+    // Wait time for completing the user journey. If a user journey is not complete within this
+    // time, the remaining lifecycle events for the journey would not be logged in statsd.
+    // Timeout set for 90 seconds.
+    private static final int USER_JOURNEY_TIMEOUT_MS = 90_000;
+
     // UI thread message constants
     static final int START_USER_SWITCH_UI_MSG = 1000;
 
@@ -194,14 +202,37 @@
             FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__START_USER;
     private static final int USER_LIFECYCLE_EVENT_CREATE_USER =
             FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__CREATE_USER;
+    private static final int USER_LIFECYCLE_EVENT_USER_RUNNING_LOCKED =
+            FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__USER_RUNNING_LOCKED;
+    private static final int USER_LIFECYCLE_EVENT_UNLOCKING_USER =
+            FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__UNLOCKING_USER;
+    private static final int USER_LIFECYCLE_EVENT_UNLOCKED_USER =
+            FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__UNLOCKED_USER;
     @IntDef(prefix = { "USER_LIFECYCLE_EVENT" }, value = {
             USER_LIFECYCLE_EVENT_UNKNOWN,
             USER_LIFECYCLE_EVENT_SWITCH_USER,
             USER_LIFECYCLE_EVENT_START_USER,
             USER_LIFECYCLE_EVENT_CREATE_USER,
+            USER_LIFECYCLE_EVENT_USER_RUNNING_LOCKED,
+            USER_LIFECYCLE_EVENT_UNLOCKING_USER,
+            USER_LIFECYCLE_EVENT_UNLOCKED_USER,
     })
     @interface UserLifecycleEvent {}
 
+    // User lifecyle event state, defined in the UserLifecycleEventOccurred atom for statsd
+    private static final int USER_LIFECYCLE_EVENT_STATE_BEGIN =
+            FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__BEGIN;
+    private static final int USER_LIFECYCLE_EVENT_STATE_FINISH =
+            FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__FINISH;
+    private static final int USER_LIFECYCLE_EVENT_STATE_NONE =
+            FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__NONE;
+    @IntDef(prefix = { "USER_LIFECYCLE_EVENT_STATE" }, value = {
+            USER_LIFECYCLE_EVENT_STATE_BEGIN,
+            USER_LIFECYCLE_EVENT_STATE_FINISH,
+            USER_LIFECYCLE_EVENT_STATE_NONE,
+    })
+    @interface UserLifecycleEventState {}
+
     /**
      * Maximum number of users we allow to be running at a time, including system user.
      *
@@ -311,11 +342,11 @@
     private final ArrayList<Integer> mLastActiveUsers = new ArrayList<>();
 
     /**
-     * A per-user, journey to session id map, used for statsd logging for the
+     * {@link UserIdInt} to {@link UserJourneySession} mapping used for statsd logging for the
      * UserLifecycleJourneyReported and UserLifecycleEventOccurred atoms.
      */
-    @GuardedBy("mUserJourneyToSessionIdMap")
-    private final SparseArray<SparseLongArray> mUserJourneyToSessionIdMap = new SparseArray<>();
+    @GuardedBy("mUserIdToUserJourneyMap")
+    private final SparseArray<UserJourneySession> mUserIdToUserJourneyMap = new SparseArray<>();
 
     UserController(ActivityManagerService service) {
         this(new Injector(service));
@@ -447,6 +478,8 @@
         // but we might immediately step into RUNNING below if the user
         // storage is already unlocked.
         if (uss.setState(STATE_BOOTING, STATE_RUNNING_LOCKED)) {
+            logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_USER_RUNNING_LOCKED,
+                    USER_LIFECYCLE_EVENT_STATE_NONE);
             mInjector.getUserManagerInternal().setUserState(userId, uss.state);
             // Do not report secondary users, runtime restarts or first boot/upgrade
             if (userId == UserHandle.USER_SYSTEM
@@ -503,6 +536,8 @@
     private boolean finishUserUnlocking(final UserState uss) {
         final int userId = uss.mHandle.getIdentifier();
         EventLog.writeEvent(EventLogTags.UC_FINISH_USER_UNLOCKING, userId);
+        logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_UNLOCKING_USER,
+                USER_LIFECYCLE_EVENT_STATE_BEGIN);
         // Only keep marching forward if user is actually unlocked
         if (!StorageManager.isUserKeyUnlocked(userId)) return false;
         synchronized (mLock) {
@@ -2396,8 +2431,8 @@
             case START_USER_SWITCH_FG_MSG:
                 logUserJourneyInfo(getUserInfo(getCurrentUserId()), getUserInfo(msg.arg1),
                         USER_JOURNEY_USER_SWITCH_FG);
-                logUserLifecycleEvent(msg.arg1, USER_JOURNEY_USER_SWITCH_FG,
-                        USER_LIFECYCLE_EVENT_SWITCH_USER, true);
+                logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_SWITCH_USER,
+                        USER_LIFECYCLE_EVENT_STATE_BEGIN);
                 startUserInForeground(msg.arg1);
                 break;
             case REPORT_USER_SWITCH_MSG:
@@ -2420,14 +2455,14 @@
                         BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
                         Integer.toString(msg.arg1), msg.arg1);
                 logUserJourneyInfo(null, getUserInfo(msg.arg1), USER_JOURNEY_USER_START);
-                logUserLifecycleEvent(msg.arg1, USER_JOURNEY_USER_START,
-                        USER_LIFECYCLE_EVENT_START_USER, true);
+                logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_START_USER,
+                        USER_LIFECYCLE_EVENT_STATE_BEGIN);
 
                 mInjector.getSystemServiceManager().startUser(TimingsTraceAndSlog.newAsyncLog(),
                         msg.arg1);
 
-                logUserLifecycleEvent(msg.arg1, USER_JOURNEY_USER_START,
-                        USER_LIFECYCLE_EVENT_START_USER, false);
+                logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_START_USER,
+                        USER_LIFECYCLE_EVENT_STATE_FINISH);
                 clearSessionId(msg.arg1, USER_JOURNEY_USER_START);
                 break;
             case USER_UNLOCK_MSG:
@@ -2437,10 +2472,17 @@
                 FgThread.getHandler().post(() -> {
                     mInjector.loadUserRecents(userId);
                 });
+                logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_UNLOCKING_USER,
+                        USER_LIFECYCLE_EVENT_STATE_FINISH);
+                logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_UNLOCKED_USER,
+                        USER_LIFECYCLE_EVENT_STATE_BEGIN);
                 finishUserUnlocked((UserState) msg.obj);
                 break;
             case USER_UNLOCKED_MSG:
                 mInjector.getSystemServiceManager().onUserUnlocked(msg.arg1);
+                logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_UNLOCKED_USER,
+                        USER_LIFECYCLE_EVENT_STATE_FINISH);
+                clearSessionId(msg.arg1);
                 break;
             case USER_CURRENT_MSG:
                 mInjector.batteryStatsServiceNoteEvent(
@@ -2458,11 +2500,8 @@
             case REPORT_USER_SWITCH_COMPLETE_MSG:
                 dispatchUserSwitchComplete(msg.arg1);
 
-                final int currentJourney = mUserSwitchUiEnabled ? USER_JOURNEY_USER_SWITCH_UI
-                                                                : USER_JOURNEY_USER_SWITCH_FG;
-                logUserLifecycleEvent(msg.arg1, currentJourney,
-                        USER_LIFECYCLE_EVENT_SWITCH_USER, false);
-                clearSessionId(msg.arg1, currentJourney);
+                logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_SWITCH_USER,
+                        USER_LIFECYCLE_EVENT_STATE_FINISH);
                 break;
             case REPORT_LOCKED_BOOT_COMPLETE_MSG:
                 dispatchLockedBootComplete(msg.arg1);
@@ -2471,10 +2510,13 @@
                 final Pair<UserInfo, UserInfo> fromToUserPair = (Pair<UserInfo, UserInfo>) msg.obj;
                 logUserJourneyInfo(fromToUserPair.first, fromToUserPair.second,
                         USER_JOURNEY_USER_SWITCH_UI);
-                logUserLifecycleEvent(fromToUserPair.second.id, USER_JOURNEY_USER_SWITCH_UI,
-                        USER_LIFECYCLE_EVENT_SWITCH_USER, true);
+                logUserLifecycleEvent(fromToUserPair.second.id, USER_LIFECYCLE_EVENT_SWITCH_USER,
+                        USER_LIFECYCLE_EVENT_STATE_BEGIN);
                 showUserSwitchDialog(fromToUserPair);
                 break;
+            case CLEAR_USER_JOURNEY_SESSION_MSG:
+                clearSessionId(msg.arg1);
+                break;
         }
         return false;
     }
@@ -2482,27 +2524,61 @@
     /**
      * statsd helper method for logging the start of a user journey via a UserLifecycleEventOccurred
      * atom given the originating and targeting users for the journey.
-     *
-     * Note: these info atoms are currently logged more than once per journey since there is no
-     * state associated with the user's ongoing journey - this will be updated in a later CL.
      */
     private void logUserJourneyInfo(UserInfo origin, UserInfo target, @UserJourney int journey) {
         final long newSessionId = ThreadLocalRandom.current().nextLong(1, Long.MAX_VALUE);
-        synchronized (mUserJourneyToSessionIdMap) {
-            SparseLongArray userSessions = mUserJourneyToSessionIdMap.get(target.id);
-            if (userSessions == null) {
-                userSessions = new SparseLongArray();
-                mUserJourneyToSessionIdMap.put(target.id, userSessions);
-            }
-            final long oldSessionId = userSessions.get(journey);
-            if (oldSessionId != INVALID_SESSION_ID) {
-                // potentially an incomplete or timed-out session
+        synchronized (mUserIdToUserJourneyMap) {
+            UserJourneySession userJourneySession = mUserIdToUserJourneyMap.get(target.id);
+            if (userJourneySession != null) {
+                // TODO(b/157007231): Move this logic to a separate class/file.
+                if ((userJourneySession.mJourney == USER_JOURNEY_USER_SWITCH_UI
+                        && journey == USER_JOURNEY_USER_START)
+                        || (userJourneySession.mJourney == USER_JOURNEY_USER_SWITCH_FG
+                                && journey == USER_JOURNEY_USER_START)) {
+                    /*
+                     * There is already a user switch journey, and a user start journey for the same
+                     * target user received. User start journey is most likely a part of user switch
+                     * journey so no need to create a new journey for user start.
+                     */
+                    if (DEBUG_MU) {
+                        Slog.d(TAG, journey + " not logged as it is expected to be part of "
+                                + userJourneySession.mJourney);
+                    }
+                    return;
+                }
+                /*
+                 * Possible reasons for this condition to be true:
+                 * - A user switch journey is received while another user switch journey is in
+                 *   process for the same user.
+                 * - A user switch journey is received while user start journey is in process for
+                 *   the same user.
+                 * - A user start journey is received while another user start journey is in process
+                 *   for the same user.
+                 * In all cases potentially an incomplete, timed-out session or multiple
+                 * simultaneous requests. It is not possible to keep track of multiple sessions for
+                 * the same user, so previous session is abandoned.
+                 */
                 FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED,
-                        oldSessionId, target.id, USER_LIFECYCLE_EVENT_UNKNOWN,
-                        FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__NONE);
+                        userJourneySession.mSessionId, target.id, USER_LIFECYCLE_EVENT_UNKNOWN,
+                        USER_LIFECYCLE_EVENT_STATE_NONE);
             }
-            // update session id
-            userSessions.put(journey, newSessionId);
+
+            if (DEBUG_MU) {
+                Slog.d(TAG,
+                        "Starting a new journey: " + journey + " with session id: " + newSessionId);
+            }
+
+            userJourneySession = new UserJourneySession(newSessionId, journey);
+            mUserIdToUserJourneyMap.put(target.id, userJourneySession);
+            /*
+             * User lifecyle journey would be complete when {@code #clearSessionId} is called after
+             * the last expected lifecycle event for the journey. It may be possible that the last
+             * event is not called, e.g., user not unlocked after user switching. In such cases user
+             * journey is cleared after {@link USER_JOURNEY_TIMEOUT}.
+             */
+            mHandler.removeMessages(CLEAR_USER_JOURNEY_SESSION_MSG);
+            mHandler.sendMessageDelayed(mHandler.obtainMessage(CLEAR_USER_JOURNEY_SESSION_MSG,
+                    target.id), USER_JOURNEY_TIMEOUT_MS);
         }
 
         FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED, newSessionId,
@@ -2511,41 +2587,65 @@
     }
 
     /**
-     * statsd helper method for logging the begin or finish of the given event for the
-     * UserLifecycleEventOccurred statsd atom.
-     * Note: This does not clear the user's journey session id - if this event represents the end of
-     * a particular journey, call {@link #clearSessionId} to indicate that the session is over.
+     * statsd helper method for logging the given event for the UserLifecycleEventOccurred statsd
+     * atom.
      */
-    private void logUserLifecycleEvent(@UserIdInt int userId, @UserJourney int journey,
-            @UserLifecycleEvent int event, boolean begin) {
+    private void logUserLifecycleEvent(@UserIdInt int userId, @UserLifecycleEvent int event,
+            @UserLifecycleEventState int eventState) {
         final long sessionId;
-        synchronized (mUserJourneyToSessionIdMap) {
-            final SparseLongArray eventToSessionMap = mUserJourneyToSessionIdMap.get(userId);
-            if (eventToSessionMap == null || eventToSessionMap.size() == 0) {
+        synchronized (mUserIdToUserJourneyMap) {
+            final UserJourneySession userJourneySession = mUserIdToUserJourneyMap.get(userId);
+            if (userJourneySession == null || userJourneySession.mSessionId == INVALID_SESSION_ID) {
+                Slog.w(TAG, "UserLifecycleEvent " + event
+                        + " received without an active userJourneySession.");
                 return;
             }
-            sessionId = eventToSessionMap.get(journey);
-            if (sessionId == INVALID_SESSION_ID) {
-                return;
-            }
+            sessionId = userJourneySession.mSessionId;
         }
 
         FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED, sessionId, userId,
-                event, begin ? FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__BEGIN
-                             : FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__FINISH);
+                event, eventState);
     }
 
     /**
-     * Clears the user's session id associated with the given UserJourney (for statsd).
+     * Clears the {@link UserJourneySession} for a given {@link UserIdInt} and {@link UserJourney}.
      */
     private void clearSessionId(@UserIdInt int userId, @UserJourney int journey) {
-        synchronized (mUserJourneyToSessionIdMap) {
-            if (mUserJourneyToSessionIdMap.get(userId) != null) {
-                mUserJourneyToSessionIdMap.get(userId).delete(journey);
+        synchronized (mUserIdToUserJourneyMap) {
+            final UserJourneySession userJourneySession = mUserIdToUserJourneyMap.get(userId);
+            if (userJourneySession != null && userJourneySession.mJourney == journey) {
+                clearSessionId(userId);
             }
         }
     }
 
+    /**
+     * Clears the {@link UserJourneySession} for a given {@link UserIdInt}.
+     */
+    private void clearSessionId(@UserIdInt int userId) {
+        synchronized (mUserIdToUserJourneyMap) {
+            mHandler.removeMessages(CLEAR_USER_JOURNEY_SESSION_MSG);
+            mUserIdToUserJourneyMap.delete(userId);
+        }
+    }
+
+    /**
+     * Helper class to store user journey and session id.
+     *
+     * <p> User journey tracks a chain of user lifecycle events occurring during different user
+     * activities such as user start, user switch, and user creation.
+     */
+    // TODO(b/157007231): Move this class and user journey tracking logic to a separate file.
+    private static class UserJourneySession {
+        final long mSessionId;
+        @UserJourney final int mJourney;
+
+        UserJourneySession(long sessionId, @UserJourney int journey) {
+            mJourney = journey;
+            mSessionId = sessionId;
+        }
+    }
+
     private static class UserProgressListener extends IProgressListener.Stub {
         private volatile long mUnlockStarted;
         @Override
@@ -2736,19 +2836,13 @@
 
         void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser,
                 String switchingFromSystemUserMessage, String switchingToSystemUserMessage) {
-            Dialog d;
             if (!mService.mContext.getPackageManager()
                     .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
-                d = new UserSwitchingDialog(mService, mService.mContext, fromUser, toUser,
-                    true /* above system */, switchingFromSystemUserMessage,
-                    switchingToSystemUserMessage);
-            } else {
-                d = new CarUserSwitchingDialog(mService, mService.mContext, fromUser, toUser,
-                    true /* above system */, switchingFromSystemUserMessage,
-                    switchingToSystemUserMessage);
+                final Dialog d = new UserSwitchingDialog(mService, mService.mContext, fromUser,
+                        toUser, true /* above system */, switchingFromSystemUserMessage,
+                        switchingToSystemUserMessage);
+                d.show();
             }
-
-            d.show();
         }
 
         void reportGlobalUsageEventLocked(int event) {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 63e01e0..e70de57 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -66,11 +66,11 @@
 import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
 import static android.content.pm.PermissionInfo.PROTECTION_FLAG_APPOP;
 
-import static com.android.server.am.OomAdjuster.DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA;
-import static com.android.server.am.OomAdjuster.DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q;
-import static com.android.server.am.OomAdjuster.DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION;
-import static com.android.server.am.OomAdjuster.DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
-import static com.android.server.am.OomAdjuster.DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q;
+import static android.app.ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA;
+import static android.app.ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q;
+import static android.app.ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION;
+import static android.app.ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+import static android.app.ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q;
 import static com.android.server.appop.AppOpsService.ModeCallback.ALL_OPS;
 
 import static java.lang.Long.max;
@@ -521,6 +521,7 @@
         public boolean hasForegroundWatchers;
 
         public long lastTimeShowDebugToast;
+        public long lastTimePendingTopUid;
 
         public UidState(int uid) {
             this.uid = uid;
@@ -542,6 +543,10 @@
             if (mode == MODE_FOREGROUND) {
                 if (appWidgetVisible) {
                     return MODE_ALLOWED;
+                } else if (mActivityManagerInternal != null
+                        && mActivityManagerInternal.isPendingTopUid(uid)) {
+                    maybeLogPendingTopUid(op, mode);
+                    return MODE_ALLOWED;
                 } else if (state <= UID_STATE_TOP) {
                     // process is in TOP.
                     return MODE_ALLOWED;
@@ -604,7 +609,11 @@
             } else if (mode == MODE_ALLOWED) {
                 switch (op) {
                     case OP_CAMERA:
-                        if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
+                        if (mActivityManagerInternal != null
+                                && mActivityManagerInternal.isPendingTopUid(uid)) {
+                            maybeLogPendingTopUid(op, mode);
+                            return MODE_ALLOWED;
+                        } else if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
                             return MODE_ALLOWED;
                         } else if ((capability
                                 & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q) != 0) {
@@ -618,7 +627,11 @@
                             return MODE_IGNORED;
                         }
                     case OP_RECORD_AUDIO:
-                        if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
+                        if (mActivityManagerInternal != null
+                                && mActivityManagerInternal.isPendingTopUid(uid)) {
+                            maybeLogPendingTopUid(op, mode);
+                            return MODE_ALLOWED;
+                        } else if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
                             return MODE_ALLOWED;
                         } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q)
                                 != 0) {
@@ -704,6 +717,19 @@
                         mActivityManagerInternal, uid, op, mode));
             }
         }
+
+
+        void maybeLogPendingTopUid(int op, int mode) {
+            final long now = System.currentTimeMillis();
+            if (lastTimePendingTopUid == 0 ||  now - lastTimePendingTopUid > 300000) {
+                lastTimePendingTopUid = now;
+                Slog.wtf(TAG, "PendingStartActivityUids evalMode, isPendingTopUid true, uid:"
+                        + uid
+                        + " packageName:" + Settings.getPackageNameForUid(mContext, uid)
+                        + " op:" + op
+                        + " mode:" + mode);
+            }
+        }
     }
 
     final static class Ops extends SparseArray<Op> {
@@ -2582,6 +2608,28 @@
         }
     }
 
+    private static ArrayList<ChangeRec> addChange(ArrayList<ChangeRec> reports,
+            int op, int uid, String packageName) {
+        boolean duplicate = false;
+        if (reports == null) {
+            reports = new ArrayList<>();
+        } else {
+            final int reportCount = reports.size();
+            for (int j = 0; j < reportCount; j++) {
+                ChangeRec report = reports.get(j);
+                if (report.op == op && report.pkg.equals(packageName)) {
+                    duplicate = true;
+                    break;
+                }
+            }
+        }
+        if (!duplicate) {
+            reports.add(new ChangeRec(op, uid, packageName));
+        }
+
+        return reports;
+    }
+
     private static HashMap<ModeCallback, ArrayList<ChangeRec>> addCallbacks(
             HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks,
             int op, int uid, String packageName, ArraySet<ModeCallback> cbs) {
@@ -2595,22 +2643,9 @@
         for (int i=0; i<N; i++) {
             ModeCallback cb = cbs.valueAt(i);
             ArrayList<ChangeRec> reports = callbacks.get(cb);
-            boolean duplicate = false;
-            if (reports == null) {
-                reports = new ArrayList<>();
-                callbacks.put(cb, reports);
-            } else {
-                final int reportCount = reports.size();
-                for (int j = 0; j < reportCount; j++) {
-                    ChangeRec report = reports.get(j);
-                    if (report.op == op && report.pkg.equals(packageName)) {
-                        duplicate = true;
-                        break;
-                    }
-                }
-            }
-            if (!duplicate) {
-                reports.add(new ChangeRec(op, uid, packageName));
+            ArrayList<ChangeRec> changed = addChange(reports, op, uid, packageName);
+            if (changed != reports) {
+                callbacks.put(cb, changed);
             }
         }
         return callbacks;
@@ -2648,6 +2683,7 @@
         enforceManageAppOpsModes(callingPid, callingUid, reqUid);
 
         HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks = null;
+        ArrayList<ChangeRec> allChanges = new ArrayList<>();
         synchronized (this) {
             boolean changed = false;
             for (int i = mUidStates.size() - 1; i >= 0; i--) {
@@ -2668,6 +2704,9 @@
                                         mOpModeWatchers.get(code));
                                 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
                                         mPackageModeWatchers.get(packageName));
+
+                                allChanges = addChange(allChanges, code, uidState.uid,
+                                        packageName);
                             }
                         }
                     }
@@ -2707,6 +2746,7 @@
                             callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
                                     mPackageModeWatchers.get(packageName));
 
+                            allChanges = addChange(allChanges, curOp.op, uid, packageName);
                             curOp.removeAttributionsWithNoTime();
                             if (curOp.mAttributions.isEmpty()) {
                                 pkgOps.removeAt(j);
@@ -2741,6 +2781,15 @@
                 }
             }
         }
+
+        if (allChanges != null) {
+            int numChanges = allChanges.size();
+            for (int i = 0; i < numChanges; i++) {
+                ChangeRec change = allChanges.get(i);
+                notifyOpChangedSync(change.op, change.uid, change.pkg,
+                        AppOpsManager.opToDefaultMode(change.op));
+            }
+        }
     }
 
     private void evalAllForegroundOpsLocked() {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 40b6f42..df4c269 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -36,6 +36,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
+import android.os.RemoteException;
 import android.os.SystemClock;
 import android.util.Log;
 import android.util.PrintWriterPrinter;
@@ -43,6 +44,9 @@
 import com.android.internal.annotations.GuardedBy;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.NoSuchElementException;
+
 
 /** @hide */
 /*package*/ final class AudioDeviceBroker {
@@ -91,6 +95,9 @@
     // TODO do not "share" the lock between AudioService and BtHelpr, see b/123769055
     /*package*/ final Object mSetModeLock = new Object();
 
+    /** PID of current audio mode owner communicated by AudioService */
+    private int mModeOwnerPid = 0;
+
     //-------------------------------------------------------------------
     /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service) {
         mContext = context;
@@ -136,6 +143,7 @@
     /*package*/ void onSystemReady() {
         synchronized (mSetModeLock) {
             synchronized (mDeviceStateLock) {
+                mModeOwnerPid = mAudioService.getModeOwnerPid();
                 mBtHelper.onSystemReady();
             }
         }
@@ -202,24 +210,57 @@
      * @param eventSource for logging purposes
      * @return true if speakerphone state changed
      */
-    /*package*/ boolean setSpeakerphoneOn(boolean on, String eventSource) {
+    /*package*/ boolean setSpeakerphoneOn(IBinder cb, int pid, boolean on, String eventSource) {
         synchronized (mDeviceStateLock) {
-            final boolean wasOn = isSpeakerphoneOn();
-            if (on) {
-                if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
-                    setForceUse_Async(AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource);
-                }
-                mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
-            } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) {
-                mForcedUseForComm = AudioSystem.FORCE_NONE;
+            if (!addSpeakerphoneClient(cb, pid, on)) {
+                return false;
             }
-
-            mForcedUseForCommExt = mForcedUseForComm;
-            setForceUse_Async(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource);
+            final boolean wasOn = isSpeakerphoneOn();
+            updateSpeakerphoneOn(eventSource);
             return (wasOn != isSpeakerphoneOn());
         }
     }
 
+    @GuardedBy("mDeviceStateLock")
+    private void updateSpeakerphoneOn(String eventSource) {
+        if (isSpeakerphoneOnRequested()) {
+            if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
+                setForceUse_Async(AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource);
+            }
+            mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
+        } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) {
+            if (mBtHelper.isBluetoothScoOn()) {
+                mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
+                setForceUse_Async(
+                        AudioSystem.FOR_RECORD, AudioSystem.FORCE_BT_SCO, eventSource);
+            } else {
+                mForcedUseForComm = AudioSystem.FORCE_NONE;
+            }
+        }
+        mForcedUseForCommExt = mForcedUseForComm;
+        setForceUse_Async(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource);
+    }
+
+    /**
+     * Returns if speakerphone is requested ON or OFF.
+     * If the current audio mode owner is in the speakerphone client list, use this preference.
+     * Otherwise use first client's preference (first client corresponds to latest request).
+     * Speakerphone is requested OFF if no client is in the list.
+     * @return true if speakerphone is requested ON, false otherwise
+     */
+    @GuardedBy("mDeviceStateLock")
+    private boolean isSpeakerphoneOnRequested() {
+        if (mSpeakerphoneClients.isEmpty()) {
+            return false;
+        }
+        for (SpeakerphoneClient cl : mSpeakerphoneClients) {
+            if (cl.getPid() == mModeOwnerPid) {
+                return cl.isOn();
+            }
+        }
+        return mSpeakerphoneClients.get(0).isOn();
+    }
+
     /*package*/ boolean isSpeakerphoneOn() {
         synchronized (mDeviceStateLock) {
             return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER);
@@ -280,6 +321,13 @@
         final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile,
                 suppressNoisyIntent, a2dpVolume);
 
+        new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR
+                + "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent")
+                .set(MediaMetrics.Property.STATE, state == BluetoothProfile.STATE_CONNECTED
+                        ? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED)
+                .set(MediaMetrics.Property.INDEX, a2dpVolume)
+                .record();
+
         // operations of removing and posting messages related to A2DP device state change must be
         // mutually exclusive
         synchronized (mDeviceStateLock) {
@@ -371,7 +419,8 @@
                 }
                 mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
             } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
-                mForcedUseForComm = AudioSystem.FORCE_NONE;
+                mForcedUseForComm = isSpeakerphoneOnRequested()
+                        ? AudioSystem.FORCE_SPEAKER : AudioSystem.FORCE_NONE;
             }
             mForcedUseForCommExt = mForcedUseForComm;
             AudioSystem.setParameters("BT_SCO=" + (on ? "on" : "off"));
@@ -416,8 +465,8 @@
         sendIIMsgNoDelay(MSG_II_SET_HEARING_AID_VOLUME, SENDMSG_REPLACE, index, streamType);
     }
 
-    /*package*/ void postDisconnectBluetoothSco(int exceptPid) {
-        sendIMsgNoDelay(MSG_I_DISCONNECT_BT_SCO, SENDMSG_REPLACE, exceptPid);
+    /*package*/ void postSetModeOwnerPid(int pid) {
+        sendIMsgNoDelay(MSG_I_SET_MODE_OWNER_PID, SENDMSG_REPLACE, pid);
     }
 
     /*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) {
@@ -470,7 +519,7 @@
     }
 
     /*package*/ int getModeOwnerPid() {
-        return mAudioService.getModeOwnerPid();
+        return mModeOwnerPid;
     }
 
     /*package*/ int getDeviceForStream(int streamType) {
@@ -592,6 +641,10 @@
         sendLMsgNoDelay(MSG_L_SCOCLIENT_DIED, SENDMSG_QUEUE, obj);
     }
 
+    /*package*/ void postSpeakerphoneClientDied(Object obj) {
+        sendLMsgNoDelay(MSG_L_SPEAKERPHONE_CLIENT_DIED, SENDMSG_QUEUE, obj);
+    }
+
     /*package*/ void postSaveSetPreferredDeviceForStrategy(int strategy,
                                                            AudioDeviceAttributes device)
     {
@@ -661,7 +714,7 @@
                 new BtHelper.BluetoothA2dpDeviceInfo(btDevice);
         return (mBrokerHandler.hasEqualMessages(
                     MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED, devInfoToCheck)
-                || mBrokerHandler.hasEqualMessages(
+            || mBrokerHandler.hasEqualMessages(
                     MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED, devInfoToCheck));
     }
 
@@ -694,7 +747,20 @@
         } else {
             pw.println("Message handler is null");
         }
+
         mDeviceInventory.dump(pw, prefix);
+
+        pw.println("\n" + prefix + "mForcedUseForComm: "
+                +  AudioSystem.forceUseConfigToString(mForcedUseForComm));
+        pw.println(prefix + "mForcedUseForCommExt: "
+                + AudioSystem.forceUseConfigToString(mForcedUseForCommExt));
+        pw.println(prefix + "mModeOwnerPid: " + mModeOwnerPid);
+        pw.println(prefix + "Speakerphone clients:");
+        mSpeakerphoneClients.forEach((cl) -> {
+            pw.println("  " + prefix + "pid: " + cl.getPid() + " on: "
+                        + cl.isOn() + " cb: " + cl.getBinder()); });
+
+        mBtHelper.dump(pw, prefix);
     }
 
     //---------------------------------------------------------------------
@@ -864,10 +930,16 @@
                         mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1);
                     }
                     break;
-                case MSG_I_DISCONNECT_BT_SCO:
+                case MSG_I_SET_MODE_OWNER_PID:
                     synchronized (mSetModeLock) {
                         synchronized (mDeviceStateLock) {
-                            mBtHelper.disconnectBluetoothSco(msg.arg1);
+                            if (mModeOwnerPid != msg.arg1) {
+                                mModeOwnerPid = msg.arg1;
+                                updateSpeakerphoneOn("setNewModeOwner");
+                                if (mModeOwnerPid != 0) {
+                                    mBtHelper.disconnectBluetoothSco(mModeOwnerPid);
+                                }
+                            }
                         }
                     }
                     break;
@@ -878,6 +950,11 @@
                         }
                     }
                     break;
+                case MSG_L_SPEAKERPHONE_CLIENT_DIED:
+                    synchronized (mDeviceStateLock) {
+                        speakerphoneClientDied(msg.obj);
+                    }
+                    break;
                 case MSG_TOGGLE_HDMI:
                     synchronized (mDeviceStateLock) {
                         mDeviceInventory.onToggleHdmi();
@@ -1008,7 +1085,7 @@
     private static final int MSG_REPORT_NEW_ROUTES = 13;
     private static final int MSG_II_SET_HEARING_AID_VOLUME = 14;
     private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15;
-    private static final int MSG_I_DISCONNECT_BT_SCO = 16;
+    private static final int MSG_I_SET_MODE_OWNER_PID = 16;
 
     // process active A2DP device change, obj is BtHelper.BluetoothA2dpDeviceInfo
     private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE = 18;
@@ -1038,6 +1115,8 @@
     private static final int MSG_IL_SAVE_PREF_DEVICE_FOR_STRATEGY = 33;
     private static final int MSG_I_SAVE_REMOVE_PREF_DEVICE_FOR_STRATEGY = 34;
 
+    private static final int MSG_L_SPEAKERPHONE_CLIENT_DIED = 35;
+
 
     private static boolean isMessageHandledUnderWakelock(int msgId) {
         switch(msgId) {
@@ -1153,4 +1232,93 @@
                     time);
         }
     }
+
+    private class SpeakerphoneClient implements IBinder.DeathRecipient {
+        private final IBinder mCb;
+        private final int mPid;
+        private final boolean mOn;
+        SpeakerphoneClient(IBinder cb, int pid, boolean on) {
+            mCb = cb;
+            mPid = pid;
+            mOn = on;
+        }
+
+        public boolean registerDeathRecipient() {
+            boolean status = false;
+            try {
+                mCb.linkToDeath(this, 0);
+                status = true;
+            } catch (RemoteException e) {
+                Log.w(TAG, "SpeakerphoneClient could not link to " + mCb + " binder death");
+            }
+            return status;
+        }
+
+        public void unregisterDeathRecipient() {
+            try {
+                mCb.unlinkToDeath(this, 0);
+            } catch (NoSuchElementException e) {
+                Log.w(TAG, "SpeakerphoneClient could not not unregistered to binder");
+            }
+        }
+
+        @Override
+        public void binderDied() {
+            postSpeakerphoneClientDied(this);
+        }
+
+        IBinder getBinder() {
+            return mCb;
+        }
+
+        int getPid() {
+            return mPid;
+        }
+
+        boolean isOn() {
+            return mOn;
+        }
+    }
+
+    @GuardedBy("mDeviceStateLock")
+    private void speakerphoneClientDied(Object obj) {
+        if (obj == null) {
+            return;
+        }
+        Log.w(TAG, "Speaker client died");
+        if (removeSpeakerphoneClient(((SpeakerphoneClient) obj).getBinder(), false) != null) {
+            updateSpeakerphoneOn("speakerphoneClientDied");
+        }
+    }
+
+    private SpeakerphoneClient removeSpeakerphoneClient(IBinder cb, boolean unregister) {
+        for (SpeakerphoneClient cl : mSpeakerphoneClients) {
+            if (cl.getBinder() == cb) {
+                if (unregister) {
+                    cl.unregisterDeathRecipient();
+                }
+                mSpeakerphoneClients.remove(cl);
+                return cl;
+            }
+        }
+        return null;
+    }
+
+    @GuardedBy("mDeviceStateLock")
+    private boolean addSpeakerphoneClient(IBinder cb, int pid, boolean on) {
+        // always insert new request at first position
+        removeSpeakerphoneClient(cb, true);
+        SpeakerphoneClient client = new SpeakerphoneClient(cb, pid, on);
+        if (client.registerDeathRecipient()) {
+            mSpeakerphoneClients.add(0, client);
+            return true;
+        }
+        return false;
+    }
+
+    // List of clients requesting speakerPhone ON
+    @GuardedBy("mDeviceStateLock")
+    private final @NonNull ArrayList<SpeakerphoneClient> mSpeakerphoneClients =
+            new ArrayList<SpeakerphoneClient>();
+
 }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 17baead..78e06a3 100755
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -52,7 +52,6 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
@@ -570,6 +569,10 @@
     private int[] mAccessibilityServiceUids;
     private final Object mAccessibilityServiceUidsLock = new Object();
 
+    // Uid of the active input method service to check if caller is the one or not.
+    private int mInputMethodServiceUid = android.os.Process.INVALID_UID;
+    private final Object mInputMethodServiceUidLock = new Object();
+
     private int mEncodedSurroundMode;
     private String mEnabledSurroundFormats;
     private boolean mSurroundModeChanged;
@@ -952,6 +955,8 @@
 
         mMicMuteFromSystemCached = mAudioSystem.isMicrophoneMuted();
         setMicMuteFromSwitchInput();
+
+        initMinStreamVolumeWithoutModifyAudioSettings();
     }
 
     RoleObserver mRoleObserver;
@@ -1078,12 +1083,14 @@
             sendEncodedSurroundMode(mContentResolver, "onAudioServerDied");
             sendEnabledSurroundFormats(mContentResolver, true);
             updateAssistantUId(true);
-            updateCurrentImeUid(true);
             AudioSystem.setRttEnabled(mRttEnabled);
         }
         synchronized (mAccessibilityServiceUidsLock) {
             AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
         }
+        synchronized (mInputMethodServiceUidLock) {
+            mAudioSystem.setCurrentImeUid(mInputMethodServiceUid);
+        }
         synchronized (mHdmiClientLock) {
             if (mHdmiManager != null && mHdmiTvClient != null) {
                 setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
@@ -1303,7 +1310,7 @@
                 mStreamStates[streamType].setIndex(
                         mStreamStates[mStreamVolumeAlias[streamType]]
                                 .getIndex(AudioSystem.DEVICE_OUT_DEFAULT),
-                        device, caller);
+                        device, caller, true /*hasModifyAudioSettings*/);
             }
             mStreamStates[streamType].checkFixedVolumeDevices();
         }
@@ -1629,37 +1636,6 @@
         }
     }
 
-    @GuardedBy("mSettingsLock")
-    private void updateCurrentImeUid(boolean forceUpdate) {
-        String imeId = Settings.Secure.getStringForUser(
-                mContentResolver,
-                Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT);
-        if (TextUtils.isEmpty(imeId)) {
-            Log.e(TAG, "updateCurrentImeUid() could not find current IME");
-            return;
-        }
-        ComponentName componentName = ComponentName.unflattenFromString(imeId);
-        if (componentName == null) {
-            Log.e(TAG, "updateCurrentImeUid() got invalid service name for "
-                    + Settings.Secure.DEFAULT_INPUT_METHOD + ": " + imeId);
-            return;
-        }
-        String packageName = componentName.getPackageName();
-        int currentUserId = LocalServices.getService(ActivityManagerInternal.class)
-                .getCurrentUserId();
-        int currentImeUid = LocalServices.getService(PackageManagerInternal.class)
-                .getPackageUidInternal(packageName, 0 /* flags */, currentUserId);
-        if (currentImeUid < 0) {
-            Log.e(TAG, "updateCurrentImeUid() could not find UID for package: " + packageName);
-            return;
-        }
-
-        if (currentImeUid != mCurrentImeUid || forceUpdate) {
-            mAudioSystem.setCurrentImeUid(currentImeUid);
-            mCurrentImeUid = currentImeUid;
-        }
-    }
-
     private void readPersistedSettings() {
         if (!mSystemServer.isPrivileged()) {
             return;
@@ -1707,7 +1683,6 @@
             sendEncodedSurroundMode(cr, "readPersistedSettings");
             sendEnabledSurroundFormats(cr, true);
             updateAssistantUId(true);
-            updateCurrentImeUid(true);
             AudioSystem.setRttEnabled(mRttEnabled);
         }
 
@@ -1900,13 +1875,16 @@
                     direction, 0 /*ignored*/,
                     extVolCtlr, 0 /*delay*/);
         } else {
+            final boolean hasModifyAudioSettings =
+                    mContext.checkCallingPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS)
+                            == PackageManager.PERMISSION_GRANTED;
             adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
-                    caller, Binder.getCallingUid());
+                    caller, Binder.getCallingUid(), hasModifyAudioSettings);
         }
     }
 
     private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
-            String callingPackage, String caller, int uid) {
+            String callingPackage, String caller, int uid, boolean hasModifyAudioSettings) {
         if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType
                 + ", flags=" + flags + ", caller=" + caller
                 + ", volControlStream=" + mVolumeControlStream
@@ -1960,10 +1938,12 @@
             if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
         }
 
-        adjustStreamVolume(streamType, direction, flags, callingPackage, caller, uid);
+        adjustStreamVolume(streamType, direction, flags, callingPackage, caller, uid,
+                hasModifyAudioSettings);
     }
 
-    /** @see AudioManager#adjustStreamVolume(int, int, int) */
+    /** @see AudioManager#adjustStreamVolume(int, int, int)
+     * Part of service interface, check permissions here */
     public void adjustStreamVolume(int streamType, int direction, int flags,
             String callingPackage) {
         if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
@@ -1971,14 +1951,17 @@
                     + "CHANGE_ACCESSIBILITY_VOLUME / callingPackage=" + callingPackage);
             return;
         }
+        final boolean hasModifyAudioSettings =
+                mContext.checkCallingPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS)
+                        == PackageManager.PERMISSION_GRANTED;
         sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_STREAM_VOL, streamType,
                 direction/*val1*/, flags/*val2*/, callingPackage));
         adjustStreamVolume(streamType, direction, flags, callingPackage, callingPackage,
-                Binder.getCallingUid());
+                Binder.getCallingUid(), hasModifyAudioSettings);
     }
 
     protected void adjustStreamVolume(int streamType, int direction, int flags,
-            String callingPackage, String caller, int uid) {
+            String callingPackage, String caller, int uid, boolean hasModifyAudioSettings) {
         if (mUseFixedVolume) {
             return;
         }
@@ -2132,7 +2115,8 @@
                 Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
                 mVolumeController.postDisplaySafeVolumeWarning(flags);
             } else if (!isFullVolumeDevice(device)
-                    && (streamState.adjustIndex(direction * step, device, caller)
+                    && (streamState.adjustIndex(direction * step, device, caller,
+                            hasModifyAudioSettings)
                             || streamState.mIsMuted)) {
                 // Post message to set system volume (it in turn will post a
                 // message to persist).
@@ -2354,9 +2338,9 @@
     }
 
     private void onSetStreamVolume(int streamType, int index, int flags, int device,
-            String caller) {
+            String caller, boolean hasModifyAudioSettings) {
         final int stream = mStreamVolumeAlias[streamType];
-        setStreamVolumeInt(stream, index, device, false, caller);
+        setStreamVolumeInt(stream, index, device, false, caller, hasModifyAudioSettings);
         // setting volume on ui sounds stream type also controls silent mode
         if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
                 (stream == getUiSoundsStreamType())) {
@@ -2404,7 +2388,7 @@
                 continue;
             }
             setStreamVolume(groupedStream, index, flags, callingPackage, callingPackage,
-                            Binder.getCallingUid());
+                            Binder.getCallingUid(), true /*hasModifyAudioSettings*/);
         }
     }
 
@@ -2446,7 +2430,8 @@
         return AudioSystem.getMinVolumeIndexForAttributes(attr);
     }
 
-    /** @see AudioManager#setStreamVolume(int, int, int) */
+    /** @see AudioManager#setStreamVolume(int, int, int)
+     * Part of service interface, check permissions here */
     public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
         if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
             Log.w(TAG, "Trying to call setStreamVolume() for a11y without"
@@ -2469,10 +2454,13 @@
                     + " MODIFY_AUDIO_ROUTING  callingPackage=" + callingPackage);
             return;
         }
+        final boolean hasModifyAudioSettings =
+                mContext.checkCallingOrSelfPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS)
+                        == PackageManager.PERMISSION_GRANTED;
         sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
                 index/*val1*/, flags/*val2*/, callingPackage));
         setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
-                Binder.getCallingUid());
+                Binder.getCallingUid(), hasModifyAudioSettings);
     }
 
     private boolean canChangeAccessibilityVolume() {
@@ -2596,7 +2584,7 @@
     }
 
     private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
-            String caller, int uid) {
+            String caller, int uid, boolean hasModifyAudioSettings) {
         if (DEBUG_VOL) {
             Log.d(TAG, "setStreamVolume(stream=" + streamType+", index=" + index
                     + ", calling=" + callingPackage + ")");
@@ -2687,7 +2675,7 @@
                 mPendingVolumeCommand = new StreamVolumeCommand(
                                                     streamType, index, flags, device);
             } else {
-                onSetStreamVolume(streamType, index, flags, device, caller);
+                onSetStreamVolume(streamType, index, flags, device, caller, hasModifyAudioSettings);
                 index = mStreamStates[streamType].getIndex(device);
             }
         }
@@ -2899,19 +2887,22 @@
      * @param index Desired volume index of the stream
      * @param device the device whose volume must be changed
      * @param force If true, set the volume even if the desired volume is same
+     * @param caller
+     * @param hasModifyAudioSettings true if the caller is granted MODIFY_AUDIO_SETTINGS or
+     *                              MODIFY_AUDIO_ROUTING permission
      * as the current volume.
      */
     private void setStreamVolumeInt(int streamType,
                                     int index,
                                     int device,
                                     boolean force,
-                                    String caller) {
+                                    String caller, boolean hasModifyAudioSettings) {
         if (isFullVolumeDevice(device)) {
             return;
         }
         VolumeStreamState streamState = mStreamStates[streamType];
 
-        if (streamState.setIndex(index, device, caller) || force) {
+        if (streamState.setIndex(index, device, caller, hasModifyAudioSettings) || force) {
             // Post message to set system volume (it in turn will post a message
             // to persist).
             sendMsg(mAudioHandler,
@@ -3444,7 +3435,7 @@
                             int device = vss.mIndexMap.keyAt(i);
                             int value = vss.mIndexMap.valueAt(i);
                             if (value == 0) {
-                                vss.setIndex(10, device, TAG);
+                                vss.setIndex(10, device, TAG, true /*hasModifyAudioSettings*/);
                             }
                         }
                         // Persist volume for stream ring when it is changed here
@@ -3594,11 +3585,9 @@
         }
 
         public void binderDied() {
-            int oldModeOwnerPid;
             int newModeOwnerPid = 0;
             synchronized (mDeviceBroker.mSetModeLock) {
                 Log.w(TAG, "setMode() client died");
-                oldModeOwnerPid = getModeOwnerPid();
                 int index = mSetModeDeathHandlers.indexOf(this);
                 if (index < 0) {
                     Log.w(TAG, "unregistered setMode() client died");
@@ -3608,9 +3597,7 @@
             }
             // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
             // SCO connections not started by the application changing the mode when pid changes
-            if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
-                mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
-            }
+            mDeviceBroker.postSetModeOwnerPid(newModeOwnerPid);
         }
 
         public int getPid() {
@@ -3662,17 +3649,20 @@
             return;
         }
 
-        int oldModeOwnerPid;
         int newModeOwnerPid;
         synchronized (mDeviceBroker.mSetModeLock) {
             if (mode == AudioSystem.MODE_CURRENT) {
                 mode = mMode;
             }
-            oldModeOwnerPid = getModeOwnerPid();
+            int oldModeOwnerPid = getModeOwnerPid();
             // Do not allow changing mode if a call is active and the requester
-            // does not have permission to modify phone state or is not the mode owner.
-            if (((mMode == AudioSystem.MODE_IN_CALL)
-                    || (mMode == AudioSystem.MODE_IN_COMMUNICATION))
+            // does not have permission to modify phone state or is not the mode owner,
+            // unless returning to NORMAL mode (will not change current mode owner) or
+            // not changing mode in which case the mode owner will reflect the last
+            // requester of current mode
+            if (!((mode == mMode) || (mode == AudioSystem.MODE_NORMAL))
+                    && ((mMode == AudioSystem.MODE_IN_CALL)
+                        || (mMode == AudioSystem.MODE_IN_COMMUNICATION))
                     && !(hasModifyPhoneStatePermission || (oldModeOwnerPid == callingPid))) {
                 Log.w(TAG, "setMode(" + mode + ") from pid=" + callingPid
                         + ", uid=" + Binder.getCallingUid()
@@ -3685,9 +3675,7 @@
         }
         // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
         // SCO connections not started by the application changing the mode when pid changes
-        if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
-            mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
-        }
+        mDeviceBroker.postSetModeOwnerPid(newModeOwnerPid);
     }
 
     // setModeInt() returns a valid PID if the audio mode was successfully set to
@@ -3792,7 +3780,8 @@
             int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
             int device = getDeviceForStream(streamType);
             int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
-            setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true, caller);
+            setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true, caller,
+                    true /*hasModifyAudioSettings*/);
 
             updateStreamVolumeAlias(true /*updateVolumes*/, caller);
 
@@ -3964,32 +3953,18 @@
     }
 
     /** @see AudioManager#setSpeakerphoneOn(boolean) */
-    public void setSpeakerphoneOn(boolean on){
+    public void setSpeakerphoneOn(IBinder cb, boolean on) {
         if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
             return;
         }
 
-        if (mContext.checkCallingOrSelfPermission(
-                android.Manifest.permission.MODIFY_PHONE_STATE)
-                != PackageManager.PERMISSION_GRANTED) {
-            synchronized (mSetModeDeathHandlers) {
-                for (SetModeDeathHandler h : mSetModeDeathHandlers) {
-                    if (h.getMode() == AudioSystem.MODE_IN_CALL) {
-                        Log.w(TAG, "getMode is call, Permission Denial: setSpeakerphoneOn from pid="
-                                + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
-                        return;
-                    }
-                }
-            }
-        }
-
         // for logging only
         final int uid = Binder.getCallingUid();
         final int pid = Binder.getCallingPid();
         final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on)
                 .append(") from u/pid:").append(uid).append("/")
                 .append(pid).toString();
-        final boolean stateChanged = mDeviceBroker.setSpeakerphoneOn(on, eventSource);
+        final boolean stateChanged = mDeviceBroker.setSpeakerphoneOn(cb, pid, on, eventSource);
         new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE
                 + MediaMetrics.SEPARATOR + "setSpeakerphoneOn")
                 .setUid(uid)
@@ -4715,6 +4690,44 @@
         return false;
     }
 
+    /**
+     * Minimum attenuation that can be set for alarms over speaker by an application that
+     * doesn't have the MODIFY_AUDIO_SETTINGS permission.
+     */
+    protected static final float MIN_ALARM_ATTENUATION_NON_PRIVILEGED_DB = -36.0f;
+
+    /**
+     * Configures the VolumeStreamState instances for minimum stream index that can be accessed
+     * without MODIFY_AUDIO_SETTINGS permission.
+     * Can only be done successfully once audio policy has finished reading its configuration files
+     * for the volume curves. If not, getStreamVolumeDB will return NaN, and the min value will
+     * remain at the stream min index value.
+     */
+    protected void initMinStreamVolumeWithoutModifyAudioSettings() {
+        int idx;
+        int deviceForAlarm = AudioSystem.DEVICE_OUT_SPEAKER_SAFE;
+        if (Float.isNaN(AudioSystem.getStreamVolumeDB(AudioSystem.STREAM_ALARM,
+                MIN_STREAM_VOLUME[AudioSystem.STREAM_ALARM], deviceForAlarm))) {
+            deviceForAlarm = AudioSystem.DEVICE_OUT_SPEAKER;
+        }
+        for (idx = MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM];
+                idx >= MIN_STREAM_VOLUME[AudioSystem.STREAM_ALARM]; idx--) {
+            if (AudioSystem.getStreamVolumeDB(AudioSystem.STREAM_ALARM, idx, deviceForAlarm)
+                    < MIN_ALARM_ATTENUATION_NON_PRIVILEGED_DB) {
+                break;
+            }
+        }
+        final int safeIndex = idx <= MIN_STREAM_VOLUME[AudioSystem.STREAM_ALARM]
+                ? MIN_STREAM_VOLUME[AudioSystem.STREAM_ALARM]
+                : Math.min(idx + 1, MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]);
+        // update the VolumeStreamState for STREAM_ALARM and its aliases
+        for (int stream : mStreamVolumeAlias) {
+            if (mStreamVolumeAlias[stream] == AudioSystem.STREAM_ALARM) {
+                mStreamStates[stream].updateNoPermMinIndex(safeIndex);
+            }
+        }
+    }
+
     /** only public for mocking/spying, do not call outside of AudioService */
     @VisibleForTesting
     public int getDeviceForStream(int stream) {
@@ -5379,6 +5392,8 @@
     private class VolumeStreamState {
         private final int mStreamType;
         private int mIndexMin;
+        // min index when user doesn't have permission to change audio settings
+        private int mIndexMinNoPerm;
         private int mIndexMax;
 
         private boolean mIsMuted;
@@ -5420,6 +5435,7 @@
 
             mStreamType = streamType;
             mIndexMin = MIN_STREAM_VOLUME[streamType] * 10;
+            mIndexMinNoPerm = mIndexMin; // may be overwritten later in updateNoPermMinIndex()
             mIndexMax = MAX_STREAM_VOLUME[streamType] * 10;
             AudioSystem.initStreamVolume(streamType, mIndexMin / 10, mIndexMax / 10);
 
@@ -5430,6 +5446,18 @@
             mStreamDevicesChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
         }
 
+        /**
+         * Update the minimum index that can be used without MODIFY_AUDIO_SETTINGS permission
+         * @param index minimum index expressed in "UI units", i.e. no 10x factor
+         */
+        public void updateNoPermMinIndex(int index) {
+            mIndexMinNoPerm = index * 10;
+            if (mIndexMinNoPerm < mIndexMin) {
+                Log.e(TAG, "Invalid mIndexMinNoPerm for stream " + mStreamType);
+                mIndexMinNoPerm = mIndexMin;
+            }
+        }
+
         public int observeDevicesForStream_syncVSS(boolean checkOthers) {
             if (!mSystemServer.isPrivileged()) {
                 return AudioSystem.DEVICE_NONE;
@@ -5511,7 +5539,8 @@
                         continue;
                     }
 
-                    mIndexMap.put(device, getValidIndex(10 * index));
+                    mIndexMap.put(device, getValidIndex(10 * index,
+                            true /*hasModifyAudioSettings*/));
                 }
             }
         }
@@ -5599,17 +5628,20 @@
             }
         }
 
-        public boolean adjustIndex(int deltaIndex, int device, String caller) {
-            return setIndex(getIndex(device) + deltaIndex, device, caller);
+        public boolean adjustIndex(int deltaIndex, int device, String caller,
+                boolean hasModifyAudioSettings) {
+            return setIndex(getIndex(device) + deltaIndex, device, caller,
+                    hasModifyAudioSettings);
         }
 
-        public boolean setIndex(int index, int device, String caller) {
+        public boolean setIndex(int index, int device, String caller,
+                boolean hasModifyAudioSettings) {
             boolean changed;
             int oldIndex;
             synchronized (mSettingsLock) {
                 synchronized (VolumeStreamState.class) {
                     oldIndex = getIndex(device);
-                    index = getValidIndex(index);
+                    index = getValidIndex(index, hasModifyAudioSettings);
                     if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
                         index = mIndexMax;
                     }
@@ -5629,10 +5661,12 @@
                                 mStreamVolumeAlias[streamType] == mStreamType &&
                                 (changed || !aliasStreamState.hasIndexForDevice(device))) {
                             final int scaledIndex = rescaleIndex(index, mStreamType, streamType);
-                            aliasStreamState.setIndex(scaledIndex, device, caller);
+                            aliasStreamState.setIndex(scaledIndex, device, caller,
+                                    hasModifyAudioSettings);
                             if (isCurrentDevice) {
                                 aliasStreamState.setIndex(scaledIndex,
-                                        getDeviceForStream(streamType), caller);
+                                        getDeviceForStream(streamType), caller,
+                                        hasModifyAudioSettings);
                             }
                         }
                     }
@@ -5722,7 +5756,7 @@
                 index = srcMap.valueAt(i);
                 index = rescaleIndex(index, srcStreamType, mStreamType);
 
-                setIndex(index, device, caller);
+                setIndex(index, device, caller, true /*hasModifyAudioSettings*/);
             }
         }
 
@@ -5789,9 +5823,10 @@
             }
         }
 
-        private int getValidIndex(int index) {
-            if (index < mIndexMin) {
-                return mIndexMin;
+        private int getValidIndex(int index, boolean hasModifyAudioSettings) {
+            final int indexMin = hasModifyAudioSettings ? mIndexMin : mIndexMinNoPerm;
+            if (index < indexMin) {
+                return indexMin;
             } else if (mUseFixedVolume || index > mIndexMax) {
                 return mIndexMax;
             }
@@ -5803,7 +5838,13 @@
             pw.print("   Muted: ");
             pw.println(mIsMuted);
             pw.print("   Min: ");
-            pw.println((mIndexMin + 5) / 10);
+            pw.print((mIndexMin + 5) / 10);
+            if (mIndexMin != mIndexMinNoPerm) {
+                pw.print(" w/o perm:");
+                pw.println((mIndexMinNoPerm + 5) / 10);
+            } else {
+                pw.println();
+            }
             pw.print("   Max: ");
             pw.println((mIndexMax + 5) / 10);
             pw.print("   streamVolume:"); pw.println(getStreamVolume(mStreamType));
@@ -5924,7 +5965,9 @@
         final VolumeStreamState streamState = mStreamStates[update.mStreamType];
         if (update.hasVolumeIndex()) {
             final int index = update.getVolumeIndex();
-            streamState.setIndex(index, update.mDevice, update.mCaller);
+            streamState.setIndex(index, update.mDevice, update.mCaller,
+                    // trusted as index is always validated before message is posted
+                    true /*hasModifyAudioSettings*/);
             sVolumeLogger.log(new AudioEventLogger.StringEvent(update.mCaller + " dev:0x"
                     + Integer.toHexString(update.mDevice) + " volIdx:" + index));
         } else {
@@ -6217,8 +6260,6 @@
 
             mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
                     Settings.Secure.VOICE_INTERACTION_SERVICE), false, this);
-            mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
         }
 
         @Override
@@ -6242,7 +6283,6 @@
                 updateEncodedSurroundOutput();
                 sendEnabledSurroundFormats(mContentResolver, mSurroundModeChanged);
                 updateAssistantUId(false);
-                updateCurrentImeUid(false);
             }
         }
 
@@ -6870,7 +6910,8 @@
         for (int device : devices) {
             int index = streamState.getIndex(device);
             if (index > safeMediaVolumeIndex(device)) {
-                streamState.setIndex(safeMediaVolumeIndex(device), device, caller);
+                streamState.setIndex(safeMediaVolumeIndex(device), device, caller,
+                            true /*hasModifyAudioSettings*/);
                 sendMsg(mAudioHandler,
                         MSG_SET_DEVICE_VOLUME,
                         SENDMSG_QUEUE,
@@ -6904,7 +6945,7 @@
                                   mPendingVolumeCommand.mIndex,
                                   mPendingVolumeCommand.mFlags,
                                   mPendingVolumeCommand.mDevice,
-                                  callingPackage);
+                                  callingPackage, true /*hasModifyAudioSettings*/);
                 mPendingVolumeCommand = null;
             }
         }
@@ -7369,10 +7410,32 @@
                 return false;
             }
             boolean suppress = false;
-            if (resolvedStream != AudioSystem.STREAM_MUSIC && mController != null) {
+            // Intended behavior:
+            // 1/ if the stream is not the default UI stream, do not suppress (as it is not involved
+            //    in bringing up the UI)
+            // 2/ if the resolved and default stream is MUSIC, and media is playing, do not suppress
+            // 3/ otherwise suppress the first adjustments that occur during the "long press
+            //    timeout" interval. Note this is true regardless of whether this is a "real long
+            //    press" (where the user keeps pressing on the volume button), or repeated single
+            //    presses (here we don't know if we are in a real long press, or repeated fast
+            //    button presses).
+            //    Once the long press timeout occurs (mNextLongPress reset to 0), do not suppress.
+            // Example: for a default and resolved stream of MUSIC, this allows modifying rapidly
+            // the volume when media is playing (whether by long press or repeated individual
+            // presses), or to bring up the volume UI when media is not playing, in order to make
+            // another change (e.g. switch ringer modes) without changing media volume.
+            if (resolvedStream == DEFAULT_VOL_STREAM_NO_PLAYBACK && mController != null) {
+                // never suppress media vol adjustement during media playback
+                if (resolvedStream == AudioSystem.STREAM_MUSIC
+                        && AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, mLongPressTimeout))
+                {
+                    // media is playing, adjust the volume right away
+                    return false;
+                }
+
                 final long now = SystemClock.uptimeMillis();
                 if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
-                    // ui will become visible
+                    // UI is not visible yet, adjustment is ignored
                     if (mNextLongPress < now) {
                         mNextLongPress = now + mLongPressTimeout;
                     }
@@ -7490,29 +7553,39 @@
 
         @Override
         public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
-                String callingPackage, int uid) {
+                String callingPackage, int uid, int pid) {
+            final boolean hasModifyAudioSettings =
+                    mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid)
+                    == PackageManager.PERMISSION_GRANTED;
             // direction and stream type swap here because the public
             // adjustSuggested has a different order than the other methods.
             adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage,
-                    callingPackage, uid);
+                    callingPackage, uid, hasModifyAudioSettings);
         }
 
         @Override
         public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
-                String callingPackage, int uid) {
+                String callingPackage, int uid, int pid) {
             if (direction != AudioManager.ADJUST_SAME) {
                 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_VOL_UID, streamType,
                         direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
                         .append(" uid:").append(uid).toString()));
             }
+            final boolean hasModifyAudioSettings =
+                    mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid)
+                            == PackageManager.PERMISSION_GRANTED;
             adjustStreamVolume(streamType, direction, flags, callingPackage,
-                    callingPackage, uid);
+                    callingPackage, uid, hasModifyAudioSettings);
         }
 
         @Override
         public void setStreamVolumeForUid(int streamType, int direction, int flags,
-                String callingPackage, int uid) {
-            setStreamVolume(streamType, direction, flags, callingPackage, callingPackage, uid);
+                String callingPackage, int uid, int pid) {
+            final boolean hasModifyAudioSettings =
+                    mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid)
+                            == PackageManager.PERMISSION_GRANTED;
+            setStreamVolume(streamType, direction, flags, callingPackage, callingPackage, uid,
+                    hasModifyAudioSettings);
         }
 
         @Override
@@ -7562,6 +7635,19 @@
                 AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
             }
         }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void setInputMethodServiceUid(int uid) {
+            synchronized (mInputMethodServiceUidLock) {
+                if (mInputMethodServiceUid != uid) {
+                    mAudioSystem.setCurrentImeUid(uid);
+                    mInputMethodServiceUid = uid;
+                }
+            }
+        }
     }
 
     //==========================================================================================
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 0654f86..b4c41b2 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -38,6 +38,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.NoSuchElementException;
@@ -131,6 +132,26 @@
         }
     }
 
+    /**
+     * Returns a string representation of the scoAudioState.
+     */
+    public static String scoAudioStateToString(int scoAudioState) {
+        switch (scoAudioState) {
+            case SCO_STATE_INACTIVE:
+                return "SCO_STATE_INACTIVE";
+            case SCO_STATE_ACTIVATE_REQ:
+                return "SCO_STATE_ACTIVATE_REQ";
+            case SCO_STATE_ACTIVE_EXTERNAL:
+                return "SCO_STATE_ACTIVE_EXTERNAL";
+            case SCO_STATE_ACTIVE_INTERNAL:
+                return "SCO_STATE_ACTIVE_INTERNAL";
+            case SCO_STATE_DEACTIVATING:
+                return "SCO_STATE_DEACTIVATING";
+            default:
+                return "SCO_STATE_(" + scoAudioState + ")";
+        }
+    }
+
     //----------------------------------------------------------------------
     /*package*/ static class BluetoothA2dpDeviceInfo {
         private final @NonNull BluetoothDevice mBtDevice;
@@ -307,8 +328,15 @@
                 case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
                     mDeviceBroker.setBluetoothScoOn(false, "BtHelper.receiveBtEvent");
                     scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
-                    // startBluetoothSco called after stopBluetoothSco
-                    if (mScoAudioState == SCO_STATE_ACTIVATE_REQ) {
+                    // There are two cases where we want to immediately reconnect audio:
+                    // 1) If a new start request was received while disconnecting: this was
+                    // notified by requestScoState() setting state to SCO_STATE_ACTIVATE_REQ.
+                    // 2) If audio was connected then disconnected via Bluetooth APIs and
+                    // we still have pending activation requests by apps: this is indicated by
+                    // state SCO_STATE_ACTIVE_EXTERNAL and the mScoClients list not empty.
+                    if (mScoAudioState == SCO_STATE_ACTIVATE_REQ
+                            || (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL
+                                    && !mScoClients.isEmpty())) {
                         if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null
                                 && connectBluetoothScoAudioHelper(mBluetoothHeadset,
                                 mBluetoothHeadsetDevice, mScoAudioMode)) {
@@ -318,7 +346,9 @@
                         }
                     }
                     // Tear down SCO if disconnected from external
-                    clearAllScoClients(0, mScoAudioState == SCO_STATE_ACTIVE_INTERNAL);
+                    if (mScoAudioState == SCO_STATE_DEACTIVATING) {
+                        clearAllScoClients(0, false);
+                    }
                     mScoAudioState = SCO_STATE_INACTIVE;
                     break;
                 case BluetoothHeadset.STATE_AUDIO_CONNECTING:
@@ -349,14 +379,11 @@
      * @return false if SCO isn't connected
      */
     /*package*/ synchronized boolean isBluetoothScoOn() {
-        if ((mBluetoothHeadset != null)
-                && (mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice)
-                != BluetoothHeadset.STATE_AUDIO_CONNECTED)) {
-            Log.w(TAG, "isBluetoothScoOn(true) returning false because "
-                    + mBluetoothHeadsetDevice + " is not in audio connected mode");
+        if (mBluetoothHeadset == null) {
             return false;
         }
-        return true;
+        return mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice)
+                == BluetoothHeadset.STATE_AUDIO_CONNECTED;
     }
 
     /**
@@ -1001,4 +1028,20 @@
                 return "ENCODING_BT_CODEC_TYPE(" + btCodecType + ")";
         }
     }
+
+    //------------------------------------------------------------
+    /*package*/ void dump(PrintWriter pw, String prefix) {
+        pw.println("\n" + prefix + "mBluetoothHeadset: " + mBluetoothHeadset);
+        pw.println(prefix + "mBluetoothHeadsetDevice: " + mBluetoothHeadsetDevice);
+        pw.println(prefix + "mScoAudioState: " + scoAudioStateToString(mScoAudioState));
+        pw.println(prefix + "mScoAudioMode: " + scoAudioModeToString(mScoAudioMode));
+        pw.println(prefix + "Sco clients:");
+        mScoClients.forEach((cl) -> {
+            pw.println("  " + prefix + "pid: " + cl.getPid() + " cb: " + cl.getBinder()); });
+
+        pw.println("\n" + prefix + "mHearingAid: " + mHearingAid);
+        pw.println(prefix + "mA2dp: " + mA2dp);
+        pw.println(prefix + "mAvrcpAbsVolSupported: " + mAvrcpAbsVolSupported);
+    }
+
 }
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
index 5d334c2..edc8f15 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
@@ -84,11 +84,8 @@
 
     @Override
     public void binderDied() {
-        super.binderDied();
-        // When the binder dies, we should stop the client. This probably belongs in
-        // ClientMonitor's binderDied(), but testing all the cases would be tricky.
-        // AuthenticationClient is the most user-visible case.
-        stop(false /* initiatedByClient */);
+        final boolean clearListener = !isBiometricPrompt();
+        binderDiedInternal(clearListener);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 7e28e94..4ddfe1b 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -113,6 +113,7 @@
     private static final int MSG_ON_AUTHENTICATION_TIMED_OUT = 11;
     private static final int MSG_ON_DEVICE_CREDENTIAL_PRESSED = 12;
     private static final int MSG_ON_SYSTEM_EVENT = 13;
+    private static final int MSG_CLIENT_DIED = 14;
 
     /**
      * Authentication either just called and we have not transitioned to the CALLED state, or
@@ -151,8 +152,13 @@
      * Device credential in AuthController is showing
      */
     static final int STATE_SHOWING_DEVICE_CREDENTIAL = 8;
+    /**
+     * The client binder died, and sensors were authenticating at the time. Cancel has been
+     * requested and we're waiting for the HAL(s) to send ERROR_CANCELED.
+     */
+    static final int STATE_CLIENT_DIED_CANCELLING = 9;
 
-    final class AuthSession {
+    final class AuthSession implements IBinder.DeathRecipient {
         // Map of Authenticator/Cookie pairs. We expect to receive the cookies back from
         // <Biometric>Services before we can start authenticating. Pairs that have been returned
         // are moved to mModalitiesMatched.
@@ -211,7 +217,14 @@
             mCallingUserId = callingUserId;
             mModality = modality;
             mRequireConfirmation = requireConfirmation;
+
             Slog.d(TAG, "New AuthSession, mSysUiSessionId: " + mSysUiSessionId);
+
+            try {
+                mClientReceiver.asBinder().linkToDeath(this, 0 /* flags */);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Unable to link to death");
+            }
         }
 
         boolean isCrypto() {
@@ -231,6 +244,12 @@
         boolean isAllowDeviceCredential() {
             return Utils.isCredentialRequested(mBundle);
         }
+
+        @Override
+        public void binderDied() {
+            Slog.e(TAG, "Binder died, sysUiSessionId: " + mSysUiSessionId);
+            mHandler.obtainMessage(MSG_CLIENT_DIED).sendToTarget();
+        }
     }
 
     private final Injector mInjector;
@@ -370,6 +389,11 @@
                     break;
                 }
 
+                case MSG_CLIENT_DIED: {
+                    handleClientDied();
+                    break;
+                }
+
                 default:
                     Slog.e(TAG, "Unknown message: " + msg);
                     break;
@@ -1391,6 +1415,7 @@
     }
 
     private void handleOnError(int cookie, int modality, int error, int vendorCode) {
+
         Slog.d(TAG, "handleOnError: " + error + " cookie: " + cookie);
         // Errors can either be from the current auth session or the pending auth session.
         // The pending auth session may receive errors such as ERROR_LOCKOUT before
@@ -1431,6 +1456,9 @@
                 } else if (mCurrentAuthSession.mState == STATE_SHOWING_DEVICE_CREDENTIAL) {
                     Slog.d(TAG, "Biometric canceled, ignoring from state: "
                             + mCurrentAuthSession.mState);
+                } else if (mCurrentAuthSession.mState == STATE_CLIENT_DIED_CANCELLING) {
+                    mStatusBarService.hideAuthenticationDialog();
+                    mCurrentAuthSession = null;
                 } else {
                     Slog.e(TAG, "Impossible session error state: "
                             + mCurrentAuthSession.mState);
@@ -1622,6 +1650,36 @@
         }
     }
 
+    private void handleClientDied() {
+        if (mCurrentAuthSession == null) {
+            Slog.e(TAG, "Auth session null");
+            return;
+        }
+
+        Slog.e(TAG, "SysUiSessionId: " + mCurrentAuthSession.mSysUiSessionId
+                + " State: " + mCurrentAuthSession.mState);
+
+        try {
+            // Check if any sensors are authenticating. If so, need to cancel them. When
+            // ERROR_CANCELED is received from the HAL, we hide the dialog and cleanup the session.
+            if (mCurrentAuthSession.mState == STATE_AUTH_STARTED) {
+                mCurrentAuthSession.mState = STATE_CLIENT_DIED_CANCELLING;
+                cancelInternal(mCurrentAuthSession.mToken,
+                        mCurrentAuthSession.mOpPackageName,
+                        mCurrentAuthSession.mCallingUid,
+                        mCurrentAuthSession.mCallingPid,
+                        mCurrentAuthSession.mCallingUserId,
+                        false /* fromClient */);
+            } else {
+                // If the sensors are not authenticating, set the auth session to null.
+                mStatusBarService.hideAuthenticationDialog();
+                mCurrentAuthSession = null;
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Remote exception: " + e);
+        }
+    }
+
     /**
      * Invoked when each service has notified that its client is ready to be started. When
      * all biometrics are ready, this invokes the SystemUI dialog through StatusBar.
@@ -1822,11 +1880,11 @@
 
     void cancelInternal(IBinder token, String opPackageName, int callingUid, int callingPid,
             int callingUserId, boolean fromClient) {
-
         if (mCurrentAuthSession == null) {
             Slog.w(TAG, "Skipping cancelInternal");
             return;
-        } else if (mCurrentAuthSession.mState != STATE_AUTH_STARTED) {
+        } else if (mCurrentAuthSession.mState != STATE_AUTH_STARTED
+                && mCurrentAuthSession.mState != STATE_CLIENT_DIED_CANCELLING) {
             Slog.w(TAG, "Skipping cancelInternal, state: " + mCurrentAuthSession.mState);
             return;
         }
diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
index 808f8c21..5a6ab4e5 100644
--- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
+++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
@@ -978,6 +978,10 @@
     }
 
     protected void addLockoutResetCallback(IBiometricServiceLockoutResetCallback callback) {
+        if (callback == null) {
+            Slog.w(getTag(), "Null LockoutResetCallback");
+            return;
+        }
         mHandler.post(() -> {
            final LockoutResetMonitor monitor = new LockoutResetMonitor(callback);
            if (!mLockoutMonitors.contains(monitor)) {
diff --git a/services/core/java/com/android/server/biometrics/ClientMonitor.java b/services/core/java/com/android/server/biometrics/ClientMonitor.java
index 942e050..b029695 100644
--- a/services/core/java/com/android/server/biometrics/ClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/ClientMonitor.java
@@ -233,11 +233,17 @@
 
     @Override
     public void binderDied() {
+        binderDiedInternal(true /* clearListener */);
+    }
+
+    void binderDiedInternal(boolean clearListener) {
         // If the current client dies we should cancel the current operation.
         Slog.e(getLogTag(), "Binder died, cancelling client");
         stop(false /* initiatedByClient */);
         mToken = null;
-        mListener = null;
+        if (clearListener) {
+            mListener = null;
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
index 8520f5a..d90f3af 100644
--- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
@@ -330,6 +330,7 @@
         @Override
         public void addLockoutResetCallback(final IBiometricServiceLockoutResetCallback callback)
                 throws RemoteException {
+            checkPermission(USE_BIOMETRIC_INTERNAL);
             FingerprintService.super.addLockoutResetCallback(callback);
         }
 
diff --git a/services/core/java/com/android/server/compat/TEST_MAPPING b/services/core/java/com/android/server/compat/TEST_MAPPING
index 0c30c79..bc1c728 100644
--- a/services/core/java/com/android/server/compat/TEST_MAPPING
+++ b/services/core/java/com/android/server/compat/TEST_MAPPING
@@ -15,7 +15,7 @@
         },
         // CTS tests
         {
-            "name": "CtsAppCompatHostTestCases#"
+            "name": "CtsAppCompatHostTestCases"
         }
     ]
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 15628f0..37b2de1 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -168,6 +168,9 @@
     // Obtained by ConnectivityService and merged into NetworkAgent-provided information.
     public CaptivePortalData captivePortalData;
 
+    // The UID of the remote entity that created this Network.
+    public final int creatorUid;
+
     // Networks are lingered when they become unneeded as a result of their NetworkRequests being
     // satisfied by a higher-scoring network. so as to allow communication to wrap up before the
     // network is taken down.  This usually only happens to the default network. Lingering ends with
@@ -268,7 +271,8 @@
     public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
             LinkProperties lp, NetworkCapabilities nc, int score, Context context,
             Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd,
-            IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber) {
+            IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber,
+            int creatorUid) {
         this.messenger = messenger;
         asyncChannel = ac;
         network = net;
@@ -282,6 +286,7 @@
         mHandler = handler;
         networkAgentConfig = config;
         this.factorySerialNumber = factorySerialNumber;
+        this.creatorUid = creatorUid;
     }
 
     /**
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 093e906..f3c7874 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -21,6 +21,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
 import static android.net.RouteInfo.RTN_THROW;
 import static android.net.RouteInfo.RTN_UNREACHABLE;
 
@@ -317,8 +318,7 @@
      *
      * @param defaultNetwork underlying network for VPNs following platform's default
      */
-    public synchronized NetworkCapabilities updateCapabilities(
-            @Nullable Network defaultNetwork) {
+    public synchronized NetworkCapabilities updateCapabilities(@Nullable Network defaultNetwork) {
         if (mConfig == null) {
             // VPN is not running.
             return null;
@@ -350,11 +350,10 @@
         int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
         int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
         int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
-        // VPN's meteredness is OR'd with isAlwaysMetered and meteredness of its underlying
-        // networks.
-        boolean metered = isAlwaysMetered;
-        boolean roaming = false;
-        boolean congested = false;
+        boolean metered = isAlwaysMetered; // metered if any underlying is metered, or alwaysMetered
+        boolean roaming = false; // roaming if any underlying is roaming
+        boolean congested = false; // congested if any underlying is congested
+        boolean suspended = true; // suspended if all underlying are suspended
 
         boolean hadUnderlyingNetworks = false;
         if (null != underlyingNetworks) {
@@ -367,15 +366,24 @@
                     transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType);
                 }
 
-                // When we have multiple networks, we have to assume the
-                // worst-case link speed and restrictions.
+                // Merge capabilities of this underlying network. For bandwidth, assume the
+                // worst case.
                 downKbps = NetworkCapabilities.minBandwidth(downKbps,
                         underlyingCaps.getLinkDownstreamBandwidthKbps());
                 upKbps = NetworkCapabilities.minBandwidth(upKbps,
                         underlyingCaps.getLinkUpstreamBandwidthKbps());
+                // If this underlying network is metered, the VPN is metered (it may cost money
+                // to send packets on this network).
                 metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
+                // If this underlying network is roaming, the VPN is roaming (the billing structure
+                // is different than the usual, local one).
                 roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING);
+                // If this underlying network is congested, the VPN is congested (the current
+                // condition of the network affects the performance of this network).
                 congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED);
+                // If this network is not suspended, the VPN is not suspended (the VPN
+                // is able to transfer some data).
+                suspended &= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
             }
         }
         if (!hadUnderlyingNetworks) {
@@ -383,6 +391,7 @@
             metered = true;
             roaming = false;
             congested = false;
+            suspended = false;
         }
 
         caps.setTransportTypes(transportTypes);
@@ -391,6 +400,7 @@
         caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
         caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
         caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
+        caps.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended);
     }
 
     /**
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index a099606..b9cd43d 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -51,6 +51,11 @@
     private static final float MAX_GRAD = 1.0f;
     private static final float SHORT_TERM_MODEL_THRESHOLD_RATIO = 0.6f;
 
+    // Constant that ensures that each step of the curve can increase by up to at least
+    // MIN_PERMISSABLE_INCREASE. Otherwise when the brightness is set to 0, the curve will never
+    // increase and will always be 0.
+    private static final float MIN_PERMISSABLE_INCREASE =  0.004f;
+
     protected boolean mLoggingEnabled;
 
     private static final Plog PLOG = Plog.createSystemPlog(TAG);
@@ -400,7 +405,9 @@
         for (int i = idx+1; i < lux.length; i++) {
             float currLux = lux[i];
             float currBrightness = brightness[i];
-            float maxBrightness = prevBrightness * permissibleRatio(currLux, prevLux);
+            float maxBrightness = MathUtils.max(
+                    prevBrightness * permissibleRatio(currLux, prevLux),
+                    prevBrightness + MIN_PERMISSABLE_INCREASE);
             float newBrightness = MathUtils.constrain(
                     currBrightness, prevBrightness, maxBrightness);
             if (newBrightness == currBrightness) {
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index c54ebf8..3c05080 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -92,7 +92,7 @@
     private final AppRequestObserver mAppRequestObserver;
     private final SettingsObserver mSettingsObserver;
     private final DisplayObserver mDisplayObserver;
-    private final BrightnessObserver mBrightnessObserver;
+    private BrightnessObserver mBrightnessObserver;
 
     private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
     private DesiredDisplayModeSpecsListener mDesiredDisplayModeSpecsListener;
@@ -460,6 +460,21 @@
         mVotesByDisplay = votesByDisplay;
     }
 
+    @VisibleForTesting
+    void injectBrightnessObserver(BrightnessObserver brightnessObserver) {
+        mBrightnessObserver = brightnessObserver;
+    }
+
+    @VisibleForTesting
+    DesiredDisplayModeSpecs getDesiredDisplayModeSpecsWithInjectedFpsSettings(
+            float minRefreshRate, float peakRefreshRate, float defaultRefreshRate) {
+        synchronized (mLock) {
+            mSettingsObserver.updateRefreshRateSettingLocked(
+                    minRefreshRate, peakRefreshRate, defaultRefreshRate);
+            return getDesiredDisplayModeSpecs(Display.DEFAULT_DISPLAY);
+        }
+    }
+
     /**
      * Listens for changes refresh rate coordination.
      */
@@ -666,14 +681,18 @@
 
     @VisibleForTesting
     static final class Vote {
+        // DEFAULT_FRAME_RATE votes for [0, DEFAULT]. As the lowest priority vote, it's overridden
+        // by all other considerations. It acts to set a default frame rate for a device.
+        public static final int PRIORITY_DEFAULT_REFRESH_RATE = 0;
+
         // LOW_BRIGHTNESS votes for a single refresh rate like [60,60], [90,90] or null.
         // If the higher voters result is a range, it will fix the rate to a single choice.
         // It's used to avoid rate switch in certain conditions.
-        public static final int PRIORITY_LOW_BRIGHTNESS = 0;
+        public static final int PRIORITY_LOW_BRIGHTNESS = 1;
 
         // SETTING_MIN_REFRESH_RATE is used to propose a lower bound of display refresh rate.
         // It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY]
-        public static final int PRIORITY_USER_SETTING_MIN_REFRESH_RATE = 1;
+        public static final int PRIORITY_USER_SETTING_MIN_REFRESH_RATE = 2;
 
         // We split the app request into different priorities in case we can satisfy one desire
         // without the other.
@@ -683,20 +702,20 @@
         // @see android.view.WindowManager.LayoutParams#preferredDisplayModeId
         // System also forces some apps like blacklisted app to run at a lower refresh rate.
         // @see android.R.array#config_highRefreshRateBlacklist
-        public static final int PRIORITY_APP_REQUEST_REFRESH_RATE = 2;
-        public static final int PRIORITY_APP_REQUEST_SIZE = 3;
+        public static final int PRIORITY_APP_REQUEST_REFRESH_RATE = 3;
+        public static final int PRIORITY_APP_REQUEST_SIZE = 4;
 
         // SETTING_PEAK_REFRESH_RATE has a high priority and will restrict the bounds of the rest
         // of low priority voters. It votes [0, max(PEAK, MIN)]
-        public static final int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 4;
+        public static final int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 5;
 
         // LOW_POWER_MODE force display to [0, 60HZ] if Settings.Global.LOW_POWER_MODE is on.
-        public static final int PRIORITY_LOW_POWER_MODE = 5;
+        public static final int PRIORITY_LOW_POWER_MODE = 6;
 
         // 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.
 
-        public static final int MIN_PRIORITY = PRIORITY_LOW_BRIGHTNESS;
+        public static final int MIN_PRIORITY = PRIORITY_DEFAULT_REFRESH_RATE;
         public static final int MAX_PRIORITY = PRIORITY_LOW_POWER_MODE;
 
         // The cutoff for the app request refresh rate range. Votes with priorities lower than this
@@ -740,6 +759,8 @@
 
         public static String priorityToString(int priority) {
             switch (priority) {
+                case PRIORITY_DEFAULT_REFRESH_RATE:
+                    return "PRIORITY_DEFAULT_REFRESH_RATE";
                 case PRIORITY_LOW_BRIGHTNESS:
                     return "PRIORITY_LOW_BRIGHTNESS";
                 case PRIORITY_USER_SETTING_MIN_REFRESH_RATE:
@@ -776,12 +797,15 @@
 
         private final Context mContext;
         private float mDefaultPeakRefreshRate;
+        private float mDefaultRefreshRate;
 
         SettingsObserver(@NonNull Context context, @NonNull Handler handler) {
             super(handler);
             mContext = context;
             mDefaultPeakRefreshRate = (float) context.getResources().getInteger(
                     R.integer.config_defaultPeakRefreshRate);
+            mDefaultRefreshRate =
+                    (float) context.getResources().getInteger(R.integer.config_defaultRefreshRate);
         }
 
         public void observe() {
@@ -849,17 +873,48 @@
                     Settings.System.MIN_REFRESH_RATE, 0f);
             float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(),
                     Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate);
+            updateRefreshRateSettingLocked(minRefreshRate, peakRefreshRate, mDefaultRefreshRate);
+        }
 
-            updateVoteLocked(Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE,
-                    Vote.forRefreshRates(0f, Math.max(minRefreshRate, peakRefreshRate)));
+        private void updateRefreshRateSettingLocked(
+                float minRefreshRate, float peakRefreshRate, float defaultRefreshRate) {
+            // TODO(b/156304339): The logic in here, aside from updating the refresh rate votes, is
+            // used to predict if we're going to be doing frequent refresh rate switching, and if
+            // so, enable the brightness observer. The logic here is more complicated and fragile
+            // than necessary, and we should improve it. See b/156304339 for more info.
+            Vote peakVote = peakRefreshRate == 0f
+                    ? null
+                    : Vote.forRefreshRates(0f, Math.max(minRefreshRate, peakRefreshRate));
+            updateVoteLocked(Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE, peakVote);
             updateVoteLocked(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE,
                     Vote.forRefreshRates(minRefreshRate, Float.POSITIVE_INFINITY));
+            Vote defaultVote =
+                    defaultRefreshRate == 0f ? null : Vote.forRefreshRates(0f, defaultRefreshRate);
+            updateVoteLocked(Vote.PRIORITY_DEFAULT_REFRESH_RATE, defaultVote);
 
-            mBrightnessObserver.onRefreshRateSettingChangedLocked(minRefreshRate, peakRefreshRate);
+            float maxRefreshRate;
+            if (peakRefreshRate == 0f && defaultRefreshRate == 0f) {
+                // We require that at least one of the peak or default refresh rate values are
+                // set. The brightness observer requires that we're able to predict whether or not
+                // we're going to do frequent refresh rate switching, and with the way the code is
+                // currently written, we need either a default or peak refresh rate value for that.
+                Slog.e(TAG, "Default and peak refresh rates are both 0. One of them should be set"
+                        + " to a valid value.");
+                maxRefreshRate = minRefreshRate;
+            } else if (peakRefreshRate == 0f) {
+                maxRefreshRate = defaultRefreshRate;
+            } else if (defaultRefreshRate == 0f) {
+                maxRefreshRate = peakRefreshRate;
+            } else {
+                maxRefreshRate = Math.min(defaultRefreshRate, peakRefreshRate);
+            }
+
+            mBrightnessObserver.onRefreshRateSettingChangedLocked(minRefreshRate, maxRefreshRate);
         }
 
         public void dumpLocked(PrintWriter pw) {
             pw.println("  SettingsObserver");
+            pw.println("    mDefaultRefreshRate: " + mDefaultRefreshRate);
             pw.println("    mDefaultPeakRefreshRate: " + mDefaultPeakRefreshRate);
         }
     }
@@ -1014,7 +1069,8 @@
      * {@link R.array#config_brightnessThresholdsOfPeakRefreshRate} and
      * {@link R.array#config_ambientThresholdsOfPeakRefreshRate}.
      */
-    private class BrightnessObserver extends ContentObserver {
+    @VisibleForTesting
+    public class BrightnessObserver extends ContentObserver {
         // TODO: brightnessfloat: change this to the float setting
         private final Uri mDisplayBrightnessSetting =
                 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 4f5a02a..2a65b33 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -201,7 +201,6 @@
         private SurfaceControl.DisplayConfig[] mDisplayConfigs;
         private Spline mSystemBrightnessToNits;
         private Spline mNitsToHalBrightness;
-        private boolean mHalBrightnessSupport;
 
         private DisplayDeviceConfig mDisplayDeviceConfig;
 
@@ -225,7 +224,6 @@
             }
             mAllmSupported = SurfaceControl.getAutoLowLatencyModeSupport(displayToken);
             mGameContentTypeSupported = SurfaceControl.getGameContentTypeSupport(displayToken);
-            mHalBrightnessSupport = SurfaceControl.getDisplayBrightnessSupport(displayToken);
             mDisplayDeviceConfig = null;
             // Defer configuration file loading
             BackgroundThread.getHandler().sendMessage(PooledLambda.obtainMessage(
@@ -717,11 +715,10 @@
                         Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
                                 + "id=" + physicalDisplayId + ", brightness=" + brightness + ")");
                         try {
-                            // TODO: make it float
                             if (isHalBrightnessRangeSpecified()) {
                                 brightness = displayBrightnessToHalBrightness(
-                                        BrightnessSynchronizer.brightnessFloatToInt(getContext(),
-                                                brightness));
+                                        BrightnessSynchronizer.brightnessFloatToIntRange(
+                                                getContext(), brightness));
                             }
                             if (mBacklight != null) {
                                 mBacklight.setBrightness(brightness);
@@ -744,12 +741,13 @@
                      * Hal brightness space if the HAL brightness space has been provided via
                      * a display device configuration file.
                      */
-                    private float displayBrightnessToHalBrightness(int brightness) {
+                    private float displayBrightnessToHalBrightness(float brightness) {
                         if (!isHalBrightnessRangeSpecified()) {
                             return PowerManager.BRIGHTNESS_INVALID_FLOAT;
                         }
 
-                        if (brightness == 0) {
+                        if (BrightnessSynchronizer.floatEquals(
+                                brightness, PowerManager.BRIGHTNESS_OFF)) {
                             return PowerManager.BRIGHTNESS_OFF_FLOAT;
                         }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 5541b11..1810963 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -44,9 +44,6 @@
 public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
     private static final String TAG = "HdmiCecLocalDevicePlayback";
 
-    private static final boolean WAKE_ON_HOTPLUG =
-            SystemProperties.getBoolean(Constants.PROPERTY_WAKE_ON_HOTPLUG, false);
-
     private static final boolean SET_MENU_LANGUAGE =
             HdmiProperties.set_menu_language().orElse(false);
 
@@ -152,9 +149,6 @@
         assertRunOnServiceThread();
         mCecMessageCache.flushAll();
         // We'll not clear mIsActiveSource on the hotplug event to pass CETC 11.2.2-2 ~ 3.
-        if (WAKE_ON_HOTPLUG && connected && mService.isPowerStandbyOrTransient()) {
-            mService.wakeUp();
-        }
         if (!connected) {
             getWakeLock().release();
         }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 53f9ebc..9de95ab 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -2207,13 +2207,13 @@
         @Override
         public void setHdmiCecVolumeControlEnabled(final boolean isHdmiCecVolumeControlEnabled) {
             enforceAccessPermission();
-            runOnServiceThread(new Runnable() {
-                @Override
-                public void run() {
-                    HdmiControlService.this.setHdmiCecVolumeControlEnabled(
-                            isHdmiCecVolumeControlEnabled);
-                }
-            });
+            long token = Binder.clearCallingIdentity();
+            try {
+                HdmiControlService.this.setHdmiCecVolumeControlEnabled(
+                        isHdmiCecVolumeControlEnabled);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
         }
 
         @Override
@@ -3014,7 +3014,6 @@
     }
 
     void setHdmiCecVolumeControlEnabled(boolean isHdmiCecVolumeControlEnabled) {
-        assertRunOnServiceThread();
         synchronized (mLock) {
             mHdmiCecVolumeControlEnabled = isHdmiCecVolumeControlEnabled;
 
@@ -3030,7 +3029,6 @@
     }
 
     boolean isHdmiCecVolumeControlEnabled() {
-        assertRunOnServiceThread();
         synchronized (mLock) {
             return mHdmiCecVolumeControlEnabled;
         }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
index d49d4b2..de13bd8 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
@@ -45,6 +45,12 @@
     }
 
     /**
+     * Called by the power manager to tell the input method manager whether it
+     * should start watching for wake events.
+     */
+    public abstract void setInteractive(boolean interactive);
+
+    /**
      * Hides the current input method, if visible.
      */
     public abstract void hideCurrentInputMethod(@SoftInputShowHideReason int reason);
@@ -108,6 +114,10 @@
     private static final InputMethodManagerInternal NOP =
             new InputMethodManagerInternal() {
                 @Override
+                public void setInteractive(boolean interactive) {
+                }
+
+                @Override
                 public void hideCurrentInputMethod(@SoftInputShowHideReason int reason) {
                 }
 
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index b949d6b..52116a0 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -56,6 +56,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.res.Configuration;
@@ -67,6 +68,7 @@
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.input.InputManagerInternal;
 import android.inputmethodservice.InputMethodService;
+import android.media.AudioManagerInternal;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -223,6 +225,8 @@
 
     static final int MSG_INLINE_SUGGESTIONS_REQUEST = 6000;
 
+    static final int MSG_NOTIFY_IME_UID_TO_AUDIO_SERVICE = 7000;
+
     static final long TIME_TO_RECONNECT = 3 * 1000;
 
     static final int SECURE_SUGGESTION_SPANS_MAX_SIZE = 20;
@@ -308,6 +312,7 @@
     final SettingsObserver mSettingsObserver;
     final IWindowManager mIWindowManager;
     final WindowManagerInternal mWindowManagerInternal;
+    final PackageManagerInternal mPackageManagerInternal;
     final InputManagerInternal mInputManagerInternal;
     private final DisplayManagerInternal mDisplayManagerInternal;
     final HandlerCaller mCaller;
@@ -320,6 +325,16 @@
     private final UserManager mUserManager;
     private final UserManagerInternal mUserManagerInternal;
 
+    /**
+     * Cache the result of {@code LocalServices.getService(AudioManagerInternal.class)}.
+     *
+     * <p>This field is used only within {@link #handleMessage(Message)} hence synchronization is
+     * not necessary.</p>
+     */
+    @Nullable
+    private AudioManagerInternal mAudioManagerInternal = null;
+
+
     // All known input methods.  mMethodMap also serves as the global
     // lock for this class.
     final ArrayList<InputMethodInfo> mMethodList = new ArrayList<>();
@@ -643,6 +658,11 @@
     IInputMethod mCurMethod;
 
     /**
+     * If not {@link Process#INVALID_UID}, then the UID of {@link #mCurIntent}.
+     */
+    int mCurMethodUid = Process.INVALID_UID;
+
+    /**
      * Time that we last initiated a bind to the input method, to determine
      * if we should try to disconnect and reconnect to it.
      */
@@ -1625,6 +1645,7 @@
         mIWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService(Context.WINDOW_SERVICE));
         mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
+        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
         mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
         mImeDisplayValidator = displayId -> mWindowManagerInternal.shouldShowIme(displayId);
@@ -2521,11 +2542,26 @@
         return checker.displayCanShowIme(displayId) ? displayId : FALLBACK_DISPLAY_ID;
     }
 
+    @AnyThread
+    private void scheduleNotifyImeUidToAudioService(int uid) {
+        mCaller.removeMessages(MSG_NOTIFY_IME_UID_TO_AUDIO_SERVICE);
+        mCaller.obtainMessageI(MSG_NOTIFY_IME_UID_TO_AUDIO_SERVICE, uid).sendToTarget();
+    }
+
     @Override
     public void onServiceConnected(ComponentName name, IBinder service) {
         synchronized (mMethodMap) {
             if (mCurIntent != null && name.equals(mCurIntent.getComponent())) {
                 mCurMethod = IInputMethod.Stub.asInterface(service);
+                final String curMethodPackage = mCurIntent.getComponent().getPackageName();
+                final int curMethodUid = mPackageManagerInternal.getPackageUidInternal(
+                        curMethodPackage, 0 /* flags */, mSettings.getCurrentUserId());
+                if (curMethodUid < 0) {
+                    Slog.e(TAG, "Failed to get UID for package=" + curMethodPackage);
+                    mCurMethodUid = Process.INVALID_UID;
+                } else {
+                    mCurMethodUid = curMethodUid;
+                }
                 if (mCurToken == null) {
                     Slog.w(TAG, "Service connected without a token!");
                     unbindCurrentMethodLocked();
@@ -2535,6 +2571,7 @@
                 // Dispatch display id for InputMethodService to update context display.
                 executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
                         MSG_INITIALIZE_IME, mCurTokenDisplayId, mCurMethod, mCurToken));
+                scheduleNotifyImeUidToAudioService(mCurMethodUid);
                 if (mCurClient != null) {
                     clearClientSessionLocked(mCurClient);
                     requestClientSessionLocked(mCurClient);
@@ -2656,6 +2693,8 @@
             finishSessionLocked(mEnabledSession);
             mEnabledSession = null;
             mCurMethod = null;
+            mCurMethodUid = Process.INVALID_UID;
+            scheduleNotifyImeUidToAudioService(mCurMethodUid);
         }
         if (mStatusBar != null) {
             mStatusBar.setIconVisibility(mSlotIme, false);
@@ -4202,6 +4241,9 @@
                             + ((ClientState)msg.obj).uid);
                 }
                 return true;
+            case MSG_SET_INTERACTIVE:
+                handleSetInteractive(msg.arg1 != 0);
+                return true;
             case MSG_REPORT_FULLSCREEN_MODE: {
                 final boolean fullscreen = msg.arg1 != 0;
                 final ClientState clientState = (ClientState)msg.obj;
@@ -4259,7 +4301,7 @@
             }
 
             // ---------------------------------------------------------------
-            case MSG_INLINE_SUGGESTIONS_REQUEST:
+            case MSG_INLINE_SUGGESTIONS_REQUEST: {
                 args = (SomeArgs) msg.obj;
                 final InlineSuggestionsRequestInfo requestInfo =
                         (InlineSuggestionsRequestInfo) args.arg2;
@@ -4271,11 +4313,38 @@
                 } catch (RemoteException e) {
                     Slog.w(TAG, "RemoteException calling onCreateInlineSuggestionsRequest(): " + e);
                 }
+                args.recycle();
                 return true;
+            }
+
+            // ---------------------------------------------------------------
+            case MSG_NOTIFY_IME_UID_TO_AUDIO_SERVICE: {
+                if (mAudioManagerInternal == null) {
+                    mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
+                }
+                if (mAudioManagerInternal != null) {
+                    mAudioManagerInternal.setInputMethodServiceUid(msg.arg1 /* uid */);
+                }
+                return true;
+            }
         }
         return false;
     }
 
+    private void handleSetInteractive(final boolean interactive) {
+        synchronized (mMethodMap) {
+            mIsInteractive = interactive;
+            updateSystemUiLocked(interactive ? mImeWindowVis : 0, mBackDisposition);
+
+            // Inform the current client of the change in active status
+            if (mCurClient != null && mCurClient.client != null) {
+                executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIIO(
+                        MSG_SET_ACTIVE, mIsInteractive ? 1 : 0, mInFullscreenMode ? 1 : 0,
+                        mCurClient));
+            }
+        }
+    }
+
     private boolean chooseNewDefaultIMELocked() {
         final InputMethodInfo imi = InputMethodUtils.getMostApplicableDefaultIME(
                 mSettings.getEnabledInputMethodListLocked());
@@ -4885,6 +4954,13 @@
         }
 
         @Override
+        public void setInteractive(boolean interactive) {
+            // Do everything in handler so as not to block the caller.
+            mService.mHandler.obtainMessage(MSG_SET_INTERACTIVE, interactive ? 1 : 0, 0)
+                    .sendToTarget();
+        }
+
+        @Override
         public void hideCurrentInputMethod(@SoftInputShowHideReason int reason) {
             mService.mHandler.removeMessages(MSG_HIDE_CURRENT_INPUT_METHOD);
             mService.mHandler.obtainMessage(MSG_HIDE_CURRENT_INPUT_METHOD, reason).sendToTarget();
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index 0b73e4f..2129e9b 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -171,6 +171,11 @@
             LocalServices.addService(InputMethodManagerInternal.class,
                     new InputMethodManagerInternal() {
                         @Override
+                        public void setInteractive(boolean interactive) {
+                            reportNotSupported();
+                        }
+
+                        @Override
                         public void hideCurrentInputMethod(@SoftInputShowHideReason int reason) {
                             reportNotSupported();
                         }
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index 905a10b..817902d 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -190,6 +190,9 @@
     public void updateRuleSet(
             String version, ParceledListSlice<Rule> rules, IntentSender statusReceiver) {
         String ruleProvider = getCallerPackageNameOrThrow(Binder.getCallingUid());
+        if (DEBUG_INTEGRITY_COMPONENT) {
+            Slog.i(TAG, String.format("Calling rule provider name is: %s.", ruleProvider));
+        }
 
         mHandler.post(
                 () -> {
@@ -201,6 +204,9 @@
                         success = false;
                     }
 
+                    if (DEBUG_INTEGRITY_COMPONENT) {
+                        Slog.i(TAG, String.format("Successfully pushed rule set: %s", version));
+                    }
                     FrameworkStatsLog.write(
                             FrameworkStatsLog.INTEGRITY_RULES_PUSHED,
                             success,
@@ -673,9 +679,6 @@
 
         // Identify the package names in the caller list.
         List<String> callingPackageNames = getPackageListForUid(callingUid);
-        if (DEBUG_INTEGRITY_COMPONENT) {
-            Slog.i(TAG, String.format("Calling packages are: ", callingPackageNames));
-        }
 
         // Find the intersection between the allowed and calling packages. Ideally, we will have
         // at most one package name here. But if we have more, it is fine.
@@ -685,10 +688,7 @@
                 allowedCallingPackages.add(packageName);
             }
         }
-        if (DEBUG_INTEGRITY_COMPONENT) {
-            Slog.i(TAG,
-                    String.format("Calling rule pusher packages are: ", allowedCallingPackages));
-        }
+
         return allowedCallingPackages.isEmpty() ? null : allowedCallingPackages.get(0);
     }
 
@@ -706,9 +706,6 @@
                 Arrays.asList(
                         mContext.getResources()
                                 .getStringArray(R.array.config_integrityRuleProviderPackages));
-        if (DEBUG_INTEGRITY_COMPONENT) {
-            Slog.i(TAG, String.format("Rule provider list contains: %s", integrityRuleProviders));
-        }
 
         // Filter out the rule provider packages that are not system apps.
         List<String> systemAppRuleProviders = new ArrayList<>();
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index 8888108..c4f8441 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -41,9 +41,12 @@
 import com.android.internal.BrightnessSynchronizer;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.Preconditions;
 import com.android.server.SystemService;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -174,6 +177,36 @@
             closeSessionInternal(token);
         }
 
+        @Override
+        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
+
+            synchronized (LightsService.this) {
+                if (mVintfLights != null) {
+                    pw.println("Service: aidl (" + mVintfLights.get() + ")");
+                } else {
+                    pw.println("Service: hidl");
+                }
+
+                pw.println("Lights:");
+                for (int i = 0; i < mLightsById.size(); i++) {
+                    final LightImpl light = mLightsById.valueAt(i);
+                    pw.println(String.format("  Light id=%d ordinal=%d color=%08x",
+                            light.mHwLight.id, light.mHwLight.ordinal, light.getColor()));
+                }
+
+                pw.println("Session clients:");
+                for (Session session : mSessions) {
+                    pw.println("  Session token=" + session.mToken);
+                    for (int i = 0; i < session.mRequests.size(); i++) {
+                        pw.println(String.format("    Request id=%d color=%08x",
+                                session.mRequests.keyAt(i),
+                                session.mRequests.valueAt(i).getColor()));
+                    }
+                }
+            }
+        }
+
         private void closeSessionInternal(IBinder token) {
             synchronized (LightsService.this) {
                 final Session session = getSessionLocked(token);
diff --git a/services/core/java/com/android/server/lights/TEST_MAPPING b/services/core/java/com/android/server/lights/TEST_MAPPING
new file mode 100644
index 0000000..f868ea0
--- /dev/null
+++ b/services/core/java/com/android/server/lights/TEST_MAPPING
@@ -0,0 +1,21 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsHardwareTestCases",
+      "options": [
+        {"include-filter": "com.android.hardware.lights"},
+        {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
+        {"exclude-annotation": "androidx.test.filters.LargeTest"},
+        {"exclude-annotation": "androidx.test.filters.FlakyTest"}
+      ]
+    },
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {"include-filter": "com.android.server.lights"},
+        {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
+        {"exclude-annotation": "androidx.test.filters.FlakyTest"}
+      ]
+    }
+  ]
+}
diff --git a/services/core/java/com/android/server/location/gnss/GnssVisibilityControl.java b/services/core/java/com/android/server/location/gnss/GnssVisibilityControl.java
index 75fd7dc..927fcfb 100644
--- a/services/core/java/com/android/server/location/gnss/GnssVisibilityControl.java
+++ b/services/core/java/com/android/server/location/gnss/GnssVisibilityControl.java
@@ -630,7 +630,7 @@
         }
 
         Notification.Builder builder = new Notification.Builder(mContext,
-                SystemNotificationChannels.NETWORK_ALERTS)
+                SystemNotificationChannels.NETWORK_STATUS)
                 .setSmallIcon(R.drawable.stat_sys_gps_on)
                 .setCategory(Notification.CATEGORY_SYSTEM)
                 .setVisibility(Notification.VISIBILITY_SECRET)
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index ac982dd..1a8de97 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -312,7 +312,7 @@
         }
 
         void register(LockSettingsStrongAuth strongAuth) {
-            strongAuth.registerStrongAuthTracker(this.mStub);
+            strongAuth.registerStrongAuthTracker(getStub());
         }
     }
 
diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
index 54958d3..6acfd45 100644
--- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java
+++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
@@ -28,10 +28,12 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.media.AudioManager;
+import android.media.AudioSystem;
 import android.media.MediaRoute2Info;
 import android.text.TextUtils;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
 
 import com.android.internal.R;
 
@@ -55,6 +57,9 @@
     @SuppressWarnings("WeakerAccess") /* synthetic access */
     BluetoothHearingAid mHearingAidProfile;
 
+    // Route type -> volume map
+    private final SparseIntArray mVolumeMap = new SparseIntArray();
+
     private final Context mContext;
     private final BluetoothAdapter mBluetoothAdapter;
     private final BluetoothRoutesUpdatedListener mListener;
@@ -164,7 +169,9 @@
         for (BluetoothDevice device : mBluetoothAdapter.getBondedDevices()) {
             if (device.isConnected()) {
                 BluetoothRouteInfo newBtRoute = createBluetoothRoute(device);
-                mBluetoothRoutes.put(device.getAddress(), newBtRoute);
+                if (newBtRoute.connectedProfiles.size() > 0) {
+                    mBluetoothRoutes.put(device.getAddress(), newBtRoute);
+                }
             }
         }
     }
@@ -192,11 +199,30 @@
         return routes;
     }
 
-    boolean setSelectedRouteVolume(int volume) {
-        if (mSelectedRoute == null) return false;
+    /**
+     * Updates the volume for {@link AudioManager#getDevicesForStream(int) devices}.
+     *
+     * @return true if devices can be handled by the provider.
+     */
+    public boolean updateVolumeForDevices(int devices, int volume) {
+        int routeType;
+        if ((devices & (AudioSystem.DEVICE_OUT_HEARING_AID)) != 0) {
+            routeType = MediaRoute2Info.TYPE_HEARING_AID;
+        } else if ((devices & (AudioManager.DEVICE_OUT_BLUETOOTH_A2DP
+                | AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES
+                | AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0) {
+            routeType = MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+        } else {
+            return false;
+        }
+        mVolumeMap.put(routeType, volume);
+        if (mSelectedRoute == null || mSelectedRoute.route.getType() != routeType) {
+            return true;
+        }
         mSelectedRoute.route = new MediaRoute2Info.Builder(mSelectedRoute.route)
                 .setVolume(volume)
                 .build();
+        notifyBluetoothRoutesUpdated();
         return true;
     }
 
@@ -209,21 +235,32 @@
     private BluetoothRouteInfo createBluetoothRoute(BluetoothDevice device) {
         BluetoothRouteInfo newBtRoute = new BluetoothRouteInfo();
         newBtRoute.btDevice = device;
-        // Current / Max volume will be set when connected.
+        // Current volume will be set when connected.
         // TODO: Is there any BT device which has fixed volume?
         String deviceName = device.getName();
         if (TextUtils.isEmpty(deviceName)) {
             deviceName = mContext.getResources().getText(R.string.unknownName).toString();
         }
+        int type = MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+        newBtRoute.connectedProfiles = new SparseBooleanArray();
+        if (mA2dpProfile != null && mA2dpProfile.getConnectedDevices().contains(device)) {
+            newBtRoute.connectedProfiles.put(BluetoothProfile.A2DP, true);
+        }
+        if (mHearingAidProfile != null
+                && mHearingAidProfile.getConnectedDevices().contains(device)) {
+            newBtRoute.connectedProfiles.put(BluetoothProfile.HEARING_AID, true);
+            type = MediaRoute2Info.TYPE_HEARING_AID;
+        }
+
         newBtRoute.route = new MediaRoute2Info.Builder(device.getAddress(), deviceName)
                 .addFeature(MediaRoute2Info.FEATURE_LIVE_AUDIO)
                 .setConnectionState(MediaRoute2Info.CONNECTION_STATE_DISCONNECTED)
                 .setDescription(mContext.getResources().getText(
                         R.string.bluetooth_a2dp_audio_route_name).toString())
-                .setType(MediaRoute2Info.TYPE_BLUETOOTH_A2DP)
+                .setType(type)
                 .setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+                .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
                 .build();
-        newBtRoute.connectedProfiles = new SparseBooleanArray();
         return newBtRoute;
     }
 
@@ -240,13 +277,10 @@
         // Update volume when the connection state is changed.
         MediaRoute2Info.Builder builder = new MediaRoute2Info.Builder(btRoute.route)
                 .setConnectionState(state);
-        builder.setType(btRoute.connectedProfiles.get(BluetoothProfile.HEARING_AID, false)
-                ? MediaRoute2Info.TYPE_HEARING_AID : MediaRoute2Info.TYPE_BLUETOOTH_A2DP);
+        builder.setType(btRoute.getRouteType());
 
         if (state == MediaRoute2Info.CONNECTION_STATE_CONNECTED) {
-            int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
-            int currentVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
-            builder.setVolumeMax(maxVolume).setVolume(currentVolume);
+            builder.setVolume(mVolumeMap.get(btRoute.getRouteType(), 0));
         }
         btRoute.route = builder.build();
     }
@@ -259,6 +293,15 @@
         public BluetoothDevice btDevice;
         public MediaRoute2Info route;
         public SparseBooleanArray connectedProfiles;
+
+        @MediaRoute2Info.Type
+        int getRouteType() {
+            // Let hearing aid profile have a priority.
+            if (connectedProfiles.get(BluetoothProfile.HEARING_AID, false)) {
+                return MediaRoute2Info.TYPE_HEARING_AID;
+            }
+            return MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+        }
     }
 
     // These callbacks run on the main thread.
@@ -290,8 +333,6 @@
                     setRouteConnectionState(mSelectedRoute,
                             MediaRoute2Info.CONNECTION_STATE_CONNECTED);
                 }
-
-                btRoute.connectedProfiles.put(profile, true);
             }
             notifyBluetoothRoutesUpdated();
         }
@@ -349,15 +390,10 @@
             BluetoothRouteInfo btRoute = mBluetoothRoutes.get(device.getAddress());
             if (bondState == BluetoothDevice.BOND_BONDED && btRoute == null) {
                 btRoute = createBluetoothRoute(device);
-                if (mA2dpProfile != null && mA2dpProfile.getConnectedDevices().contains(device)) {
-                    btRoute.connectedProfiles.put(BluetoothProfile.A2DP, true);
+                if (btRoute.connectedProfiles.size() > 0) {
+                    mBluetoothRoutes.put(device.getAddress(), btRoute);
+                    notifyBluetoothRoutesUpdated();
                 }
-                if (mHearingAidProfile != null
-                        && mHearingAidProfile.getConnectedDevices().contains(device)) {
-                    btRoute.connectedProfiles.put(BluetoothProfile.HEARING_AID, true);
-                }
-                mBluetoothRoutes.put(device.getAddress(), btRoute);
-                notifyBluetoothRoutesUpdated();
             } else if (bondState == BluetoothDevice.BOND_NONE
                     && mBluetoothRoutes.remove(device.getAddress()) != null) {
                 notifyBluetoothRoutesUpdated();
@@ -398,9 +434,10 @@
             if (state == BluetoothProfile.STATE_CONNECTED) {
                 if (btRoute == null) {
                     btRoute = createBluetoothRoute(device);
-                    mBluetoothRoutes.put(device.getAddress(), btRoute);
-                    btRoute.connectedProfiles.put(profile, true);
-                    notifyBluetoothRoutesUpdated();
+                    if (btRoute.connectedProfiles.size() > 0) {
+                        mBluetoothRoutes.put(device.getAddress(), btRoute);
+                        notifyBluetoothRoutesUpdated();
+                    }
                 } else {
                     btRoute.connectedProfiles.put(profile, true);
                 }
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
index a435f1e..53205ad 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
@@ -60,7 +60,7 @@
     private Connection mActiveConnection;
     private boolean mConnectionReady;
 
-    private RouteDiscoveryPreference mPendingDiscoveryPreference = null;
+    private RouteDiscoveryPreference mLastDiscoveryPreference = null;
 
     MediaRoute2ProviderServiceProxy(@NonNull Context context, @NonNull ComponentName componentName,
             int userId) {
@@ -98,11 +98,10 @@
 
     @Override
     public void updateDiscoveryPreference(RouteDiscoveryPreference discoveryPreference) {
+        mLastDiscoveryPreference = discoveryPreference;
         if (mConnectionReady) {
             mActiveConnection.updateDiscoveryPreference(discoveryPreference);
             updateBinding();
-        } else {
-            mPendingDiscoveryPreference = discoveryPreference;
         }
     }
 
@@ -277,9 +276,8 @@
     private void onConnectionReady(Connection connection) {
         if (mActiveConnection == connection) {
             mConnectionReady = true;
-            if (mPendingDiscoveryPreference != null) {
-                updateDiscoveryPreference(mPendingDiscoveryPreference);
-                mPendingDiscoveryPreference = null;
+            if (mLastDiscoveryPreference != null) {
+                updateDiscoveryPreference(mLastDiscoveryPreference);
             }
         }
     }
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 5e865e7..c65800a 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -584,7 +584,8 @@
         mAllRouterRecords.put(binder, routerRecord);
 
         userRecord.mHandler.sendMessage(
-                obtainMessage(UserHandler::notifyRoutesToRouter, userRecord.mHandler, router));
+                obtainMessage(UserHandler::notifyRoutesToRouter,
+                        userRecord.mHandler, routerRecord));
     }
 
     private void unregisterRouter2Locked(@NonNull IMediaRouter2 router, boolean died) {
@@ -807,14 +808,11 @@
                 userRecord.mHandler, manager));
 
         for (RouterRecord routerRecord : userRecord.mRouterRecords) {
-            // TODO: Do not use notifyPreferredFeaturesChangedToManagers since it updates all
-            // managers. Instead, Notify only to the manager that is currently being registered.
-
             // TODO: UserRecord <-> routerRecord, why do they reference each other?
             // How about removing mUserRecord from routerRecord?
             routerRecord.mUserRecord.mHandler.sendMessage(
-                    obtainMessage(UserHandler::notifyPreferredFeaturesChangedToManagers,
-                        routerRecord.mUserRecord.mHandler, routerRecord));
+                    obtainMessage(UserHandler::notifyPreferredFeaturesChangedToManager,
+                        routerRecord.mUserRecord.mHandler, routerRecord, manager));
         }
     }
 
@@ -1775,16 +1773,36 @@
             }
         }
 
-        private void notifyRoutesToRouter(@NonNull IMediaRouter2 router) {
+        private void notifyRoutesToRouter(@NonNull RouterRecord routerRecord) {
             List<MediaRoute2Info> routes = new ArrayList<>();
+
+            MediaRoute2ProviderInfo systemProviderInfo = null;
             for (MediaRoute2ProviderInfo providerInfo : mLastProviderInfos) {
+                // TODO: Create MediaRoute2ProviderInfo#isSystemProvider()
+                if (TextUtils.equals(providerInfo.getUniqueId(), mSystemProvider.getUniqueId())) {
+                    // Adding routes from system provider will be handled below, so skip it here.
+                    systemProviderInfo = providerInfo;
+                    continue;
+                }
                 routes.addAll(providerInfo.getRoutes());
             }
+
+            if (routerRecord.mHasModifyAudioRoutingPermission) {
+                if (systemProviderInfo != null) {
+                    routes.addAll(systemProviderInfo.getRoutes());
+                } else {
+                    // This shouldn't happen.
+                    Slog.w(TAG, "notifyRoutesToRouter: System route provider not found.");
+                }
+            } else {
+                routes.add(mSystemProvider.getDefaultRoute());
+            }
+
             if (routes.size() == 0) {
                 return;
             }
             try {
-                router.notifyRoutesAdded(routes);
+                routerRecord.mRouter.notifyRoutesAdded(routes);
             } catch (RemoteException ex) {
                 Slog.w(TAG, "Failed to notify all routes. Router probably died.", ex);
             }
@@ -1907,6 +1925,17 @@
             }
         }
 
+        private void notifyPreferredFeaturesChangedToManager(@NonNull RouterRecord routerRecord,
+                @NonNull IMediaRouter2Manager manager) {
+            try {
+                manager.notifyPreferredFeaturesChanged(routerRecord.mPackageName,
+                        routerRecord.mDiscoveryPreference.getPreferredFeatures());
+            } catch (RemoteException ex) {
+                Slog.w(TAG, "Failed to notify preferred features changed."
+                        + " Manager probably died.", ex);
+            }
+        }
+
         private void notifyPreferredFeaturesChangedToManagers(@NonNull RouterRecord routerRecord) {
             MediaRouter2ServiceImpl service = mServiceRef.get();
             if (service == null) {
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 67f9782..02b7582 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -328,7 +328,7 @@
                 public void run() {
                     try {
                         mAudioManagerInternal.setStreamVolumeForUid(stream, volumeValue, flags,
-                                opPackageName, uid);
+                                opPackageName, uid, pid);
                     } catch (IllegalArgumentException | SecurityException e) {
                         Log.e(TAG, "Cannot set volume: stream=" + stream + ", value=" + volumeValue
                                 + ", flags=" + flags, e);
@@ -501,12 +501,15 @@
         // Must use opPackageName for adjusting volumes with UID.
         final String opPackageName;
         final int uid;
+        final int pid;
         if (asSystemService) {
             opPackageName = mContext.getOpPackageName();
             uid = Process.SYSTEM_UID;
+            pid = Process.myPid();
         } else {
             opPackageName = callingOpPackageName;
             uid = callingUid;
+            pid = callingPid;
         }
         mHandler.post(new Runnable() {
             @Override
@@ -515,15 +518,15 @@
                     if (useSuggested) {
                         if (AudioSystem.isStreamActive(stream, 0)) {
                             mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream,
-                                    direction, flags, opPackageName, uid);
+                                    direction, flags, opPackageName, uid, pid);
                         } else {
                             mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(
                                     AudioManager.USE_DEFAULT_STREAM_TYPE, direction,
-                                    flags | previousFlagPlaySound, opPackageName, uid);
+                                    flags | previousFlagPlaySound, opPackageName, uid, pid);
                         }
                     } else {
                         mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags,
-                                opPackageName, uid);
+                                opPackageName, uid, pid);
                     }
                 } catch (IllegalArgumentException | SecurityException e) {
                     Log.e(TAG, "Cannot adjust volume: direction=" + direction + ", stream="
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index bc0e816..f360a4a 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -342,13 +342,10 @@
         updateUser();
     }
 
-    // Called when the user with the userId is removed.
     @Override
-    public void onStopUser(int userId) {
-        if (DEBUG) Log.d(TAG, "onStopUser: " + userId);
+    public void onCleanupUser(int userId) {
+        if (DEBUG) Log.d(TAG, "onCleanupUser: " + userId);
         synchronized (mLock) {
-            // TODO: Also handle removing user in updateUser() because adding/switching user is
-            //       handled in updateUser().
             FullUserRecord user = getFullUserRecordLocked(userId);
             if (user != null) {
                 if (user.mFullUserId == userId) {
@@ -1134,8 +1131,19 @@
                 if (cb == null) {
                     throw new IllegalArgumentException("Controller callback cannot be null");
                 }
-                return createSessionInternal(pid, uid, resolvedUserId, packageName, cb, tag,
-                        sessionInfo).getSessionBinder();
+                MediaSessionRecord session = createSessionInternal(
+                        pid, uid, resolvedUserId, packageName, cb, tag, sessionInfo);
+                if (session == null) {
+                    throw new IllegalStateException("Failed to create a new session record");
+                }
+                ISession sessionBinder = session.getSessionBinder();
+                if (sessionBinder == null) {
+                    throw new IllegalStateException("Invalid session record");
+                }
+                return sessionBinder;
+            } catch (Exception e) {
+                Slog.w(TAG, "Exception in creating a new session", e);
+                throw e;
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -2096,16 +2104,19 @@
                     public void run() {
                         final String callingOpPackageName;
                         final int callingUid;
+                        final int callingPid;
                         if (asSystemService) {
                             callingOpPackageName = mContext.getOpPackageName();
                             callingUid = Process.myUid();
+                            callingPid = Process.myPid();
                         } else {
                             callingOpPackageName = opPackageName;
                             callingUid = uid;
+                            callingPid = pid;
                         }
                         try {
                             mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(suggestedStream,
-                                    direction, flags, callingOpPackageName, callingUid);
+                                    direction, flags, callingOpPackageName, callingUid, callingPid);
                         } catch (SecurityException | IllegalArgumentException e) {
                             Log.e(TAG, "Cannot adjust volume: direction=" + direction
                                     + ", suggestedStream=" + suggestedStream + ", flags=" + flags
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index b585b49..d7e7247 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -45,7 +45,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.text.TextUtils;
-import android.util.Log;
+import android.util.Slog;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
@@ -58,7 +58,8 @@
 // TODO: check thread safety. We may need to use lock to protect variables.
 class SystemMediaRoute2Provider extends MediaRoute2Provider {
     private static final String TAG = "MR2SystemProvider";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    // TODO(b/156996903): Revert it when releasing the framework.
+    private static final boolean DEBUG = true;
 
     static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
     static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
@@ -81,6 +82,7 @@
     MediaRoute2Info mDeviceRoute;
     RoutingSessionInfo mDefaultSessionInfo;
     final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();
+    int mDeviceVolume;
 
     private final Object mRequestLock = new Object();
     @GuardedBy("mRequestLock")
@@ -127,8 +129,9 @@
         });
         updateSessionInfosIfNeeded();
 
-        mContext.registerReceiver(new VolumeChangeReceiver(),
-                new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION));
+        IntentFilter intentFilter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
+        intentFilter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
+        mContext.registerReceiver(new AudioManagerBroadcastReceiver(), intentFilter);
 
         if (mBtRouteProvider != null) {
             mHandler.post(() -> {
@@ -136,6 +139,7 @@
                 notifyProviderState();
             });
         }
+        updateVolume();
     }
 
     @Override
@@ -248,8 +252,8 @@
                 .setVolumeHandling(mAudioManager.isVolumeFixed()
                         ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
                         : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+                .setVolume(mDeviceVolume)
                 .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
-                .setVolume(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC))
                 .setType(type)
                 .addFeature(FEATURE_LIVE_AUDIO)
                 .addFeature(FEATURE_LIVE_VIDEO)
@@ -266,7 +270,11 @@
                 builder.addRoute(route);
             }
         }
-        setProviderState(builder.build());
+        MediaRoute2ProviderInfo providerInfo = builder.build();
+        setProviderState(providerInfo);
+        if (DEBUG) {
+            Slog.d(TAG, "Updating system provider info : " + providerInfo);
+        }
     }
 
     /**
@@ -324,6 +332,9 @@
             if (Objects.equals(oldSessionInfo, newSessionInfo)) {
                 return false;
             } else {
+                if (DEBUG) {
+                    Slog.d(TAG, "Updating system routing session info : " + newSessionInfo);
+                }
                 mSessionInfos.clear();
                 mSessionInfos.add(newSessionInfo);
                 mDefaultSessionInfo = new RoutingSessionInfo.Builder(
@@ -361,36 +372,43 @@
         }
     }
 
-    private class VolumeChangeReceiver extends BroadcastReceiver {
+    void updateVolume() {
+        int devices = mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC);
+        int volume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
+
+        if (mDefaultRoute.getVolume() != volume) {
+            mDefaultRoute = new MediaRoute2Info.Builder(mDefaultRoute)
+                    .setVolume(volume)
+                    .build();
+        }
+
+        if (mBtRouteProvider != null && mBtRouteProvider.updateVolumeForDevices(devices, volume)) {
+            return;
+        }
+        if (mDeviceVolume != volume) {
+            mDeviceVolume = volume;
+            mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
+                    .setVolume(volume)
+                    .build();
+        }
+        publishProviderState();
+    }
+
+    private class AudioManagerBroadcastReceiver extends BroadcastReceiver {
         // This will be called in the main thread.
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (!intent.getAction().equals(AudioManager.VOLUME_CHANGED_ACTION)) {
+            if (!intent.getAction().equals(AudioManager.VOLUME_CHANGED_ACTION)
+                    && !intent.getAction().equals(AudioManager.STREAM_DEVICES_CHANGED_ACTION)) {
                 return;
             }
 
-            final int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+            int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
             if (streamType != AudioManager.STREAM_MUSIC) {
                 return;
             }
 
-            final int newVolume = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
-            final int oldVolume = intent.getIntExtra(
-                    AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, 0);
-
-            if (newVolume != oldVolume) {
-                if (TextUtils.equals(mDeviceRoute.getId(), mSelectedRouteId)) {
-                    mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
-                            .setVolume(newVolume)
-                            .build();
-                } else if (mBtRouteProvider != null) {
-                    mBtRouteProvider.setSelectedRouteVolume(newVolume);
-                }
-                mDefaultRoute = new MediaRoute2Info.Builder(mDefaultRoute)
-                        .setVolume(newVolume)
-                        .build();
-                publishProviderState();
-            }
+            updateVolume();
         }
     }
 }
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 9e509f4..1a749b3 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -22,6 +22,7 @@
 import android.app.IProcessObserver;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ServiceInfo;
@@ -43,6 +44,7 @@
 import android.util.ArrayMap;
 import android.util.Slog;
 
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -399,11 +401,12 @@
         public final UserHandle userHandle;
         private final int mTargetSdkVersion;
         private final boolean mIsPrivileged;
+        private final int mType;
 
         private IMediaProjectionCallback mCallback;
         private IBinder mToken;
         private IBinder.DeathRecipient mDeathEater;
-        private int mType;
+        private boolean mRestoreSystemAlertWindow;
 
         MediaProjection(int type, int uid, String packageName, int targetSdkVersion,
                 boolean isPrivileged) {
@@ -494,6 +497,35 @@
                             "MediaProjectionCallbacks must be valid, aborting MediaProjection", e);
                     return;
                 }
+                if (mType == MediaProjectionManager.TYPE_SCREEN_CAPTURE) {
+                    final long token = Binder.clearCallingIdentity();
+                    try {
+                        // We allow an app running a current screen capture session to use
+                        // SYSTEM_ALERT_WINDOW for the duration of the session, to enable
+                        // them to overlay their UX on top of what is being captured.
+                        // We only do this if the app requests the permission, and the appop
+                        // is in its default state (the user has neither explicitly allowed nor
+                        // disallowed it).
+                        final PackageInfo packageInfo = mPackageManager.getPackageInfoAsUser(
+                                packageName, PackageManager.GET_PERMISSIONS,
+                                UserHandle.getUserId(uid));
+                        if (ArrayUtils.contains(packageInfo.requestedPermissions,
+                                Manifest.permission.SYSTEM_ALERT_WINDOW)) {
+                            final int currentMode = mAppOps.unsafeCheckOpRawNoThrow(
+                                    AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName);
+                            if (currentMode == AppOpsManager.MODE_DEFAULT) {
+                                mAppOps.setMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid,
+                                        packageName, AppOpsManager.MODE_ALLOWED);
+                                mRestoreSystemAlertWindow = true;
+                            }
+                        }
+                    } catch (PackageManager.NameNotFoundException e) {
+                        Slog.w(TAG, "Package not found, aborting MediaProjection", e);
+                        return;
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
                 startProjectionLocked(this);
             }
         }
@@ -507,6 +539,24 @@
                             + "pid=" + Binder.getCallingPid() + ")");
                     return;
                 }
+                if (mRestoreSystemAlertWindow) {
+                    final long token = Binder.clearCallingIdentity();
+                    try {
+                        // Put the appop back how it was, unless it has been changed from what
+                        // we set it to.
+                        // Note that WindowManager takes care of removing any existing overlay
+                        // windows when we do this.
+                        final int currentMode = mAppOps.unsafeCheckOpRawNoThrow(
+                                AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName);
+                        if (currentMode == AppOpsManager.MODE_ALLOWED) {
+                            mAppOps.setMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName,
+                                    AppOpsManager.MODE_DEFAULT);
+                        }
+                        mRestoreSystemAlertWindow = false;
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
                 stopProjectionLocked(this);
                 mToken.unlinkToDeath(mDeathEater, 0);
                 mToken = null;
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index adf0176..dcbdfdf 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -119,7 +119,6 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.PowerManager;
-import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.Trace;
@@ -160,6 +159,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
@@ -227,12 +227,6 @@
     private static final String PREFIX_UID_TAG = "uid_tag";
 
     /**
-     * Virtual network interface for video telephony. This is for VT data usage counting purpose.
-     */
-    // TODO: Remove this after no one is using it.
-    public static final String VT_INTERFACE = NetworkStats.IFACE_VT;
-
-    /**
      * Settings that can be changed externally.
      */
     public interface NetworkStatsSettings {
@@ -304,8 +298,8 @@
             new DropBoxNonMonotonicObserver();
 
     private static final int MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS = 100;
-    private final RemoteCallbackList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList =
-            new RemoteCallbackList<>();
+    private final CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList =
+            new CopyOnWriteArrayList<>();
     /** Semaphore used to wait for stats provider to respond to request stats update. */
     private final Semaphore mStatsProviderSem = new Semaphore(0, true);
 
@@ -1466,10 +1460,14 @@
         final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
 
         // Request asynchronous stats update from all providers for next poll. And wait a bit of
-        // time to allow providers report-in given that normally binder call should be fast.
+        // time to allow providers report-in given that normally binder call should be fast. Note
+        // that size of list might be changed because addition/removing at the same time. For
+        // addition, the stats of the missed provider can only be collected in next poll;
+        // for removal, wait might take up to MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS
+        // once that happened.
         // TODO: request with a valid token.
         Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate");
-        final int registeredCallbackCount = mStatsProviderCbList.getRegisteredCallbackCount();
+        final int registeredCallbackCount = mStatsProviderCbList.size();
         mStatsProviderSem.drainPermits();
         invokeForAllStatsProviderCallbacks(
                 (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */));
@@ -1643,7 +1641,7 @@
 
         @Override
         public void setStatsProviderLimitAsync(@NonNull String iface, long quota) {
-            Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")");
+            if (LOGV) Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")");
             invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetLimit(iface, quota));
         }
     }
@@ -1934,7 +1932,7 @@
             NetworkStatsProviderCallbackImpl callback = new NetworkStatsProviderCallbackImpl(
                     tag, provider, mStatsProviderSem, mAlertObserver,
                     mStatsProviderCbList);
-            mStatsProviderCbList.register(callback);
+            mStatsProviderCbList.add(callback);
             Log.d(TAG, "registerNetworkStatsProvider from " + callback.mTag + " uid/pid="
                     + getCallingUid() + "/" + getCallingPid());
             return callback;
@@ -1958,20 +1956,11 @@
 
     private void invokeForAllStatsProviderCallbacks(
             @NonNull ThrowingConsumer<NetworkStatsProviderCallbackImpl, RemoteException> task) {
-        synchronized (mStatsLock) {
-            final int length = mStatsProviderCbList.beginBroadcast();
+        for (final NetworkStatsProviderCallbackImpl cb : mStatsProviderCbList) {
             try {
-                for (int i = 0; i < length; i++) {
-                    final NetworkStatsProviderCallbackImpl cb =
-                            mStatsProviderCbList.getBroadcastItem(i);
-                    try {
-                        task.accept(cb);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Fail to broadcast to provider: " + cb.mTag, e);
-                    }
-                }
-            } finally {
-                mStatsProviderCbList.finishBroadcast();
+                task.accept(cb);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Fail to broadcast to provider: " + cb.mTag, e);
             }
         }
     }
@@ -1983,7 +1972,7 @@
         @NonNull final INetworkStatsProvider mProvider;
         @NonNull private final Semaphore mSemaphore;
         @NonNull final INetworkManagementEventObserver mAlertObserver;
-        @NonNull final RemoteCallbackList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList;
+        @NonNull final CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList;
 
         @NonNull private final Object mProviderStatsLock = new Object();
 
@@ -1997,7 +1986,7 @@
                 @NonNull String tag, @NonNull INetworkStatsProvider provider,
                 @NonNull Semaphore semaphore,
                 @NonNull INetworkManagementEventObserver alertObserver,
-                @NonNull RemoteCallbackList<NetworkStatsProviderCallbackImpl> cbList)
+                @NonNull CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> cbList)
                 throws RemoteException {
             mTag = tag;
             mProvider = provider;
@@ -2054,13 +2043,13 @@
         @Override
         public void binderDied() {
             Log.d(TAG, mTag + ": binderDied");
-            mStatsProviderCbList.unregister(this);
+            mStatsProviderCbList.remove(this);
         }
 
         @Override
         public void unregister() {
             Log.d(TAG, mTag + ": unregister");
-            mStatsProviderCbList.unregister(this);
+            mStatsProviderCbList.remove(this);
         }
 
     }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index bc7bd23..86e8734 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2725,9 +2725,18 @@
         Context appContext = r.getSbn().getPackageContext(getContext());
         Notification.Builder nb =
                 Notification.Builder.recoverBuilder(appContext, r.getNotification());
-        if (nb.getStyle() instanceof Notification.MessagingStyle && r.getShortcutInfo() == null) {
-            mPreferencesHelper.setMessageSent(r.getSbn().getPackageName(), r.getUid());
-            handleSavePolicyFile();
+        if (nb.getStyle() instanceof Notification.MessagingStyle) {
+            if (r.getShortcutInfo() != null) {
+                if (mPreferencesHelper.setValidMessageSent(
+                        r.getSbn().getPackageName(), r.getUid())) {
+                    handleSavePolicyFile();
+                }
+            } else {
+                if (mPreferencesHelper.setInvalidMessageSent(
+                        r.getSbn().getPackageName(), r.getUid())) {
+                    handleSavePolicyFile();
+                }
+            }
         }
     }
 
@@ -3158,9 +3167,22 @@
         }
 
         @Override
-        public boolean hasSentMessage(String pkg, int uid) {
+        public boolean isInInvalidMsgState(String pkg, int uid) {
             checkCallerIsSystem();
-            return mPreferencesHelper.hasSentMessage(pkg, uid);
+            return mPreferencesHelper.isInInvalidMsgState(pkg, uid);
+        }
+
+        @Override
+        public boolean hasUserDemotedInvalidMsgApp(String pkg, int uid) {
+            checkCallerIsSystem();
+            return mPreferencesHelper.hasUserDemotedInvalidMsgApp(pkg, uid);
+        }
+
+        @Override
+        public void setInvalidMsgAppDemoted(String pkg, int uid, boolean isDemoted) {
+            checkCallerIsSystem();
+            mPreferencesHelper.setInvalidMsgAppDemoted(pkg, uid, isDemoted);
+            handleSavePolicyFile();
         }
 
         @Override
@@ -5698,6 +5720,9 @@
             Slog.w(TAG, "notification " + r.getKey() + " added an invalid shortcut");
         }
         r.setShortcutInfo(info);
+        r.setHasSentValidMsg(mPreferencesHelper.hasSentValidMsg(pkg, notificationUid));
+        r.userDemotedAppFromConvoSpace(
+                mPreferencesHelper.hasUserDemotedInvalidMsgApp(pkg, notificationUid));
 
         if (!checkDisqualifyingFeatures(userId, notificationUid, id, tag, r,
                 r.getSbn().getOverrideGroupKey() != null)) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index a9fa2b1..c107822 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -188,6 +188,8 @@
     private boolean mHasSeenSmartReplies;
     private boolean mFlagBubbleRemoved;
     private boolean mPostSilently;
+    private boolean mHasSentValidMsg;
+    private boolean mAppDemotedFromConvo;
     /**
      * Whether this notification (and its channels) should be considered user locked. Used in
      * conjunction with user sentiment calculation.
@@ -1377,6 +1379,14 @@
         return mShortcutInfo;
     }
 
+    public void setHasSentValidMsg(boolean hasSentValidMsg) {
+        mHasSentValidMsg = hasSentValidMsg;
+    }
+
+    public void userDemotedAppFromConvoSpace(boolean userDemoted) {
+        mAppDemotedFromConvo = userDemoted;
+    }
+
     /**
      * Whether this notification is a conversation notification.
      */
@@ -1397,6 +1407,12 @@
             && mShortcutInfo == null) {
             return false;
         }
+        if (mHasSentValidMsg && mShortcutInfo == null) {
+            return false;
+        }
+        if (mAppDemotedFromConvo) {
+            return false;
+        }
         return true;
     }
 
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
index c6ec95a..2b8ee92 100644
--- a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
+++ b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
@@ -62,7 +62,7 @@
                 /* android.stats.sysui.NotificationImportance importance_asst = 19 */
                 r.getAssistantImportance(),
                 /* int32 assistant_hash = 20 */ p.getAssistantHash(),
-                /* float assistant_ranking_score = 21 */ 0 // TODO connect up ranking score
+                /* float assistant_ranking_score = 21 */ r.getRankingScore()
         );
     }
 
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index ec0fc4a..9d56d81 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -116,7 +116,9 @@
     private static final String ATT_ENABLED = "enabled";
     private static final String ATT_USER_ALLOWED = "allowed";
     private static final String ATT_HIDE_SILENT = "hide_gentle";
-    private static final String ATT_SENT_MESSAGE = "sent_invalid_msg";
+    private static final String ATT_SENT_INVALID_MESSAGE = "sent_invalid_msg";
+    private static final String ATT_SENT_VALID_MESSAGE = "sent_valid_msg";
+    private static final String ATT_USER_DEMOTED_INVALID_MSG_APP = "user_demote_msg_app";
 
     private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT;
     private static final int DEFAULT_VISIBILITY = NotificationManager.VISIBILITY_NO_OVERRIDE;
@@ -253,8 +255,12 @@
                                     parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE);
                             r.lockedAppFields = XmlUtils.readIntAttribute(parser,
                                     ATT_APP_USER_LOCKED_FIELDS, DEFAULT_LOCKED_APP_FIELDS);
-                            r.hasSentMessage = XmlUtils.readBooleanAttribute(
-                                    parser, ATT_SENT_MESSAGE, false);
+                            r.hasSentInvalidMessage = XmlUtils.readBooleanAttribute(
+                                    parser, ATT_SENT_INVALID_MESSAGE, false);
+                            r.hasSentValidMessage = XmlUtils.readBooleanAttribute(
+                                    parser, ATT_SENT_VALID_MESSAGE, false);
+                            r.userDemotedMsgApp = XmlUtils.readBooleanAttribute(
+                                    parser, ATT_USER_DEMOTED_INVALID_MSG_APP, false);
 
                             final int innerDepth = parser.getDepth();
                             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -497,7 +503,9 @@
                                 || r.groups.size() > 0
                                 || r.delegate != null
                                 || r.bubblePreference != DEFAULT_BUBBLE_PREFERENCE
-                                || r.hasSentMessage;
+                                || r.hasSentInvalidMessage
+                                || r.userDemotedMsgApp
+                                || r.hasSentValidMessage;
                 if (hasNonDefaultSettings) {
                     out.startTag(null, TAG_PACKAGE);
                     out.attribute(null, ATT_NAME, r.pkg);
@@ -516,7 +524,12 @@
                     out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(r.showBadge));
                     out.attribute(null, ATT_APP_USER_LOCKED_FIELDS,
                             Integer.toString(r.lockedAppFields));
-                    out.attribute(null, ATT_SENT_MESSAGE, Boolean.toString(r.hasSentMessage));
+                    out.attribute(null, ATT_SENT_INVALID_MESSAGE,
+                            Boolean.toString(r.hasSentInvalidMessage));
+                    out.attribute(null, ATT_SENT_VALID_MESSAGE,
+                            Boolean.toString(r.hasSentValidMessage));
+                    out.attribute(null, ATT_USER_DEMOTED_INVALID_MSG_APP,
+                            Boolean.toString(r.userDemotedMsgApp));
 
                     if (!forBackup) {
                         out.attribute(null, ATT_UID, Integer.toString(r.uid));
@@ -635,15 +648,68 @@
         updateConfig();
     }
 
-    public boolean hasSentMessage(String packageName, int uid) {
+    public boolean isInInvalidMsgState(String packageName, int uid) {
         synchronized (mPackagePreferences) {
-            return getOrCreatePackagePreferencesLocked(packageName, uid).hasSentMessage;
+            PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
+            return r.hasSentInvalidMessage && !r.hasSentValidMessage;
         }
     }
 
-    public void setMessageSent(String packageName, int uid) {
+    public boolean hasUserDemotedInvalidMsgApp(String packageName, int uid) {
         synchronized (mPackagePreferences) {
-            getOrCreatePackagePreferencesLocked(packageName, uid).hasSentMessage = true;
+            PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
+            return isInInvalidMsgState(packageName, uid) ? r.userDemotedMsgApp : false;
+        }
+    }
+
+    public void setInvalidMsgAppDemoted(String packageName, int uid, boolean isDemoted) {
+        synchronized (mPackagePreferences) {
+            PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
+            r.userDemotedMsgApp = isDemoted;
+        }
+    }
+
+    public boolean setInvalidMessageSent(String packageName, int uid) {
+        synchronized (mPackagePreferences) {
+            PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
+            boolean valueChanged = r.hasSentInvalidMessage == false;
+            r.hasSentInvalidMessage = true;
+
+            return valueChanged;
+        }
+    }
+
+    public boolean setValidMessageSent(String packageName, int uid) {
+        synchronized (mPackagePreferences) {
+            PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
+            boolean valueChanged = r.hasSentValidMessage == false;
+            r.hasSentValidMessage = true;
+
+            return valueChanged;
+        }
+    }
+
+    @VisibleForTesting
+    boolean hasSentInvalidMsg(String packageName, int uid) {
+        synchronized (mPackagePreferences) {
+            PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
+            return r.hasSentInvalidMessage;
+        }
+    }
+
+    @VisibleForTesting
+    boolean hasSentValidMsg(String packageName, int uid) {
+        synchronized (mPackagePreferences) {
+            PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
+            return r.hasSentValidMessage;
+        }
+    }
+
+    @VisibleForTesting
+    boolean didUserEverDemoteInvalidMsgApp(String packageName, int uid) {
+        synchronized (mPackagePreferences) {
+            PackagePreferences r = getOrCreatePackagePreferencesLocked(packageName, uid);
+            return r.userDemotedMsgApp;
         }
     }
 
@@ -1870,6 +1936,9 @@
                     event.writeInt(channel.getImportance());
                     event.writeInt(channel.getUserLockedFields());
                     event.writeBoolean(channel.isDeleted());
+                    event.writeBoolean(channel.getConversationId() != null);
+                    event.writeBoolean(channel.isDemoted());
+                    event.writeBoolean(channel.isImportantConversation());
                     events.add(event.build());
                 }
             }
@@ -2273,7 +2342,11 @@
         boolean oemLockedImportance = DEFAULT_OEM_LOCKED_IMPORTANCE;
         List<String> oemLockedChannels = new ArrayList<>();
         boolean defaultAppLockedImportance = DEFAULT_APP_LOCKED_IMPORTANCE;
-        boolean hasSentMessage = false;
+
+        boolean hasSentInvalidMessage = false;
+        boolean hasSentValidMessage = false;
+        // notE: only valid while hasSentMessage is false and hasSentInvalidMessage is true
+        boolean userDemotedMsgApp = false;
 
         Delegate delegate = null;
         ArrayMap<String, NotificationChannel> channels = new ArrayMap<>();
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 70d1ade..830388d 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -417,7 +417,7 @@
     public void grantImplicitAccess(int recipientUid, int visibleUid) {
         if (recipientUid != visibleUid
                 && mImplicitlyQueryable.add(recipientUid, visibleUid) && DEBUG_LOGGING) {
-            Slog.wtf(TAG, "implicit access granted: " + recipientUid + " -> " + visibleUid);
+            Slog.i(TAG, "implicit access granted: " + recipientUid + " -> " + visibleUid);
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index 28c8642d..37f14e8 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -31,6 +31,7 @@
 import android.app.AppOpsManager.Mode;
 import android.app.IApplicationThread;
 import android.app.admin.DevicePolicyEventLogger;
+import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.ComponentName;
 import android.content.Context;
@@ -50,6 +51,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.permission.PermissionManager;
 import android.stats.devicepolicy.DevicePolicyEnums;
 import android.text.TextUtils;
 import android.util.Slog;
@@ -255,6 +257,9 @@
         if (enabledProfileIds.length < 2) {
             return false;
         }
+        if (isProfileOwner(packageName, enabledProfileIds)) {
+            return false;
+        }
         return hasRequestedAppOpPermission(
                 AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName);
     }
@@ -458,6 +463,10 @@
                     + packageName + " on user ID " + userId);
             return;
         }
+
+        final boolean hadPermission = hasInteractAcrossProfilesPermission(
+                packageName, uid, PermissionChecker.PID_UNKNOWN);
+
         final int callingUid = mInjector.getCallingUid();
         if (isPermissionGranted(
                 Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) {
@@ -472,6 +481,22 @@
         }
         sendCanInteractAcrossProfilesChangedBroadcast(packageName, uid, UserHandle.of(userId));
         maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, userId, logMetrics, uid);
+        maybeKillUid(packageName, uid, hadPermission);
+    }
+
+    /**
+     * Kills the process represented by the given UID if it has lost the permission to
+     * interact across profiles.
+     */
+    private void maybeKillUid(
+            String packageName, int uid, boolean hadPermission) {
+        if (!hadPermission) {
+            return;
+        }
+        if (hasInteractAcrossProfilesPermission(packageName, uid, PermissionChecker.PID_UNKNOWN)) {
+            return;
+        }
+        mInjector.killUid(packageName, uid);
     }
 
     private void maybeLogSetInteractAcrossProfilesAppOp(
@@ -554,6 +579,9 @@
         if (profileIds.length < 2) {
             return false;
         }
+        if (isProfileOwner(packageName, profileIds)) {
+            return false;
+        }
         return hasRequestedAppOpPermission(
                 AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)
                 && !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds);
@@ -677,6 +705,25 @@
                         packageName);
     }
 
+    private boolean isProfileOwner(String packageName, int[] userIds) {
+        for (int userId : userIds) {
+            if (isProfileOwner(packageName, userId)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isProfileOwner(String packageName, final @UserIdInt int userId) {
+        final ComponentName profileOwner =
+                mInjector.withCleanCallingIdentity(() ->
+                        mInjector.getDevicePolicyManagerInternal().getProfileOwnerAsUser(userId));
+        if (profileOwner == null) {
+            return false;
+        }
+        return profileOwner.getPackageName().equals(packageName);
+    }
+
     private static class InjectorImpl implements Injector {
         private Context mContext;
 
@@ -774,6 +821,18 @@
                 String permission, int uid, int owningUid, boolean exported) {
             return ActivityManager.checkComponentPermission(permission, uid, owningUid, exported);
         }
+
+        @Override
+        public void killUid(String packageName, int uid) {
+            try {
+                ActivityManager.getService().killApplication(
+                        packageName,
+                        UserHandle.getAppId(uid),
+                        UserHandle.getUserId(uid),
+                        PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED);
+            } catch (RemoteException ignored) {
+            }
+        }
     }
 
     @VisibleForTesting
@@ -813,6 +872,8 @@
         void sendBroadcastAsUser(Intent intent, UserHandle user);
 
         int checkComponentPermission(String permission, int uid, int owningUid, boolean exported);
+
+        void killUid(String packageName, int uid);
     }
 
     class LocalService extends CrossProfileAppsInternal {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 5b5f334..236a681 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -934,6 +934,21 @@
     }
 
     @Override
+    public void uninstallExistingPackage(VersionedPackage versionedPackage,
+            String callerPackageName, IntentSender statusReceiver, int userId) {
+        final int callingUid = Binder.getCallingUid();
+        mContext.enforceCallingOrSelfPermission(Manifest.permission.DELETE_PACKAGES, null);
+        mPermissionManager.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall");
+        if ((callingUid != Process.SHELL_UID) && (callingUid != Process.ROOT_UID)) {
+            mAppOps.checkPackage(callingUid, callerPackageName);
+        }
+
+        final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
+                statusReceiver, versionedPackage.getPackageName(), false, userId);
+        mPm.deleteExistingPackageAsUser(versionedPackage, adapter.getBinder(), userId);
+    }
+
+    @Override
     public void installExistingPackage(String packageName, int installFlags, int installReason,
             IntentSender statusReceiver, int userId, List<String> whiteListedPermissions) {
         mPm.installExistingPackageAsUser(packageName, userId, installFlags, installReason,
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 7af0787..f8278de 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -395,7 +395,6 @@
 
     private boolean mDataLoaderFinished = false;
 
-    // TODO(b/146080380): merge file list with Callback installation.
     private IncrementalFileStorages mIncrementalFileStorages;
 
     private static final FileFilter sAddedApkFilter = new FileFilter() {
@@ -2698,6 +2697,7 @@
 
     /**
      * Makes sure files are present in staging location.
+     * @return if the image is ready for installation
      */
     @GuardedBy("mLock")
     private boolean prepareDataLoaderLocked()
@@ -2709,6 +2709,17 @@
             return true;
         }
 
+        // Retrying commit.
+        if (mIncrementalFileStorages != null) {
+            try {
+                mIncrementalFileStorages.startLoading();
+            } catch (IOException e) {
+                throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE, e.getMessage(),
+                        e.getCause());
+            }
+            return false;
+        }
+
         final List<InstallationFileParcel> addedFiles = new ArrayList<>();
         final List<String> removedFiles = new ArrayList<>();
 
@@ -2811,8 +2822,7 @@
                         }
                         case IDataLoaderStatusListener.DATA_LOADER_UNAVAILABLE: {
                             // Don't fail or commit the session. Allow caller to commit again.
-                            sendPendingStreaming(mContext, mRemoteStatusReceiver, sessionId,
-                                    "DataLoader unavailable");
+                            sendPendingStreaming("DataLoader unavailable");
                             break;
                         }
                         case IDataLoaderStatusListener.DATA_LOADER_UNRECOVERABLE:
@@ -2824,8 +2834,7 @@
                 } catch (RemoteException e) {
                     // In case of streaming failure we don't want to fail or commit the session.
                     // Just return from this method and allow caller to commit again.
-                    sendPendingStreaming(mContext, mRemoteStatusReceiver, sessionId,
-                            e.getMessage());
+                    sendPendingStreaming(e.getMessage());
                 }
             }
         };
@@ -3185,8 +3194,17 @@
         }
     }
 
-    private static void sendPendingStreaming(Context context, IntentSender target, int sessionId,
-            @Nullable String cause) {
+    private void sendPendingStreaming(@Nullable String cause) {
+        final IntentSender statusReceiver;
+        synchronized (mLock) {
+            statusReceiver = mRemoteStatusReceiver;
+        }
+
+        if (statusReceiver == null) {
+            Slog.e(TAG, "Missing receiver for pending streaming status.");
+            return;
+        }
+
         final Intent intent = new Intent();
         intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
         intent.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_STREAMING);
@@ -3197,7 +3215,7 @@
             intent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, "Staging Image Not Ready");
         }
         try {
-            target.sendIntent(context, 0, intent, null, null);
+            statusReceiver.sendIntent(mContext, 0, intent, null, null);
         } catch (IntentSender.SendIntentException ignored) {
         }
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index bde9d57..395e835 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -608,6 +608,12 @@
     private static final long DEFAULT_VERIFICATION_TIMEOUT = 10 * 1000;
 
     /**
+     * The default maximum time to wait for the integrity verification to return in
+     * milliseconds.
+     */
+    private static final long DEFAULT_INTEGRITY_VERIFICATION_TIMEOUT = 30 * 1000;
+
+    /**
      * Timeout duration in milliseconds for enabling package rollback. If we fail to enable
      * rollback within that period, the install will proceed without rollback enabled.
      *
@@ -1560,13 +1566,17 @@
     // Recordkeeping of restore-after-install operations that are currently in flight
     // between the Package Manager and the Backup Manager
     static class PostInstallData {
+        @Nullable
         public final InstallArgs args;
+        @NonNull
         public final PackageInstalledInfo res;
+        @Nullable
         public final Runnable mPostInstallRunnable;
 
-        PostInstallData(InstallArgs _a, PackageInstalledInfo _r, Runnable postInstallRunnable) {
-            args = _a;
-            res = _r;
+        PostInstallData(@Nullable InstallArgs args, @NonNull PackageInstalledInfo res,
+                @Nullable Runnable postInstallRunnable) {
+            this.args = args;
+            this.res = res;
             mPostInstallRunnable = postInstallRunnable;
         }
     }
@@ -1708,7 +1718,7 @@
 
                     if (data != null && data.mPostInstallRunnable != null) {
                         data.mPostInstallRunnable.run();
-                    } else if (data != null) {
+                    } else if (data != null && data.args != null) {
                         InstallArgs args = data.args;
                         PackageInstalledInfo parentRes = data.res;
 
@@ -1726,26 +1736,12 @@
                                 : args.whitelistedRestrictedPermissions;
                         int autoRevokePermissionsMode = args.autoRevokePermissionsMode;
 
-                        // Handle the parent package
                         handlePackagePostInstall(parentRes, grantPermissions,
                                 killApp, virtualPreload, grantedPermissions,
                                 whitelistedRestrictedPermissions, autoRevokePermissionsMode,
                                 didRestore, args.installSource.installerPackageName, args.observer,
                                 args.mDataLoaderType);
 
-                        // Handle the child packages
-                        final int childCount = (parentRes.addedChildPackages != null)
-                                ? parentRes.addedChildPackages.size() : 0;
-                        for (int i = 0; i < childCount; i++) {
-                            PackageInstalledInfo childRes = parentRes.addedChildPackages.valueAt(i);
-                            handlePackagePostInstall(childRes, grantPermissions,
-                                    killApp, virtualPreload, grantedPermissions,
-                                    whitelistedRestrictedPermissions, autoRevokePermissionsMode,
-                                    false /*didRestore*/,
-                                    args.installSource.installerPackageName, args.observer,
-                                    args.mDataLoaderType);
-                        }
-
                         // Log tracing if needed
                         if (args.traceMethod != null) {
                             Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, args.traceMethod,
@@ -2300,27 +2296,8 @@
             // Work that needs to happen on first install within each user
             if (firstUserIds != null && firstUserIds.length > 0) {
                 for (int userId : firstUserIds) {
-                    // If this app is a browser and it's newly-installed for some
-                    // users, clear any default-browser state in those users. The
-                    // app's nature doesn't depend on the user, so we can just check
-                    // its browser nature in any user and generalize.
-                    if (packageIsBrowser(packageName, userId)) {
-                        // If this browser is restored from user's backup, do not clear
-                        // default-browser state for this user
-                        if (pkgSetting.getInstallReason(userId)
-                                != PackageManager.INSTALL_REASON_DEVICE_RESTORE) {
-                            mPermissionManager.setDefaultBrowser(null, true, true, userId);
-                        }
-                    }
-
-                    // We may also need to apply pending (restored) runtime permission grants
-                    // within these users.
-                    mPermissionManager.restoreDelayedRuntimePermissions(packageName,
-                            UserHandle.of(userId));
-
-                    // Persistent preferred activity might have came into effect due to this
-                    // install.
-                    updateDefaultHomeNotLocked(userId);
+                    clearRolesAndRestorePermissionsForNewUserInstall(packageName,
+                            pkgSetting.getInstallReason(userId), userId);
                 }
             }
 
@@ -3204,7 +3181,7 @@
                 }
             }
 
-            final int cachedSystemApps = PackageParser.sCachedPackageReadCount.get();
+            final int cachedSystemApps = PackageCacher.sCachedPackageReadCount.get();
 
             // Remove any shared userIDs that have no associated packages
             mSettings.pruneSharedUsersLPw();
@@ -3338,7 +3315,7 @@
                 // This must be done last to ensure all stubs are replaced or disabled.
                 installSystemStubPackages(stubSystemApps, scanFlags);
 
-                final int cachedNonSystemApps = PackageParser.sCachedPackageReadCount.get()
+                final int cachedNonSystemApps = PackageCacher.sCachedPackageReadCount.get()
                                 - cachedSystemApps;
 
                 final long dataScanTime = SystemClock.uptimeMillis() - systemScanTime - startTime;
@@ -7204,11 +7181,14 @@
                     sortResult = true;
                 }
             } else {
-                final AndroidPackage pkg = mPackages.get(pkgName);
+                final PackageSetting setting =
+                        getPackageSettingInternal(pkgName, Process.SYSTEM_UID);
                 result = null;
-                if (pkg != null) {
+                if (setting != null && setting.pkg != null
+                        && !shouldFilterApplicationLocked(setting, filterCallingUid, userId)) {
                     result = filterIfNotSystemUser(mComponentResolver.queryActivities(
-                            intent, resolvedType, flags, pkg.getActivities(), userId), userId);
+                            intent, resolvedType, flags, setting.pkg.getActivities(), userId),
+                            userId);
                 }
                 if (result == null || result.size() == 0) {
                     // the caller wants to resolve for a particular package; however, there
@@ -8624,7 +8604,7 @@
                         // Shared lib filtering done in generateApplicationInfoFromSettingsLPw
                         // and already converts to externally visible package name
                         ai = generateApplicationInfoFromSettingsLPw(ps.name,
-                                callingUid, effectiveFlags, userId);
+                                effectiveFlags, callingUid, userId);
                     }
                     if (ai != null) {
                         list.add(ai);
@@ -13116,9 +13096,15 @@
                         createPackageInstalledInfo(PackageManager.INSTALL_SUCCEEDED);
                 res.pkg = pkgSetting.pkg;
                 res.newUsers = new int[]{ userId };
-                PostInstallData postInstallData = intentSender == null ? null :
-                        new PostInstallData(null, res, () -> onRestoreComplete(res.returnCode,
-                              mContext, intentSender));
+
+                PostInstallData postInstallData =
+                        new PostInstallData(null, res, () -> {
+                            clearRolesAndRestorePermissionsForNewUserInstall(packageName,
+                                    pkgSetting.getInstallReason(userId), userId);
+                            if (intentSender != null) {
+                                onRestoreComplete(res.returnCode, mContext, intentSender);
+                            }
+                        });
                 restoreAndPostInstall(userId, res, postInstallData);
             }
         } finally {
@@ -13235,7 +13221,9 @@
 
     private void enforceCanSetPackagesSuspendedAsUser(String callingPackage, int callingUid,
             int userId, String callingMethod) {
-        if (callingUid == Process.ROOT_UID || callingUid == Process.SYSTEM_UID) {
+        if (callingUid == Process.ROOT_UID
+                // Need to compare app-id to allow system dialogs access on secondary users
+                || UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
             return;
         }
 
@@ -13838,6 +13826,19 @@
     }
 
     /**
+     * Get the integrity verification timeout.
+     *
+     * @return verification timeout in milliseconds
+     */
+    private long getIntegrityVerificationTimeout() {
+        long timeout = Global.getLong(mContext.getContentResolver(),
+                Global.APP_INTEGRITY_VERIFICATION_TIMEOUT, DEFAULT_INTEGRITY_VERIFICATION_TIMEOUT);
+        // The setting can be used to increase the timeout but not decrease it, since that is
+        // equivalent to disabling the integrity component.
+        return Math.max(timeout, DEFAULT_INTEGRITY_VERIFICATION_TIMEOUT);
+    }
+
+    /**
      * Get the default verification agent response code.
      *
      * @return default verification response code
@@ -15032,8 +15033,7 @@
                             final Message msg =
                                     mHandler.obtainMessage(CHECK_PENDING_INTEGRITY_VERIFICATION);
                             msg.arg1 = verificationId;
-                            // TODO: do we want to use the same timeout?
-                            mHandler.sendMessageDelayed(msg, getVerificationTimeout());
+                            mHandler.sendMessageDelayed(msg, getIntegrityVerificationTimeout());
                         }
                     }, /* scheduler= */ null,
                     /* initialCode= */ 0,
@@ -15783,7 +15783,6 @@
         String returnMsg;
         String installerPackageName;
         PackageRemovedInfo removedInfo;
-        ArrayMap<String, PackageInstalledInfo> addedChildPackages;
         // The set of packages consuming this shared library or null if no consumers exist.
         ArrayList<AndroidPackage> libraryConsumers;
         PackageFreezer freezer;
@@ -15797,37 +15796,21 @@
         public void setError(String msg, PackageParserException e) {
             setReturnCode(e.error);
             setReturnMessage(ExceptionUtils.getCompleteMessage(msg, e));
-            final int childCount = (addedChildPackages != null) ? addedChildPackages.size() : 0;
-            for (int i = 0; i < childCount; i++) {
-                addedChildPackages.valueAt(i).setError(msg, e);
-            }
             Slog.w(TAG, msg, e);
         }
 
         public void setError(String msg, PackageManagerException e) {
             returnCode = e.error;
             setReturnMessage(ExceptionUtils.getCompleteMessage(msg, e));
-            final int childCount = (addedChildPackages != null) ? addedChildPackages.size() : 0;
-            for (int i = 0; i < childCount; i++) {
-                addedChildPackages.valueAt(i).setError(msg, e);
-            }
             Slog.w(TAG, msg, e);
         }
 
         public void setReturnCode(int returnCode) {
             this.returnCode = returnCode;
-            final int childCount = (addedChildPackages != null) ? addedChildPackages.size() : 0;
-            for (int i = 0; i < childCount; i++) {
-                addedChildPackages.valueAt(i).returnCode = returnCode;
-            }
         }
 
         private void setReturnMessage(String returnMsg) {
             this.returnMsg = returnMsg;
-            final int childCount = (addedChildPackages != null) ? addedChildPackages.size() : 0;
-            for (int i = 0; i < childCount; i++) {
-                addedChildPackages.valueAt(i).returnMsg = returnMsg;
-            }
         }
 
         // In some error cases we want to convey more info back to the observer
@@ -17377,7 +17360,6 @@
             int targetParseFlags = parseFlags;
             final PackageSetting ps;
             final PackageSetting disabledPs;
-            final PackageSetting[] childPackages;
             if (replace) {
                 if (parsedPackage.isStaticSharedLibrary()) {
                     // Static libs have a synthetic package name containing the version
@@ -17911,8 +17893,46 @@
     }
 
     @Override
+    public void deleteExistingPackageAsUser(VersionedPackage versionedPackage,
+            final IPackageDeleteObserver2 observer, final int userId) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.DELETE_PACKAGES, null);
+        Preconditions.checkNotNull(versionedPackage);
+        Preconditions.checkNotNull(observer);
+        final String packageName = versionedPackage.getPackageName();
+        final long versionCode = versionedPackage.getLongVersionCode();
+
+        int installedForUsersCount = 0;
+        synchronized (mLock) {
+            // Normalize package name to handle renamed packages and static libs
+            final String internalPkgName = resolveInternalPackageNameLPr(packageName, versionCode);
+            final PackageSetting ps = mSettings.getPackageLPr(internalPkgName);
+            if (ps != null) {
+                int[] installedUsers = ps.queryInstalledUsers(mUserManager.getUserIds(), true);
+                installedForUsersCount = installedUsers.length;
+            }
+        }
+
+        if (installedForUsersCount > 1) {
+            deletePackageVersionedInternal(versionedPackage, observer, userId, 0, true);
+        } else {
+            try {
+                observer.onPackageDeleted(packageName, PackageManager.DELETE_FAILED_INTERNAL_ERROR,
+                        null);
+            } catch (RemoteException re) {
+            }
+        }
+    }
+
+    @Override
     public void deletePackageVersioned(VersionedPackage versionedPackage,
             final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
+        deletePackageVersionedInternal(versionedPackage, observer, userId, deleteFlags, false);
+    }
+
+    private void deletePackageVersionedInternal(VersionedPackage versionedPackage,
+            final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags,
+            final boolean allowSilentUninstall) {
         final int callingUid = Binder.getCallingUid();
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.DELETE_PACKAGES, null);
@@ -17933,6 +17953,7 @@
 
         final int uid = Binder.getCallingUid();
         if (!isOrphaned(internalPackageName)
+                && !allowSilentUninstall
                 && !isCallerAllowedToSilentlyUninstall(uid, internalPackageName)) {
             mHandler.post(() -> {
                 try {
@@ -18340,7 +18361,6 @@
             final boolean killApp = (deleteFlags & PackageManager.DELETE_DONT_KILL_APP) == 0;
             info.sendPackageRemovedBroadcasts(killApp);
             info.sendSystemPackageUpdatedBroadcasts();
-            info.sendSystemPackageAppearedBroadcasts();
         }
         // Force a gc here.
         Runtime.getRuntime().gc();
@@ -18398,7 +18418,6 @@
         SparseArray<int[]> broadcastWhitelist;
         // Clean up resources deleted packages.
         InstallArgs args = null;
-        ArrayMap<String, PackageInstalledInfo> appearedChildPackages;
 
         PackageRemovedInfo(PackageSender packageSender) {
             this.packageSender = packageSender;
@@ -18414,18 +18433,6 @@
             }
         }
 
-        void sendSystemPackageAppearedBroadcasts() {
-            final int packageCount = (appearedChildPackages != null)
-                    ? appearedChildPackages.size() : 0;
-            for (int i = 0; i < packageCount; i++) {
-                PackageInstalledInfo installedInfo = appearedChildPackages.valueAt(i);
-                packageSender.sendPackageAddedForNewUsers(installedInfo.name,
-                    true /*sendBootCompleted*/, false /*startReceiver*/,
-                        UserHandle.getAppId(installedInfo.uid), installedInfo.newUsers, null,
-                        DataLoaderType.NONE);
-            }
-        }
-
         private void sendSystemPackageUpdatedBroadcastsInternal() {
             Bundle extras = new Bundle(2);
             extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
@@ -19692,6 +19699,30 @@
         }
     }
 
+    private void clearRolesAndRestorePermissionsForNewUserInstall(String packageName,
+            int installReason, @UserIdInt int userId) {
+        // If this app is a browser and it's newly-installed for some
+        // users, clear any default-browser state in those users. The
+        // app's nature doesn't depend on the user, so we can just check
+        // its browser nature in any user and generalize.
+        if (packageIsBrowser(packageName, userId)) {
+            // If this browser is restored from user's backup, do not clear
+            // default-browser state for this user
+            if (installReason != PackageManager.INSTALL_REASON_DEVICE_RESTORE) {
+                mPermissionManager.setDefaultBrowser(null, true, true, userId);
+            }
+        }
+
+        // We may also need to apply pending (restored) runtime permission grants
+        // within these users.
+        mPermissionManager.restoreDelayedRuntimePermissions(packageName,
+                UserHandle.of(userId));
+
+        // Persistent preferred activity might have came into effect due to this
+        // install.
+        updateDefaultHomeNotLocked(userId);
+    }
+
     @Override
     public void resetApplicationPreferences(int userId) {
         mContext.enforceCallingOrSelfPermission(
@@ -24479,9 +24510,10 @@
                 if (updatedPackageNames != null) {
                     outUpdatedPackageNames.addAll(updatedPackageNames);
                 }
-
-                return true;
             }
+
+            PackageManager.invalidatePackageInfoCache();
+            return true;
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index bc94528..0dc4d13 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -3172,7 +3172,7 @@
             metadata = (streamingVersion == 0) ? Metadata.forDataOnlyStreaming(fileId)
                     : Metadata.forStreaming(fileId);
             try {
-                if (V4Signature.readFrom(signature) == null) {
+                if ((signature.length > 0) && (V4Signature.readFrom(signature) == null)) {
                     getErrPrintWriter().println("V4 signature is invalid in: " + arg);
                     return 1;
                 }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 9de34a9..a5b1bf9 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -5595,10 +5595,7 @@
                             userId);
                 } else if (packageSetting.sharedUser == null && !isUpgradeToR) {
                     Slog.w(TAG, "Missing permission state for package: " + packageName);
-                    generateFallbackPermissionsStateLpr(
-                            packageSetting.pkg.getRequestedPermissions(),
-                            packageSetting.pkg.getTargetSdkVersion(),
-                            packageSetting.getPermissionsState(), userId);
+                    packageSetting.getPermissionsState().setMissing(true, userId);
                 }
             }
 
@@ -5616,22 +5613,7 @@
                             userId);
                 } else if (!isUpgradeToR) {
                     Slog.w(TAG, "Missing permission state for shared user: " + sharedUserName);
-                    ArraySet<String> requestedPermissions = new ArraySet<>();
-                    int targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
-                    int sharedUserPackagesSize = sharedUserSetting.packages.size();
-                    for (int packagesI = 0; packagesI < sharedUserPackagesSize; packagesI++) {
-                        PackageSetting packageSetting = sharedUserSetting.packages.valueAt(
-                                packagesI);
-                        if (packageSetting == null || packageSetting.pkg == null
-                                || !packageSetting.getInstalled(userId)) {
-                            continue;
-                        }
-                        AndroidPackage pkg = packageSetting.pkg;
-                        requestedPermissions.addAll(pkg.getRequestedPermissions());
-                        targetSdkVersion = Math.min(targetSdkVersion, pkg.getTargetSdkVersion());
-                    }
-                    generateFallbackPermissionsStateLpr(requestedPermissions, targetSdkVersion,
-                            sharedUserSetting.getPermissionsState(), userId);
+                    sharedUserSetting.getPermissionsState().setMissing(true, userId);
                 }
             }
         }
@@ -5663,30 +5645,6 @@
             }
         }
 
-        private void generateFallbackPermissionsStateLpr(
-                @NonNull Collection<String> requestedPermissions, int targetSdkVersion,
-                @NonNull PermissionsState permissionsState, @UserIdInt int userId) {
-            for (String permissionName : requestedPermissions) {
-                BasePermission permission = mPermissions.getPermission(permissionName);
-                if (Objects.equals(permission.getSourcePackageName(), PLATFORM_PACKAGE_NAME)
-                        && permission.isRuntime() && !permission.isRemoved()) {
-                    if (permission.isHardOrSoftRestricted() || permission.isImmutablyRestricted()) {
-                        permissionsState.updatePermissionFlags(permission, userId,
-                                PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT,
-                                PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT);
-                    }
-                    if (targetSdkVersion < Build.VERSION_CODES.M) {
-                        permissionsState.updatePermissionFlags(permission, userId,
-                                PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
-                                        | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT,
-                                PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
-                                        | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT);
-                        permissionsState.grantRuntimePermission(permission, userId);
-                    }
-                }
-            }
-        }
-
         @GuardedBy("Settings.this.mLock")
         private void readLegacyStateForUserSyncLPr(int userId) {
             File permissionsFile = getUserRuntimePermissionsFile(userId);
diff --git a/services/core/java/com/android/server/pm/ShortcutLauncher.java b/services/core/java/com/android/server/pm/ShortcutLauncher.java
index 0fecb63..0ebe5961 100644
--- a/services/core/java/com/android/server/pm/ShortcutLauncher.java
+++ b/services/core/java/com/android/server/pm/ShortcutLauncher.java
@@ -22,20 +22,29 @@
 import android.content.pm.ShortcutInfo;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.AtomicFile;
 import android.util.Slog;
+import android.util.Xml;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.pm.ShortcutService.DumpFilter;
 import com.android.server.pm.ShortcutUser.PackageWithUser;
 
+import libcore.io.IoUtils;
+
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -254,6 +263,53 @@
         out.endTag(null, TAG_ROOT);
     }
 
+    public static ShortcutLauncher loadFromFile(File path, ShortcutUser shortcutUser,
+            int ownerUserId, boolean fromBackup) {
+
+        final AtomicFile file = new AtomicFile(path);
+        final FileInputStream in;
+        try {
+            in = file.openRead();
+        } catch (FileNotFoundException e) {
+            if (ShortcutService.DEBUG) {
+                Slog.d(TAG, "Not found " + path);
+            }
+            return null;
+        }
+
+        try {
+            final BufferedInputStream bis = new BufferedInputStream(in);
+
+            ShortcutLauncher ret = null;
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(bis, StandardCharsets.UTF_8.name());
+
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+                if (type != XmlPullParser.START_TAG) {
+                    continue;
+                }
+                final int depth = parser.getDepth();
+
+                final String tag = parser.getName();
+                if (ShortcutService.DEBUG_LOAD) {
+                    Slog.d(TAG, String.format("depth=%d type=%d name=%s", depth, type, tag));
+                }
+                if ((depth == 1) && TAG_ROOT.equals(tag)) {
+                    ret = loadFromXml(parser, shortcutUser, ownerUserId, fromBackup);
+                    continue;
+                }
+                ShortcutService.throwForInvalidTag(depth, tag);
+            }
+            return ret;
+        } catch (IOException | XmlPullParserException e) {
+            Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
+            return null;
+        } finally {
+            IoUtils.closeQuietly(in);
+        }
+    }
+
     /**
      * Load.
      */
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 71a4bb4..1642607 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -27,12 +27,15 @@
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
 import android.content.res.Resources;
+import android.graphics.drawable.Icon;
 import android.os.PersistableBundle;
 import android.text.format.Formatter;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.AtomicFile;
 import android.util.Log;
 import android.util.Slog;
+import android.util.Xml;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
@@ -43,15 +46,21 @@
 import com.android.server.pm.ShortcutService.ShortcutOperation;
 import com.android.server.pm.ShortcutService.Stats;
 
+import libcore.io.IoUtils;
+
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import java.io.BufferedInputStream;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -248,6 +257,28 @@
         }
     }
 
+    public void ensureNoBitmapIconIfShortcutIsLongLived(@NonNull List<ShortcutInfo> shortcuts) {
+        for (int i = shortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = shortcuts.get(i);
+            if (!si.isLongLived()) {
+                continue;
+            }
+            final Icon icon = si.getIcon();
+            if (icon != null && icon.getType() != Icon.TYPE_BITMAP
+                    && icon.getType() == Icon.TYPE_ADAPTIVE_BITMAP) {
+                continue;
+            }
+            if (icon == null && !si.hasIconFile()) {
+                continue;
+            }
+
+            // TODO: Throw IllegalArgumentException instead.
+            Slog.e(TAG, "Invalid icon type in shortcut " + si.getId() + ". Bitmaps are not allowed"
+                    + " in long-lived shortcuts. Use Resource icons, or Uri-based icons instead.");
+            return;  // Do not spam and return early.
+        }
+    }
+
     /**
      * Delete a shortcut by ID. This will *always* remove it even if it's immutable or invisible.
      */
@@ -1444,10 +1475,6 @@
                     // Don't adjust ranks for manifest shortcuts.
                     continue;
                 }
-                if (si.isCached() && !si.isDynamic()) {
-                    // Don't adjust ranks for cached shortcuts that are not dynamic anymore.
-                    continue;
-                }
                 // At this point, it must be dynamic.
                 if (!si.isDynamic()) {
                     s.wtf("Non-dynamic shortcut found.");
@@ -1720,6 +1747,53 @@
         out.endTag(null, TAG_SHORTCUT);
     }
 
+    public static ShortcutPackage loadFromFile(ShortcutService s, ShortcutUser shortcutUser,
+            File path, boolean fromBackup) {
+
+        final AtomicFile file = new AtomicFile(path);
+        final FileInputStream in;
+        try {
+            in = file.openRead();
+        } catch (FileNotFoundException e) {
+            if (ShortcutService.DEBUG) {
+                Slog.d(TAG, "Not found " + path);
+            }
+            return null;
+        }
+
+        try {
+            final BufferedInputStream bis = new BufferedInputStream(in);
+
+            ShortcutPackage ret = null;
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(bis, StandardCharsets.UTF_8.name());
+
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+                if (type != XmlPullParser.START_TAG) {
+                    continue;
+                }
+                final int depth = parser.getDepth();
+
+                final String tag = parser.getName();
+                if (ShortcutService.DEBUG_LOAD) {
+                    Slog.d(TAG, String.format("depth=%d type=%d name=%s", depth, type, tag));
+                }
+                if ((depth == 1) && TAG_ROOT.equals(tag)) {
+                    ret = loadFromXml(s, shortcutUser, parser, fromBackup);
+                    continue;
+                }
+                ShortcutService.throwForInvalidTag(depth, tag);
+            }
+            return ret;
+        } catch (IOException | XmlPullParserException e) {
+            Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
+            return null;
+        } finally {
+            IoUtils.closeQuietly(in);
+        }
+    }
+
     public static ShortcutPackage loadFromXml(ShortcutService s, ShortcutUser shortcutUser,
             XmlPullParser parser, boolean fromBackup)
             throws IOException, XmlPullParserException {
@@ -1984,7 +2058,7 @@
             dynamicList.removeIf((si) -> !si.isDynamic());
 
             final ArrayList<ShortcutInfo> manifestList = new ArrayList<>(list);
-            dynamicList.removeIf((si) -> !si.isManifestShortcut());
+            manifestList.removeIf((si) -> !si.isManifestShortcut());
 
             verifyRanksSequential(dynamicList);
             verifyRanksSequential(manifestList);
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index 6d9d69e..801c6cb 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -18,8 +18,10 @@
 import android.annotation.NonNull;
 import android.content.pm.PackageInfo;
 import android.content.pm.ShortcutInfo;
+import android.util.AtomicFile;
 import android.util.Slog;
 
+import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.Preconditions;
 
 import org.json.JSONException;
@@ -27,7 +29,11 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.Objects;
 
 /**
@@ -143,6 +149,31 @@
     public abstract void saveToXml(@NonNull XmlSerializer out, boolean forBackup)
             throws IOException, XmlPullParserException;
 
+    public void saveToFile(File path, boolean forBackup) {
+        final AtomicFile file = new AtomicFile(path);
+        FileOutputStream os = null;
+        try {
+            os = file.startWrite();
+            final BufferedOutputStream bos = new BufferedOutputStream(os);
+
+            // Write to XML
+            XmlSerializer itemOut = new FastXmlSerializer();
+            itemOut.setOutput(bos, StandardCharsets.UTF_8.name());
+            itemOut.startDocument(null, true);
+
+            saveToXml(itemOut, forBackup);
+
+            itemOut.endDocument();
+
+            bos.flush();
+            os.flush();
+            file.finishWrite(os);
+        } catch (XmlPullParserException | IOException e) {
+            Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
+            file.failWrite(os);
+        }
+    }
+
     public JSONObject dumpCheckin(boolean clear) throws JSONException {
         final JSONObject result = new JSONObject();
         result.put(KEY_NAME, mPackageName);
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index e4ae007..3732b47 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -169,7 +169,7 @@
     static final int DEFAULT_MAX_UPDATES_PER_INTERVAL = 10;
 
     @VisibleForTesting
-    static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 10;
+    static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = 15;
 
     @VisibleForTesting
     static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;
@@ -730,7 +730,7 @@
                 ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL, DEFAULT_MAX_UPDATES_PER_INTERVAL));
 
         mMaxShortcuts = Math.max(0, (int) parser.getLong(
-                ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_APP));
+                ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY));
 
         final int iconDimensionDp = Math.max(1, injectIsLowRamDevice()
                 ? (int) parser.getLong(
@@ -1849,6 +1849,7 @@
             final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
 
             ps.ensureImmutableShortcutsNotIncluded(newShortcuts, /*ignoreInvisible=*/ true);
+            ps.ensureNoBitmapIconIfShortcutIsLongLived(newShortcuts);
 
             fillInDefaultActivity(newShortcuts);
 
@@ -1915,6 +1916,7 @@
             final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
 
             ps.ensureImmutableShortcutsNotIncluded(newShortcuts, /*ignoreInvisible=*/ true);
+            ps.ensureNoBitmapIconIfShortcutIsLongLived(newShortcuts);
 
             // For update, don't fill in the default activity.  Having null activity means
             // "don't update the activity" here.
@@ -2013,6 +2015,7 @@
             final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
 
             ps.ensureImmutableShortcutsNotIncluded(newShortcuts, /*ignoreInvisible=*/ true);
+            ps.ensureNoBitmapIconIfShortcutIsLongLived(newShortcuts);
 
             fillInDefaultActivity(newShortcuts);
 
@@ -3103,15 +3106,15 @@
                     }
 
                     if (doCache) {
-                        if (si.isDynamic() && si.isLongLived()) {
+                        if (si.isLongLived()) {
                             si.addFlags(ShortcutInfo.FLAG_CACHED);
                             if (changedShortcuts == null) {
                                 changedShortcuts = new ArrayList<>(1);
                             }
                             changedShortcuts.add(si);
                         } else {
-                            Log.w(TAG, "Only dynamic long lived shortcuts can get cached. Ignoring"
-                                    + "shortcut " + si.getId());
+                            Log.w(TAG, "Only long lived shortcuts can get cached. Ignoring id "
+                                    + si.getId());
                         }
                     } else {
                         ShortcutInfo removed = null;
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index eab3f4d..df6d321 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -21,6 +21,7 @@
 import android.content.ComponentName;
 import android.content.pm.ShortcutManager;
 import android.metrics.LogMaker;
+import android.os.FileUtils;
 import android.text.TextUtils;
 import android.text.format.Formatter;
 import android.util.ArrayMap;
@@ -30,7 +31,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.util.Preconditions;
 import com.android.server.pm.ShortcutService.DumpFilter;
 import com.android.server.pm.ShortcutService.InvalidFileFormatException;
 
@@ -55,6 +55,9 @@
 class ShortcutUser {
     private static final String TAG = ShortcutService.TAG;
 
+    static final String DIRECTORY_PACKAGES = "packages";
+    static final String DIRECTORY_LUANCHERS = "launchers";
+
     static final String TAG_ROOT = "user";
     private static final String TAG_LAUNCHER = "launcher";
 
@@ -354,6 +357,13 @@
                     mService.injectBuildFingerprint());
         }
 
+        if (!forBackup) {
+            // Since we are not handling package deletion yet, or any single package changes, just
+            // clean the directory and rewrite all the ShortcutPackageItems.
+            final File root = mService.injectUserDataPath(mUserId);
+            FileUtils.deleteContents(new File(root, DIRECTORY_PACKAGES));
+            FileUtils.deleteContents(new File(root, DIRECTORY_LUANCHERS));
+        }
         // Can't use forEachPackageItem due to the checked exceptions.
         {
             final int size = mLaunchers.size();
@@ -371,20 +381,47 @@
         out.endTag(null, TAG_ROOT);
     }
 
-    private void saveShortcutPackageItem(XmlSerializer out,
-            ShortcutPackageItem spi, boolean forBackup) throws IOException, XmlPullParserException {
+    private void saveShortcutPackageItem(XmlSerializer out, ShortcutPackageItem spi,
+            boolean forBackup) throws IOException, XmlPullParserException {
         if (forBackup) {
             if (spi.getPackageUserId() != spi.getOwnerUserId()) {
                 return; // Don't save cross-user information.
             }
+            spi.saveToXml(out, forBackup);
+        } else {
+            // Save each ShortcutPackageItem in a separate Xml file.
+            final File path = getShortcutPackageItemFile(spi);
+            if (ShortcutService.DEBUG) {
+                Slog.d(TAG, "Saving package item " + spi.getPackageName() + " to " + path);
+            }
+
+            path.getParentFile().mkdirs();
+            spi.saveToFile(path, forBackup);
         }
-        spi.saveToXml(out, forBackup);
+    }
+
+    private File getShortcutPackageItemFile(ShortcutPackageItem spi) {
+        boolean isShortcutLauncher = spi instanceof ShortcutLauncher;
+
+        final File path = new File(mService.injectUserDataPath(mUserId),
+                isShortcutLauncher ? DIRECTORY_LUANCHERS : DIRECTORY_PACKAGES);
+
+        final String fileName;
+        if (isShortcutLauncher) {
+            // Package user id and owner id can have different values for ShortcutLaunchers. Adding
+            // user Id to the file name to create a unique path. Owner id is used in the root path.
+            fileName = spi.getPackageName() + spi.getPackageUserId() + ".xml";
+        } else {
+            fileName = spi.getPackageName() + ".xml";
+        }
+
+        return new File(path, fileName);
     }
 
     public static ShortcutUser loadFromXml(ShortcutService s, XmlPullParser parser, int userId,
             boolean fromBackup) throws IOException, XmlPullParserException, InvalidFileFormatException {
         final ShortcutUser ret = new ShortcutUser(s, userId);
-
+        boolean readShortcutItems = false;
         try {
             ret.mKnownLocales = ShortcutService.parseStringAttribute(parser,
                     ATTR_KNOWN_LOCALES);
@@ -422,12 +459,14 @@
 
                             // Don't use addShortcut(), we don't need to save the icon.
                             ret.mPackages.put(shortcuts.getPackageName(), shortcuts);
+                            readShortcutItems = true;
                             continue;
                         }
 
                         case ShortcutLauncher.TAG_ROOT: {
                             ret.addLauncher(
                                     ShortcutLauncher.loadFromXml(parser, ret, userId, fromBackup));
+                            readShortcutItems = true;
                             continue;
                         }
                     }
@@ -438,9 +477,44 @@
             throw new ShortcutService.InvalidFileFormatException(
                     "Unable to parse file", e);
         }
+
+        if (readShortcutItems) {
+            // If the shortcuts info was read from the main Xml, skip reading from individual files.
+            // Data will get stored in the new format during the next call to saveToXml().
+            // TODO: ret.forAllPackageItems((ShortcutPackageItem item) -> item.markDirty());
+            s.scheduleSaveUser(userId);
+        } else {
+            final File root = s.injectUserDataPath(userId);
+
+            forAllFilesIn(new File(root, DIRECTORY_PACKAGES), (File f) -> {
+                final ShortcutPackage sp = ShortcutPackage.loadFromFile(s, ret, f, fromBackup);
+                if (sp != null) {
+                    ret.mPackages.put(sp.getPackageName(), sp);
+                }
+            });
+
+            forAllFilesIn(new File(root, DIRECTORY_LUANCHERS), (File f) -> {
+                final ShortcutLauncher sl =
+                        ShortcutLauncher.loadFromFile(f, ret, userId, fromBackup);
+                if (sl != null) {
+                    ret.addLauncher(sl);
+                }
+            });
+        }
+
         return ret;
     }
 
+    private static void forAllFilesIn(File path, Consumer<File> callback) {
+        if (!path.exists()) {
+            return;
+        }
+        File[] list = path.listFiles();
+        for (File f : list) {
+            callback.accept(f);
+        }
+    }
+
     public ComponentName getLastKnownLauncher() {
         return mLastKnownLauncher;
     }
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index b805a24..79805e3 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -69,6 +69,8 @@
 import com.android.internal.content.PackageHelper;
 import com.android.internal.os.BackgroundThread;
 import com.android.server.LocalServices;
+import com.android.server.SystemService;
+import com.android.server.SystemServiceManager;
 import com.android.server.pm.parsing.PackageParser2;
 import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
@@ -110,6 +112,9 @@
     private final List<String> mFailedPackageNames = new ArrayList<>();
     private String mNativeFailureReason;
 
+    @GuardedBy("mSuccessfulStagedSessionIds")
+    private final List<Integer> mSuccessfulStagedSessionIds = new ArrayList<>();
+
     StagingManager(PackageInstallerService pi, Context context,
             Supplier<PackageParser2> packageParserSupplier) {
         mPi = pi;
@@ -122,6 +127,34 @@
                 BackgroundThread.get().getLooper());
     }
 
+    /**
+     This class manages lifecycle events for StagingManager.
+     */
+    public static final class Lifecycle extends SystemService {
+        private static StagingManager sStagingManager;
+
+        public Lifecycle(Context context) {
+            super(context);
+        }
+
+        void startService(StagingManager stagingManager) {
+            sStagingManager = stagingManager;
+            LocalServices.getService(SystemServiceManager.class).startService(this);
+        }
+
+        @Override
+        public void onStart() {
+            // no-op
+        }
+
+        @Override
+        public void onBootPhase(int phase) {
+            if (phase == SystemService.PHASE_BOOT_COMPLETED && sStagingManager != null) {
+                sStagingManager.markStagedSessionsAsSuccessful();
+            }
+        }
+    }
+
     private void updateStoredSession(@NonNull PackageInstallerSession sessionInfo) {
         synchronized (mStagedSessions) {
             PackageInstallerSession storedSession = mStagedSessions.get(sessionInfo.sessionId);
@@ -652,7 +685,22 @@
         Slog.d(TAG, "Marking session " + session.sessionId + " as applied");
         session.setStagedSessionApplied();
         if (hasApex) {
-            mApexManager.markStagedSessionSuccessful(session.sessionId);
+            try {
+                if (supportsCheckpoint()) {
+                    // Store the session ID, which will be marked as successful by ApexManager
+                    // upon boot completion.
+                    synchronized (mSuccessfulStagedSessionIds) {
+                        mSuccessfulStagedSessionIds.add(session.sessionId);
+                    }
+                } else {
+                    // Mark sessions as successful immediately on non-checkpointing devices.
+                    mApexManager.markStagedSessionSuccessful(session.sessionId);
+                }
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Checkpoint support unknown, marking session as successful "
+                        + "immediately.");
+                mApexManager.markStagedSessionSuccessful(session.sessionId);
+            }
         }
     }
 
@@ -1121,7 +1169,16 @@
         }
     }
 
+    void markStagedSessionsAsSuccessful() {
+        synchronized (mSuccessfulStagedSessionIds) {
+            for (int i = 0; i < mSuccessfulStagedSessionIds.size(); i++) {
+                mApexManager.markStagedSessionSuccessful(mSuccessfulStagedSessionIds.get(i));
+            }
+        }
+    }
+
     void systemReady() {
+        new Lifecycle(mContext).startService(this);
         // Register the receiver of boot completed intent for staging manager.
         mContext.registerReceiver(new BroadcastReceiver() {
             @Override
diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING
index d3cd1a9..2614076 100644
--- a/services/core/java/com/android/server/pm/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/TEST_MAPPING
@@ -118,6 +118,9 @@
         },
         {
           "include-filter": "com.android.server.pm.UserSystemPackageInstallerTest"
+        },
+        {
+          "include-filter": "com.android.server.pm.parsing.SystemPartitionParseTest"
         }
       ]
     }
diff --git a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
index f8d039c..530c115 100644
--- a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
+++ b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
@@ -344,7 +344,7 @@
      */
     @NonNull
     private List<String> getPackagesWhitelistErrors(@PackageWhitelistMode int mode) {
-        if ((!isEnforceMode(mode) || isImplicitWhitelistMode(mode)) && !isLogMode(mode)) {
+        if ((!isEnforceMode(mode) || isImplicitWhitelistMode(mode))) {
             return Collections.emptyList();
         }
 
@@ -752,6 +752,10 @@
         } else if (mode == USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT) {
             mode = getDeviceDefaultWhitelistMode();
         }
+        if (criticalOnly) {
+            // Flip-out log mode
+            mode &= ~USER_TYPE_PACKAGE_WHITELIST_MODE_LOG;
+        }
         Slog.v(TAG, "dumpPackageWhitelistProblems(): using mode " + modeToString(mode));
 
         final List<String> errors = getPackagesWhitelistErrors(mode);
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index a1cc44a..b0d4d95 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -124,6 +124,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.os.RoSystemProperties;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IntPair;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.function.pooled.PooledLambda;
@@ -154,6 +155,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -421,7 +423,11 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mContext.getSystemService(PermissionControllerManager.class).dump(fd, pw, args);
+        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) {
+            return;
+        }
+
+        mContext.getSystemService(PermissionControllerManager.class).dump(fd, args);
     }
 
     /**
@@ -2473,13 +2479,60 @@
         }
 
         final PermissionsState permissionsState = ps.getPermissionsState();
-        PermissionsState origPermissions = permissionsState;
 
         final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
 
         boolean runtimePermissionsRevoked = false;
         int[] updatedUserIds = EMPTY_INT_ARRAY;
 
+        for (int userId : currentUserIds) {
+            if (permissionsState.isMissing(userId)) {
+                Collection<String> requestedPermissions;
+                int targetSdkVersion;
+                if (!ps.isSharedUser()) {
+                    requestedPermissions = pkg.getRequestedPermissions();
+                    targetSdkVersion = pkg.getTargetSdkVersion();
+                } else {
+                    requestedPermissions = new ArraySet<>();
+                    targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
+                    List<AndroidPackage> packages = ps.getSharedUser().getPackages();
+                    int packagesSize = packages.size();
+                    for (int i = 0; i < packagesSize; i++) {
+                        AndroidPackage sharedUserPackage = packages.get(i);
+                        requestedPermissions.addAll(sharedUserPackage.getRequestedPermissions());
+                        targetSdkVersion = Math.min(targetSdkVersion,
+                                sharedUserPackage.getTargetSdkVersion());
+                    }
+                }
+
+                for (String permissionName : requestedPermissions) {
+                    BasePermission permission = mSettings.getPermission(permissionName);
+                    if (Objects.equals(permission.getSourcePackageName(), PLATFORM_PACKAGE_NAME)
+                            && permission.isRuntime() && !permission.isRemoved()) {
+                        if (permission.isHardOrSoftRestricted()
+                                || permission.isImmutablyRestricted()) {
+                            permissionsState.updatePermissionFlags(permission, userId,
+                                    PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT,
+                                    PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT);
+                        }
+                        if (targetSdkVersion < Build.VERSION_CODES.M) {
+                            permissionsState.updatePermissionFlags(permission, userId,
+                                    PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
+                                            | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT,
+                                    PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
+                                            | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT);
+                            permissionsState.grantRuntimePermission(permission, userId);
+                        }
+                    }
+                }
+
+                permissionsState.setMissing(false, userId);
+                updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
+            }
+        }
+
+        PermissionsState origPermissions = permissionsState;
+
         boolean changedInstallPermission = false;
 
         if (replace) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionsState.java b/services/core/java/com/android/server/pm/permission/PermissionsState.java
index 11e29a0..bad59cb 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionsState.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionsState.java
@@ -16,6 +16,8 @@
 
 package com.android.server.pm.permission;
 
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.content.pm.PackageManager;
 import android.os.UserHandle;
 import android.util.ArrayMap;
@@ -30,6 +32,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -70,6 +73,9 @@
 
     private int[] mGlobalGids = NO_GIDS;
 
+    @Nullable
+    private SparseBooleanArray mMissing;
+
     private SparseBooleanArray mPermissionReviewRequired;
 
     public PermissionsState() {
@@ -132,6 +138,23 @@
                     other.mGlobalGids.length);
         }
 
+        if (mMissing != null) {
+            if (other.mMissing == null) {
+                mMissing = null;
+            } else {
+                mMissing.clear();
+            }
+        }
+        if (other.mMissing != null) {
+            if (mMissing == null) {
+                mMissing = new SparseBooleanArray();
+            }
+            final int missingSize = other.mMissing.size();
+            for (int i = 0; i < missingSize; i++) {
+                mMissing.put(other.mMissing.keyAt(i), other.mMissing.valueAt(i));
+            }
+        }
+
         if (mPermissionReviewRequired != null) {
             if (other.mPermissionReviewRequired == null) {
                 mPermissionReviewRequired = null;
@@ -175,6 +198,10 @@
             }
         }
 
+        if (!Objects.equals(mMissing, other.mMissing)) {
+            return false;
+        }
+
         if (mPermissionReviewRequired == null) {
             if (other.mPermissionReviewRequired != null) {
                 return false;
@@ -185,6 +212,35 @@
         return Arrays.equals(mGlobalGids, other.mGlobalGids);
     }
 
+    /**
+     * Check whether the permissions state is missing for a user. This can happen if permission
+     * state is rolled back and we'll need to generate a reasonable default state to keep the app
+     * usable.
+     */
+    public boolean isMissing(@UserIdInt int userId) {
+        return mMissing != null && mMissing.get(userId);
+    }
+
+    /**
+     * Set whether the permissions state is missing for a user. This can happen if permission state
+     * is rolled back and we'll need to generate a reasonable default state to keep the app usable.
+     */
+    public void setMissing(boolean missing, @UserIdInt int userId) {
+        if (missing) {
+            if (mMissing == null) {
+                mMissing = new SparseBooleanArray();
+            }
+            mMissing.put(userId, true);
+        } else {
+            if (mMissing != null) {
+                mMissing.delete(userId);
+                if (mMissing.size() == 0) {
+                    mMissing = null;
+                }
+            }
+        }
+    }
+
     public boolean isPermissionReviewRequired(int userId) {
         return mPermissionReviewRequired != null && mPermissionReviewRequired.get(userId);
     }
@@ -569,6 +625,7 @@
             invalidateCache();
         }
 
+        mMissing = null;
         mPermissionReviewRequired = null;
     }
 
diff --git a/services/core/java/com/android/server/policy/LegacyGlobalActions.java b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
index 39f7ac0..9c3a394 100644
--- a/services/core/java/com/android/server/policy/LegacyGlobalActions.java
+++ b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
@@ -339,7 +339,7 @@
         });
         dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
         // Don't acquire soft keyboard focus, to avoid destroying state when capturing bugreports
-        mDialog.getWindow().setFlags(FLAG_ALT_FOCUSABLE_IM, FLAG_ALT_FOCUSABLE_IM);
+        dialog.getWindow().setFlags(FLAG_ALT_FOCUSABLE_IM, FLAG_ALT_FOCUSABLE_IM);
 
         dialog.setOnDismissListener(this);
 
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 8648a23..5e2c4eb 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -16,17 +16,14 @@
 
 package com.android.server.policy;
 
-import static android.Manifest.permission.READ_PHONE_STATE;
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.MODE_FOREGROUND;
 import static android.app.AppOpsManager.MODE_IGNORED;
 import static android.app.AppOpsManager.OP_NONE;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
-import static android.content.pm.PackageManager.FLAG_PERMISSION_AUTO_REVOKED;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
 import static android.content.pm.PackageManager.GET_PERMISSIONS;
-import static android.content.pm.PackageManager.MATCH_ALL;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -45,7 +42,6 @@
 import android.content.pm.PackageManagerInternal.PackageListObserver;
 import android.content.pm.PermissionInfo;
 import android.os.Build;
-import android.os.Handler;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -57,7 +53,6 @@
 import android.telecom.TelecomManager;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.Log;
 import android.util.LongSparseLongArray;
 import android.util.Pair;
 import android.util.Slog;
@@ -93,6 +88,7 @@
 public final class PermissionPolicyService extends SystemService {
     private static final String LOG_TAG = PermissionPolicyService.class.getSimpleName();
     private static final boolean DEBUG = false;
+    private static final long USER_SENSITIVE_UPDATE_DELAY_MS = 10000;
 
     private final Object mLock = new Object();
 
@@ -365,53 +361,12 @@
         // Force synchronization as permissions might have changed
         synchronizePermissionsAndAppOpsForUser(userId);
 
-        restoreReadPhoneStatePermissions(userId);
-
         // Tell observers we are initialized for this user.
         if (callback != null) {
             callback.onInitialized(userId);
         }
     }
 
-    /**
-     * Ensure READ_PHONE_STATE user sensitive flags are assigned properly
-     * TODO ntmyren: Remove once propagated, and state is repaired
-     */
-    private void restoreReadPhoneStatePermissions(int userId) {
-        PermissionControllerManager manager = new PermissionControllerManager(this.getContext(),
-                Handler.getMain());
-        PackageManager pm = getContext().getPackageManager();
-        List<PackageInfo> packageInfos = pm.getInstalledPackagesAsUser(
-                MATCH_ALL | GET_PERMISSIONS, userId);
-        for (int i = packageInfos.size() - 1; i >= 0; i--) {
-            PackageInfo pI = packageInfos.get(i);
-            if (pI.requestedPermissions == null) {
-                continue;
-            }
-
-            boolean hasReadPhoneState = false;
-            for (int j = pI.requestedPermissions.length - 1; j >= 0; j--) {
-                if (pI.requestedPermissions[j].equals(READ_PHONE_STATE)) {
-                    hasReadPhoneState = true;
-                }
-            }
-            if (!hasReadPhoneState) {
-                continue;
-            }
-
-            Log.i(LOG_TAG, "Updating read phone state for " + pI.packageName + " "
-                    + pI.applicationInfo.uid);
-            manager.updateUserSensitiveForApp(pI.applicationInfo.uid);
-
-            UserHandle user = UserHandle.getUserHandleForUid(pI.applicationInfo.uid);
-            int permFlags = pm.getPermissionFlags(READ_PHONE_STATE, pI.packageName, user);
-            if ((permFlags & FLAG_PERMISSION_AUTO_REVOKED) != 0) {
-                pm.updatePermissionFlags(READ_PHONE_STATE, pI.packageName,
-                        FLAG_PERMISSION_AUTO_REVOKED, 0, user);
-            }
-        }
-    }
-
     @Override
     public void onStopUser(@UserIdInt int userId) {
         if (DEBUG) Slog.i(LOG_TAG, "onStopUser(" + userId + ")");
@@ -460,7 +415,8 @@
                 throw new IllegalStateException(e);
             }
 
-            permissionControllerManager.updateUserSensitive();
+            FgThread.getHandler().postDelayed(permissionControllerManager::updateUserSensitive,
+                    USER_SENSITIVE_UPDATE_DELAY_MS);
 
             packageManagerInternal.updateRuntimePermissionsFingerprint(userId);
         }
diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
index d6c48a0..cc36935 100644
--- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
+++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
@@ -26,7 +26,6 @@
 import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.os.storage.StorageManager.PROP_LEGACY_OP_STICKY;
 
 import static java.lang.Integer.min;
 
@@ -37,13 +36,17 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.os.Build;
-import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.os.storage.StorageManager;
 import android.os.storage.StorageManagerInternal;
+import android.provider.DeviceConfig;
 
 import com.android.server.LocalServices;
 import com.android.server.pm.parsing.pkg.AndroidPackage;
 
+import java.util.Arrays;
+import java.util.HashSet;
+
 /**
  * The behavior of soft restricted permissions is different for each permission. This class collects
  * the policies in one place.
@@ -65,8 +68,8 @@
                 }
             };
 
-    private static final boolean isLegacyStorageAppOpStickyGlobal = SystemProperties.getBoolean(
-            PROP_LEGACY_OP_STICKY, /*defaultValue*/true);
+    private static final HashSet<String> sForcedScopedStorageAppWhitelist = new HashSet<>(
+            Arrays.asList(getForcedScopedStorageAppWhitelist()));
 
     /**
      * TargetSDK is per package. To make sure two apps int the same shared UID do not fight over
@@ -141,12 +144,13 @@
                     shouldPreserveLegacyExternalStorage = pkg.hasPreserveLegacyExternalStorage()
                             && smInternal.hasLegacyExternalStorage(appInfo.uid);
                     targetSDK = getMinimumTargetSDK(context, appInfo, user);
-                    // LEGACY_STORAGE op is normally sticky for apps targetig <= Q.
-                    // However, this device can be configured to make it non-sticky.
-                    boolean isLegacyAppOpSticky = isLegacyStorageAppOpStickyGlobal
-                            && targetSDK <= Build.VERSION_CODES.Q;
+
                     shouldApplyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0
-                            || (!isLegacyAppOpSticky && !shouldPreserveLegacyExternalStorage);
+                            || (targetSDK > Build.VERSION_CODES.Q
+                            && !shouldPreserveLegacyExternalStorage)
+                            // If the device is configured to force this app into scoped storage,
+                            // then we should apply the restriction
+                            || sForcedScopedStorageAppWhitelist.contains(appInfo.packageName);
                 } else {
                     isWhiteListed = false;
                     shouldApplyRestriction = false;
@@ -245,6 +249,15 @@
         return false;
     }
 
+    private static String[] getForcedScopedStorageAppWhitelist() {
+        final String rawList = DeviceConfig.getString(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+                StorageManager.PROP_FORCED_SCOPED_STORAGE_WHITELIST, /*defaultValue*/"");
+        if (rawList == null || rawList.equals("")) {
+            return new String[0];
+        }
+        return rawList.split(",");
+    }
+
     /**
      * @return If the permission can be granted
      */
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 199cb49..0b95be1 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -413,6 +413,7 @@
 
             // Start input as soon as we start waking up or going to sleep.
             mInputManagerInternal.setInteractive(interactive);
+            mInputMethodManagerInternal.setInteractive(interactive);
 
             // Notify battery stats.
             try {
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 3336697..f075790 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -301,10 +301,7 @@
                 }
                 if (Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) {
                     String packageName = intent.getData().getSchemeSpecificPart();
-                    if (LOCAL_LOGV) {
-                        Slog.v(TAG, "broadcast=ACTION_PACKAGE_FULLY_REMOVED"
-                                + " pkg=" + packageName);
-                    }
+                    Slog.i(TAG, "broadcast=ACTION_PACKAGE_FULLY_REMOVED pkg=" + packageName);
                     onPackageFullyRemoved(packageName);
                 }
             }
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 3b4c423..29c1243 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -17,18 +17,22 @@
 package com.android.server.stats.pull;
 
 import static android.app.AppOpsManager.OP_FLAG_SELF;
-import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXY;
+import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
 import static android.app.usage.NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
 import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
 import static android.os.Debug.getIonHeapsSizeKb;
 import static android.os.Process.getUidForPid;
 import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
 import static android.os.storage.VolumeInfo.TYPE_PUBLIC;
+import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION;
 import static android.util.MathUtils.abs;
 import static android.util.MathUtils.constrain;
 
+import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
 import static com.android.internal.util.FrameworkStatsLog.ANNOTATION_ID_IS_UID;
 import static com.android.internal.util.FrameworkStatsLog.ANNOTATION_ID_TRUNCATE_TIMESTAMP;
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
@@ -38,6 +42,7 @@
 import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs;
 import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
 
+import static java.util.concurrent.TimeUnit.HOURS;
 import static java.util.concurrent.TimeUnit.MICROSECONDS;
 
 import android.annotation.NonNull;
@@ -133,6 +138,7 @@
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.ProcessCpuTracker;
 import com.android.internal.os.StoragedUidIoStatsReader;
+import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.BatteryService;
 import com.android.server.BinderCallsStatsService;
@@ -202,9 +208,15 @@
     private static final long MILLIS_PER_SEC = 1000;
     private static final long MILLI_AMP_HR_TO_NANO_AMP_SECS = 1_000_000L * 3600L;
 
+    /**
+     * The default bucket duration used when query a snapshot from NetworkStatsService.
+     * The value should be sync with NetworkStatsService#DefaultNetworkStatsSettings#getUidConfig.
+     */
+    private static final long NETSTATS_UID_DEFAULT_BUCKET_DURATION_MS = HOURS.toMillis(2);
+
     private static final int MAX_BATTERY_STATS_HELPER_FREQUENCY_MS = 1000;
     private static final int CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES = 8;
-    private static final int OP_FLAGS_PULLED = OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXY;
+    private static final int OP_FLAGS_PULLED = OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED;
     private static final String COMMON_PERMISSION_PREFIX = "android.permission.";
     private static final String APP_OPS_TARGET_COLLECTION_SIZE = "app_ops_target_collection_size";
     private static final String DANGEROUS_PERMISSION_STATE_SAMPLE_RATE =
@@ -278,6 +290,14 @@
     private StatsPullAtomCallbackImpl mStatsCallbackImpl;
 
     private int mAppOpsSamplingRate = 0;
+    private final ArraySet<Integer> mDangerousAppOpsList = new ArraySet<>();
+
+    // Baselines that stores list of NetworkStats right after initializing, with associated
+    // information. This is used to calculate difference when pulling
+    // {Mobile|Wifi}BytesTransfer* atoms. Note that this is not thread-safe, and must
+    // only be accessed on the background thread.
+    @NonNull
+    private final List<NetworkStatsExt> mNetworkStatsBaselines = new ArrayList<>();
 
     public StatsPullAtomService(Context context) {
         super(context);
@@ -302,13 +322,10 @@
             try {
                 switch (atomTag) {
                     case FrameworkStatsLog.WIFI_BYTES_TRANSFER:
-                        return pullWifiBytesTransfer(atomTag, data, false);
                     case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG:
-                        return pullWifiBytesTransfer(atomTag, data, true);
                     case FrameworkStatsLog.MOBILE_BYTES_TRANSFER:
-                        return pullMobileBytesTransfer(atomTag, data, false);
                     case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG:
-                        return pullMobileBytesTransfer(atomTag, data, true);
+                        return pullDataBytesTransfer(atomTag, data);
                     case FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER:
                         return pullBluetoothBytesTransfer(atomTag, data);
                     case FrameworkStatsLog.KERNEL_WAKELOCK:
@@ -423,6 +440,8 @@
                         return pullAttributedAppOps(atomTag, data);
                     case FrameworkStatsLog.SETTING_SNAPSHOT:
                         return pullSettingsStats(atomTag, data);
+                    case FrameworkStatsLog.DISPLAY_WAKE_REASON:
+                        return pullDisplayWakeStats(atomTag, data);
                     default:
                         throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
                 }
@@ -444,9 +463,12 @@
             BackgroundThread.getHandler().post(() -> {
                 nativeInit();
                 initializePullersState();
-                registerAllPullers();
+                registerPullers();
                 registerEventListeners();
             });
+        } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+            // Network stats related pullers can only be initialized after service is ready.
+            BackgroundThread.getHandler().post(() -> initAndRegisterNetworkStatsPullers());
         }
     }
 
@@ -499,6 +521,25 @@
         } catch (RemoteException e) {
             Slog.e(TAG, "failed to initialize healthHalWrapper");
         }
+
+        // Initialize list of AppOps related to DangerousPermissions
+        PackageManager pm = mContext.getPackageManager();
+        for (int op = 0; op < AppOpsManager._NUM_OP; op++) {
+            String perm = AppOpsManager.opToPermission(op);
+            if (perm == null) {
+                continue;
+            } else {
+                PermissionInfo permInfo;
+                try {
+                    permInfo = pm.getPermissionInfo(perm, 0);
+                    if (permInfo.getProtection() == PROTECTION_DANGEROUS) {
+                        mDangerousAppOpsList.add(op);
+                    }
+                } catch (PackageManager.NameNotFoundException exception) {
+                    continue;
+                }
+            }
+        }
     }
 
     void registerEventListeners() {
@@ -521,15 +562,11 @@
         }
     }
 
-    void registerAllPullers() {
+    void registerPullers() {
         if (DEBUG) {
-            Slog.d(TAG, "Registering all pullers with statsd");
+            Slog.d(TAG, "Registering pullers with statsd");
         }
         mStatsCallbackImpl = new StatsPullAtomCallbackImpl();
-        registerWifiBytesTransfer();
-        registerWifiBytesTransferBackground();
-        registerMobileBytesTransfer();
-        registerMobileBytesTransferBackground();
         registerBluetoothBytesTransfer();
         registerKernelWakelock();
         registerCpuTimePerFreq();
@@ -588,6 +625,27 @@
         registerBatteryVoltage();
         registerBatteryCycleCount();
         registerSettingsStats();
+        registerDisplayWakeStats();
+    }
+
+    private void initAndRegisterNetworkStatsPullers() {
+        if (DEBUG) {
+            Slog.d(TAG, "Registering NetworkStats pullers with statsd");
+        }
+        // Initialize NetworkStats baselines.
+        mNetworkStatsBaselines.addAll(
+                collectNetworkStatsSnapshotForAtom(FrameworkStatsLog.WIFI_BYTES_TRANSFER));
+        mNetworkStatsBaselines.addAll(
+                collectNetworkStatsSnapshotForAtom(FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG));
+        mNetworkStatsBaselines.addAll(
+                collectNetworkStatsSnapshotForAtom(FrameworkStatsLog.MOBILE_BYTES_TRANSFER));
+        mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtom(
+                FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG));
+
+        registerWifiBytesTransfer();
+        registerWifiBytesTransferBackground();
+        registerMobileBytesTransfer();
+        registerMobileBytesTransferBackground();
     }
 
     /**
@@ -718,42 +776,98 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
 
-    private int pullWifiBytesTransfer(
-            int atomTag, @NonNull List<StatsEvent> pulledData, boolean withFgbg) {
-        final NetworkTemplate template = NetworkTemplate.buildTemplateWifiWildcard();
-        final NetworkStats stats = getUidNetworkStatsSinceBoot(template, withFgbg);
+    /**
+     * A data class to store a NetworkStats object with information associated to it.
+     */
+    private static class NetworkStatsExt {
+        @NonNull
+        public final NetworkStats stats;
+        public final int transport;
+        public final boolean withFgbg;
 
-        // Return with PULL_SKIP to indicate there is an error.
-        if (stats == null) return StatsManager.PULL_SKIP;
-
-        addNetworkStats(atomTag, pulledData, stats, withFgbg, 0 /* ratType */);
-        return StatsManager.PULL_SUCCESS;
+        NetworkStatsExt(@NonNull NetworkStats stats, int transport, boolean withFgbg) {
+            this.stats = stats;
+            this.transport = transport;
+            this.withFgbg = withFgbg;
+        }
     }
 
-    private int pullMobileBytesTransfer(
-            int atomTag, @NonNull List<StatsEvent> pulledData, boolean withFgbg) {
-        final NetworkTemplate template =
-                NetworkTemplate.buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL);
-        final NetworkStats stats = getUidNetworkStatsSinceBoot(template, withFgbg);
+    @NonNull
+    private List<NetworkStatsExt> collectNetworkStatsSnapshotForAtom(int atomTag) {
+        switch(atomTag) {
+            case FrameworkStatsLog.WIFI_BYTES_TRANSFER:
+                return collectUidNetworkStatsSnapshot(TRANSPORT_WIFI, /*withFgbg=*/false);
+            case  FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG:
+                return collectUidNetworkStatsSnapshot(TRANSPORT_WIFI, /*withFgbg=*/true);
+            case FrameworkStatsLog.MOBILE_BYTES_TRANSFER:
+                return collectUidNetworkStatsSnapshot(TRANSPORT_CELLULAR, /*withFgbg=*/false);
+            case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG:
+                return collectUidNetworkStatsSnapshot(TRANSPORT_CELLULAR, /*withFgbg=*/true);
+            default:
+                throw new IllegalArgumentException("Unknown atomTag " + atomTag);
+        }
+    }
 
-        // Return with PULL_SKIP to indicate there is an error.
-        if (stats == null) return StatsManager.PULL_SKIP;
+    // Get a snapshot of Uid NetworkStats. The snapshot contains NetworkStats with its associated
+    // information, and wrapped by a list since multiple NetworkStatsExt objects might be collected.
+    @NonNull
+    private List<NetworkStatsExt> collectUidNetworkStatsSnapshot(int transport, boolean withFgbg) {
+        final List<NetworkStatsExt> ret = new ArrayList<>();
+        final NetworkTemplate template = (transport == TRANSPORT_CELLULAR
+                ? NetworkTemplate.buildTemplateMobileWithRatType(
+                        /*subscriptionId=*/null, NETWORK_TYPE_ALL)
+                : NetworkTemplate.buildTemplateWifiWildcard());
 
-        addNetworkStats(atomTag, pulledData, stats, withFgbg, NETWORK_TYPE_ALL);
+        final NetworkStats stats = getUidNetworkStatsSnapshot(template, withFgbg);
+        if (stats != null) {
+            ret.add(new NetworkStatsExt(stats, transport, withFgbg));
+        }
+        return ret;
+    }
+
+
+    private int pullDataBytesTransfer(
+            int atomTag, @NonNull List<StatsEvent> pulledData) {
+        final List<NetworkStatsExt> current = collectNetworkStatsSnapshotForAtom(atomTag);
+
+        if (current == null) {
+            Slog.e(TAG, "current snapshot is null for " + atomTag + ", return.");
+            return StatsManager.PULL_SKIP;
+        }
+
+        for (final NetworkStatsExt item : current) {
+            final NetworkStatsExt baseline = CollectionUtils.find(mNetworkStatsBaselines,
+                    it -> it.withFgbg == item.withFgbg && it.transport == item.transport);
+
+            // No matched baseline indicates error has occurred during initialization stage,
+            // skip reporting anything since the snapshot is invalid.
+            if (baseline == null) {
+                Slog.e(TAG, "baseline is null for " + atomTag + ", transport="
+                        + item.transport + " , withFgbg=" + item.withFgbg + ", return.");
+                return StatsManager.PULL_SKIP;
+            }
+            final NetworkStatsExt diff = new NetworkStatsExt(item.stats.subtract(
+                    baseline.stats).removeEmptyEntries(), item.transport, item.withFgbg);
+
+            // If no diff, skip.
+            if (diff.stats.size() == 0) continue;
+
+            addNetworkStats(atomTag, pulledData, diff);
+        }
         return StatsManager.PULL_SUCCESS;
     }
 
     private void addNetworkStats(int atomTag, @NonNull List<StatsEvent> ret,
-            @NonNull NetworkStats stats, boolean withFgbg, int ratType) {
-        int size = stats.size();
+            @NonNull NetworkStatsExt statsExt) {
+        int size = statsExt.stats.size();
         final NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling
         for (int j = 0; j < size; j++) {
-            stats.getValues(j, entry);
+            statsExt.stats.getValues(j, entry);
             StatsEvent.Builder e = StatsEvent.newBuilder();
             e.setAtomId(atomTag);
             switch (atomTag) {
@@ -765,7 +879,7 @@
             }
             e.writeInt(entry.uid);
             e.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
-            if (withFgbg) {
+            if (statsExt.withFgbg) {
                 e.writeInt(entry.set);
             }
             e.writeLong(entry.rxBytes);
@@ -776,14 +890,23 @@
         }
     }
 
-    @Nullable private NetworkStats getUidNetworkStatsSinceBoot(
+    /**
+     * Create a snapshot of NetworkStats since boot, but add 1 bucket duration before boot as a
+     * buffer to ensure at least one full bucket will be included.
+     * Note that this should be only used to calculate diff since the snapshot might contains
+     * some traffic before boot.
+     */
+    @Nullable private NetworkStats getUidNetworkStatsSnapshot(
             @NonNull NetworkTemplate template, boolean withFgbg) {
 
         final long elapsedMillisSinceBoot = SystemClock.elapsedRealtime();
         final long currentTimeInMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro());
+        final long bucketDuration = Settings.Global.getLong(mContext.getContentResolver(),
+                NETSTATS_UID_BUCKET_DURATION, NETSTATS_UID_DEFAULT_BUCKET_DURATION_MS);
         try {
             final NetworkStats stats = getNetworkStatsSession().getSummaryForAllUid(template,
-                    currentTimeInMillis - elapsedMillisSinceBoot, currentTimeInMillis, false);
+                    currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration,
+                    currentTimeInMillis, /*includeTags=*/false);
             return withFgbg ? rollupNetworkStatsByFgbg(stats) : stats.groupedByUid();
         } catch (RemoteException | NullPointerException e) {
             Slog.e(TAG, "Pulling netstats for " + template
@@ -833,7 +956,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -846,7 +969,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -859,7 +982,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -872,7 +995,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -942,7 +1065,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 /* PullAtomMetadata */ null,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -973,7 +1096,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1004,7 +1127,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1034,7 +1157,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1067,7 +1190,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1095,7 +1218,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1121,7 +1244,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1173,7 +1296,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1211,7 +1334,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 /* metadata */ null,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1243,7 +1366,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1262,7 +1385,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1284,7 +1407,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1328,7 +1451,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1383,7 +1506,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1445,7 +1568,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1468,7 +1591,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 /* PullAtomMetadata */ null,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1488,7 +1611,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1515,7 +1638,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1553,7 +1676,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1593,7 +1716,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1637,7 +1760,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1672,7 +1795,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1715,7 +1838,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1781,7 +1904,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1822,7 +1945,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1866,7 +1989,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1970,7 +2093,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -1980,7 +2103,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2038,7 +2161,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2048,7 +2171,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2124,7 +2247,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2158,7 +2281,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 /* PullAtomMetadata */ null,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2185,7 +2308,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2221,7 +2344,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2315,7 +2438,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2335,7 +2458,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2366,7 +2489,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2402,7 +2525,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2453,7 +2576,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 metadata,
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2491,7 +2614,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2518,7 +2641,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2577,7 +2700,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2670,7 +2793,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2697,7 +2820,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2747,7 +2870,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2803,7 +2926,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2857,7 +2980,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2867,7 +2990,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -2900,7 +3023,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -3014,22 +3137,8 @@
         e.writeLong(op.getBackgroundRejectCount(OP_FLAGS_PULLED));
         e.writeLong(op.getForegroundAccessDuration(OP_FLAGS_PULLED));
         e.writeLong(op.getBackgroundAccessDuration(OP_FLAGS_PULLED));
+        e.writeBoolean(mDangerousAppOpsList.contains(op.getOpCode()));
 
-        String perm = AppOpsManager.opToPermission(op.getOpCode());
-        if (perm == null) {
-            e.writeBoolean(false);
-        } else {
-            PermissionInfo permInfo;
-            try {
-                permInfo = mContext.getPackageManager().getPermissionInfo(
-                        perm,
-                        0);
-                e.writeBoolean(
-                        permInfo.getProtection() == PROTECTION_DANGEROUS);
-            } catch (PackageManager.NameNotFoundException exception) {
-                e.writeBoolean(false);
-            }
-        }
         if (atomTag == FrameworkStatsLog.ATTRIBUTED_APP_OPS) {
             e.writeInt(mAppOpsSamplingRate);
         }
@@ -3119,7 +3228,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -3163,7 +3272,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -3173,7 +3282,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -3183,7 +3292,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -3193,7 +3302,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -3203,7 +3312,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -3213,7 +3322,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -3263,7 +3372,7 @@
         mStatsManager.setPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                BackgroundThread.getExecutor(),
+                DIRECT_EXECUTOR,
                 mStatsCallbackImpl
         );
     }
@@ -3295,6 +3404,21 @@
         return StatsManager.PULL_SUCCESS;
     }
 
+    private void registerDisplayWakeStats() {
+        int tagId = FrameworkStatsLog.DISPLAY_WAKE_REASON;
+        mStatsManager.setPullAtomCallback(
+                tagId,
+                null, // use default PullAtomMetadata values
+                DIRECT_EXECUTOR,
+                mStatsCallbackImpl
+        );
+    }
+
+    int pullDisplayWakeStats(int atomTag, List<StatsEvent> pulledData) {
+        //TODO: Denny, implement read/write DisplayWakeStats, b/154172964
+        return 0;
+    }
+
     // Thermal event received from vendor thermal management subsystem
     private static final class ThermalEventListener extends IThermalEventListener.Stub {
         @Override
diff --git a/services/core/java/com/android/server/textclassifier/IconsContentProvider.java b/services/core/java/com/android/server/textclassifier/IconsContentProvider.java
index d19a707..9b3176d 100644
--- a/services/core/java/com/android/server/textclassifier/IconsContentProvider.java
+++ b/services/core/java/com/android/server/textclassifier/IconsContentProvider.java
@@ -25,6 +25,7 @@
 import android.net.Uri;
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
+import android.os.UserHandle;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -51,7 +52,7 @@
         try {
             final ResourceInfo res = IconsUriHelper.getInstance().getResourceInfo(uri);
             final Drawable drawable = Icon.createWithResource(res.packageName, res.id)
-                    .loadDrawable(getContext());
+                    .loadDrawableAsUser(getContext(), UserHandle.getCallingUserId());
             final byte[] data = getBitmapData(drawable);
             final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
             final ParcelFileDescriptor readSide = pipe[0];
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 63952b0..31fbaff 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -2743,7 +2743,7 @@
                     mContext, 0,
                     Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
                             mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
-                    0, null, new UserHandle(serviceUserId)));
+                    PendingIntent.FLAG_IMMUTABLE, null, new UserHandle(serviceUserId)));
             if (!mContext.bindServiceAsUser(intent, newConn,
                     Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI
                             | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 785ca90..34998a0 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -50,7 +50,7 @@
 import android.util.SparseArray;
 import android.util.TypedValue;
 import android.view.Display;
-import android.view.InsetsState;
+import android.view.InsetsSource;
 import android.view.MagnificationSpec;
 import android.view.Surface;
 import android.view.Surface.OutOfResourcesException;
@@ -80,6 +80,7 @@
 
     private final WindowManagerService mService;
 
+    private static final Rect EMPTY_RECT = new Rect();
     private static final float[] sTempFloats = new float[9];
 
     public AccessibilityController(WindowManagerService service) {
@@ -1166,9 +1167,9 @@
     }
 
     static Rect getNavBarInsets(DisplayContent displayContent) {
-        final InsetsState insetsState =
-                displayContent.getInsetsStateController().getRawInsetsState();
-        return insetsState.getSource(ITYPE_NAVIGATION_BAR).getFrame();
+        final InsetsSource source = displayContent.getInsetsStateController().getRawInsetsState()
+                .peekSource(ITYPE_NAVIGATION_BAR);
+        return source != null ? source.getFrame() : EMPTY_RECT;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index ed74e89..b5b82d3 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1286,12 +1286,6 @@
         }
 
         if (stack != null && stack.topRunningActivity() == this) {
-            // carry over the PictureInPictureParams to the parent stack without calling
-            // TaskOrganizerController#dispatchTaskInfoChanged.
-            // this is to ensure the stack holding up-to-dated pinned stack information
-            // when activity is re-parented to enter pip mode, see also
-            // RootWindowContainer#moveActivityToPinnedStack
-            stack.mPictureInPictureParams.copyOnlySet(pictureInPictureArgs);
             // make ensure the TaskOrganizer still works after re-parenting
             if (firstWindowDrawn) {
                 stack.setHasBeenVisible(true);
@@ -1711,7 +1705,7 @@
     boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
             CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
             IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
-            boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
+            boolean allowTaskSnapshot, boolean activityCreated) {
         // If the display is frozen, we won't do anything until the actual window is
         // displayed so there is no reason to put in the starting window.
         if (!okToDisplay()) {
@@ -1732,7 +1726,7 @@
                 mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, task.mUserId,
                         false /* restoreFromDisk */, false /* isLowResolution */);
         final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
-                allowTaskSnapshot, activityCreated, fromRecents, snapshot);
+                allowTaskSnapshot, activityCreated, snapshot);
 
         if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
             if (isActivityTypeHome()) {
@@ -1894,12 +1888,12 @@
     private final AddStartingWindow mAddStartingWindow = new AddStartingWindow();
 
     private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
-            boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
+            boolean allowTaskSnapshot, boolean activityCreated,
             ActivityManager.TaskSnapshot snapshot) {
         if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
             return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
         } else if (taskSwitch && allowTaskSnapshot) {
-            if (snapshotOrientationSameAsTask(snapshot) || (snapshot != null && fromRecents)) {
+            if (isSnapshotCompatible(snapshot)) {
                 return STARTING_WINDOW_TYPE_SNAPSHOT;
             }
             if (!isActivityTypeHome()) {
@@ -1911,11 +1905,22 @@
         }
     }
 
-    private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
+    /**
+     * Returns {@code true} if the task snapshot is compatible with this activity (at least the
+     * rotation must be the same).
+     */
+    @VisibleForTesting
+    boolean isSnapshotCompatible(ActivityManager.TaskSnapshot snapshot) {
         if (snapshot == null) {
             return false;
         }
-        return task.getConfiguration().orientation == snapshot.getOrientation();
+        final int rotation = mDisplayContent.rotationForActivityInDifferentOrientation(this);
+        final int targetRotation = rotation != ROTATION_UNDEFINED
+                // The display may rotate according to the orientation of this activity.
+                ? rotation
+                // The activity won't change display orientation.
+                : task.getWindowConfiguration().getRotation();
+        return snapshot.getRotation() == targetRotation;
     }
 
     void removeStartingWindow() {
@@ -2190,8 +2195,10 @@
 
     @Override
     boolean isFocusable() {
-        return super.isFocusable()
-                && (getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable());
+        // TODO(156521483): Propagate the state down the hierarchy instead of checking the parent
+        boolean canReceiveKeys = getWindowConfiguration().canReceiveKeys()
+                && getTask().getWindowConfiguration().canReceiveKeys();
+        return super.isFocusable() && (canReceiveKeys || isAlwaysFocusable());
     }
 
     boolean isResizeable() {
@@ -3582,7 +3589,7 @@
 
     @Override
     ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom,
-            WindowContainer boundary) {
+            ActivityRecord boundary) {
         return callback.test(this) ? this : null;
     }
 
@@ -4791,16 +4798,7 @@
         if (!task.hasChild(this)) {
             throw new IllegalStateException("Activity not found in its task");
         }
-        final ActivityRecord activityAbove = task.getActivityAbove(this);
-        if (activityAbove == null) {
-            // It's the topmost activity in the task - should become resumed now
-            return true;
-        }
-        // Check if activity above is finishing now and this one becomes the topmost in task.
-        if (activityAbove.finishing) {
-            return true;
-        }
-        return false;
+        return task.topRunningActivity() == this;
     }
 
     void handleAlreadyVisible() {
@@ -5679,11 +5677,6 @@
     }
 
     void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch) {
-        showStartingWindow(prev, newTask, taskSwitch, false /* fromRecents */);
-    }
-
-    void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
-            boolean fromRecents) {
         if (mTaskOverlay) {
             // We don't show starting window for overlay activities.
             return;
@@ -5700,8 +5693,7 @@
                 compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
                 prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
                 allowTaskSnapshot(),
-                mState.ordinal() >= STARTED.ordinal() && mState.ordinal() <= STOPPED.ordinal(),
-                fromRecents);
+                mState.ordinal() >= STARTED.ordinal() && mState.ordinal() <= STOPPED.ordinal());
         if (shown) {
             mStartingWindowState = STARTING_WINDOW_SHOWN;
         }
@@ -6692,6 +6684,13 @@
     }
 
     @Override
+    void getAnimationPosition(Point outPosition) {
+        // Always animate from zero because if the activity doesn't fill the task, the letterbox
+        // will fill the remaining area that should be included in the animation.
+        outPosition.set(0, 0);
+    }
+
+    @Override
     public void onConfigurationChanged(Configuration newParentConfig) {
         if (mCompatDisplayInsets != null) {
             Configuration overrideConfig = getRequestedOverrideConfiguration();
@@ -7785,6 +7784,6 @@
 
     void setPictureInPictureParams(PictureInPictureParams p) {
         pictureInPictureArgs.copyOnlySet(p);
-        getTask().getRootTask().setPictureInPictureParams(p);
+        getTask().getRootTask().onPictureInPictureParamsChanged();
     }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index a84635d..9b9b613 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -382,6 +382,7 @@
             return mBehindFullscreenActivity;
         }
 
+        /** Returns {@code true} to stop the outer loop and indicate the result is computed. */
         private boolean processActivity(ActivityRecord r, ActivityRecord topActivity) {
             if (mAboveTop) {
                 if (r == topActivity) {
@@ -397,7 +398,10 @@
             }
 
             if (mHandlingOccluded) {
-                mHandleBehindFullscreenActivity.accept(r);
+                // Iterating through all occluded activities.
+                if (mBehindFullscreenActivity) {
+                    mHandleBehindFullscreenActivity.accept(r);
+                }
             } else if (r == mToCheck) {
                 return true;
             } else if (mBehindFullscreenActivity) {
@@ -702,8 +706,10 @@
         // Need to make sure windowing mode is supported. If we in the process of creating the stack
         // no need to resolve the windowing mode again as it is already resolved to the right mode.
         if (!creating) {
-            windowingMode = taskDisplayArea.validateWindowingMode(windowingMode,
-                    null /* ActivityRecord */, topTask, getActivityType());
+            if (!taskDisplayArea.isValidWindowingMode(windowingMode, null /* ActivityRecord */,
+                    topTask, getActivityType())) {
+                windowingMode = WINDOWING_MODE_UNDEFINED;
+            }
         }
         if (taskDisplayArea.getRootSplitScreenPrimaryTask() == this
                 && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
@@ -2702,7 +2708,9 @@
      */
     @Nullable
     private ActivityRecord getOccludingActivityAbove(ActivityRecord activity) {
-        return getActivity((ar) -> ar.occludesParent(), true /* traverseTopToBottom */, activity);
+        ActivityRecord top = getActivity((ar) -> ar.occludesParent(),
+                true /* traverseTopToBottom */, activity);
+        return top != activity ? top : null;
     }
 
     boolean willActivityBeVisible(IBinder token) {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index fb7ba62..62979ff 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -842,7 +842,7 @@
                         r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
                         r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
                         dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
-                                r.assistToken));
+                        r.assistToken, r.createFixedRotationAdjustmentsIfNeeded()));
 
                 // Set desired final state.
                 final ActivityLifecycleItem lifecycleItem;
@@ -1440,6 +1440,7 @@
         mService.deferWindowLayout();
         try {
             stack.setWindowingMode(WINDOWING_MODE_UNDEFINED);
+            stack.setBounds(null);
             if (toDisplay.getDisplayId() != stack.getDisplayId()) {
                 stack.reparent(toDisplay.getDefaultTaskDisplayArea(), false /* onTop */);
             } else {
@@ -2497,7 +2498,7 @@
                         mActivityMetricsLogger.notifyActivityLaunching(task.intent);
                 try {
                     mService.moveTaskToFrontLocked(null /* appThread */, null /* callingPackage */,
-                            task.mTaskId, 0, options, true /* fromRecents */);
+                            task.mTaskId, 0, options);
                     // Apply options to prevent pendingOptions be taken by client to make sure
                     // the override pending app transition will be applied immediately.
                     targetActivity.applyOptionsLocked();
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index dfa3fe0..c28d47c 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -19,7 +19,6 @@
 import static android.app.ActivityManager.START_SUCCESS;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.os.FactoryTest.FACTORY_TEST_LOW_LEVEL;
 
@@ -193,9 +192,7 @@
         final ActivityStack homeStack;
         try {
             // Make sure home stack exists on display area.
-            // TODO(b/153624902): Replace with TaskDisplayArea#getOrCreateRootHomeTask()
-            homeStack = taskDisplayArea.getOrCreateStack(WINDOWING_MODE_UNDEFINED,
-                    ACTIVITY_TYPE_HOME, ON_TOP);
+            homeStack = taskDisplayArea.getOrCreateRootHomeTask(ON_TOP);
         } finally {
             mSupervisor.endDeferResume();
         }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index f21ec6b..fdbb2b2 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2476,13 +2476,12 @@
         if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToFront: moving taskId=" + taskId);
         synchronized (mGlobalLock) {
             moveTaskToFrontLocked(appThread, callingPackage, taskId, flags,
-                    SafeActivityOptions.fromBundle(bOptions), false /* fromRecents */);
+                    SafeActivityOptions.fromBundle(bOptions));
         }
     }
 
     void moveTaskToFrontLocked(@Nullable IApplicationThread appThread,
-            @Nullable String callingPackage, int taskId, int flags, SafeActivityOptions options,
-            boolean fromRecents) {
+            @Nullable String callingPackage, int taskId, int flags, SafeActivityOptions options) {
         final int callingPid = Binder.getCallingPid();
         final int callingUid = Binder.getCallingUid();
         assertPackageMatchesCallingUid(callingPackage);
@@ -2527,7 +2526,7 @@
                 // We are reshowing a task, use a starting window to hide the initial draw delay
                 // so the transition can start earlier.
                 topActivity.showStartingWindow(null /* prev */, false /* newTask */,
-                        true /* taskSwitch */, fromRecents);
+                        true /* taskSwitch */);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -3213,7 +3212,7 @@
             if (TextUtils.equals(pae.intent.getAction(),
                     android.service.voice.VoiceInteractionService.SERVICE_INTERFACE)) {
                 // Start voice interaction through VoiceInteractionManagerService.
-                mAssistUtils.showSessionForActiveService(sendBundle, SHOW_SOURCE_APPLICATION,
+                mAssistUtils.showSessionForActiveService(pae.extras, SHOW_SOURCE_APPLICATION,
                         null, null);
             } else {
                 pae.intent.replaceExtras(pae.extras);
@@ -3320,7 +3319,7 @@
     }
 
     @Override
-    public void resizeTask(int taskId, Rect bounds, int resizeMode) {
+    public boolean resizeTask(int taskId, Rect bounds, int resizeMode) {
         mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "resizeTask()");
         long ident = Binder.clearCallingIdentity();
         try {
@@ -3329,10 +3328,11 @@
                         MATCH_TASK_IN_STACKS_ONLY);
                 if (task == null) {
                     Slog.w(TAG, "resizeTask: taskId=" + taskId + " not found");
-                    return;
+                    return false;
                 }
                 if (!task.getWindowConfiguration().canResizeTask()) {
-                    throw new IllegalArgumentException("resizeTask not allowed on task=" + task);
+                    Slog.w(TAG, "resizeTask not allowed on task=" + task);
+                    return false;
                 }
 
                 // Reparent the task to the right stack if necessary
@@ -3340,7 +3340,7 @@
 
                 // After reparenting (which only resizes the task to the stack bounds), resize the
                 // task to the actual bounds provided
-                task.resize(bounds, resizeMode, preserveWindow);
+                return task.resize(bounds, resizeMode, preserveWindow);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/wm/AnimationAdapter.java b/services/core/java/com/android/server/wm/AnimationAdapter.java
index 0519b80..529c4f6 100644
--- a/services/core/java/com/android/server/wm/AnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/AnimationAdapter.java
@@ -85,4 +85,25 @@
     }
 
     void dumpDebug(ProtoOutputStream proto);
+
+    /**
+     * Gets called when the animation is about to finish and gives the client the opportunity to
+     * defer finishing the animation, i.e. it keeps the leash around until the client calls
+     * endDeferFinishCallback.
+     * <p>
+     * This has the same effect as
+     * {@link com.android.server.wm.SurfaceAnimator.Animatable#shouldDeferAnimationFinish(Runnable)}
+     * . The later will be evaluated first and has precedence over this method if it returns true,
+     * which means that if the {@link com.android.server.wm.SurfaceAnimator.Animatable} requests to
+     * defer its finish, this method won't be called so this adapter will never have access to the
+     * finish callback. On the other hand, if the
+     * {@link com.android.server.wm.SurfaceAnimator.Animatable}, doesn't request to defer, this
+     * {@link AnimationAdapter} is responsible for ending the animation.
+     *
+     * @param endDeferFinishCallback The callback to call when defer finishing should be ended.
+     * @return Whether the client would like to defer the animation finish.
+     */
+    default boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
+        return false;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index 345cfb0..8260cb3 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -66,6 +66,7 @@
     final int mFeatureId;
     private final DisplayAreaOrganizerController mOrganizerController;
     IDisplayAreaOrganizer mOrganizer;
+    private final Configuration mTmpConfiguration = new Configuration();
 
     DisplayArea(WindowManagerService wms, Type type, String name) {
         this(wms, type, name, FEATURE_UNDEFINED);
@@ -106,6 +107,12 @@
     }
 
     @Override
+    boolean needsZBoost() {
+        // Z Boost should only happen at or below the ActivityStack level.
+        return false;
+    }
+
+    @Override
     boolean fillsParent() {
         return true;
     }
@@ -162,8 +169,10 @@
 
     @Override
     public void onConfigurationChanged(Configuration newParentConfig) {
+        mTmpConfiguration.setTo(getConfiguration());
         super.onConfigurationChanged(newParentConfig);
-        if (mOrganizer != null) {
+
+        if (mOrganizer != null && getConfiguration().diff(mTmpConfiguration) != 0) {
             mOrganizerController.onDisplayAreaInfoChanged(mOrganizer, this);
         }
     }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e31eaf7..d93e976 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -235,7 +235,6 @@
         implements WindowManagerPolicy.DisplayContentInfo {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
     private static final String TAG_STACK = TAG + POSTFIX_STACK;
-    private static final int NO_ROTATION = -1;
 
     /** The default scaling mode that scales content automatically. */
     static final int FORCE_SCALING_MODE_AUTO = 0;
@@ -494,10 +493,10 @@
      * The launching activity which is using fixed rotation transformation.
      *
      * @see #handleTopActivityLaunchingInDifferentOrientation
-     * @see #setFixedRotationLaunchingApp
+     * @see #setFixedRotationLaunchingApp(ActivityRecord, int)
      * @see DisplayRotation#shouldRotateSeamlessly
      */
-    ActivityRecord mFixedRotationLaunchingApp;
+    private ActivityRecord mFixedRotationLaunchingApp;
 
     final FixedRotationTransitionListener mFixedRotationTransitionListener =
             new FixedRotationTransitionListener();
@@ -1392,36 +1391,40 @@
         final WindowContainer orientationSource = getLastOrientationSource();
         final ActivityRecord r =
                 orientationSource != null ? orientationSource.asActivityRecord() : null;
-        if (r != null && r.getTask() != null
-                && orientation != r.getTask().mLastReportedRequestedOrientation) {
+        if (r != null) {
             final Task task = r.getTask();
-            task.mLastReportedRequestedOrientation = orientation;
-            mAtmService.getTaskChangeNotificationController()
-                    .notifyTaskRequestedOrientationChanged(task.mTaskId, orientation);
-        }
-        // Currently there is no use case from non-activity.
-        if (r != null && handleTopActivityLaunchingInDifferentOrientation(r)) {
-            // Display orientation should be deferred until the top fixed rotation is finished.
-            return false;
+            if (task != null && orientation != task.mLastReportedRequestedOrientation) {
+                task.mLastReportedRequestedOrientation = orientation;
+                mAtmService.getTaskChangeNotificationController()
+                        .notifyTaskRequestedOrientationChanged(task.mTaskId, orientation);
+            }
+            // Currently there is no use case from non-activity.
+            if (handleTopActivityLaunchingInDifferentOrientation(r, true /* checkOpening */)) {
+                // Display orientation should be deferred until the top fixed rotation is finished.
+                return false;
+            }
         }
         return mDisplayRotation.updateOrientation(orientation, forceUpdate);
     }
 
-    /** @return a valid rotation if the activity can use different orientation than the display. */
+    /**
+     * Returns a valid rotation if the activity can use different orientation than the display.
+     * Otherwise {@link #ROTATION_UNDEFINED}.
+     */
     @Surface.Rotation
-    private int rotationForActivityInDifferentOrientation(@NonNull ActivityRecord r) {
+    int rotationForActivityInDifferentOrientation(@NonNull ActivityRecord r) {
         if (!mWmService.mIsFixedRotationTransformEnabled) {
-            return NO_ROTATION;
+            return ROTATION_UNDEFINED;
         }
         if (r.inMultiWindowMode()
                 || r.getRequestedConfigurationOrientation() == getConfiguration().orientation) {
-            return NO_ROTATION;
+            return ROTATION_UNDEFINED;
         }
         final int currentRotation = getRotation();
         final int rotation = mDisplayRotation.rotationForOrientation(r.getRequestedOrientation(),
                 currentRotation);
         if (rotation == currentRotation) {
-            return NO_ROTATION;
+            return ROTATION_UNDEFINED;
         }
         return rotation;
     }
@@ -1431,9 +1434,13 @@
      * is launching until the launch animation is done to avoid showing the previous activity
      * inadvertently in a wrong orientation.
      *
+     * @param r The launching activity which may change display orientation.
+     * @param checkOpening Whether to check if the activity is animating by transition. Set to
+     *                     {@code true} if the caller is not sure whether the activity is launching.
      * @return {@code true} if the fixed rotation is started.
      */
-    private boolean handleTopActivityLaunchingInDifferentOrientation(@NonNull ActivityRecord r) {
+    boolean handleTopActivityLaunchingInDifferentOrientation(@NonNull ActivityRecord r,
+            boolean checkOpening) {
         if (!mWmService.mIsFixedRotationTransformEnabled) {
             return false;
         }
@@ -1444,19 +1451,18 @@
             // It has been set and not yet finished.
             return true;
         }
-        if (!mAppTransition.isTransitionSet()) {
-            // Apply normal rotation animation in case of the activity set different requested
-            // orientation without activity switch.
-            return false;
-        }
-        if (!mOpeningApps.contains(r)
-                // Without screen rotation, the rotation behavior of non-top visible activities is
-                // undefined. So the fixed rotated activity needs to cover the screen.
-                && r.findMainWindow() != mDisplayPolicy.getTopFullscreenOpaqueWindow()) {
+        if (checkOpening) {
+            if (!mAppTransition.isTransitionSet() && !mOpeningApps.contains(r)) {
+                // Apply normal rotation animation in case of the activity set different requested
+                // orientation without activity switch.
+                return false;
+            }
+        } else if (r != topRunningActivity()) {
+            // If the transition has not started yet, the activity must be the top.
             return false;
         }
         final int rotation = rotationForActivityInDifferentOrientation(r);
-        if (rotation == NO_ROTATION) {
+        if (rotation == ROTATION_UNDEFINED) {
             return false;
         }
         if (!r.getParent().matchParentBounds()) {
@@ -1469,6 +1475,23 @@
         return true;
     }
 
+    @Nullable ActivityRecord getFixedRotationLaunchingApp() {
+        return mFixedRotationLaunchingApp;
+    }
+
+    void setFixedRotationLaunchingAppUnchecked(@Nullable ActivityRecord r) {
+        setFixedRotationLaunchingAppUnchecked(r, ROTATION_UNDEFINED);
+    }
+
+    void setFixedRotationLaunchingAppUnchecked(@Nullable ActivityRecord r, int rotation) {
+        if (mFixedRotationLaunchingApp == null && r != null) {
+            mWmService.mDisplayNotificationController.dispatchFixedRotationStarted(this, rotation);
+        } else if (mFixedRotationLaunchingApp != null && r == null) {
+            mWmService.mDisplayNotificationController.dispatchFixedRotationFinished(this);
+        }
+        mFixedRotationLaunchingApp = r;
+    }
+
     /**
      * Sets the provided record to {@link mFixedRotationLaunchingApp} if possible to apply fixed
      * rotation transform to it and indicate that the display may be rotated after it is launched.
@@ -1490,7 +1513,7 @@
         if (!r.hasFixedRotationTransform()) {
             startFixedRotationTransform(r, rotation);
         }
-        mFixedRotationLaunchingApp = r;
+        setFixedRotationLaunchingAppUnchecked(r, rotation);
         if (prevRotatedLaunchingApp != null) {
             prevRotatedLaunchingApp.finishFixedRotationTransform();
         }
@@ -1509,12 +1532,16 @@
             sendNewConfiguration();
             return;
         }
+        if (mDisplayRotation.isWaitingForRemoteRotation()) {
+            // There is pending rotation change to apply.
+            return;
+        }
         // The orientation of display is not changed.
         clearFixedRotationLaunchingApp();
     }
 
     /**
-     * Clears the {@link mFixedRotationLaunchingApp} without applying rotation to display. It is
+     * Clears the {@link #mFixedRotationLaunchingApp} without applying rotation to display. It is
      * used when the display won't rotate (e.g. the orientation from sensor has updated again before
      * applying rotation to display) but the launching app has been transformed. So the record need
      * to be cleared and restored to stop using seamless rotation and rotated configuration.
@@ -1524,7 +1551,7 @@
             return;
         }
         mFixedRotationLaunchingApp.finishFixedRotationTransform();
-        mFixedRotationLaunchingApp = null;
+        setFixedRotationLaunchingAppUnchecked(null);
     }
 
     private void startFixedRotationTransform(WindowToken token, int rotation) {
@@ -1544,7 +1571,7 @@
      */
     void rotateInDifferentOrientationIfNeeded(ActivityRecord activityRecord) {
         int rotation = rotationForActivityInDifferentOrientation(activityRecord);
-        if (rotation != NO_ROTATION) {
+        if (rotation != ROTATION_UNDEFINED) {
             startFixedRotationTransform(activityRecord, rotation);
         }
     }
@@ -3293,7 +3320,7 @@
                     mInputMethodWindow.getDisplayId());
         }
         mInsetsStateController.getSourceProvider(ITYPE_IME).setWindow(win,
-                null /* frameProvider */, null /* imeFrameProvider */);
+                mDisplayPolicy.getImeSourceFrameProvider(), null /* imeFrameProvider */);
         computeImeTarget(true /* updateImeTarget */);
         updateImeControlTarget();
     }
@@ -4676,9 +4703,11 @@
     boolean supportsSystemDecorations() {
         return (mWmService.mDisplayWindowSettings.shouldShowSystemDecorsLocked(this)
                 || (mDisplay.getFlags() & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0
-                || (mWmService.mForceDesktopModeOnExternalDisplays && !isUntrustedVirtualDisplay()))
+                || mWmService.mForceDesktopModeOnExternalDisplays)
                 // VR virtual display will be used to run and render 2D app within a VR experience.
-                && mDisplayId != mWmService.mVr2dDisplayId;
+                && mDisplayId != mWmService.mVr2dDisplayId
+                // Do not show system decorations on untrusted virtual display.
+                && !isUntrustedVirtualDisplay();
     }
 
     /**
@@ -5248,7 +5277,7 @@
 
         rotatedLaunchingApp.finishFixedRotationTransform(
                 () -> applyRotation(oldRotation, newRotation));
-        mFixedRotationLaunchingApp = null;
+        setFixedRotationLaunchingAppUnchecked(null);
     }
 
     /** Checks whether the given activity is in size compatibility mode and notifies the change. */
@@ -5562,7 +5591,7 @@
             if (animatingRecents != null && animatingRecents == mFixedRotationLaunchingApp) {
                 // Because it won't affect display orientation, just finish the transform.
                 animatingRecents.finishFixedRotationTransform();
-                mFixedRotationLaunchingApp = null;
+                setFixedRotationLaunchingAppUnchecked(null);
             } else {
                 // If there is already a launching activity that is not the recents, before its
                 // transition is completed, the recents animation may be started. So if the recents
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index eb5cff6..2f18a0d 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -874,10 +874,6 @@
                 }
                 break;
 
-            case TYPE_SCREENSHOT:
-                attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-                break;
-
             case TYPE_TOAST:
                 // While apps should use the dedicated toast APIs to add such windows
                 // it possible legacy apps to add the window directly. Therefore, we
@@ -1110,6 +1106,24 @@
         }
     }
 
+    TriConsumer<DisplayFrames, WindowState, Rect> getImeSourceFrameProvider() {
+        return (displayFrames, windowState, inOutFrame) -> {
+            if (mNavigationBar != null && navigationBarPosition(displayFrames.mDisplayWidth,
+                    displayFrames.mDisplayHeight,
+                    displayFrames.mRotation) == NAV_BAR_BOTTOM) {
+                // In gesture navigation, nav bar frame is larger than frame to calculate insets.
+                // IME should not provide frame which is smaller than the nav bar frame. Otherwise,
+                // nav bar might be overlapped with the content of the client when IME is shown.
+                sTmpRect.set(inOutFrame);
+                sTmpRect.intersectUnchecked(mNavigationBar.getFrameLw());
+                inOutFrame.inset(windowState.getGivenContentInsetsLw());
+                inOutFrame.union(sTmpRect);
+            } else {
+                inOutFrame.inset(windowState.getGivenContentInsetsLw());
+            }
+        };
+    }
+
     private static void enforceSingleInsetsTypeCorrespondingToWindowType(int[] insetsTypes) {
         int count = 0;
         for (int insetsType : insetsTypes) {
@@ -2036,9 +2050,13 @@
             final Rect dfu = displayFrames.mUnrestricted;
             Insets insets = Insets.of(0, 0, 0, 0);
             for (int i = types.size() - 1; i >= 0; i--) {
-                insets = Insets.max(insets, mDisplayContent.getInsetsPolicy()
-                        .getInsetsForDispatch(win).getSource(types.valueAt(i))
-                        .calculateInsets(dfu, attrs.isFitInsetsIgnoringVisibility()));
+                final InsetsSource source = mDisplayContent.getInsetsPolicy()
+                        .getInsetsForDispatch(win).peekSource(types.valueAt(i));
+                if (source == null) {
+                    continue;
+                }
+                insets = Insets.max(insets, source.calculateInsets(
+                        dfu, attrs.isFitInsetsIgnoringVisibility()));
             }
             final int left = (sidesToFit & Side.LEFT) != 0 ? insets.left : 0;
             final int top = (sidesToFit & Side.TOP) != 0 ? insets.top : 0;
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index ebfe70c..702df2a 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -577,7 +577,7 @@
     boolean shouldRotateSeamlessly(int oldRotation, int newRotation, boolean forceUpdate) {
         // Display doesn't need to be frozen because application has been started in correct
         // rotation already, so the rest of the windows can use seamless rotation.
-        if (mDisplayContent.mFixedRotationLaunchingApp != null) {
+        if (mDisplayContent.getFixedRotationLaunchingApp() != null) {
             return true;
         }
 
diff --git a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
index af13e3a..b627b33 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
@@ -95,4 +95,27 @@
         }
         mDisplayListeners.finishBroadcast();
     }
+
+    void dispatchFixedRotationStarted(DisplayContent display, int newRotation) {
+        int count = mDisplayListeners.beginBroadcast();
+        for (int i = 0; i < count; ++i) {
+            try {
+                mDisplayListeners.getBroadcastItem(i).onFixedRotationStarted(
+                        display.mDisplayId, newRotation);
+            } catch (RemoteException e) {
+            }
+        }
+        mDisplayListeners.finishBroadcast();
+    }
+
+    void dispatchFixedRotationFinished(DisplayContent display) {
+        int count = mDisplayListeners.beginBroadcast();
+        for (int i = 0; i < count; ++i) {
+            try {
+                mDisplayListeners.getBroadcastItem(i).onFixedRotationFinished(display.mDisplayId);
+            } catch (RemoteException e) {
+            }
+        }
+        mDisplayListeners.finishBroadcast();
+    }
 }
diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
index 9bbd4cd..5a24847 100644
--- a/services/core/java/com/android/server/wm/EmbeddedWindowController.java
+++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
@@ -135,6 +135,7 @@
         final int mOwnerPid;
         final WindowManagerService mWmService;
         InputChannel mInputChannel;
+        final int mWindowType;
 
         /**
          * @param clientToken client token used to clean up the map if the embedding process dies
@@ -146,7 +147,7 @@
          * @param ownerPid  calling pid used for anr blaming
          */
         EmbeddedWindow(WindowManagerService service, IWindow clientToken,
-                WindowState hostWindowState, int ownerUid, int ownerPid) {
+                WindowState hostWindowState, int ownerUid, int ownerPid, int windowType) {
             mWmService = service;
             mClient = clientToken;
             mHostWindowState = hostWindowState;
@@ -154,6 +155,7 @@
                     : null;
             mOwnerUid = ownerUid;
             mOwnerPid = ownerPid;
+            mWindowType = windowType;
         }
 
         String getName() {
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 1b1898b..efcd61d 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -469,8 +469,12 @@
         public void accept(WindowState w) {
             final InputChannel inputChannel = w.mInputChannel;
             final InputWindowHandle inputWindowHandle = w.mInputWindowHandle;
+            final RecentsAnimationController recentsAnimationController =
+                    mService.getRecentsAnimationController();
+            final boolean shouldApplyRecentsInputConsumer = recentsAnimationController != null
+                    && recentsAnimationController.shouldApplyInputConsumer(w.mActivityRecord);
             if (inputChannel == null || inputWindowHandle == null || w.mRemoved
-                    || w.cantReceiveTouchInput()) {
+                    || (w.cantReceiveTouchInput() && !shouldApplyRecentsInputConsumer)) {
                 if (w.mWinAnimator.hasSurface()) {
                     mInputTransaction.setInputWindowInfo(
                         w.mWinAnimator.mSurfaceController.getClientViewRootSurface(),
@@ -486,22 +490,16 @@
             final boolean hasFocus = w.isFocused();
             final boolean isVisible = w.isVisibleLw();
 
-            if (mAddRecentsAnimationInputConsumerHandle) {
-                final RecentsAnimationController recentsAnimationController =
-                        mService.getRecentsAnimationController();
-                if (recentsAnimationController != null
-                        && recentsAnimationController.shouldApplyInputConsumer(w.mActivityRecord)) {
-                    if (recentsAnimationController.updateInputConsumerForApp(
-                            mRecentsAnimationInputConsumer.mWindowHandle, hasFocus)) {
-                        mRecentsAnimationInputConsumer.show(mInputTransaction, w);
-                        mAddRecentsAnimationInputConsumerHandle = false;
-                    }
+            if (mAddRecentsAnimationInputConsumerHandle && shouldApplyRecentsInputConsumer) {
+                if (recentsAnimationController.updateInputConsumerForApp(
+                        mRecentsAnimationInputConsumer.mWindowHandle, hasFocus)) {
+                    mRecentsAnimationInputConsumer.show(mInputTransaction, w);
+                    mAddRecentsAnimationInputConsumerHandle = false;
                 }
             }
 
             if (w.inPinnedWindowingMode()) {
                 if (mAddPipInputConsumerHandle) {
-
                     final Task rootTask = w.getTask().getRootTask();
                     mPipInputConsumer.mWindowHandle.replaceTouchableRegionWithCrop(
                             rootTask.getSurfaceControl());
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 317bb43..d02be88 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -60,7 +60,37 @@
     private final IntArray mShowingTransientTypes = new IntArray();
 
     /** For resetting visibilities of insets sources. */
-    private final InsetsControlTarget mDummyControlTarget = new InsetsControlTarget() { };
+    private final InsetsControlTarget mDummyControlTarget = new InsetsControlTarget() {
+
+        @Override
+        public void notifyInsetsControlChanged() {
+            boolean hasLeash = false;
+            final InsetsSourceControl[] controls =
+                    mStateController.getControlsForDispatch(this);
+            if (controls == null) {
+                return;
+            }
+            for (InsetsSourceControl control : controls) {
+                final @InternalInsetsType int type = control.getType();
+                if (mShowingTransientTypes.indexOf(type) != -1) {
+                    // The visibilities of transient bars will be handled with animations.
+                    continue;
+                }
+                final SurfaceControl leash = control.getLeash();
+                if (leash != null) {
+                    hasLeash = true;
+
+                    // We use alpha to control the visibility here which aligns the logic at
+                    // SurfaceAnimator.createAnimationLeash
+                    mDisplayContent.getPendingTransaction().setAlpha(
+                            leash, InsetsState.getDefaultVisibility(type) ? 1f : 0f);
+                }
+            }
+            if (hasLeash) {
+                mDisplayContent.scheduleAnimation();
+            }
+        }
+    };
 
     private WindowState mFocusedWin;
     private BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
diff --git a/services/core/java/com/android/server/wm/LaunchParamsController.java b/services/core/java/com/android/server/wm/LaunchParamsController.java
index 4cd3180..513be7a 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsController.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsController.java
@@ -146,7 +146,10 @@
 
             if (mTmpParams.hasWindowingMode()
                     && mTmpParams.mWindowingMode != task.getStack().getWindowingMode()) {
-                task.getStack().setWindowingMode(mTmpParams.mWindowingMode);
+                final int activityType = activity != null
+                        ? activity.getActivityType() : task.getActivityType();
+                task.getStack().setWindowingMode(task.getDisplayArea().validateWindowingMode(
+                        mTmpParams.mWindowingMode, activity, task, activityType));
             }
 
             if (mTmpParams.mBounds.isEmpty()) {
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index d8a4ecb..1cd94b4 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -1387,9 +1387,7 @@
         return false;
     }
 
-    /**
-     * @return whether the given task can be trimmed even if it is outside the visible range.
-     */
+    /** @return whether the given task can be trimmed even if it is outside the visible range. */
     protected boolean isTrimmable(Task task) {
         final ActivityStack stack = task.getStack();
 
@@ -1404,9 +1402,13 @@
             return false;
         }
 
+        final ActivityStack rootHomeTask = stack.getDisplayArea().getRootHomeTask();
+        // Home stack does not exist. Don't trim the task.
+        if (rootHomeTask == null) {
+            return false;
+        }
         // Trim tasks that are behind the home task.
-        final TaskDisplayArea taskDisplayArea = stack.getDisplayArea();
-        return task.compareTo(taskDisplayArea.getRootHomeTask()) < 0;
+        return task.compareTo(rootHomeTask) < 0;
     }
 
     /** Remove the tasks that user may not be able to return. */
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index d6ddcd0..f1b322e 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -406,8 +406,9 @@
         }
 
         // Save the minimized home height
-        mMinimizedHomeBounds = mDisplayContent.getDefaultTaskDisplayArea().getRootHomeTask()
-                .getBounds();
+        final ActivityStack rootHomeTask =
+                mDisplayContent.getDefaultTaskDisplayArea().getRootHomeTask();
+        mMinimizedHomeBounds = rootHomeTask != null ? rootHomeTask.getBounds() : null;
 
         mService.mWindowPlacerLocked.performSurfacePlacement();
 
@@ -799,7 +800,8 @@
         // Only apply the input consumer if it is enabled, it is not the target (home/recents)
         // being revealed with the transition, and we are actively animating the app as a part of
         // the animation
-        return mInputConsumerEnabled && !isTargetApp(activity) && isAnimatingApp(activity);
+        return mInputConsumerEnabled && activity != null
+                && !isTargetApp(activity) && isAnimatingApp(activity);
     }
 
     boolean updateInputConsumerForApp(InputWindowHandle inputWindowHandle,
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index c02e0a1..c7f7834 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -387,9 +387,11 @@
         int getMode() {
             final DisplayContent dc = mWindowContainer.getDisplayContent();
             final ActivityRecord topActivity = mWindowContainer.getTopMostActivity();
+            // Note that opening/closing transitions are per-activity while changing transitions
+            // are per-task.
             if (dc.mOpeningApps.contains(topActivity)) {
                 return RemoteAnimationTarget.MODE_OPENING;
-            } else if (dc.mChangingContainers.contains(topActivity)) {
+            } else if (dc.mChangingContainers.contains(mWindowContainer)) {
                 return RemoteAnimationTarget.MODE_CHANGING;
             } else {
                 return RemoteAnimationTarget.MODE_CLOSING;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 9a30f1c..0ecde72 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -327,7 +327,7 @@
             documentData = isDocument ? intent.getData() : null;
 
             if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + parent);
-            parent.forAllTasks(this);
+            parent.forAllLeafTasks(this);
         }
 
         void clear() {
@@ -1369,7 +1369,7 @@
         calculateDefaultMinimalSizeOfResizeableTasks();
 
         final TaskDisplayArea defaultTaskDisplayArea = getDefaultTaskDisplayArea();
-        defaultTaskDisplayArea.getOrCreateRootHomeTask();
+        defaultTaskDisplayArea.getOrCreateRootHomeTask(ON_TOP);
         positionChildAt(POSITION_TOP, defaultTaskDisplayArea.mDisplayContent,
                 false /* includingParents */);
     }
@@ -2170,12 +2170,16 @@
             final boolean singleActivity = task.getChildCount() == 1;
             final ActivityStack stack;
             if (singleActivity) {
-                stack = r.getRootTask();
+                stack = (ActivityStack) task;
             } else {
                 // In the case of multiple activities, we will create a new task for it and then
                 // move the PIP activity into the task.
                 stack = taskDisplayArea.createStack(WINDOWING_MODE_UNDEFINED, r.getActivityType(),
                         ON_TOP, r.info, r.intent, false /* createdByOrganizer */);
+                // It's possible the task entering PIP is in freeform, so save the last
+                // non-fullscreen bounds. Then when this new PIP task exits PIP, it can restore
+                // to its previous freeform bounds.
+                stack.setLastNonFullscreenBounds(task.mLastNonFullscreenBounds);
 
                 // There are multiple activities in the task and moving the top activity should
                 // reveal/leave the other activities in their original task.
@@ -2183,6 +2187,15 @@
                 // up-to-dated pinned stack information on this newly created stack.
                 r.reparent(stack, MAX_VALUE, reason);
             }
+            if (stack.getParent() != taskDisplayArea) {
+                // stack is nested, but pinned tasks need to be direct children of their
+                // display area, so reparent.
+                stack.reparent(taskDisplayArea, true /* onTop */);
+            }
+            // Defer the windowing mode change until after the transition to prevent the activity
+            // from doing work and changing the activity visuals while animating
+            // TODO(task-org): Figure-out more structured way to do this long term.
+            r.setWindowingMode(stack.getWindowingMode());
             stack.setWindowingMode(WINDOWING_MODE_PINNED);
 
             // Reset the state that indicates it can enter PiP while pausing after we've moved it
diff --git a/services/core/java/com/android/server/wm/SeamlessRotator.java b/services/core/java/com/android/server/wm/SeamlessRotator.java
index c79cb04..3d305e4 100644
--- a/services/core/java/com/android/server/wm/SeamlessRotator.java
+++ b/services/core/java/com/android/server/wm/SeamlessRotator.java
@@ -45,11 +45,22 @@
     private final float[] mFloat9 = new float[9];
     private final int mOldRotation;
     private final int mNewRotation;
+    /* If the seamless rotator is used to rotate part of the hierarchy, then provide a transform
+     * hint based on the display orientation if the entire display was rotated. When the display
+     * orientation matches the hierarchy orientation, the fixed transform hint will be removed.
+     * This will prevent allocating different buffer sizes by the graphic producers when the
+     * orientation of a layer changes.
+     */
+    private final boolean mApplyFixedTransformHint;
+    private final int mFixedTransformHint;
 
-    public SeamlessRotator(@Rotation int oldRotation, @Rotation int newRotation, DisplayInfo info) {
+
+    public SeamlessRotator(@Rotation int oldRotation, @Rotation int newRotation, DisplayInfo info,
+            boolean applyFixedTransformationHint) {
         mOldRotation = oldRotation;
         mNewRotation = newRotation;
-
+        mApplyFixedTransformHint = applyFixedTransformationHint;
+        mFixedTransformHint = oldRotation;
         final boolean flipped = info.rotation == ROTATION_90 || info.rotation == ROTATION_270;
         final int pH = flipped ? info.logicalWidth : info.logicalHeight;
         final int pW = flipped ? info.logicalHeight : info.logicalWidth;
@@ -70,6 +81,9 @@
         final float[] winSurfacePos = {win.mLastSurfacePosition.x, win.mLastSurfacePosition.y};
         mTransform.mapPoints(winSurfacePos);
         transaction.setPosition(win.getSurfaceControl(), winSurfacePos[0], winSurfacePos[1]);
+        if (mApplyFixedTransformHint) {
+            transaction.setFixedTransformHint(win.mSurfaceControl, mFixedTransformHint);
+        }
     }
 
     /**
@@ -109,6 +123,9 @@
         mTransform.reset();
         t.setMatrix(win.mSurfaceControl, mTransform, mFloat9);
         t.setPosition(win.mSurfaceControl, win.mLastSurfacePosition.x, win.mLastSurfacePosition.y);
+        if (mApplyFixedTransformHint) {
+            t.unsetFixedTransformHint(win.mSurfaceControl);
+        }
     }
 
     public void dump(PrintWriter pw) {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index bf20cb9..e225809 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -91,6 +91,7 @@
     private float mLastReportedAnimatorScale;
     private String mPackageName;
     private String mRelayoutTag;
+    private final InsetsSourceControl[] mDummyControls =  new InsetsSourceControl[0];
 
     public Session(WindowManagerService service, IWindowSessionCallback callback) {
         mService = service;
@@ -184,7 +185,7 @@
         return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
                 new Rect() /* outFrame */, outContentInsets, outStableInsets,
                 new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */,
-                outInsetsState, null, UserHandle.getUserId(mUid));
+                outInsetsState, mDummyControls, UserHandle.getUserId(mUid));
     }
 
     @Override
@@ -661,17 +662,23 @@
 
     @Override
     public void grantInputChannel(int displayId, SurfaceControl surface,
-            IWindow window, IBinder hostInputToken, int flags, InputChannel outInputChannel) {
+            IWindow window, IBinder hostInputToken, int flags, int type,
+            InputChannel outInputChannel) {
         if (hostInputToken == null && !mCanAddInternalSystemWindow) {
             // Callers without INTERNAL_SYSTEM_WINDOW permission cannot grant input channel to
             // embedded windows without providing a host window input token
             throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
         }
 
+        if (!mCanAddInternalSystemWindow && type != 0) {
+            Slog.w(TAG_WM, "Requires INTERNAL_SYSTEM_WINDOW permission if assign type to"
+                    + " input");
+        }
+
         final long identity = Binder.clearCallingIdentity();
         try {
             mService.grantInputChannel(mUid, mPid, displayId, surface, window, hostInputToken,
-                    flags, outInputChannel);
+                    flags, mCanAddInternalSystemWindow ? type : 0, outInputChannel);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 18e32c0..42342a6 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -109,7 +109,10 @@
                         animationFinishCallback.onAnimationFinished(type, anim);
                     }
                 };
-                if (!mAnimatable.shouldDeferAnimationFinish(resetAndInvokeFinish)) {
+                // If both the Animatable and AnimationAdapter requests to be deferred, only the
+                // first one will be called.
+                if (!(mAnimatable.shouldDeferAnimationFinish(resetAndInvokeFinish)
+                        || anim.shouldDeferAnimationFinish(resetAndInvokeFinish))) {
                     resetAndInvokeFinish.run();
                 }
             }
@@ -592,6 +595,12 @@
          * Gets called when the animation is about to finish and gives the client the opportunity to
          * defer finishing the animation, i.e. it keeps the leash around until the client calls
          * {@link #cancelAnimation}.
+         * <p>
+         * {@link AnimationAdapter} has a similar method which is called only if this method returns
+         * false. This mean that if both this {@link Animatable} and the {@link AnimationAdapter}
+         * request to be deferred, this method is the sole responsible to call
+         * endDeferFinishCallback. On the other hand, the animation finish might still be deferred
+         * if this method return false and the one from the {@link AnimationAdapter} returns true.
          *
          * @param endDeferFinishCallback The callback to call when defer finishing should be ended.
          * @return Whether the client would like to defer the animation finish.
diff --git a/services/core/java/com/android/server/wm/TEST_MAPPING b/services/core/java/com/android/server/wm/TEST_MAPPING
deleted file mode 100644
index b2e8bbe..0000000
--- a/services/core/java/com/android/server/wm/TEST_MAPPING
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-  "postsubmit": [
-    {
-      "name": "CtsWindowManagerDeviceTestCases"
-    },
-    {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.wm."
-        }
-      ]
-    },
-    {
-      "name": "WmTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.wm."
-        }
-      ]
-    }
-  ]
-}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 4845da1..cc72dcf 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -107,7 +107,6 @@
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.app.AppGlobals;
-import android.app.PictureInPictureParams;
 import android.app.TaskInfo;
 import android.app.WindowConfiguration;
 import android.content.ComponentName;
@@ -488,12 +487,6 @@
     boolean mTaskAppearedSent;
 
     /**
-     * Last Picture-in-Picture params applicable to the task. Updated when the app
-     * enters Picture-in-Picture or when setPictureInPictureParams is called.
-     */
-    PictureInPictureParams mPictureInPictureParams = new PictureInPictureParams.Builder().build();
-
-    /**
      * This task was created by the task organizer which has the following implementations.
      * <ul>
      *     <lis>The task won't be removed when it is empty. Removal has to be an explicit request
@@ -949,7 +942,7 @@
             return;
         }
 
-        affinity = info.taskAffinity;
+        affinity = isLeafTask() ? info.taskAffinity : null;
         if (intent == null) {
             // If this task already has an intent associated with it, don't set the root
             // affinity -- we don't want it changing after initially set, but the initially
@@ -1947,7 +1940,6 @@
                 setLastNonFullscreenBounds(currentBounds);
             }
         }
-        // TODO: Should also take care of Pip mode changes here.
 
         saveLaunchingStateIfNeeded();
         final boolean taskOrgChanged = updateTaskOrganizerState(false /* forceUpdate */);
@@ -3407,6 +3399,24 @@
     }
 
     @Override
+    boolean forAllLeafTasks(Function<Task, Boolean> callback) {
+        boolean isLeafTask = true;
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final Task child = mChildren.get(i).asTask();
+            if (child != null) {
+                isLeafTask = false;
+                if (child.forAllLeafTasks(callback)) {
+                    return true;
+                }
+            }
+        }
+        if (isLeafTask) {
+            return callback.apply(this);
+        }
+        return false;
+    }
+
+    @Override
     Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
         final Task t = super.getTask(callback, traverseTopToBottom);
         if (t != null) return t;
@@ -3571,10 +3581,11 @@
         info.resizeMode = top != null ? top.mResizeMode : mResizeMode;
         info.topActivityType = top.getActivityType();
 
-        if (mPictureInPictureParams.empty()) {
+        ActivityRecord rootActivity = top.getRootActivity();
+        if (rootActivity == null || rootActivity.pictureInPictureArgs.empty()) {
             info.pictureInPictureParams = null;
         } else {
-            info.pictureInPictureParams = mPictureInPictureParams;
+            info.pictureInPictureParams = rootActivity.pictureInPictureArgs;
         }
         info.topActivityInfo = mReuseActivitiesReport.top != null
                 ? mReuseActivitiesReport.top.info
@@ -4490,8 +4501,7 @@
         updateShadowsRadius(hasFocus, getPendingTransaction());
     }
 
-    void setPictureInPictureParams(PictureInPictureParams p) {
-        mPictureInPictureParams.copyOnlySet(p);
+    void onPictureInPictureParamsChanged() {
         if (isOrganized()) {
             mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, true /* force */);
         }
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 0a1ee2b..9130483 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -21,7 +21,6 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
@@ -196,7 +195,7 @@
         return mChildren.indexOf(stack);
     }
 
-    ActivityStack getRootHomeTask() {
+    @Nullable ActivityStack getRootHomeTask() {
         return mRootHomeTask;
     }
 
@@ -1276,14 +1275,10 @@
             return true;
         }
 
-        final int displayWindowingMode = getWindowingMode();
         if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
                 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
             return supportsSplitScreen
-                    && WindowConfiguration.supportSplitScreenWindowingMode(activityType)
-                    // Freeform windows and split-screen windows don't mix well, so prevent
-                    // split windowing modes on freeform displays.
-                    && displayWindowingMode != WINDOWING_MODE_FREEFORM;
+                    && WindowConfiguration.supportSplitScreenWindowingMode(activityType);
         }
 
         if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
@@ -1333,16 +1328,16 @@
     }
 
     /**
-     * Check that the requested windowing-mode is appropriate for the specified task and/or activity
+     * Check if the requested windowing-mode is appropriate for the specified task and/or activity
      * on this display.
      *
      * @param windowingMode The windowing-mode to validate.
      * @param r The {@link ActivityRecord} to check against.
      * @param task The {@link Task} to check against.
      * @param activityType An activity type.
-     * @return The provided windowingMode or the closest valid mode which is appropriate.
+     * @return {@code true} if windowingMode is valid, {@code false} otherwise.
      */
-    int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task,
+    boolean isValidWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task,
             int activityType) {
         // Make sure the windowing mode we are trying to use makes sense for what is supported.
         boolean supportsMultiWindow = mAtmService.mSupportsMultiWindow;
@@ -1362,24 +1357,35 @@
             }
         }
 
+        return windowingMode != WINDOWING_MODE_UNDEFINED
+                && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
+                        supportsFreeform, supportsPip, activityType);
+    }
+
+    /**
+     * Check that the requested windowing-mode is appropriate for the specified task and/or activity
+     * on this display.
+     *
+     * @param windowingMode The windowing-mode to validate.
+     * @param r The {@link ActivityRecord} to check against.
+     * @param task The {@link Task} to check against.
+     * @param activityType An activity type.
+     * @return The provided windowingMode or the closest valid mode which is appropriate.
+     */
+    int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task,
+            int activityType) {
         final boolean inSplitScreenMode = isSplitScreenModeActivated();
-        if (!inSplitScreenMode
-                && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
+        if (!inSplitScreenMode && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
             // Switch to the display's windowing mode if we are not in split-screen mode and we are
             // trying to launch in split-screen secondary.
             windowingMode = WINDOWING_MODE_UNDEFINED;
-        } else if (inSplitScreenMode && (windowingMode == WINDOWING_MODE_FULLSCREEN
-                || windowingMode == WINDOWING_MODE_UNDEFINED)
-                && supportsSplitScreen) {
+        } else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_UNDEFINED) {
             windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
         }
-
-        if (windowingMode != WINDOWING_MODE_UNDEFINED
-                && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
-                supportsFreeform, supportsPip, activityType)) {
-            return windowingMode;
+        if (!isValidWindowingMode(windowingMode, r, task, activityType)) {
+            return WINDOWING_MODE_UNDEFINED;
         }
-        return WINDOWING_MODE_UNDEFINED;
+        return windowingMode;
     }
 
     boolean isTopStack(ActivityStack stack) {
@@ -1451,16 +1457,23 @@
         return mChildren.get(index);
     }
 
+    @Nullable
+    ActivityStack getOrCreateRootHomeTask() {
+        return getOrCreateRootHomeTask(false /* onTop */);
+    }
+
     /**
      * Returns the existing home stack or creates and returns a new one if it should exist for the
      * display.
+     * @param onTop Only be used when there is no existing home stack. If true the home stack will
+     *              be created at the top of the display, else at the bottom.
      */
     @Nullable
-    ActivityStack getOrCreateRootHomeTask() {
+    ActivityStack getOrCreateRootHomeTask(boolean onTop) {
         ActivityStack homeTask = getRootHomeTask();
         if (homeTask == null && mDisplayContent.supportsSystemDecorations()
                 && !mDisplayContent.isUntrustedVirtualDisplay()) {
-            homeTask = createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, false /* onTop */);
+            homeTask = createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, onTop);
         }
         return homeTask;
     }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 0f5cafe..1a2672b 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -297,6 +297,13 @@
             Slog.w(TAG_WM, "Failed to take screenshot. No main window for " + task);
             return false;
         }
+        if (activity.hasFixedRotationTransform()) {
+            if (DEBUG_SCREENSHOT) {
+                Slog.i(TAG_WM, "Skip taking screenshot. App has fixed rotation " + activity);
+            }
+            // The activity is in a temporal state that it has different rotation than the task.
+            return false;
+        }
 
         builder.setIsRealSnapshot(true);
         builder.setId(System.currentTimeMillis());
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 45023ac..c6e1c95 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -28,12 +28,14 @@
 import android.graphics.Bitmap.Config;
 import android.os.Process;
 import android.os.SystemClock;
+import android.os.UserManagerInternal;
 import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.LocalServices;
 import com.android.server.wm.nano.WindowManagerProtos.TaskSnapshotProto;
 
 import java.io.File;
@@ -72,6 +74,7 @@
     private final float mLowResScaleFactor;
     private boolean mEnableLowResSnapshots;
     private final boolean mUse16BitFormat;
+    private final UserManagerInternal mUserManagerInternal;
 
     /**
      * The list of ids of the tasks that have been persisted since {@link #removeObsoleteFiles} was
@@ -82,6 +85,8 @@
 
     TaskSnapshotPersister(WindowManagerService service, DirectoryResolver resolver) {
         mDirectoryResolver = resolver;
+        mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
+
         final float highResTaskSnapshotScale = service.mContext.getResources().getFloat(
                 com.android.internal.R.dimen.config_highResTaskSnapshotScale);
         final float lowResTaskSnapshotScale = service.mContext.getResources().getFloat(
@@ -191,7 +196,7 @@
                     return;
                 }
             }
-            SystemClock.sleep(100);
+            SystemClock.sleep(DELAY_MS);
         }
     }
 
@@ -233,7 +238,7 @@
 
     private boolean createDirectory(int userId) {
         final File dir = getDirectory(userId);
-        return dir.exists() || dir.mkdirs();
+        return dir.exists() || dir.mkdir();
     }
 
     private void deleteSnapshot(int taskId, int userId) {
@@ -258,18 +263,26 @@
             android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
             while (true) {
                 WriteQueueItem next;
+                boolean isReadyToWrite = false;
                 synchronized (mLock) {
                     if (mPaused) {
                         next = null;
                     } else {
                         next = mWriteQueue.poll();
                         if (next != null) {
-                            next.onDequeuedLocked();
+                            if (next.isReady()) {
+                                isReadyToWrite = true;
+                                next.onDequeuedLocked();
+                            } else {
+                                mWriteQueue.addLast(next);
+                            }
                         }
                     }
                 }
                 if (next != null) {
-                    next.write();
+                    if (isReadyToWrite) {
+                        next.write();
+                    }
                     SystemClock.sleep(DELAY_MS);
                 }
                 synchronized (mLock) {
@@ -289,6 +302,13 @@
     };
 
     private abstract class WriteQueueItem {
+        /**
+         * @return {@code true} if item is ready to have {@link WriteQueueItem#write} called
+         */
+        boolean isReady() {
+            return true;
+        }
+
         abstract void write();
 
         /**
@@ -328,6 +348,11 @@
         }
 
         @Override
+        boolean isReady() {
+            return mUserManagerInternal.isUserUnlocked(mUserId);
+        }
+
+        @Override
         void write() {
             if (!createDirectory(mUserId)) {
                 Slog.e(TAG, "Unable to create snapshot directory for user dir="
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 24cd7d1..3925570 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -195,6 +195,16 @@
                         + activity);
                 return null;
             }
+            if (topFullscreenActivity.getWindowConfiguration().getRotation()
+                    != snapshot.getRotation()) {
+                // The snapshot should have been checked by ActivityRecord#isSnapshotCompatible
+                // that the activity will be updated to the same rotation as the snapshot. Since
+                // the transition is not started yet, fixed rotation transform needs to be applied
+                // earlier to make the snapshot show in a rotated container.
+                activity.mDisplayContent.handleTopActivityLaunchingInDifferentOrientation(
+                        topFullscreenActivity, false /* checkOpening */);
+            }
+
             sysUiVis = topFullscreenOpaqueWindow.getSystemUiVisibility();
             WindowManager.LayoutParams attrs = topFullscreenOpaqueWindow.mAttrs;
             windowFlags = attrs.flags;
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index b9b6c08..d1cb210 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -238,23 +238,12 @@
         }
     }
 
-    private final boolean isWallpaperVisible(WindowState wallpaperTarget) {
-        final RecentsAnimationController recentsAnimationController =
-                mService.getRecentsAnimationController();
-        boolean isAnimatingWithRecentsComponent = recentsAnimationController != null
-                && recentsAnimationController.isWallpaperVisible(wallpaperTarget);
-        if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
-                + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
-                + " animating=" + ((wallpaperTarget != null && wallpaperTarget.mActivityRecord != null)
-                ? wallpaperTarget.mActivityRecord.isAnimating(TRANSITION | PARENTS) : null)
-                + " prev=" + mPrevWallpaperTarget
-                + " recentsAnimationWallpaperVisible=" + isAnimatingWithRecentsComponent);
-        return (wallpaperTarget != null
-                && (!wallpaperTarget.mObscured
-                        || isAnimatingWithRecentsComponent
-                        || (wallpaperTarget.mActivityRecord != null
-                        && wallpaperTarget.mActivityRecord.isAnimating(TRANSITION | PARENTS))))
-                || mPrevWallpaperTarget != null;
+    private boolean isWallpaperVisible(WindowState wallpaperTarget) {
+        if (DEBUG_WALLPAPER) {
+            Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + " prev="
+                    + mPrevWallpaperTarget);
+        }
+        return wallpaperTarget != null || mPrevWallpaperTarget != null;
     }
 
     boolean isWallpaperTargetAnimating() {
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 3f8d7b5..a1fbb59 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1415,11 +1415,12 @@
     }
 
     ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom,
-            WindowContainer boundary) {
+            ActivityRecord boundary) {
         if (traverseTopToBottom) {
             for (int i = mChildren.size() - 1; i >= 0; --i) {
                 final WindowContainer wc = mChildren.get(i);
-                if (wc == boundary) return null;
+                // TODO(b/156986561): Improve the correctness of the boundary check.
+                if (wc == boundary) return boundary;
 
                 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary);
                 if (r != null) {
@@ -1430,7 +1431,8 @@
             final int count = mChildren.size();
             for (int i = 0; i < count; i++) {
                 final WindowContainer wc = mChildren.get(i);
-                if (wc == boundary) return null;
+                // TODO(b/156986561): Improve the correctness of the boundary check.
+                if (wc == boundary) return boundary;
 
                 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary);
                 if (r != null) {
@@ -1552,6 +1554,15 @@
         return false;
     }
 
+    boolean forAllLeafTasks(Function<Task, Boolean> callback) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            if (mChildren.get(i).forAllLeafTasks(callback)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * For all tasks at or below this container call the callback.
      *
@@ -2111,6 +2122,11 @@
         return getBounds();
     }
 
+    /** Gets the position relative to parent for animation. */
+    void getAnimationPosition(Point outPosition) {
+        getRelativePosition(outPosition);
+    }
+
     /**
      * Applies the app transition animation according the given the layout properties in the
      * window hierarchy.
@@ -2168,10 +2184,11 @@
         final int appStackClipMode = getDisplayContent().mAppTransition.getAppStackClipMode();
 
         // Separate position and size for use in animators.
-        mTmpRect.set(getAnimationBounds(appStackClipMode));
-        if (sHierarchicalAnimations) {
-            getRelativePosition(mTmpPoint);
-        } else {
+        final Rect screenBounds = getAnimationBounds(appStackClipMode);
+        mTmpRect.set(screenBounds);
+        getAnimationPosition(mTmpPoint);
+        if (!sHierarchicalAnimations) {
+            // Non-hierarchical animation uses position in global coordinates.
             mTmpPoint.set(mTmpRect.left, mTmpRect.top);
         }
         mTmpRect.offsetTo(0, 0);
@@ -2187,7 +2204,7 @@
             localBounds.offsetTo(mTmpPoint.x, mTmpPoint.y);
             final RemoteAnimationController.RemoteAnimationRecord adapters =
                     controller.createRemoteAnimationRecord(this, mTmpPoint, localBounds,
-                            mTmpRect, (isChanging ? mSurfaceFreezer.mFreezeBounds : null));
+                            screenBounds, (isChanging ? mSurfaceFreezer.mFreezeBounds : null));
             resultAdapters = new Pair<>(adapters.mAdapter, adapters.mThumbnailAdapter);
         } else if (isChanging) {
             final float durationScale = mWmService.getTransitionAnimationScaleLocked();
@@ -2600,10 +2617,8 @@
         return willSync;
     }
 
-    boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener,
-            int waitingId) {
-        boolean willSync = true;
-
+    boolean setPendingListener(BLASTSyncEngine.TransactionReadyListener waitingListener,
+        int waitingId) {
         // If we are invisible, no need to sync, likewise if we are already engaged in a sync,
         // we can't support overlapping syncs on a single container yet.
         if (!isVisible() || mWaitingListener != null) {
@@ -2614,6 +2629,15 @@
         // Make sure to set these before we call setReady in case the sync was a no-op
         mWaitingSyncId = waitingId;
         mWaitingListener = waitingListener;
+        return true;
+    }
+
+    boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener,
+            int waitingId) {
+        boolean willSync = setPendingListener(waitingListener, waitingId);
+        if (!willSync) {
+            return false;
+        }
 
         int localId = mBLASTSyncEngine.startSyncSet(this);
         willSync |= addChildrenToSyncSet(localId);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 13a0b2c..159c59b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1387,6 +1387,7 @@
             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
             InsetsState outInsetsState, InsetsSourceControl[] outActiveControls,
             int requestUserId) {
+        Arrays.fill(outActiveControls, null);
         int[] appOp = new int[1];
         final boolean isRoundedCornerOverlay = (attrs.privateFlags
                 & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;
@@ -2133,6 +2134,7 @@
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
             InsetsSourceControl[] outActiveControls, Point outSurfaceSize,
             SurfaceControl outBLASTSurfaceControl) {
+        Arrays.fill(outActiveControls, null);
         int result = 0;
         boolean configChanged;
         final int pid = Binder.getCallingPid();
@@ -2259,7 +2261,7 @@
             win.mRelayoutCalled = true;
             win.mInRelayout = true;
 
-            win.mViewVisibility = viewVisibility;
+            win.setViewVisibility(viewVisibility);
             ProtoLog.i(WM_DEBUG_SCREEN_ON,
                     "Relayout %s: oldVis=%d newVis=%d. %s", win, oldVisibility,
                             viewVisibility, new RuntimeException().fillInStackTrace());
@@ -2470,23 +2472,20 @@
     }
 
     private void getInsetsSourceControls(WindowState win, InsetsSourceControl[] outControls) {
-        if (outControls != null) {
-            final InsetsSourceControl[] controls =
-                    win.getDisplayContent().getInsetsStateController().getControlsForDispatch(win);
-            Arrays.fill(outControls, null);
-            if (controls != null) {
-                final int length = Math.min(controls.length, outControls.length);
-                for (int i = 0; i < length; i++) {
-                    // We will leave the critical section before returning the leash to the client,
-                    // so we need to copy the leash to prevent others release the one that we are
-                    // about to return.
-                    // TODO: We will have an extra copy if the client is not local.
-                    //       For now, we rely on GC to release it.
-                    //       Maybe we can modify InsetsSourceControl.writeToParcel so it can release
-                    //       the extra leash as soon as possible.
-                    outControls[i] = controls[i] != null
-                            ? new InsetsSourceControl(controls[i]) : null;
-                }
+        final InsetsSourceControl[] controls =
+                win.getDisplayContent().getInsetsStateController().getControlsForDispatch(win);
+        if (controls != null) {
+            final int length = Math.min(controls.length, outControls.length);
+            for (int i = 0; i < length; i++) {
+                // We will leave the critical section before returning the leash to the client,
+                // so we need to copy the leash to prevent others release the one that we are
+                // about to return.
+                // TODO: We will have an extra copy if the client is not local.
+                //       For now, we rely on GC to release it.
+                //       Maybe we can modify InsetsSourceControl.writeToParcel so it can release
+                //       the extra leash as soon as possible.
+                outControls[i] = controls[i] != null
+                        ? new InsetsSourceControl(controls[i]) : null;
             }
         }
     }
@@ -7923,18 +7922,23 @@
 
     @Override
     public void syncInputTransactions() {
-        waitForAnimationsToComplete();
+        long token = Binder.clearCallingIdentity();
+        try {
+            waitForAnimationsToComplete();
 
-        // Collect all input transactions from all displays to make sure we could sync all input
-        // windows at same time.
-        final SurfaceControl.Transaction t = mTransactionFactory.get();
-        synchronized (mGlobalLock) {
-            mWindowPlacerLocked.performSurfacePlacementIfScheduled();
-            mRoot.forAllDisplays(displayContent ->
-                    displayContent.getInputMonitor().updateInputWindowsImmediately(t));
+            // Collect all input transactions from all displays to make sure we could sync all input
+            // windows at same time.
+            final SurfaceControl.Transaction t = mTransactionFactory.get();
+            synchronized (mGlobalLock) {
+                mWindowPlacerLocked.performSurfacePlacementIfScheduled();
+                mRoot.forAllDisplays(displayContent ->
+                        displayContent.getInputMonitor().updateInputWindowsImmediately(t));
+            }
+
+            t.syncInputWindows().apply();
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
-
-        t.syncInputWindows().apply();
     }
 
     /**
@@ -8027,14 +8031,15 @@
      * views.
      */
     void grantInputChannel(int callingUid, int callingPid, int displayId, SurfaceControl surface,
-            IWindow window, IBinder hostInputToken, int flags, InputChannel outInputChannel) {
+            IWindow window, IBinder hostInputToken, int flags, int type,
+            InputChannel outInputChannel) {
         final InputApplicationHandle applicationHandle;
         final String name;
         final InputChannel clientChannel;
         synchronized (mGlobalLock) {
             EmbeddedWindowController.EmbeddedWindow win =
                     new EmbeddedWindowController.EmbeddedWindow(this, window,
-                            mInputToWindowMap.get(hostInputToken), callingUid, callingPid);
+                            mInputToWindowMap.get(hostInputToken), callingUid, callingPid, type);
             clientChannel = win.openInputChannel();
             mEmbeddedWindowController.add(clientChannel.getToken(), win);
             applicationHandle = win.getApplicationHandle();
@@ -8042,7 +8047,7 @@
         }
 
         updateInputChannel(clientChannel.getToken(), callingUid, callingPid, displayId, surface,
-                name, applicationHandle, flags, null /* region */);
+                name, applicationHandle, flags, type, null /* region */);
 
         clientChannel.transferTo(outInputChannel);
         clientChannel.dispose();
@@ -8050,7 +8055,7 @@
 
     private void updateInputChannel(IBinder channelToken, int callingUid, int callingPid,
             int displayId, SurfaceControl surface, String name,
-            InputApplicationHandle applicationHandle, int flags, Region region) {
+            InputApplicationHandle applicationHandle, int flags, int type, Region region) {
         InputWindowHandle h = new InputWindowHandle(applicationHandle, displayId);
         h.token = channelToken;
         h.name = name;
@@ -8058,7 +8063,7 @@
         final int sanitizedFlags = flags & (LayoutParams.FLAG_NOT_TOUCHABLE
                 | LayoutParams.FLAG_SLIPPERY);
         h.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | sanitizedFlags;
-        h.layoutParamsType = 0;
+        h.layoutParamsType = type;
         h.dispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
         h.canReceiveKeys = false;
         h.hasFocus = false;
@@ -8082,6 +8087,7 @@
         t.setInputWindowInfo(surface, h);
         t.apply();
         t.close();
+        surface.release();
     }
 
     /**
@@ -8105,7 +8111,7 @@
         }
 
         updateInputChannel(channelToken, win.mOwnerUid, win.mOwnerPid, displayId, surface, name,
-                applicationHandle, flags, region);
+                applicationHandle, flags, win.mWindowType, region);
     }
 
     /** Return whether layer tracing is enabled */
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index c4cb4b5..707a789 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -138,6 +138,13 @@
                             Slog.e(TAG, "Attempt to operate on detached container: " + wc);
                             continue;
                         }
+                        // Make sure we add to the syncSet before performing
+                        // operations so we don't end up splitting effects between the WM
+                        // pending transaction and the BLASTSync transaction.
+                        if (syncId >= 0) {
+                            mBLASTSyncEngine.addToSyncSet(syncId, wc);
+                        }
+
                         int containerEffect = applyWindowContainerChange(wc, entry.getValue());
                         effects |= containerEffect;
 
@@ -146,9 +153,6 @@
                                 && (containerEffect & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
                             haveConfigChanges.add(wc);
                         }
-                        if (syncId >= 0) {
-                            mBLASTSyncEngine.addToSyncSet(syncId, wc);
-                        }
                     }
                     // Hierarchy changes
                     final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index fe68cd6..2ec6df5 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -44,6 +44,7 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.IApplicationThread;
 import android.app.ProfilerInfo;
@@ -1065,6 +1066,10 @@
             // to track as a separate apk in the process.
             packageName = info.packageName;
         }
+        // update ActivityManagerService.PendingStartActivityUids list.
+        if (topProcessState == ActivityManager.PROCESS_STATE_TOP) {
+            mAtm.mAmInternal.updatePendingTopUid(mUid, true);
+        }
         // Posting the message at the front of queue so WM lock isn't held when we call into AM,
         // and the process state of starting activity can be updated quicker which will give it a
         // higher scheduling group.
@@ -1315,12 +1320,15 @@
      *
      * @param isCached whether or not the process is cached.
      */
+    @HotPath(caller = HotPath.OOM_ADJUSTMENT)
     public void onProcCachedStateChanged(boolean isCached) {
-        synchronized (mAtm.mGlobalLock) {
-            if (!isCached && mPendingConfiguration != null) {
-                final Configuration config = mPendingConfiguration;
-                mPendingConfiguration = null;
-                dispatchConfigurationChange(config);
+        if (!isCached) {
+            synchronized (mAtm.mGlobalLockWithoutBoost) {
+                if (mPendingConfiguration != null) {
+                    final Configuration config = mPendingConfiguration;
+                    mPendingConfiguration = null;
+                    dispatchConfigurationChange(config);
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f6473fd..e9aff88 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -741,7 +741,8 @@
             if (mControllableInsetProvider != null) {
                 mControllableInsetProvider.startSeamlessRotation();
             }
-            mPendingSeamlessRotate = new SeamlessRotator(oldRotation, rotation, getDisplayInfo());
+            mPendingSeamlessRotate = new SeamlessRotator(oldRotation, rotation, getDisplayInfo(),
+                    false /* applyFixedTransformationHint */);
             mPendingSeamlessRotate.unrotate(transaction, this);
             getDisplayContent().getDisplayRotation().markForSeamlessRotation(this,
                     true /* seamlesslyRotated */);
@@ -1508,7 +1509,7 @@
         return mActivityRecord != null ? mActivityRecord.getTask() : null;
     }
 
-    ActivityStack getRootTask() {
+    @Nullable ActivityStack getRootTask() {
         final Task task = getTask();
         if (task != null) {
             return (ActivityStack) task.getRootTask();
@@ -2261,7 +2262,29 @@
         mHasSurface = hasSurface;
     }
 
+    /**
+     * Checks whether one of the Windows in a Display embedded in this Window can be an IME target.
+     */
+    private boolean canWindowInEmbeddedDisplayBeImeTarget() {
+        final int embeddedDisplayContentsSize = mEmbeddedDisplayContents.size();
+        for (int i = embeddedDisplayContentsSize - 1; i >= 0; i--) {
+            final DisplayContent edc = mEmbeddedDisplayContents.valueAt(i);
+            if (edc.forAllWindows(WindowState::canBeImeTarget, true)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     boolean canBeImeTarget() {
+        // If any of the embedded windows can be the IME target, this window will be the final IME
+        // target. This is because embedded windows are on a different display in WM so it would
+        // cause confusion trying to set the IME to a window on a different display. Instead, just
+        // make the host window the IME target.
+        if (canWindowInEmbeddedDisplayBeImeTarget()) {
+            return true;
+        }
+
         if (mIsImWindow) {
             // IME windows can't be IME targets. IME targets are required to be below the IME
             // windows and that wouldn't be possible if the IME window is its own target...silly.
@@ -2526,7 +2549,7 @@
             final Task task = getTask();
             if (task != null) {
                 task.getDimBounds(mTmpRect);
-            } else {
+            } else if (getRootTask() != null) {
                 getRootTask().getDimBounds(mTmpRect);
             }
         }
@@ -5688,6 +5711,17 @@
         return mSession.mPid == pid && isNonToastOrStarting() && isVisibleNow();
     }
 
+    void setViewVisibility(int viewVisibility) {
+        mViewVisibility = viewVisibility;
+        // The viewVisibility is set to GONE with a client request to relayout. If this occurs and
+        // there's a blast sync transaction waiting, finishDrawing will never be called since the
+        // client will not render when visibility is GONE. Therefore, call finishDrawing here to
+        // prevent system server from blocking on a window that will not draw.
+        if (viewVisibility == View.GONE && mUsingBLASTSyncTransaction) {
+            finishDrawing(null);
+        }
+    }
+
     SurfaceControl getClientViewRootSurface() {
         return mWinAnimator.getClientViewRootSurface();
     }
@@ -5695,16 +5729,20 @@
     @Override
     boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener,
             int waitingId) {
-        if (!isVisible()) {
+        boolean willSync = setPendingListener(waitingListener, waitingId);
+        if (!willSync) {
             return false;
         }
-        mWaitingListener = waitingListener;
-        mWaitingSyncId = waitingId;
-        mUsingBLASTSyncTransaction = true;
 
         mLocalSyncId = mBLASTSyncEngine.startSyncSet(this);
         addChildrenToSyncSet(mLocalSyncId);
 
+        // In the WindowContainer implementation we immediately mark ready
+        // since a generic WindowContainer only needs to wait for its
+        // children to finish and is immediately ready from its own
+        // perspective but at the WindowState level we need to wait for ourselves
+        // to draw even if the children draw first our don't need to sync, so we omit
+        // the set ready call until later in finishDrawing()
         mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
         mWmService.mH.sendNewMessageDelayed(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this,
             BLAST_TIMEOUT_DURATION);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index c570cf1..b30d408 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1257,19 +1257,25 @@
         mYOffset = dy;
         mWallpaperScale = scale;
 
-        try {
-            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset");
-            mService.openSurfaceTransaction();
-            setWallpaperPositionAndScale(dx, dy, scale, false);
-        } catch (RuntimeException e) {
-            Slog.w(TAG, "Error positioning surface of " + mWin
-                    + " pos=(" + dx + "," + dy + ")", e);
-        } finally {
-            mService.closeSurfaceTransaction("setWallpaperOffset");
-            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
-                    "<<< CLOSE TRANSACTION setWallpaperOffset");
-            return true;
+        if (mSurfaceController != null) {
+            try {
+                if (SHOW_LIGHT_TRANSACTIONS) {
+                    Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset");
+                }
+                mService.openSurfaceTransaction();
+                setWallpaperPositionAndScale(dx, dy, scale, false);
+            } catch (RuntimeException e) {
+                Slog.w(TAG, "Error positioning surface of " + mWin
+                        + " pos=(" + dx + "," + dy + ")", e);
+            } finally {
+                mService.closeSurfaceTransaction("setWallpaperOffset");
+                if (SHOW_LIGHT_TRANSACTIONS) {
+                    Slog.i(TAG, "<<< CLOSE TRANSACTION setWallpaperOffset");
+                }
+            }
         }
+
+        return true;
     }
 
     private void setWallpaperPositionAndScale(int dx, int dy, float scale,
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 148264a..768f89e 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -19,6 +19,7 @@
 import static android.os.Process.INVALID_UID;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
 
@@ -40,6 +41,7 @@
 
 import android.annotation.CallSuper;
 import android.app.IWindowToken;
+import android.app.servertransaction.FixedRotationAdjustmentsItem;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Debug;
@@ -47,6 +49,7 @@
 import android.os.RemoteException;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
 import android.view.DisplayInfo;
 import android.view.InsetsState;
 import android.view.SurfaceControl;
@@ -141,7 +144,7 @@
             mRotatedOverrideConfiguration = rotatedConfig;
             // This will use unrotate as rotate, so the new and old rotation are inverted.
             mRotator = new SeamlessRotator(rotatedDisplayInfo.rotation, currentRotation,
-                    rotatedDisplayInfo);
+                    rotatedDisplayInfo, true /* applyFixedTransformationHint */);
         }
 
         /**
@@ -529,6 +532,7 @@
         mFixedRotationTransformState = new FixedRotationTransformState(info, displayFrames,
                 insetsState, new Configuration(config), mDisplayContent.getRotation());
         onConfigurationChanged(getParent().getConfiguration());
+        notifyFixedRotationTransform(true /* enabled */);
     }
 
     /**
@@ -546,6 +550,7 @@
         mFixedRotationTransformState = fixedRotationState;
         fixedRotationState.mAssociatedTokens.add(this);
         onConfigurationChanged(getParent().getConfiguration());
+        notifyFixedRotationTransform(true /* enabled */);
     }
 
     void finishFixedRotationTransform() {
@@ -578,9 +583,52 @@
         // The state is cleared at the end, because it is used to indicate that other windows can
         // use seamless rotation when applying rotation to display.
         for (int i = state.mAssociatedTokens.size() - 1; i >= 0; i--) {
-            state.mAssociatedTokens.get(i).mFixedRotationTransformState = null;
+            state.mAssociatedTokens.get(i).cleanUpFixedRotationTransformState();
         }
+        cleanUpFixedRotationTransformState();
+    }
+
+    private void cleanUpFixedRotationTransformState() {
         mFixedRotationTransformState = null;
+        notifyFixedRotationTransform(false /* enabled */);
+    }
+
+    /** Notifies application side to enable or disable the rotation adjustment of display info. */
+    private void notifyFixedRotationTransform(boolean enabled) {
+        FixedRotationAdjustments adjustments = null;
+        // A token may contain windows of the same processes or different processes. The list is
+        // used to avoid sending the same adjustments to a process multiple times.
+        ArrayList<WindowProcessController> notifiedProcesses = null;
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = mChildren.get(i);
+            final WindowProcessController app;
+            if (w.mAttrs.type == TYPE_APPLICATION_STARTING) {
+                // Use the host activity because starting window is controlled by window manager.
+                final ActivityRecord r = asActivityRecord();
+                if (r == null) {
+                    continue;
+                }
+                app = r.app;
+            } else {
+                app = mWmService.mAtmService.mProcessMap.getProcess(w.mSession.mPid);
+            }
+            if (app == null || !app.hasThread()) {
+                continue;
+            }
+            if (notifiedProcesses == null) {
+                notifiedProcesses = new ArrayList<>(2);
+                adjustments = enabled ? createFixedRotationAdjustmentsIfNeeded() : null;
+            } else if (notifiedProcesses.contains(app)) {
+                continue;
+            }
+            notifiedProcesses.add(app);
+            try {
+                mWmService.mAtmService.getLifecycleManager().scheduleTransaction(
+                        app.getThread(), FixedRotationAdjustmentsItem.obtain(token, adjustments));
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Failed to schedule DisplayAdjustmentsItem to " + app, e);
+            }
+        }
     }
 
     /** Restores the changes that applies to this container. */
@@ -590,6 +638,7 @@
             // The window may be detached or detaching.
             return;
         }
+        notifyFixedRotationTransform(false /* enabled */);
         final int originalRotation = getWindowConfiguration().getRotation();
         onConfigurationChanged(parent.getConfiguration());
         onCancelFixedRotationTransform(originalRotation);
@@ -603,6 +652,14 @@
     void onCancelFixedRotationTransform(int originalDisplayRotation) {
     }
 
+    FixedRotationAdjustments createFixedRotationAdjustmentsIfNeeded() {
+        if (!isFixedRotationTransforming()) {
+            return null;
+        }
+        return new FixedRotationAdjustments(mFixedRotationTransformState.mDisplayInfo.rotation,
+                mFixedRotationTransformState.mDisplayInfo.displayCutout);
+    }
+
     @Override
     void resolveOverrideConfiguration(Configuration newParentConfig) {
         super.resolveOverrideConfiguration(newParentConfig);
diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS
new file mode 100644
index 0000000..8646a53
--- /dev/null
+++ b/services/core/jni/OWNERS
@@ -0,0 +1,13 @@
+# Display
+per-file com_android_server_lights_LightsService.cpp = michaelwr@google.com, santoscordon@google.com
+
+# Haptics
+per-file com_android_server_VibratorService.cpp = michaelwr@google.com
+
+# Input
+per-file com_android_server_input_InputManagerService.cpp = michaelwr@google.com, svv@google.com
+
+# Power
+per-file com_android_server_HardwarePropertiesManagerService.cpp = michaelwr@google.com, santoscordon@google.com
+per-file com_android_server_power_PowerManagerService.* = michaelwr@google.com, santoscordon@google.com
+
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index 6cf8133..e904645 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "PackageManagerShellCommandDataLoader-jni"
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/no_destructor.h>
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
 #include <core_jni_helpers.h>
@@ -65,6 +66,7 @@
 static constexpr MagicType INCR = 0x52434e49; // BE INCR
 
 static constexpr auto PollTimeoutMs = 5000;
+static constexpr auto TraceTagCheckInterval = 1s;
 
 struct JniIds {
     jclass packageManagerShellCommandDataLoader;
@@ -337,9 +339,47 @@
     return env;
 }
 
-class PackageManagerShellCommandDataLoaderDataLoader : public android::dataloader::DataLoader {
+class PMSCDataLoader;
+
+struct OnTraceChanged {
+    OnTraceChanged();
+    ~OnTraceChanged() {
+        mRunning = false;
+        mChecker.join();
+    }
+
+    void registerCallback(PMSCDataLoader* callback) {
+        std::unique_lock lock(mMutex);
+        mCallbacks.insert(callback);
+    }
+
+    void unregisterCallback(PMSCDataLoader* callback) {
+        std::unique_lock lock(mMutex);
+        mCallbacks.erase(callback);
+    }
+
+private:
+    std::mutex mMutex;
+    std::unordered_set<PMSCDataLoader*> mCallbacks;
+    std::atomic<bool> mRunning{true};
+    std::thread mChecker;
+};
+
+static OnTraceChanged& onTraceChanged() {
+    static android::base::NoDestructor<OnTraceChanged> instance;
+    return *instance;
+}
+
+class PMSCDataLoader : public android::dataloader::DataLoader {
 public:
-    PackageManagerShellCommandDataLoaderDataLoader(JavaVM* jvm) : mJvm(jvm) { CHECK(mJvm); }
+    PMSCDataLoader(JavaVM* jvm) : mJvm(jvm) { CHECK(mJvm); }
+    ~PMSCDataLoader() { onTraceChanged().unregisterCallback(this); }
+
+    void updateReadLogsState(const bool enabled) {
+        if (enabled != mReadLogsEnabled.exchange(enabled)) {
+            mIfs->setParams({.readLogsEnabled = enabled});
+        }
+    }
 
 private:
     // Lifecycle.
@@ -353,7 +393,8 @@
         mArgs = params.arguments();
         mIfs = ifs;
         mStatusListener = statusListener;
-        mIfs->setParams({.readLogsEnabled = true});
+        updateReadLogsState(atrace_is_tag_enabled(ATRACE_TAG));
+        onTraceChanged().registerCallback(this);
         return true;
     }
     bool onStart() final { return true; }
@@ -365,6 +406,7 @@
         }
     }
     void onDestroy() final {
+        onTraceChanged().unregisterCallback(this);
         // Make sure the receiver thread stopped.
         CHECK(!mReceiverThread.joinable());
     }
@@ -757,10 +799,28 @@
     android::base::unique_fd mEventFd;
     std::thread mReceiverThread;
     std::atomic<bool> mStopReceiving = false;
+    std::atomic<bool> mReadLogsEnabled = false;
     /** Tracks which files have been requested */
     std::unordered_set<FileIdx> mRequestedFiles;
 };
 
+OnTraceChanged::OnTraceChanged() {
+    mChecker = std::thread([this]() {
+        bool oldTrace = atrace_is_tag_enabled(ATRACE_TAG);
+        while (mRunning) {
+            bool newTrace = atrace_is_tag_enabled(ATRACE_TAG);
+            if (oldTrace != newTrace) {
+                std::unique_lock lock(mMutex);
+                for (auto&& callback : mCallbacks) {
+                    callback->updateReadLogsState(newTrace);
+                }
+            }
+            oldTrace = newTrace;
+            std::this_thread::sleep_for(TraceTagCheckInterval);
+        }
+    });
+}
+
 BlockHeader readHeader(std::span<uint8_t>& data) {
     BlockHeader header;
     if (data.size() < sizeof(header)) {
@@ -794,7 +854,7 @@
             [](auto jvm, const auto& params) -> android::dataloader::DataLoaderPtr {
                 if (params.type() == DATA_LOADER_TYPE_INCREMENTAL) {
                     // This DataLoader only supports incremental installations.
-                    return std::make_unique<PackageManagerShellCommandDataLoaderDataLoader>(jvm);
+                    return std::make_unique<PMSCDataLoader>(jvm);
                 }
                 return {};
             });
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 60d59b2..b7a9ba5 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -247,6 +247,7 @@
 import android.telephony.TelephonyManager;
 import android.telephony.data.ApnSetting;
 import android.text.TextUtils;
+import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
@@ -7972,6 +7973,9 @@
         final int userHandle = UserHandle.getCallingUserId();
         boolean requireAutoTimeChanged = false;
         synchronized (getLockObject()) {
+            if (isManagedProfile(userHandle)) {
+                throw new SecurityException("Managed profile cannot set auto time required");
+            }
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
                     DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             if (admin.requireAutoTime != required) {
@@ -11965,10 +11969,21 @@
     }
 
     private void showLocationSettingsChangedNotification(UserHandle user) {
+        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        // Fill the component explicitly to prevent the PendingIntent from being intercepted
+        // and fired with crafted target. b/155183624
+        ActivityInfo targetInfo = intent.resolveActivityInfo(
+                mInjector.getPackageManager(user.getIdentifier()),
+                PackageManager.MATCH_SYSTEM_ONLY);
+        if (targetInfo != null) {
+            intent.setComponent(targetInfo.getComponentName());
+        } else {
+            Slog.wtf(LOG_TAG, "Failed to resolve intent for location settings");
+        }
+
         PendingIntent locationSettingsIntent = mInjector.pendingIntentGetActivityAsUser(mContext, 0,
-                new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
-                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), PendingIntent.FLAG_UPDATE_CURRENT,
-                null, user);
+                intent, PendingIntent.FLAG_UPDATE_CURRENT, null, user);
         Notification notification = new Notification.Builder(mContext,
                 SystemNotificationChannels.DEVICE_ADMIN)
                 .setSmallIcon(R.drawable.ic_info_outline)
@@ -12715,6 +12730,11 @@
                 Binder.restoreCallingIdentity(ident);
             }
         }
+
+        @Override
+        public ComponentName getProfileOwnerAsUser(int userHandle) {
+            return DevicePolicyManagerService.this.getProfileOwnerAsUser(userHandle);
+        }
     }
 
     private Intent createShowAdminSupportIntent(ComponentName admin, int userId) {
@@ -15994,31 +16014,27 @@
     private @PersonalAppsSuspensionReason int updatePersonalAppsSuspension(
             int profileUserId, boolean unlocked) {
         final boolean suspendedExplicitly;
-        final int deadlineState;
-        final String poPackage;
+        final boolean suspendedByTimeout;
         synchronized (getLockObject()) {
             final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(profileUserId);
             if (profileOwner != null) {
-                deadlineState =
+                final int deadlineState =
                         updateProfileOffDeadlineLocked(profileUserId, profileOwner, unlocked);
                 suspendedExplicitly = profileOwner.mSuspendPersonalApps;
-                poPackage = profileOwner.info.getPackageName();
+                suspendedByTimeout = deadlineState == PROFILE_OFF_DEADLINE_REACHED;
+                Slog.d(LOG_TAG, String.format(
+                        "Personal apps suspended explicitly: %b, deadline state: %d",
+                        suspendedExplicitly, deadlineState));
+                final int notificationState =
+                        unlocked ? PROFILE_OFF_DEADLINE_DEFAULT : deadlineState;
+                updateProfileOffDeadlineNotificationLocked(
+                        profileUserId, profileOwner, notificationState);
             } else {
-                poPackage = null;
                 suspendedExplicitly = false;
-                deadlineState = PROFILE_OFF_DEADLINE_DEFAULT;
+                suspendedByTimeout = false;
             }
         }
 
-        Slog.d(LOG_TAG, String.format("Personal apps suspended explicitly: %b, deadline state: %d",
-                suspendedExplicitly, deadlineState));
-
-        if (poPackage != null) {
-            final int notificationState = unlocked ? PROFILE_OFF_DEADLINE_DEFAULT : deadlineState;
-            updateProfileOffDeadlineNotification(profileUserId, poPackage, notificationState);
-        }
-
-        final boolean suspendedByTimeout = deadlineState == PROFILE_OFF_DEADLINE_REACHED;
         final int parentUserId = getProfileParentId(profileUserId);
         suspendPersonalAppsInternal(parentUserId, suspendedExplicitly || suspendedByTimeout);
 
@@ -16130,9 +16146,9 @@
         }
     }
 
-    private void updateProfileOffDeadlineNotification(
-            int profileUserId, String profileOwnerPackage, int notificationState) {
-
+    @GuardedBy("getLockObject()")
+    private void updateProfileOffDeadlineNotificationLocked(
+            int profileUserId, ActiveAdmin profileOwner, int notificationState) {
         if (notificationState == PROFILE_OFF_DEADLINE_DEFAULT) {
             mInjector.getNotificationManager().cancel(SystemMessage.NOTE_PERSONAL_APPS_SUSPENDED);
             return;
@@ -16150,11 +16166,23 @@
         final Notification.Action turnProfileOnButton =
                 new Notification.Action.Builder(null /* icon */, buttonText, pendingIntent).build();
 
-        final String text = mContext.getString(
-                notificationState == PROFILE_OFF_DEADLINE_WARNING
-                ? R.string.personal_apps_suspension_tomorrow_text
-                : R.string.personal_apps_suspension_text);
-        final boolean ongoing = notificationState == PROFILE_OFF_DEADLINE_REACHED;
+        final String text;
+        final boolean ongoing;
+        if (notificationState == PROFILE_OFF_DEADLINE_WARNING) {
+            // Round to the closest integer number of days.
+            final int maxDays = (int)
+                    ((profileOwner.mProfileMaximumTimeOffMillis + MS_PER_DAY / 2) / MS_PER_DAY);
+            final String date = DateUtils.formatDateTime(
+                    mContext, profileOwner.mProfileOffDeadline, DateUtils.FORMAT_SHOW_DATE);
+            final String time = DateUtils.formatDateTime(
+                    mContext, profileOwner.mProfileOffDeadline, DateUtils.FORMAT_SHOW_TIME);
+            text = mContext.getString(
+                    R.string.personal_apps_suspension_soon_text, date, time, maxDays);
+            ongoing = false;
+        } else {
+            text = mContext.getString(R.string.personal_apps_suspension_text);
+            ongoing = true;
+        }
         final int color = mContext.getColor(R.color.personal_apps_suspension_notification_color);
         final Bundle extras = new Bundle();
         // TODO: Create a separate string for this.
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java b/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java
index da716ea..c687184 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java
@@ -30,6 +30,7 @@
 import android.os.IBinder;
 import android.os.ServiceManager;
 import android.provider.Settings;
+import android.provider.Telephony;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Slog;
@@ -84,6 +85,7 @@
         result.removeAll(getSystemLauncherPackages());
         result.removeAll(getAccessibilityServices());
         result.removeAll(getInputMethodPackages());
+        result.remove(Telephony.Sms.getDefaultSmsPackage(mContext));
         result.remove(getSettingsPackageName());
 
         final String[] unsuspendablePackages =
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
index 7cfbcc8..1630f27 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
@@ -22,9 +22,12 @@
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.format.DateUtils;
+import android.util.Slog;
 
 import com.android.internal.R;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
@@ -38,6 +41,7 @@
  */
 class RemoteBugreportUtils {
 
+    private static final String TAG = "RemoteBugreportUtils";
     static final int NOTIFICATION_ID = SystemMessage.NOTE_REMOTE_BUGREPORT;
 
     @Retention(RetentionPolicy.SOURCE)
@@ -60,6 +64,17 @@
         Intent dialogIntent = new Intent(Settings.ACTION_SHOW_REMOTE_BUGREPORT_DIALOG);
         dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
         dialogIntent.putExtra(DevicePolicyManager.EXTRA_BUGREPORT_NOTIFICATION_TYPE, type);
+
+        // Fill the component explicitly to prevent the PendingIntent from being intercepted
+        // and fired with crafted target. b/155183624
+        ActivityInfo targetInfo = dialogIntent.resolveActivityInfo(
+                context.getPackageManager(), PackageManager.MATCH_SYSTEM_ONLY);
+        if (targetInfo != null) {
+            dialogIntent.setComponent(targetInfo.getComponentName());
+        } else {
+            Slog.wtf(TAG, "Failed to resolve intent for remote bugreport dialog");
+        }
+
         PendingIntent pendingDialogIntent = PendingIntent.getActivityAsUser(context, type,
                 dialogIntent, 0, null, UserHandle.CURRENT);
 
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index a9dc92f..f0dca77 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -63,6 +63,7 @@
     static constexpr auto libDir = "lib"sv;
     static constexpr auto libSuffix = ".so"sv;
     static constexpr auto blockSize = 4096;
+    static constexpr auto systemPackage = "android"sv;
 };
 
 static const Constants& constants() {
@@ -377,7 +378,8 @@
         std::lock_guard l(mLock);
         mounts.reserve(mMounts.size());
         for (auto&& [id, ifs] : mMounts) {
-            if (ifs->mountId == id) {
+            if (ifs->mountId == id &&
+                ifs->dataLoaderStub->params().packageName == Constants::systemPackage) {
                 mounts.push_back(ifs);
             }
         }
@@ -748,7 +750,7 @@
         return -EINVAL;
     }
 
-    LOG(INFO) << "Removing bind point " << target;
+    LOG(INFO) << "Removing bind point " << target << " for storage " << storage;
 
     // Here we should only look up by the exact target, not by a subdirectory of any existing mount,
     // otherwise there's a chance to unmount something completely unrelated
@@ -1807,6 +1809,8 @@
         targetStatus = mTargetStatus;
     }
 
+    LOG(DEBUG) << "fsmStep: " << mId << ": " << currentStatus << " -> " << targetStatus;
+
     if (currentStatus == targetStatus) {
         return true;
     }
@@ -1868,8 +1872,8 @@
         listener = mListener;
 
         if (mCurrentStatus == IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE) {
-            // For unavailable, reset target status.
-            setTargetStatusLocked(IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE);
+            // For unavailable, unbind from DataLoader to ensure proper re-commit.
+            setTargetStatusLocked(IDataLoaderStatusListener::DATA_LOADER_DESTROYED);
         }
     }
 
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index 325218d..2e4625c 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -677,10 +677,10 @@
     mDataLoaderManager->bindToDataLoaderSuccess();
     mDataLoaderManager->getDataLoaderSuccess();
     EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(2);
-    EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(1);
+    EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(2);
     EXPECT_CALL(*mDataLoader, create(_, _, _, _)).Times(2);
     EXPECT_CALL(*mDataLoader, start(_)).Times(0);
-    EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
+    EXPECT_CALL(*mDataLoader, destroy(_)).Times(2);
     EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
     EXPECT_CALL(*mLooper, addFd(MockIncFs::kPendingReadsFd, _, _, _, _)).Times(1);
     EXPECT_CALL(*mLooper, removeFd(MockIncFs::kPendingReadsFd)).Times(1);
diff --git a/services/people/java/com/android/server/people/data/AppUsageStatsData.java b/services/people/java/com/android/server/people/data/AppUsageStatsData.java
new file mode 100644
index 0000000..6baef38
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/AppUsageStatsData.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/** The data containing package usage info. */
+public class AppUsageStatsData {
+
+    private int mLaunchCount;
+
+    private int mChosenCount;
+
+    @VisibleForTesting
+    public AppUsageStatsData(int chosenCount, int launchCount) {
+        this.mChosenCount = chosenCount;
+        this.mLaunchCount = launchCount;
+    }
+
+    public AppUsageStatsData() {
+    }
+
+    public int getLaunchCount() {
+        return mLaunchCount;
+    }
+
+    void incrementLaunchCountBy(int launchCount) {
+        this.mLaunchCount += launchCount;
+    }
+
+    public int getChosenCount() {
+        return mChosenCount;
+    }
+
+    void incrementChosenCountBy(int chosenCount) {
+        this.mChosenCount += chosenCount;
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
index 107c41a..bbb0215 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -257,13 +257,16 @@
     }
 
     /**
-     * Queries launch counts of apps within {@code packageNameFilter} between {@code startTime}
-     * and {@code endTime}.
+     * Queries usage stats of apps within {@code packageNameFilter} between {@code startTime} and
+     * {@code endTime}.
+     *
+     * @return a map which keys are package names and values are {@link AppUsageStatsData}.
      */
     @NonNull
-    public Map<String, Integer> queryAppLaunchCount(@UserIdInt int callingUserId, long startTime,
+    public Map<String, AppUsageStatsData> queryAppUsageStats(
+            @UserIdInt int callingUserId, long startTime,
             long endTime, Set<String> packageNameFilter) {
-        return UsageStatsQueryHelper.queryAppLaunchCount(callingUserId, startTime, endTime,
+        return UsageStatsQueryHelper.queryAppUsageStats(callingUserId, startTime, endTime,
                 packageNameFilter);
     }
 
diff --git a/services/people/java/com/android/server/people/data/UsageStatsQueryHelper.java b/services/people/java/com/android/server/people/data/UsageStatsQueryHelper.java
index 6e6fea9..d89bbe9 100644
--- a/services/people/java/com/android/server/people/data/UsageStatsQueryHelper.java
+++ b/services/people/java/com/android/server/people/data/UsageStatsQueryHelper.java
@@ -137,27 +137,48 @@
     }
 
     /**
-     * Queries {@link UsageStatsManagerInternal} for launch count of apps within {@code
-     * packageNameFilter} between {@code startTime} and {@code endTime}.obfuscateInstantApps
+     * Queries {@link UsageStatsManagerInternal} for usage stats of apps within {@code
+     * packageNameFilter} between {@code startTime} and {@code endTime}.
      *
-     * @return a map which keys are package names and values are app launch counts.
+     * @return a map which keys are package names and values are {@link AppUsageStatsData}.
      */
-    static Map<String, Integer> queryAppLaunchCount(@UserIdInt int userId, long startTime,
+    static Map<String, AppUsageStatsData> queryAppUsageStats(@UserIdInt int userId, long startTime,
             long endTime, Set<String> packageNameFilter) {
         List<UsageStats> stats = getUsageStatsManagerInternal().queryUsageStatsForUser(userId,
                 UsageStatsManager.INTERVAL_BEST, startTime, endTime,
                 /* obfuscateInstantApps= */ false);
-        Map<String, Integer> aggregatedStats = new ArrayMap<>();
+        Map<String, AppUsageStatsData> aggregatedStats = new ArrayMap<>();
         for (UsageStats stat : stats) {
             String packageName = stat.getPackageName();
             if (packageNameFilter.contains(packageName)) {
-                aggregatedStats.put(packageName,
-                        aggregatedStats.getOrDefault(packageName, 0) + stat.getAppLaunchCount());
+                AppUsageStatsData packageStats = aggregatedStats.computeIfAbsent(packageName,
+                        (key) -> new AppUsageStatsData());
+                packageStats.incrementChosenCountBy(sumChooserCounts(stat.mChooserCounts));
+                packageStats.incrementLaunchCountBy(stat.getAppLaunchCount());
             }
         }
         return aggregatedStats;
     }
 
+    private static int sumChooserCounts(ArrayMap<String, ArrayMap<String, Integer>> chooserCounts) {
+        int sum = 0;
+        if (chooserCounts == null) {
+            return sum;
+        }
+        int chooserCountsSize = chooserCounts.size();
+        for (int i = 0; i < chooserCountsSize; i++) {
+            ArrayMap<String, Integer> counts = chooserCounts.valueAt(i);
+            if (counts == null) {
+                continue;
+            }
+            final int annotationSize = counts.size();
+            for (int j = 0; j < annotationSize; j++) {
+                sum += counts.valueAt(j);
+            }
+        }
+        return sum;
+    }
+
     private void onInAppConversationEnded(@NonNull PackageData packageData,
             @NonNull UsageEvents.Event endEvent) {
         ComponentName activityName =
diff --git a/services/people/java/com/android/server/people/prediction/SharesheetModelScorer.java b/services/people/java/com/android/server/people/prediction/SharesheetModelScorer.java
index 76f252e..c77843c 100644
--- a/services/people/java/com/android/server/people/prediction/SharesheetModelScorer.java
+++ b/services/people/java/com/android/server/people/prediction/SharesheetModelScorer.java
@@ -27,17 +27,18 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.ChooserActivity;
+import com.android.server.people.data.AppUsageStatsData;
 import com.android.server.people.data.DataManager;
 import com.android.server.people.data.Event;
 
 import java.time.Duration;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.PriorityQueue;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
 
 /** Ranking scorer for Sharesheet targets. */
 class SharesheetModelScorer {
@@ -50,8 +51,8 @@
     private static final float RECENCY_SCORE_SUBSEQUENT_DECAY = 0.02F;
     private static final long ONE_MONTH_WINDOW = TimeUnit.DAYS.toMillis(30);
     private static final long FOREGROUND_APP_PROMO_TIME_WINDOW = TimeUnit.MINUTES.toMillis(10);
+    private static final float USAGE_STATS_CHOOSER_SCORE_INITIAL_DECAY = 0.9F;
     private static final float FREQUENTLY_USED_APP_SCORE_INITIAL_DECAY = 0.3F;
-    private static final float FREQUENTLY_USED_APP_SCORE_DECAY = 0.9F;
     @VisibleForTesting
     static final float FOREGROUND_APP_WEIGHT = 0F;
     @VisibleForTesting
@@ -192,14 +193,16 @@
             targetsList.add(index, shareTarget);
         }
         promoteForegroundApp(shareTargetMap, dataManager, callingUserId);
-        promoteFrequentlyUsedApps(shareTargetMap, targetsLimit, dataManager, callingUserId);
+        promoteMostChosenAndFrequentlyUsedApps(shareTargetMap, targetsLimit, dataManager,
+                callingUserId);
     }
 
     /**
-     * Promotes frequently used sharing apps, if recommended apps based on sharing history have not
-     * reached the limit (e.g. user did not share any content in last couple weeks)
+     * Promotes frequently chosen sharing apps and frequently used sharing apps as per
+     * UsageStatsManager, if recommended apps based on sharing history have not reached the limit
+     * (e.g. user did not share any content in last couple weeks)
      */
-    private static void promoteFrequentlyUsedApps(
+    private static void promoteMostChosenAndFrequentlyUsedApps(
             Map<String, List<ShareTargetPredictor.ShareTarget>> shareTargetMap, int targetsLimit,
             @NonNull DataManager dataManager, @UserIdInt int callingUserId) {
         int validPredictionNum = 0;
@@ -217,39 +220,50 @@
             return;
         }
         long now = System.currentTimeMillis();
-        Map<String, Integer> appLaunchCountsMap = dataManager.queryAppLaunchCount(
-                callingUserId, now - ONE_MONTH_WINDOW, now, shareTargetMap.keySet());
-        List<Pair<String, Integer>> appLaunchCounts = new ArrayList<>();
-        minValidScore *= FREQUENTLY_USED_APP_SCORE_INITIAL_DECAY;
-        for (Map.Entry<String, Integer> entry : appLaunchCountsMap.entrySet()) {
-            if (entry.getValue() > 0) {
-                appLaunchCounts.add(new Pair(entry.getKey(), entry.getValue()));
+        Map<String, AppUsageStatsData> appStatsMap =
+                dataManager.queryAppUsageStats(
+                        callingUserId, now - ONE_MONTH_WINDOW, now, shareTargetMap.keySet());
+        // Promotes frequently chosen sharing apps as per UsageStatsManager.
+        minValidScore = promoteApp(shareTargetMap, appStatsMap, AppUsageStatsData::getChosenCount,
+                USAGE_STATS_CHOOSER_SCORE_INITIAL_DECAY * minValidScore, minValidScore);
+        // Promotes frequently used sharing apps as per UsageStatsManager.
+        promoteApp(shareTargetMap, appStatsMap, AppUsageStatsData::getLaunchCount,
+                FREQUENTLY_USED_APP_SCORE_INITIAL_DECAY * minValidScore, minValidScore);
+    }
+
+    private static float promoteApp(
+            Map<String, List<ShareTargetPredictor.ShareTarget>> shareTargetMap,
+            Map<String, AppUsageStatsData> appStatsMap,
+            Function<AppUsageStatsData, Integer> countFunc, float baseScore, float minValidScore) {
+        int maxCount = 0;
+        for (AppUsageStatsData data : appStatsMap.values()) {
+            maxCount = Math.max(maxCount, countFunc.apply(data));
+        }
+        if (maxCount > 0) {
+            for (Map.Entry<String, AppUsageStatsData> entry : appStatsMap.entrySet()) {
+                if (!shareTargetMap.containsKey(entry.getKey())) {
+                    continue;
+                }
+                ShareTargetPredictor.ShareTarget target = shareTargetMap.get(entry.getKey()).get(0);
+                if (target.getScore() > 0f) {
+                    continue;
+                }
+                float curScore = baseScore * countFunc.apply(entry.getValue()) / maxCount;
+                target.setScore(curScore);
+                if (curScore > 0) {
+                    minValidScore = Math.min(minValidScore, curScore);
+                }
+                if (DEBUG) {
+                    Slog.d(TAG, String.format(
+                            "SharesheetModel: promote as per AppUsageStats packageName: %s, "
+                                    + "className: %s, total:%.2f",
+                            target.getAppTarget().getPackageName(),
+                            target.getAppTarget().getClassName(),
+                            target.getScore()));
+                }
             }
         }
-        Collections.sort(appLaunchCounts, (p1, p2) -> -Integer.compare(p1.second, p2.second));
-        for (Pair<String, Integer> entry : appLaunchCounts) {
-            if (!shareTargetMap.containsKey(entry.first)) {
-                continue;
-            }
-            ShareTargetPredictor.ShareTarget target = shareTargetMap.get(entry.first).get(0);
-            if (target.getScore() > 0f) {
-                continue;
-            }
-            target.setScore(minValidScore);
-            minValidScore *= FREQUENTLY_USED_APP_SCORE_DECAY;
-            if (DEBUG) {
-                Slog.d(TAG, String.format(
-                        "SharesheetModel: promoteFrequentUsedApps packageName: %s, className: %s,"
-                                + " total:%.2f",
-                        target.getAppTarget().getPackageName(),
-                        target.getAppTarget().getClassName(),
-                        target.getScore()));
-            }
-            validPredictionNum++;
-            if (validPredictionNum == targetsLimit) {
-                return;
-            }
-        }
+        return minValidScore;
     }
 
     /**
diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
index f8d197a..7154041 100644
--- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
+++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
@@ -37,7 +37,9 @@
 import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.Mode;
+import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
+import android.content.ComponentName;
 import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -46,6 +48,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
+import android.content.pm.PermissionInfo;
 import android.content.pm.ResolveInfo;
 import android.os.Process;
 import android.os.UserHandle;
@@ -96,6 +99,7 @@
     private static final int WORK_PROFILE_USER_ID = 10;
     private static final int WORK_PROFILE_UID = 3333;
     private static final int OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID = 20;
+    private static final int OUTSIDE_PROFILE_GROUP_USER_ID = 30;
 
     private final ContextWrapper mContext = ApplicationProvider.getApplicationContext();
     private final UserManager mUserManager = mContext.getSystemService(UserManager.class);
@@ -106,6 +110,7 @@
             new CrossProfileAppsServiceImpl(mContext, mInjector);
     private final Map<UserHandle, Set<Intent>> mSentUserBroadcasts = new HashMap<>();
     private final Map<Integer, List<ApplicationInfo>> installedApplications = new HashMap<>();
+    private final Set<Integer> mKilledUids = new HashSet<>();
 
     @Mock private PackageManagerInternal mPackageManagerInternal;
     @Mock private IPackageManager mIPackageManager;
@@ -224,6 +229,7 @@
                 PERSONAL_PROFILE_USER_ID,
                 WORK_PROFILE_USER_ID,
                 OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID);
+        shadowUserManager.addProfileIds(OUTSIDE_PROFILE_GROUP_USER_ID);
     }
 
     @Before
@@ -389,6 +395,33 @@
     }
 
     @Test
+    public void setInteractAcrossProfilesAppOp_toAllowed_doesNotKillApp() {
+        mCrossProfileAppsServiceImpl.setInteractAcrossProfilesAppOp(
+                CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED);
+        assertThat(mKilledUids).isEmpty();
+    }
+
+    @Test
+    public void setInteractAcrossProfilesAppOp_toDisallowed_killsAppsInBothProfiles() {
+        shadowOf(mPackageManager).addPermissionInfo(createCrossProfilesPermissionInfo());
+        mCrossProfileAppsServiceImpl.setInteractAcrossProfilesAppOp(
+                CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED);
+
+        mCrossProfileAppsServiceImpl.setInteractAcrossProfilesAppOp(
+                CROSS_PROFILE_APP_PACKAGE_NAME, MODE_DEFAULT);
+
+        assertThat(mKilledUids).contains(WORK_PROFILE_UID);
+        assertThat(mKilledUids).contains(PERSONAL_PROFILE_UID);
+    }
+
+    private PermissionInfo createCrossProfilesPermissionInfo() {
+        PermissionInfo permissionInfo = new PermissionInfo();
+        permissionInfo.name = Manifest.permission.INTERACT_ACROSS_PROFILES;
+        permissionInfo.protectionLevel = PermissionInfo.PROTECTION_FLAG_APPOP;
+        return permissionInfo;
+    }
+
+    @Test
     public void canConfigureInteractAcrossProfiles_packageNotInstalledInProfile_returnsFalse() {
         mockUninstallCrossProfileAppFromWorkProfile();
         assertThat(mCrossProfileAppsServiceImpl
@@ -475,6 +508,36 @@
     }
 
     @Test
+    public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerWorkProfile_returnsFalse() {
+        when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(WORK_PROFILE_USER_ID))
+                .thenReturn(buildCrossProfileComponentName());
+        assertThat(mCrossProfileAppsServiceImpl
+                .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
+                .isFalse();
+    }
+
+    @Test
+    public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerOtherProfile_returnsFalse() {
+        // Normally, the DPC would not be a profile owner of the personal profile, but for the
+        // purposes of this test, it is just a profile owner of any profile within the profile
+        // group.
+        when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(PERSONAL_PROFILE_USER_ID))
+                .thenReturn(buildCrossProfileComponentName());
+        assertThat(mCrossProfileAppsServiceImpl
+                .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
+                .isFalse();
+    }
+
+    @Test
+    public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerOutsideProfileGroup_returnsTrue() {
+        when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(OUTSIDE_PROFILE_GROUP_USER_ID))
+                .thenReturn(buildCrossProfileComponentName());
+        assertThat(mCrossProfileAppsServiceImpl
+                .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
+                .isTrue();
+    }
+
+    @Test
     public void canUserAttemptToConfigureInteractAcrossProfiles_returnsTrue() {
         assertThat(mCrossProfileAppsServiceImpl
                 .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
@@ -578,6 +641,10 @@
                         .hideAsParsed()).hideAsFinal());
     }
 
+    private ComponentName buildCrossProfileComponentName() {
+        return new ComponentName(CROSS_PROFILE_APP_PACKAGE_NAME, "testClassName");
+    }
+
     private class TestInjector implements CrossProfileAppsServiceImpl.Injector {
 
         @Override
@@ -678,5 +745,10 @@
             // ShadowActivityThread with Robolectric. This method is currently not supported there.
             return mContext.checkPermission(permission, Process.myPid(), uid);
         }
+
+        @Override
+        public void killUid(String packageName, int uid) {
+            mKilledUids.add(uid);
+        }
     }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
index e5ec1f7..96a44a4 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -16,14 +16,23 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+
 import static com.android.server.am.ActivityManagerService.Injector;
 import static com.android.server.am.CachedAppOptimizer.compactActionIntToString;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManagerInternal;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.MessageQueue;
 import android.os.Process;
 import android.platform.test.annotations.Presubmit;
 import android.provider.DeviceConfig;
@@ -31,9 +40,11 @@
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
 import com.android.server.appop.AppOpsService;
 import com.android.server.testables.TestableDeviceConfig;
+import com.android.server.wm.ActivityTaskManagerService;
 
 import org.junit.After;
 import org.junit.Assume;
@@ -45,6 +56,7 @@
 import org.mockito.junit.MockitoJUnitRunner;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
@@ -68,25 +80,36 @@
     private HandlerThread mHandlerThread;
     private Handler mHandler;
     private CountDownLatch mCountDown;
+    private ActivityManagerService mAms;
+    private Context mContext;
+    private TestInjector mInjector;
+    private TestProcessDependencies mProcessDependencies;
+
+    @Mock
+    private PackageManagerInternal mPackageManagerInt;
 
     @Rule
-    public TestableDeviceConfig.TestableDeviceConfigRule
+    public final TestableDeviceConfig.TestableDeviceConfigRule
             mDeviceConfigRule = new TestableDeviceConfig.TestableDeviceConfigRule();
+    @Rule
+    public final ApplicationExitInfoTest.ServiceThreadRule
+            mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule();
 
     @Before
     public void setUp() {
         mHandlerThread = new HandlerThread("");
         mHandlerThread.start();
         mHandler = new Handler(mHandlerThread.getLooper());
-
         mThread = new ServiceThread("TestServiceThread", Process.THREAD_PRIORITY_DEFAULT,
                 true /* allowIo */);
         mThread.start();
-
-        ActivityManagerService ams = new ActivityManagerService(
-                new TestInjector(InstrumentationRegistry.getInstrumentation().getContext()),
-                mThread);
-        mCachedAppOptimizerUnderTest = new CachedAppOptimizer(ams,
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        mInjector = new TestInjector(mContext);
+        mAms = new ActivityManagerService(
+                new TestInjector(mContext), mServiceThreadRule.getThread());
+        doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent();
+        mProcessDependencies = new TestProcessDependencies();
+        mCachedAppOptimizerUnderTest = new CachedAppOptimizer(mAms,
                 new CachedAppOptimizer.PropertyChangedCallbackForTest() {
                     @Override
                     public void onPropertyChanged() {
@@ -94,7 +117,9 @@
                             mCountDown.countDown();
                         }
                     }
-                });
+                }, mProcessDependencies);
+        LocalServices.removeServiceForTest(PackageManagerInternal.class);
+        LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt);
     }
 
     @After
@@ -104,6 +129,19 @@
         mCountDown = null;
     }
 
+    private ProcessRecord makeProcessRecord(int pid, int uid, int packageUid, String processName,
+            String packageName) {
+        ApplicationInfo ai = new ApplicationInfo();
+        ai.packageName = packageName;
+        ProcessRecord app = new ProcessRecord(mAms, ai, processName, uid);
+        app.pid = pid;
+        app.info.uid = packageUid;
+        // Exact value does not mater, it can be any state for which compaction is allowed.
+        app.setProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+        app.setAdj = 905;
+        return app;
+    }
+
     @Test
     public void init_setsDefaults() {
         mCachedAppOptimizerUnderTest.init();
@@ -197,7 +235,7 @@
                 CachedAppOptimizer.DEFAULT_USE_FREEZER);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 CachedAppOptimizer.KEY_USE_FREEZER, CachedAppOptimizer.DEFAULT_USE_FREEZER
-                ?  "false" : "true" , false);
+                        ? "false" : "true", false);
 
         // Then calling init will read and set that flag.
         mCachedAppOptimizerUnderTest.init();
@@ -790,6 +828,174 @@
                 .containsExactlyElementsIn(expected);
     }
 
+    @Test
+    public void processWithDeltaRSSTooSmall_notFullCompacted() throws Exception {
+        // Initialize CachedAppOptimizer and set flags to (1) enable compaction, (2) set RSS
+        // throttle to 12000.
+        mCachedAppOptimizerUnderTest.init();
+        setFlag(CachedAppOptimizer.KEY_USE_COMPACTION, "true", true);
+        setFlag(CachedAppOptimizer.KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB, "12000", false);
+        initActivityManagerService();
+
+        // Simulate RSS anon memory larger than throttle.
+        long[] rssBefore1 =
+                new long[]{/*totalRSS*/ 10000, /*fileRSS*/ 10000, /*anonRSS*/ 12000, /*swap*/
+                        10000};
+        long[] rssAfter1 =
+                new long[]{/*totalRSS*/ 9000, /*fileRSS*/ 9000, /*anonRSS*/ 11000, /*swap*/9000};
+        // Delta between rssAfter1 and rssBefore2 is below threshold (500).
+        long[] rssBefore2 =
+                new long[]{/*totalRSS*/ 9500, /*fileRSS*/ 9500, /*anonRSS*/ 11500, /*swap*/9500};
+        long[] rssAfter2 =
+                new long[]{/*totalRSS*/ 8000, /*fileRSS*/ 8000, /*anonRSS*/ 9000, /*swap*/8000};
+        // Delta between rssAfter1 and rssBefore3 is above threshold (13000).
+        long[] rssBefore3 =
+                new long[]{/*totalRSS*/ 10000, /*fileRSS*/ 18000, /*anonRSS*/ 13000, /*swap*/ 7000};
+        long[] rssAfter3 =
+                new long[]{/*totalRSS*/ 10000, /*fileRSS*/ 11000, /*anonRSS*/ 10000, /*swap*/ 6000};
+        long[] valuesAfter = {};
+        // Process that passes properties.
+        int pid = 1;
+        ProcessRecord processRecord = makeProcessRecord(pid, 2, 3, "p1", "app1");
+
+        // GIVEN we simulate RSS memory before above thresholds and it is the first time 'p1' is
+        // compacted.
+        mProcessDependencies.setRss(rssBefore1);
+        mProcessDependencies.setRssAfterCompaction(rssAfter1); //
+        // WHEN we try to run compaction
+        mCachedAppOptimizerUnderTest.compactAppFull(processRecord);
+        waitForHandler();
+        // THEN process IS compacted.
+        assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
+        valuesAfter = mCachedAppOptimizerUnderTest.mLastCompactionStats.get(
+                pid).getRssAfterCompaction();
+        assertThat(valuesAfter).isEqualTo(rssAfter1);
+
+        // WHEN delta is below threshold (500).
+        mProcessDependencies.setRss(rssBefore2);
+        mProcessDependencies.setRssAfterCompaction(rssAfter2);
+        // This is to avoid throttle of compacting too soon.
+        processRecord.lastCompactTime = processRecord.lastCompactTime - 10_000;
+        // WHEN we try to run compaction.
+        mCachedAppOptimizerUnderTest.compactAppFull(processRecord);
+        waitForHandler();
+        // THEN process IS NOT compacted - values after compaction for process 1 should remain the
+        // same as from the last compaction.
+        assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
+        valuesAfter = mCachedAppOptimizerUnderTest.mLastCompactionStats.get(
+                pid).getRssAfterCompaction();
+        assertThat(valuesAfter).isEqualTo(rssAfter1);
+
+        // WHEN delta is above threshold (13000).
+        mProcessDependencies.setRss(rssBefore3);
+        mProcessDependencies.setRssAfterCompaction(rssAfter3);
+        // This is to avoid throttle of compacting too soon.
+        processRecord.lastCompactTime = processRecord.lastCompactTime - 10_000;
+        // WHEN we try to run compaction
+        mCachedAppOptimizerUnderTest.compactAppFull(processRecord);
+        waitForHandler();
+        // THEN process IS compacted - values after compaction for process 1 should be updated.
+        assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
+        valuesAfter = mCachedAppOptimizerUnderTest.mLastCompactionStats.get(
+                pid).getRssAfterCompaction();
+        assertThat(valuesAfter).isEqualTo(rssAfter3);
+
+    }
+
+    @Test
+    public void processWithAnonRSSTooSmall_notFullCompacted() throws Exception {
+        // Initialize CachedAppOptimizer and set flags to (1) enable compaction, (2) set RSS
+        // throttle to 8000.
+        mCachedAppOptimizerUnderTest.init();
+        setFlag(CachedAppOptimizer.KEY_USE_COMPACTION, "true", true);
+        setFlag(CachedAppOptimizer.KEY_COMPACT_FULL_RSS_THROTTLE_KB, "8000", false);
+        initActivityManagerService();
+
+        // Simulate RSS anon memory larger than throttle.
+        long[] rssBelowThreshold =
+                new long[]{/*Total RSS*/ 10000, /*File RSS*/ 10000, /*Anon RSS*/ 7000, /*Swap*/
+                        10000};
+        long[] rssBelowThresholdAfter =
+                new long[]{/*Total RSS*/ 9000, /*File RSS*/ 7000, /*Anon RSS*/ 4000, /*Swap*/
+                        8000};
+        long[] rssAboveThreshold =
+                new long[]{/*Total RSS*/ 10000, /*File RSS*/ 10000, /*Anon RSS*/ 9000, /*Swap*/
+                        10000};
+        long[] rssAboveThresholdAfter =
+                new long[]{/*Total RSS*/ 8000, /*File RSS*/ 9000, /*Anon RSS*/ 6000, /*Swap*/5000};
+        // Process that passes properties.
+        int pid = 1;
+        ProcessRecord processRecord =
+                makeProcessRecord(pid, 2, 3, "p1",
+                        "app1");
+
+        // GIVEN we simulate RSS memory before below threshold.
+        mProcessDependencies.setRss(rssBelowThreshold);
+        mProcessDependencies.setRssAfterCompaction(rssBelowThresholdAfter);
+        // WHEN we try to run compaction
+        mCachedAppOptimizerUnderTest.compactAppFull(processRecord);
+        waitForHandler();
+        // THEN process IS NOT compacted.
+        assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNull();
+
+        // GIVEN we simulate RSS memory before above threshold.
+        mProcessDependencies.setRss(rssAboveThreshold);
+        mProcessDependencies.setRssAfterCompaction(rssAboveThresholdAfter);
+        // WHEN we try to run compaction
+        mCachedAppOptimizerUnderTest.compactAppFull(processRecord);
+        waitForHandler();
+        // THEN process IS compacted.
+        assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
+        long[] valuesAfter = mCachedAppOptimizerUnderTest.mLastCompactionStats.get(
+                pid).getRssAfterCompaction();
+        assertThat(valuesAfter).isEqualTo(rssAboveThresholdAfter);
+    }
+
+
+    private void setFlag(String key, String value, boolean defaultValue) throws Exception {
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, key, value, defaultValue);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+    }
+
+    private void waitForHandler() {
+        Idle idle = new Idle();
+        mCachedAppOptimizerUnderTest.mCompactionHandler.getLooper().getQueue().addIdleHandler(idle);
+        mCachedAppOptimizerUnderTest.mCompactionHandler.post(() -> { });
+        idle.waitForIdle();
+    }
+
+    private void initActivityManagerService() {
+        mAms = new ActivityManagerService(mInjector, mServiceThreadRule.getThread());
+        mAms.mActivityTaskManager = new ActivityTaskManagerService(mContext);
+        mAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper());
+        mAms.mAtmInternal = spy(mAms.mActivityTaskManager.getAtmInternal());
+        mAms.mPackageManagerInt = mPackageManagerInt;
+    }
+
+    private static final class Idle implements MessageQueue.IdleHandler {
+        private boolean mIdle;
+
+        @Override
+        public boolean queueIdle() {
+            synchronized (this) {
+                mIdle = true;
+                notifyAll();
+            }
+            return false;
+        }
+
+        public synchronized void waitForIdle() {
+            while (!mIdle) {
+                try {
+                    // Wait with a timeout of 10s.
+                    wait(10000);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+    }
+
     private class TestInjector extends Injector {
 
         TestInjector(Context context) {
@@ -806,4 +1012,29 @@
             return mHandler;
         }
     }
+
+    // Test implementation for ProcessDependencies.
+    private static final class TestProcessDependencies
+            implements CachedAppOptimizer.ProcessDependencies {
+        private long[] mRss;
+        private long[] mRssAfterCompaction;
+
+        @Override
+        public long[] getRss(int pid) {
+            return mRss;
+        }
+
+        @Override
+        public void performCompaction(String action, int pid) throws IOException {
+            mRss = mRssAfterCompaction;
+        }
+
+        public void setRss(long[] newValues) {
+            mRss = newValues;
+        }
+
+        public void setRssAfterCompaction(long[] newValues) {
+            mRssAfterCompaction = newValues;
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index 285caf3..48ec529 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -115,6 +115,8 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
+        resetReceivers();
+
         when(mContext.getContentResolver()).thenReturn(mContentResolver);
         when(mContext.getResources()).thenReturn(mResources);
         when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE))
@@ -147,6 +149,74 @@
     }
 
     @Test
+    public void testClientBinderDied_whenPaused() throws Exception {
+        setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
+
+        invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
+                true /* requireConfirmation */, null /* authenticators */);
+        waitForIdle();
+        verify(mReceiver1.asBinder()).linkToDeath(eq(mBiometricService.mCurrentAuthSession),
+                anyInt());
+
+        mBiometricService.mInternalReceiver.onError(
+                getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
+                BiometricAuthenticator.TYPE_FACE,
+                BiometricConstants.BIOMETRIC_ERROR_TIMEOUT,
+                0 /* vendorCode */);
+        waitForIdle();
+
+        assertEquals(BiometricService.STATE_AUTH_PAUSED,
+                mBiometricService.mCurrentAuthSession.mState);
+
+        mBiometricService.mCurrentAuthSession.binderDied();
+        waitForIdle();
+
+        assertNull(mBiometricService.mCurrentAuthSession);
+        verify(mBiometricService.mStatusBarService).hideAuthenticationDialog();
+        verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
+    }
+
+    @Test
+    public void testClientBinderDied_whenAuthenticating() throws Exception {
+        setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
+
+        invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
+                true /* requireConfirmation */, null /* authenticators */);
+        waitForIdle();
+        verify(mReceiver1.asBinder()).linkToDeath(eq(mBiometricService.mCurrentAuthSession),
+                anyInt());
+
+        assertEquals(BiometricService.STATE_AUTH_STARTED,
+                mBiometricService.mCurrentAuthSession.mState);
+        mBiometricService.mCurrentAuthSession.binderDied();
+        waitForIdle();
+
+        assertNotNull(mBiometricService.mCurrentAuthSession);
+        verify(mBiometricService.mStatusBarService, never()).hideAuthenticationDialog();
+        assertEquals(BiometricService.STATE_CLIENT_DIED_CANCELLING,
+                mBiometricService.mCurrentAuthSession.mState);
+
+        verify(mBiometricService.mAuthenticators.get(0).impl).cancelAuthenticationFromService(
+                any(),
+                any(),
+                anyInt(),
+                anyInt(),
+                anyInt(),
+                eq(false) /* fromClient */);
+
+        // Simulate ERROR_CANCELED received from HAL
+        mBiometricService.mInternalReceiver.onError(
+                getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
+                BiometricAuthenticator.TYPE_FACE,
+                BiometricConstants.BIOMETRIC_ERROR_CANCELED,
+                0 /* vendorCode */);
+        waitForIdle();
+        verify(mBiometricService.mStatusBarService).hideAuthenticationDialog();
+        verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
+        assertNull(mBiometricService.mCurrentAuthSession);
+    }
+
+    @Test
     public void testAuthenticate_credentialAllowedButNotSetup_returnsNoDeviceCredential()
             throws Exception {
         when(mTrustManager.isDeviceSecure(anyInt())).thenReturn(false);
@@ -311,7 +381,7 @@
                 eq(0 /* vendorCode */));
 
         // Enrolled, not disabled in settings, user requires confirmation in settings
-        resetReceiver();
+        resetReceivers();
         when(mBiometricService.mSettingObserver.getFaceEnabledForApps(anyInt())).thenReturn(true);
         when(mBiometricService.mSettingObserver.getFaceAlwaysRequireConfirmation(anyInt()))
                 .thenReturn(true);
@@ -332,7 +402,7 @@
                 anyInt() /* callingUserId */);
 
         // Enrolled, not disabled in settings, user doesn't require confirmation in settings
-        resetReceiver();
+        resetReceivers();
         when(mBiometricService.mSettingObserver.getFaceAlwaysRequireConfirmation(anyInt()))
                 .thenReturn(false);
         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
@@ -1198,7 +1268,7 @@
                 eq(0) /* vendorCode */);
 
         // Request for weak auth works
-        resetReceiver();
+        resetReceivers();
         authenticators = Authenticators.BIOMETRIC_WEAK;
         assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
                 invokeCanAuthenticate(mBiometricService, authenticators));
@@ -1217,7 +1287,7 @@
                 anyInt() /* sysUiSessionId */);
 
         // Requesting strong and credential, when credential is setup
-        resetReceiver();
+        resetReceivers();
         authenticators = Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL;
         when(mTrustManager.isDeviceSecure(anyInt())).thenReturn(true);
         assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
@@ -1244,7 +1314,7 @@
             }
         }
 
-        resetReceiver();
+        resetReceivers();
         authenticators = Authenticators.BIOMETRIC_STRONG;
         assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
                 invokeCanAuthenticate(mBiometricService, authenticators));
@@ -1449,9 +1519,12 @@
         }
     }
 
-    private void resetReceiver() {
+    private void resetReceivers() {
         mReceiver1 = mock(IBiometricServiceReceiver.class);
         mReceiver2 = mock(IBiometricServiceReceiver.class);
+
+        when(mReceiver1.asBinder()).thenReturn(mock(Binder.class));
+        when(mReceiver2.asBinder()).thenReturn(mock(Binder.class));
     }
 
     private void resetStatusBar() {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 17dd286..724048b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -204,7 +204,7 @@
     // Notification title and text for setManagedProfileMaximumTimeOff tests:
     private static final String PROFILE_OFF_SUSPENSION_TITLE = "suspension_title";
     private static final String PROFILE_OFF_SUSPENSION_TEXT = "suspension_text";
-    private static final String PROFILE_OFF_SUSPENSION_TOMORROW_TEXT = "suspension_tomorrow_text";
+    private static final String PROFILE_OFF_SUSPENSION_SOON_TEXT = "suspension_tomorrow_text";
 
     @Override
     protected void setUp() throws Exception {
@@ -6331,7 +6331,7 @@
         // Now the user should see a warning notification.
         verify(getServices().notificationManager, times(1))
                 .notify(anyInt(), argThat(hasExtra(EXTRA_TITLE, PROFILE_OFF_SUSPENSION_TITLE,
-                        EXTRA_TEXT, PROFILE_OFF_SUSPENSION_TOMORROW_TEXT)));
+                        EXTRA_TEXT, PROFILE_OFF_SUSPENSION_SOON_TEXT)));
         // Apps shouldn't be suspended yet.
         verifyZeroInteractions(getServices().ipackageManager);
         clearInvocations(getServices().alarmManager);
@@ -6482,7 +6482,7 @@
         // To allow creation of Notification via Notification.Builder
         mContext.applicationInfo = mRealTestContext.getApplicationInfo();
 
-        // Setup notification titles.
+        // Setup resources to render notification titles and texts.
         when(mServiceContext.resources
                 .getString(R.string.personal_apps_suspension_title))
                 .thenReturn(PROFILE_OFF_SUSPENSION_TITLE);
@@ -6490,14 +6490,19 @@
                 .getString(R.string.personal_apps_suspension_text))
                 .thenReturn(PROFILE_OFF_SUSPENSION_TEXT);
         when(mServiceContext.resources
-                .getString(R.string.personal_apps_suspension_tomorrow_text))
-                .thenReturn(PROFILE_OFF_SUSPENSION_TOMORROW_TEXT);
+                .getString(eq(R.string.personal_apps_suspension_soon_text),
+                        anyString(), anyString(), anyInt()))
+                .thenReturn(PROFILE_OFF_SUSPENSION_SOON_TEXT);
+
+        // Make locale available for date formatting:
+        when(mServiceContext.resources.getConfiguration())
+                .thenReturn(mRealTestContext.getResources().getConfiguration());
 
         clearInvocations(getServices().ipackageManager);
     }
 
     private static Matcher<Notification> hasExtra(String... extras) {
-        assertEquals("Odd numebr of extra key-values", 0, extras.length % 2);
+        assertEquals("Odd number of extra key-values", 0, extras.length % 2);
         return new BaseMatcher<Notification>() {
             @Override
             public boolean matches(Object item) {
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 8137c36..43a396d 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -17,6 +17,7 @@
 package com.android.server.display;
 
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
 
 import android.content.Context;
 import android.os.Handler;
@@ -28,6 +29,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.server.display.DisplayModeDirector.BrightnessObserver;
 import com.android.server.display.DisplayModeDirector.DesiredDisplayModeSpecs;
 import com.android.server.display.DisplayModeDirector.Vote;
 
@@ -36,6 +38,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 @SmallTest
@@ -52,16 +55,15 @@
         mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
     }
 
-    private DisplayModeDirector createDisplayModeDirectorWithDisplayFpsRange(
-            int minFps, int maxFps) {
+    private DisplayModeDirector createDirectorFromRefreshRateArray(
+            float[] refreshRates, int baseModeId) {
         DisplayModeDirector director =
                 new DisplayModeDirector(mContext, new Handler(Looper.getMainLooper()));
         int displayId = 0;
-        int numModes = maxFps - minFps + 1;
-        Display.Mode[] modes = new Display.Mode[numModes];
-        for (int i = minFps; i <= maxFps; i++) {
-            modes[i - minFps] = new Display.Mode(
-                    /*modeId=*/i, /*width=*/1000, /*height=*/1000, /*refreshRate=*/i);
+        Display.Mode[] modes = new Display.Mode[refreshRates.length];
+        for (int i = 0; i < refreshRates.length; i++) {
+            modes[i] = new Display.Mode(
+                    /*modeId=*/baseModeId + i, /*width=*/1000, /*height=*/1000, refreshRates[i]);
         }
         SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>();
         supportedModesByDisplay.put(displayId, modes);
@@ -72,14 +74,22 @@
         return director;
     }
 
+    private DisplayModeDirector createDirectorFromFpsRange(int minFps, int maxFps) {
+        int numRefreshRates = maxFps - minFps + 1;
+        float[] refreshRates = new float[numRefreshRates];
+        for (int i = 0; i < numRefreshRates; i++) {
+            refreshRates[i] = minFps + i;
+        }
+        return createDirectorFromRefreshRateArray(refreshRates, /*baseModeId=*/minFps);
+    }
+
     @Test
     public void testDisplayModeVoting() {
         int displayId = 0;
 
         // With no votes present, DisplayModeDirector should allow any refresh rate.
         DesiredDisplayModeSpecs modeSpecs =
-                createDisplayModeDirectorWithDisplayFpsRange(60, 90).getDesiredDisplayModeSpecs(
-                        displayId);
+                createDirectorFromFpsRange(60, 90).getDesiredDisplayModeSpecs(displayId);
         Truth.assertThat(modeSpecs.baseModeId).isEqualTo(60);
         Truth.assertThat(modeSpecs.primaryRefreshRateRange.min).isEqualTo(0f);
         Truth.assertThat(modeSpecs.primaryRefreshRateRange.max).isEqualTo(Float.POSITIVE_INFINITY);
@@ -92,7 +102,7 @@
         {
             int minFps = 60;
             int maxFps = 90;
-            DisplayModeDirector director = createDisplayModeDirectorWithDisplayFpsRange(60, 90);
+            DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
             assertTrue(2 * numPriorities < maxFps - minFps + 1);
             SparseArray<Vote> votes = new SparseArray<>();
             SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
@@ -114,7 +124,7 @@
         // presence of higher priority votes.
         {
             assertTrue(numPriorities >= 2);
-            DisplayModeDirector director = createDisplayModeDirectorWithDisplayFpsRange(60, 90);
+            DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
             SparseArray<Vote> votes = new SparseArray<>();
             SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
             votesByDisplay.put(displayId, votes);
@@ -131,7 +141,7 @@
     @Test
     public void testVotingWithFloatingPointErrors() {
         int displayId = 0;
-        DisplayModeDirector director = createDisplayModeDirectorWithDisplayFpsRange(50, 90);
+        DisplayModeDirector director = createDirectorFromFpsRange(50, 90);
         SparseArray<Vote> votes = new SparseArray<>();
         SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
         votesByDisplay.put(displayId, votes);
@@ -154,7 +164,7 @@
         assertTrue(Vote.PRIORITY_LOW_BRIGHTNESS < Vote.PRIORITY_APP_REQUEST_SIZE);
 
         int displayId = 0;
-        DisplayModeDirector director = createDisplayModeDirectorWithDisplayFpsRange(60, 90);
+        DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
         SparseArray<Vote> votes = new SparseArray<>();
         SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
         votesByDisplay.put(displayId, votes);
@@ -202,7 +212,7 @@
                 >= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
 
         int displayId = 0;
-        DisplayModeDirector director = createDisplayModeDirectorWithDisplayFpsRange(60, 90);
+        DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
         SparseArray<Vote> votes = new SparseArray<>();
         SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
         votesByDisplay.put(displayId, votes);
@@ -235,4 +245,61 @@
                 .isWithin(FLOAT_TOLERANCE)
                 .of(75);
     }
+
+    void verifySpecsWithRefreshRateSettings(DisplayModeDirector director, float minFps,
+            float peakFps, float defaultFps, float primaryMin, float primaryMax,
+            float appRequestMin, float appRequestMax) {
+        DesiredDisplayModeSpecs specs = director.getDesiredDisplayModeSpecsWithInjectedFpsSettings(
+                minFps, peakFps, defaultFps);
+        Truth.assertThat(specs.primaryRefreshRateRange.min).isEqualTo(primaryMin);
+        Truth.assertThat(specs.primaryRefreshRateRange.max).isEqualTo(primaryMax);
+        Truth.assertThat(specs.appRequestRefreshRateRange.min).isEqualTo(appRequestMin);
+        Truth.assertThat(specs.appRequestRefreshRateRange.max).isEqualTo(appRequestMax);
+    }
+
+    @Test
+    public void testSpecsFromRefreshRateSettings() {
+        // Confirm that, with varying settings for min, peak, and default refresh rate,
+        // DesiredDisplayModeSpecs is calculated correctly.
+        float[] refreshRates = {30.f, 60.f, 90.f, 120.f, 150.f};
+        DisplayModeDirector director =
+                createDirectorFromRefreshRateArray(refreshRates, /*baseModeId=*/0);
+
+        float inf = Float.POSITIVE_INFINITY;
+        verifySpecsWithRefreshRateSettings(director, 0, 0, 0, 0, inf, 0, inf);
+        verifySpecsWithRefreshRateSettings(director, 0, 0, 90, 0, 90, 0, inf);
+        verifySpecsWithRefreshRateSettings(director, 0, 90, 0, 0, 90, 0, 90);
+        verifySpecsWithRefreshRateSettings(director, 0, 90, 60, 0, 60, 0, 90);
+        verifySpecsWithRefreshRateSettings(director, 0, 90, 120, 0, 90, 0, 90);
+        verifySpecsWithRefreshRateSettings(director, 90, 0, 0, 90, inf, 0, inf);
+        verifySpecsWithRefreshRateSettings(director, 90, 0, 120, 90, 120, 0, inf);
+        verifySpecsWithRefreshRateSettings(director, 90, 0, 60, 90, inf, 0, inf);
+        verifySpecsWithRefreshRateSettings(director, 90, 120, 0, 90, 120, 0, 120);
+        verifySpecsWithRefreshRateSettings(director, 90, 60, 0, 90, 90, 0, 90);
+        verifySpecsWithRefreshRateSettings(director, 60, 120, 90, 60, 90, 0, 120);
+    }
+
+    void verifyBrightnessObserverCall(DisplayModeDirector director, float minFps, float peakFps,
+            float defaultFps, float brightnessObserverMin, float brightnessObserverMax) {
+        BrightnessObserver brightnessObserver = Mockito.mock(BrightnessObserver.class);
+        director.injectBrightnessObserver(brightnessObserver);
+        director.getDesiredDisplayModeSpecsWithInjectedFpsSettings(minFps, peakFps, defaultFps);
+        verify(brightnessObserver)
+                .onRefreshRateSettingChangedLocked(brightnessObserverMin, brightnessObserverMax);
+    }
+
+    @Test
+    public void testBrightnessObserverCallWithRefreshRateSettings() {
+        // Confirm that, with varying settings for min, peak, and default refresh rate, we make the
+        // correct call to the brightness observer.
+        float[] refreshRates = {60.f, 90.f, 120.f};
+        DisplayModeDirector director =
+                createDirectorFromRefreshRateArray(refreshRates, /*baseModeId=*/0);
+        verifyBrightnessObserverCall(director, 0, 0, 0, 0, 0);
+        verifyBrightnessObserverCall(director, 0, 0, 90, 0, 90);
+        verifyBrightnessObserverCall(director, 0, 90, 0, 0, 90);
+        verifyBrightnessObserverCall(director, 0, 90, 60, 0, 60);
+        verifyBrightnessObserverCall(director, 90, 90, 0, 90, 90);
+        verifyBrightnessObserverCall(director, 120, 90, 0, 120, 90);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/people/data/UsageStatsQueryHelperTest.java b/services/tests/servicestests/src/com/android/server/people/data/UsageStatsQueryHelperTest.java
index 03d9ad5..30ff119 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/UsageStatsQueryHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/UsageStatsQueryHelperTest.java
@@ -34,6 +34,7 @@
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.Context;
 import android.content.LocusId;
+import android.util.ArrayMap;
 
 import androidx.test.InstrumentationRegistry;
 
@@ -196,39 +197,42 @@
     }
 
     @Test
-    public void testQueryAppLaunchCount() {
-
-        UsageStats packageStats1 = createUsageStats(PKG_NAME_1, 2);
-        UsageStats packageStats2 = createUsageStats(PKG_NAME_1, 3);
-        UsageStats packageStats3 = createUsageStats(PKG_NAME_2, 1);
+    public void testQueryAppUsageStats() {
+        UsageStats packageStats1 = createUsageStats(PKG_NAME_1, 2, createDummyChooserCounts());
+        UsageStats packageStats2 = createUsageStats(PKG_NAME_1, 3, null);
+        UsageStats packageStats3 = createUsageStats(PKG_NAME_2, 1, createDummyChooserCounts());
         when(mUsageStatsManagerInternal.queryUsageStatsForUser(anyInt(), anyInt(), anyLong(),
                 anyLong(), anyBoolean())).thenReturn(
                 List.of(packageStats1, packageStats2, packageStats3));
 
-        Map<String, Integer> appLaunchCounts = mHelper.queryAppLaunchCount(USER_ID_PRIMARY, 90_000L,
-                200_000L, Set.of(PKG_NAME_1, PKG_NAME_2));
+        Map<String, AppUsageStatsData> appLaunchChooserCountCounts =
+                mHelper.queryAppUsageStats(USER_ID_PRIMARY, 90_000L,
+                        200_000L, Set.of(PKG_NAME_1, PKG_NAME_2));
 
-        assertEquals(2, appLaunchCounts.size());
-        assertEquals(5, (long) appLaunchCounts.get(PKG_NAME_1));
-        assertEquals(1, (long) appLaunchCounts.get(PKG_NAME_2));
+        assertEquals(2, appLaunchChooserCountCounts.size());
+        assertEquals(4, (long) appLaunchChooserCountCounts.get(PKG_NAME_1).getChosenCount());
+        assertEquals(5, (long) appLaunchChooserCountCounts.get(PKG_NAME_1).getLaunchCount());
+        assertEquals(4, (long) appLaunchChooserCountCounts.get(PKG_NAME_2).getChosenCount());
+        assertEquals(1, (long) appLaunchChooserCountCounts.get(PKG_NAME_2).getLaunchCount());
     }
 
     @Test
-    public void testQueryAppLaunchCount_packageNameFiltered() {
-
-        UsageStats packageStats1 = createUsageStats(PKG_NAME_1, 2);
-        UsageStats packageStats2 = createUsageStats(PKG_NAME_1, 3);
-        UsageStats packageStats3 = createUsageStats(PKG_NAME_2, 1);
+    public void testQueryAppUsageStats_packageNameFiltered() {
+        UsageStats packageStats1 = createUsageStats(PKG_NAME_1, 2, createDummyChooserCounts());
+        UsageStats packageStats2 = createUsageStats(PKG_NAME_1, 3, createDummyChooserCounts());
+        UsageStats packageStats3 = createUsageStats(PKG_NAME_2, 1, null);
         when(mUsageStatsManagerInternal.queryUsageStatsForUser(anyInt(), anyInt(), anyLong(),
                 anyLong(), anyBoolean())).thenReturn(
                 List.of(packageStats1, packageStats2, packageStats3));
 
-        Map<String, Integer> appLaunchCounts = mHelper.queryAppLaunchCount(USER_ID_PRIMARY, 90_000L,
-                200_000L,
-                Set.of(PKG_NAME_1));
+        Map<String, AppUsageStatsData> appLaunchChooserCountCounts =
+                mHelper.queryAppUsageStats(USER_ID_PRIMARY, 90_000L,
+                        200_000L,
+                        Set.of(PKG_NAME_1));
 
-        assertEquals(1, appLaunchCounts.size());
-        assertEquals(5, (long) appLaunchCounts.get(PKG_NAME_1));
+        assertEquals(1, appLaunchChooserCountCounts.size());
+        assertEquals(8, (long) appLaunchChooserCountCounts.get(PKG_NAME_1).getChosenCount());
+        assertEquals(5, (long) appLaunchChooserCountCounts.get(PKG_NAME_1).getLaunchCount());
     }
 
     private void addUsageEvents(UsageEvents.Event... events) {
@@ -237,13 +241,27 @@
                 anyInt())).thenReturn(usageEvents);
     }
 
-    private static UsageStats createUsageStats(String packageName, int launchCount) {
+    private static UsageStats createUsageStats(String packageName, int launchCount,
+            ArrayMap<String, ArrayMap<String, Integer>> chooserCounts) {
         UsageStats packageStats = new UsageStats();
         packageStats.mPackageName = packageName;
         packageStats.mAppLaunchCount = launchCount;
+        packageStats.mChooserCounts = chooserCounts;
         return packageStats;
     }
 
+    private static ArrayMap<String, ArrayMap<String, Integer>> createDummyChooserCounts() {
+        ArrayMap<String, ArrayMap<String, Integer>> chooserCounts = new ArrayMap<>();
+        ArrayMap<String, Integer> counts1 = new ArrayMap<>();
+        counts1.put("text", 2);
+        counts1.put("image", 1);
+        chooserCounts.put("intent1", counts1);
+        ArrayMap<String, Integer> counts2 = new ArrayMap<>();
+        counts2.put("video", 1);
+        chooserCounts.put("intent2", counts2);
+        return chooserCounts;
+    }
+
     private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
         LocalServices.removeServiceForTest(clazz);
         LocalServices.addService(clazz, mock);
diff --git a/services/tests/servicestests/src/com/android/server/people/prediction/SharesheetModelScorerTest.java b/services/tests/servicestests/src/com/android/server/people/prediction/SharesheetModelScorerTest.java
index 9fc1776..45fff48 100644
--- a/services/tests/servicestests/src/com/android/server/people/prediction/SharesheetModelScorerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/prediction/SharesheetModelScorerTest.java
@@ -31,6 +31,7 @@
 import android.os.UserHandle;
 import android.util.Range;
 
+import com.android.server.people.data.AppUsageStatsData;
 import com.android.server.people.data.DataManager;
 import com.android.server.people.data.Event;
 import com.android.server.people.data.EventHistory;
@@ -257,6 +258,39 @@
     }
 
     @Test
+    public void testComputeScoreForAppShare_promoteFrequentlyChosenApps() {
+        when(mEventHistory1.getEventIndex(anySet())).thenReturn(mEventIndex1);
+        when(mEventHistory2.getEventIndex(anySet())).thenReturn(mEventIndex2);
+        when(mEventHistory3.getEventIndex(anySet())).thenReturn(mEventIndex3);
+        when(mEventHistory4.getEventIndex(anySet())).thenReturn(mEventIndex4);
+        when(mEventHistory5.getEventIndex(anySet())).thenReturn(mEventIndex5);
+        when(mEventHistory1.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex6);
+        when(mEventHistory2.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex7);
+        when(mEventHistory3.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex8);
+        when(mEventHistory4.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex9);
+        when(mEventHistory5.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex10);
+        when(mDataManager.queryAppUsageStats(anyInt(), anyLong(), anyLong(), anySet()))
+                .thenReturn(
+                        Map.of(PACKAGE_1, new AppUsageStatsData(1, 0),
+                                PACKAGE_2, new AppUsageStatsData(2, 0),
+                                PACKAGE_3, new AppUsageStatsData(3, 0)));
+
+        SharesheetModelScorer.computeScoreForAppShare(
+                List.of(mShareTarget1, mShareTarget2, mShareTarget3, mShareTarget4, mShareTarget5,
+                        mShareTarget6),
+                Event.TYPE_SHARE_TEXT, 20, NOW, mDataManager, USER_ID);
+
+        verify(mDataManager, times(1)).queryAppUsageStats(anyInt(), anyLong(), anyLong(),
+                anySet());
+        assertEquals(0.9f, mShareTarget5.getScore(), DELTA);
+        assertEquals(0.6f, mShareTarget3.getScore(), DELTA);
+        assertEquals(0.3f, mShareTarget1.getScore(), DELTA);
+        assertEquals(0f, mShareTarget2.getScore(), DELTA);
+        assertEquals(0f, mShareTarget4.getScore(), DELTA);
+        assertEquals(0f, mShareTarget6.getScore(), DELTA);
+    }
+
+    @Test
     public void testComputeScoreForAppShare_promoteFrequentlyUsedApps() {
         when(mEventHistory1.getEventIndex(anySet())).thenReturn(mEventIndex1);
         when(mEventHistory2.getEventIndex(anySet())).thenReturn(mEventIndex2);
@@ -268,22 +302,22 @@
         when(mEventHistory3.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex8);
         when(mEventHistory4.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex9);
         when(mEventHistory5.getEventIndex(Event.TYPE_SHARE_TEXT)).thenReturn(mEventIndex10);
-        when(mDataManager.queryAppLaunchCount(anyInt(), anyLong(), anyLong(), anySet()))
+        when(mDataManager.queryAppUsageStats(anyInt(), anyLong(), anyLong(), anySet()))
                 .thenReturn(
-                        Map.of(PACKAGE_1, 1,
-                                PACKAGE_2, 2,
-                                PACKAGE_3, 3));
+                        Map.of(PACKAGE_1, new AppUsageStatsData(0, 1),
+                                PACKAGE_2, new AppUsageStatsData(0, 2),
+                                PACKAGE_3, new AppUsageStatsData(1, 0)));
 
         SharesheetModelScorer.computeScoreForAppShare(
                 List.of(mShareTarget1, mShareTarget2, mShareTarget3, mShareTarget4, mShareTarget5,
                         mShareTarget6),
                 Event.TYPE_SHARE_TEXT, 20, NOW, mDataManager, USER_ID);
 
-        verify(mDataManager, times(1)).queryAppLaunchCount(anyInt(), anyLong(), anyLong(),
+        verify(mDataManager, times(1)).queryAppUsageStats(anyInt(), anyLong(), anyLong(),
                 anySet());
-        assertEquals(0.3f, mShareTarget5.getScore(), DELTA);
+        assertEquals(0.9f, mShareTarget5.getScore(), DELTA);
         assertEquals(0.27f, mShareTarget3.getScore(), DELTA);
-        assertEquals(0.243f, mShareTarget1.getScore(), DELTA);
+        assertEquals(0.135f, mShareTarget1.getScore(), DELTA);
         assertEquals(0f, mShareTarget2.getScore(), DELTA);
         assertEquals(0f, mShareTarget4.getScore(), DELTA);
         assertEquals(0f, mShareTarget6.getScore(), DELTA);
@@ -306,18 +340,19 @@
         when(mEventIndex3.getMostRecentActiveTimeSlot()).thenReturn(FIVE_DAYS_AGO);
         when(mEventIndex4.getMostRecentActiveTimeSlot()).thenReturn(EIGHT_DAYS_AGO);
         when(mEventIndex5.getMostRecentActiveTimeSlot()).thenReturn(null);
-        when(mDataManager.queryAppLaunchCount(anyInt(), anyLong(), anyLong(), anySet()))
+        when(mDataManager.queryAppUsageStats(anyInt(), anyLong(), anyLong(), anySet()))
                 .thenReturn(
-                        Map.of(PACKAGE_1, 1,
-                                PACKAGE_2, 2,
-                                PACKAGE_3, 3));
+                        Map.of(PACKAGE_1, new AppUsageStatsData(0, 1),
+                                PACKAGE_2, new AppUsageStatsData(0, 2),
+                                PACKAGE_3, new AppUsageStatsData(1, 0)));
 
         SharesheetModelScorer.computeScoreForAppShare(
                 List.of(mShareTarget1, mShareTarget2, mShareTarget3, mShareTarget4, mShareTarget5,
                         mShareTarget6),
                 Event.TYPE_SHARE_TEXT, 4, NOW, mDataManager, USER_ID);
 
-        verify(mDataManager, never()).queryAppLaunchCount(anyInt(), anyLong(), anyLong(), anySet());
+        verify(mDataManager, never()).queryAppUsageStats(anyInt(), anyLong(), anyLong(),
+                anySet());
         assertEquals(0.4f, mShareTarget1.getScore(), DELTA);
         assertEquals(0.35f, mShareTarget2.getScore(), DELTA);
         assertEquals(0.33f, mShareTarget3.getScore(), DELTA);
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 6a88298..e4acdfe 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -720,6 +720,8 @@
 
     protected static final long INTERVAL = 10000;
 
+    // This doesn't need to match the max shortcuts limit in the framework, and tests should either
+    // use this or set their own limit for testing, without assuming any particular max value.
     protected static final int MAX_SHORTCUTS = 10;
 
     protected static final int MAX_UPDATES_PER_INTERVAL = 3;
diff --git a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
index e79b5af..a2393a8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
@@ -32,8 +32,10 @@
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.permission.PermissionManager;
 import android.platform.test.annotations.Presubmit;
 import android.util.SparseArray;
 
@@ -692,5 +694,17 @@
                 String permission, int uid, int owningUid, boolean exported) {
             return ActivityManager.checkComponentPermission(permission, uid, owningUid, exported);
         }
+
+        @Override
+        public void killUid(String packageName, int uid) {
+            try {
+                ActivityManager.getService().killApplication(
+                        packageName,
+                        UserHandle.getAppId(uid),
+                        UserHandle.getUserId(uid),
+                        PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED);
+            } catch (RemoteException ignored) {
+            }
+        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index efa25bd..db02524 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -234,7 +234,7 @@
         assertEquals(ShortcutService.DEFAULT_RESET_INTERVAL_SEC * 1000,
                 mService.getResetIntervalForTest());
 
-        assertEquals(ShortcutService.DEFAULT_MAX_SHORTCUTS_PER_APP,
+        assertEquals(ShortcutService.DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY,
                 mService.getMaxShortcutsForTest());
 
         assertEquals(ShortcutService.DEFAULT_MAX_UPDATES_PER_INTERVAL,
@@ -393,6 +393,8 @@
     }
 
     public void testPushDynamicShortcut() {
+        // Change the max number of shortcuts.
+        mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=5");
 
         setCaller(CALLING_PACKAGE_1, USER_0);
 
@@ -400,12 +402,11 @@
         final ShortcutInfo s2 = makeShortcut("s2");
         final ShortcutInfo s3 = makeShortcut("s3");
         final ShortcutInfo s4 = makeShortcut("s4");
-
-        final ShortcutInfo s10 = makeShortcut("s10");
-        final ShortcutInfo s11 = makeShortcut("s11");
-        final ShortcutInfo s12 = makeShortcut("s12");
-        final ShortcutInfo s13 = makeShortcut("s13");
-        final ShortcutInfo s14 = makeShortcut("s14");
+        final ShortcutInfo s5 = makeShortcut("s5");
+        final ShortcutInfo s6 = makeShortcut("s6");
+        final ShortcutInfo s7 = makeShortcut("s7");
+        final ShortcutInfo s8 = makeShortcut("s8");
+        final ShortcutInfo s9 = makeShortcut("s9");
 
         // Test push as first shortcut
         mManager.pushDynamicShortcut(s1);
@@ -440,63 +441,61 @@
         mInjectedCurrentTimeMillis += INTERVAL; // reset
 
         // Test push as last
-        assertTrue(mManager.addDynamicShortcuts(makeShortcuts("s5", "s6", "s7", "s8", "s9")));
-        mManager.pushDynamicShortcut(s10);
+        mManager.pushDynamicShortcut(s5);
         assertShortcutIds(assertAllNotKeyFieldsOnly(mManager.getDynamicShortcuts()),
-                "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10");
-        assertEquals(0, getCallerShortcut("s10").getRank());
-        assertEquals(1, getCallerShortcut("s5").getRank());
-        assertEquals(6, getCallerShortcut("s3").getRank());
-        assertEquals(7, getCallerShortcut("s1").getRank());
-        assertEquals(8, getCallerShortcut("s2").getRank());
-        assertEquals(9, getCallerShortcut("s4").getRank());
+                "s1", "s2", "s3", "s4", "s5");
+        assertEquals(0, getCallerShortcut("s5").getRank());
+        assertEquals(1, getCallerShortcut("s3").getRank());
+        assertEquals(2, getCallerShortcut("s1").getRank());
+        assertEquals(3, getCallerShortcut("s2").getRank());
+        assertEquals(4, getCallerShortcut("s4").getRank());
 
         // Push when max has already reached
-        mManager.pushDynamicShortcut(s11);
+        mManager.pushDynamicShortcut(s6);
         assertShortcutIds(assertAllNotKeyFieldsOnly(mManager.getDynamicShortcuts()),
-                "s1", "s2", "s3", "s5", "s6", "s7", "s8", "s9", "s10", "s11");
-        assertEquals(0, getCallerShortcut("s11").getRank());
-        assertEquals(1, getCallerShortcut("s10").getRank());
-        assertEquals(9, getCallerShortcut("s2").getRank());
+                "s1", "s2", "s3", "s5", "s6");
+        assertEquals(0, getCallerShortcut("s6").getRank());
+        assertEquals(1, getCallerShortcut("s5").getRank());
+        assertEquals(4, getCallerShortcut("s2").getRank());
 
         mInjectedCurrentTimeMillis += INTERVAL; // reset
 
         // Push with different activity
-        s12.setActivity(makeComponent(ShortcutActivity2.class));
-        mManager.pushDynamicShortcut(s12);
+        s7.setActivity(makeComponent(ShortcutActivity2.class));
+        mManager.pushDynamicShortcut(s7);
         assertEquals(makeComponent(ShortcutActivity2.class),
-                getCallerShortcut("s12").getActivity());
-        assertEquals(0, getCallerShortcut("s12").getRank());
+                getCallerShortcut("s7").getActivity());
+        assertEquals(0, getCallerShortcut("s7").getRank());
 
         // Push to update shortcut with different activity
         final ShortcutInfo s1_2 = makeShortcut("s1");
         s1_2.setActivity(makeComponent(ShortcutActivity2.class));
         s1_2.setRank(1);
         mManager.pushDynamicShortcut(s1_2);
-        assertEquals(0, getCallerShortcut("s12").getRank());
+        assertEquals(0, getCallerShortcut("s7").getRank());
         assertEquals(1, getCallerShortcut("s1").getRank());
-        assertEquals(0, getCallerShortcut("s11").getRank());
-        assertEquals(1, getCallerShortcut("s10").getRank());
-        assertEquals(7, getCallerShortcut("s3").getRank());
-        assertEquals(8, getCallerShortcut("s2").getRank());
+        assertEquals(0, getCallerShortcut("s6").getRank());
+        assertEquals(1, getCallerShortcut("s5").getRank());
+        assertEquals(2, getCallerShortcut("s3").getRank());
+        assertEquals(3, getCallerShortcut("s2").getRank());
 
         mInjectedCurrentTimeMillis += INTERVAL; // reset
 
         // Test push when dropped shortcut is cached
-        s13.setLongLived();
-        s13.setRank(100);
-        mManager.pushDynamicShortcut(s13);
-        assertEquals(9, getCallerShortcut("s13").getRank());
+        s8.setLongLived();
+        s8.setRank(100);
+        mManager.pushDynamicShortcut(s8);
+        assertEquals(4, getCallerShortcut("s8").getRank());
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s13"), HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s8"), HANDLE_USER_0);
         });
 
-        mManager.pushDynamicShortcut(s14);
+        mManager.pushDynamicShortcut(s9);
         assertShortcutIds(assertAllNotKeyFieldsOnly(mManager.getDynamicShortcuts()),
-                "s1", "s2", "s3", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "s12", "s14");
+                "s1", "s2", "s3", "s5", "s6", "s7", "s9");
         // Verify s13 stayed as cached
         assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
-                "s13");
+                "s8");
     }
 
     public void testUnlimitedCalls() {
@@ -1582,6 +1581,41 @@
                 "s2");
     }
 
+    public void testCachedShortcuts_canPassShortcutLimit() {
+        // Change the max number of shortcuts.
+        mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=4");
+
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(makeLongLivedShortcut("s1"),
+                    makeLongLivedShortcut("s2"), makeLongLivedShortcut("s3"),
+                    makeLongLivedShortcut("s4"))));
+        });
+
+        // Cache All
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2", "s3", "s4"),
+                    HANDLE_USER_0);
+        });
+
+        setCaller(CALLING_PACKAGE_1);
+
+        // Get dynamic shortcuts
+        assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_DYNAMIC),
+                "s1", "s2", "s3", "s4");
+        // Get cached shortcuts
+        assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
+                "s1", "s2", "s3", "s4");
+
+        assertTrue(mManager.setDynamicShortcuts(makeShortcuts("sx1", "sx2", "sx3", "sx4")));
+
+        // Get dynamic shortcuts
+        assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_DYNAMIC),
+                "sx1", "sx2", "sx3", "sx4");
+        // Get cached shortcuts
+        assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
+                "s1", "s2", "s3", "s4");
+    }
+
     // === Test for launcher side APIs ===
 
     public void testGetShortcuts() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java
index 50d290a..6219665 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java
@@ -30,6 +30,8 @@
 import android.content.pm.ShortcutInfo;
 import android.os.test.TestLooper;
 
+import com.android.server.pm.ShortcutService.ConfigConstants;
+
 import org.mockito.ArgumentCaptor;
 
 import java.util.List;
@@ -372,9 +374,11 @@
     }
 
     public void testShortcutChangeCallback_pushDynamicShortcut_existingId() {
+        // Change the max number of shortcuts.
+        mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
+
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertTrue(mManager.setDynamicShortcuts((makeShortcuts("s1", "s2", "s3", "s4", "s5",
-                    "s6", "s7", "s8", "s9", "s10"))));
+            assertTrue(mManager.setDynamicShortcuts((makeShortcuts("s1", "s2", "s3"))));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
@@ -384,7 +388,7 @@
         });
 
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            mManager.pushDynamicShortcut(makeShortcut("s5"));
+            mManager.pushDynamicShortcut(makeShortcut("s2"));
         });
 
         mTestLooper.dispatchAll();
@@ -396,13 +400,15 @@
 
         assertWith(shortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
-                .haveIds("s5");
+                .haveIds("s2");
     }
 
     public void testShortcutChangeCallback_pushDynamicShortcut_causeDeletion() {
+        // Change the max number of shortcuts.
+        mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
+
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertTrue(mManager.setDynamicShortcuts((makeShortcuts("s1", "s2", "s3", "s4", "s5",
-                    "s6", "s7", "s8", "s9", "s10"))));
+            assertTrue(mManager.setDynamicShortcuts((makeShortcuts("s1", "s2", "s3"))));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
@@ -412,7 +418,7 @@
         });
 
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            mManager.pushDynamicShortcut(makeShortcut("s11"));
+            mManager.pushDynamicShortcut(makeShortcut("s4"));
         });
 
         mTestLooper.dispatchAll();
@@ -427,31 +433,33 @@
 
         assertWith(changedShortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
-                .haveIds("s11");
+                .haveIds("s4");
 
         assertWith(removedShortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
-                .haveIds("s10");
+                .haveIds("s3");
     }
 
     public void testShortcutChangeCallback_pushDynamicShortcut_causeDeletionButCached() {
+        // Change the max number of shortcuts.
+        mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
+
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertTrue(mManager.setDynamicShortcuts((makeShortcuts("s1", "s2", "s3", "s4", "s5",
-                    "s6", "s7", "s8", "s9"))));
-            ShortcutInfo s10 = makeLongLivedShortcut("s10");
-            s10.setRank(10);
-            mManager.pushDynamicShortcut(s10);  // Add a long lived shortcut to the end of the list.
+            assertTrue(mManager.setDynamicShortcuts((makeShortcuts("s1", "s2"))));
+            ShortcutInfo s3 = makeLongLivedShortcut("s3");
+            s3.setRank(3);
+            mManager.pushDynamicShortcut(s3);  // Add a long lived shortcut to the end of the list.
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s10"), HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            mManager.pushDynamicShortcut(makeShortcut("s11"));
+            mManager.pushDynamicShortcut(makeShortcut("s4"));
         });
 
         mTestLooper.dispatchAll();
@@ -463,7 +471,7 @@
 
         assertWith(shortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
-                .haveIds("s10", "s11");
+                .haveIds("s3", "s4");
     }
 
     public void testShortcutChangeCallback_disableShortcuts() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
index d136614..6c1c019 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -22,10 +22,14 @@
 import android.os.Parcelable;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.support.test.uiautomator.UiDevice;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
 import android.util.AtomicFile;
 
+import androidx.test.InstrumentationRegistry;
+
 import java.io.File;
 import java.io.IOException;
 import java.util.Arrays;
@@ -74,6 +78,14 @@
         assertEquals(accountName, um.getUserAccount(tempUserId));
     }
 
+    public void testUserSystemPackageWhitelist() throws Exception {
+        String cmd = "cmd user report-system-user-package-whitelist-problems --critical-only";
+        final String result = runShellCommand(cmd);
+        if (!TextUtils.isEmpty(result)) {
+            fail("Command '" + cmd + " reported errors:\n" + result);
+        }
+    }
+
     private Bundle createBundle() {
         Bundle result = new Bundle();
         // Tests for 6 allowed types: Integer, Boolean, String, String[], Bundle and Parcelable[]
@@ -118,4 +130,8 @@
         assertEquals(1, childBundle.getInt("bundle_int"));
     }
 
+    private static String runShellCommand(String cmd) throws Exception {
+        return UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+                .executeShellCommand(cmd);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
index 086c845..0f028f0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
@@ -23,7 +23,6 @@
 import android.content.pm.FeatureInfo
 import android.content.pm.InstrumentationInfo
 import android.content.pm.PackageInfo
-import android.content.pm.PackageManager
 import android.content.pm.PackageParser
 import android.content.pm.PackageUserState
 import android.content.pm.PermissionInfo
@@ -38,7 +37,6 @@
 import com.android.server.pm.pkg.PackageStateUnserialized
 import com.android.server.testutils.mockThrowOnUnmocked
 import com.android.server.testutils.whenever
-import org.junit.After
 import org.junit.BeforeClass
 import org.mockito.Mockito
 import org.mockito.Mockito.anyInt
@@ -49,7 +47,7 @@
 
     companion object {
 
-        private const val VERIFY_ALL_APKS = true
+        private const val VERIFY_ALL_APKS = false
 
         /** For auditing memory usage differences */
         private const val DUMP_HPROF_TO_EXTERNAL = false
@@ -93,21 +91,25 @@
 
         lateinit var newPackages: List<AndroidPackage>
 
-        private val thrownInSetUp = mutableListOf<Throwable>()
-
         @Suppress("ConstantConditionIf")
         @JvmStatic
         @BeforeClass
         fun setUpPackages() {
             this.oldPackages = apks.mapNotNull {
-                tryOrNull {
+                try {
                     packageParser.parsePackage(it, PackageParser.PARSE_IS_SYSTEM_DIR, false)
+                } catch (ignored: Exception) {
+                    // Parsing issues will be caught by SystemPartitionParseTest
+                    null
                 }
             }
 
             this.newPackages = apks.mapNotNull {
-                tryOrNull {
+                try {
                     packageParser2.parsePackage(it, PackageParser.PARSE_IS_SYSTEM_DIR, false)
+                } catch (ignored: Exception) {
+                    // Parsing issues will be caught by SystemPartitionParseTest
+                    null
                 }
             }
 
@@ -144,41 +146,6 @@
             this.pkg = aPkg
             whenever(pkgState) { PackageStateUnserialized() }
         }
-
-        private fun <T> tryOrNull(block: () -> T) = try {
-            block()
-        } catch (e: PackageParser.PackageParserException) {
-            if (e.error != PackageManager.INSTALL_PARSE_FAILED_SKIPPED) {
-                thrownInSetUp.add(e)
-            }
-            null
-        } catch (t: Throwable) {
-            thrownInSetUp.add(t)
-            null
-        }
-    }
-
-    @After
-    fun verifySetUpPackages() {
-        if (thrownInSetUp.isEmpty()) return
-        val exception = AssertionError("setUpPackages failed with ${thrownInSetUp.size} errors:\n" +
-                thrownInSetUp.joinToString(separator = "\n") { it.message.orEmpty() })
-
-        /*
-            Testing infrastructure doesn't currently support errors thrown in @AfterClass,
-            so instead it's thrown here. But to avoid throwing a massive repeated stack for every
-            test method, only throw on the first method run in the class, clearing the list so that
-            subsequent methods can run without failing. Doing this in @After lets true method
-            failures propagate, as those should throw before this does.
-
-            This will cause the failure to be attached to a different method depending on run order,
-            which could make comparisons difficult. So if a failure points here, it's worth
-            checking failures for all methods in all subclasses.
-
-            TODO: When infrastructure supports @AfterClass errors, move this
-        */
-        thrownInSetUp.clear()
-        throw exception
     }
 
     // The following methods dump an exact set of fields from the object to compare, because
@@ -285,7 +252,8 @@
             secondaryCpuAbi=${this.secondaryCpuAbi}
             secondaryNativeLibraryDir=${this.secondaryNativeLibraryDir}
             sourceDir=${this.sourceDir}
-            splitDependencies=${this.splitDependencies.sequence().map { it.first to it.second?.contentToString() }.joinToString()}
+            splitDependencies=${this.splitDependencies.sequence()
+            .map { it.first to it.second?.contentToString() }.joinToString()}
             splitNames=${this.splitNames?.contentToString()}
             splitPublicSourceDirs=${this.splitPublicSourceDirs?.contentToString()}
             splitSourceDirs=${this.splitSourceDirs?.contentToString()}
@@ -348,7 +316,9 @@
             initOrder=${this.initOrder}
             isSyncable=${this.isSyncable}
             multiprocess=${this.multiprocess}
-            pathPermissions=${this.pathPermissions?.joinToString { "readPermission=${it.readPermission}\nwritePermission=${it.writePermission}" }}
+            pathPermissions=${this.pathPermissions?.joinToString {
+        "readPermission=${it.readPermission}\nwritePermission=${it.writePermission}"
+    }}
             readPermission=${this.readPermission}
             uriPermissionPatterns=${this.uriPermissionPatterns?.contentToString()}
             writePermission=${this.writePermission}
@@ -370,7 +340,9 @@
             compileSdkVersionCodename=${this.compileSdkVersionCodename}
             configPreferences=${this.configPreferences?.joinToString { it.dumpToString() }}
             coreApp=${this.coreApp}
-            featureGroups=${this.featureGroups?.joinToString { it.features?.joinToString { featureInfo -> featureInfo.dumpToString() }.orEmpty() }}
+            featureGroups=${this.featureGroups?.joinToString {
+        it.features?.joinToString { featureInfo -> featureInfo.dumpToString() }.orEmpty()
+    }}
             firstInstallTime=${this.firstInstallTime}
             gids=${gids?.contentToString()}
             installLocation=${this.installLocation}
@@ -396,7 +368,8 @@
             sharedUserId=${this.sharedUserId}
             sharedUserLabel=${this.sharedUserLabel}
             signatures=${this.signatures?.joinToString { it.toCharsString() }}
-            signingInfo=${this.signingInfo?.signingCertificateHistory?.joinToString { it.toCharsString() }.orEmpty()}
+            signingInfo=${this.signingInfo?.signingCertificateHistory
+            ?.joinToString { it.toCharsString() }.orEmpty()}
             splitNames=${this.splitNames?.contentToString()}
             splitRevisionCodes=${this.splitRevisionCodes?.contentToString()}
             targetOverlayableName=${this.targetOverlayableName}
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/SystemPartitionParseTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/SystemPartitionParseTest.kt
new file mode 100644
index 0000000..605841d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/SystemPartitionParseTest.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.parsing
+
+import android.content.pm.PackageManager
+import android.content.pm.PackageParser
+import android.platform.test.annotations.Postsubmit
+import com.android.server.pm.PackageManagerService
+import org.junit.Test
+
+/**
+ * This test parses all the system APKs on the device image to ensure that they succeed.
+ *
+ * Any invalid APKs should be removed from the device or marked as skipped through any mechanism
+ * for ignoring packages.
+ *
+ * This test must run on deferred postsubmit. Targeted presubmit will not catch errors fast enough,
+ * and the low failure rate does not warrant global presubmit.
+ */
+@Postsubmit
+class SystemPartitionParseTest {
+
+    private val APKS = PackageManagerService.SYSTEM_PARTITIONS
+            .flatMap { listOfNotNull(it.appFolder, it.privAppFolder, it.overlayFolder) }
+            .flatMap {
+                it.walkTopDown()
+                        .filter { it.name.endsWith(".apk") }
+                        .toList()
+            }
+            .distinct()
+
+    private val parser = PackageParser2.forParsingFileWithDefaults()
+
+    @Test
+    fun verify() {
+        val exceptions = APKS
+                .map {
+                    runCatching {
+                        parser.parsePackage(it, PackageParser.PARSE_IS_SYSTEM_DIR, false)
+                    }
+                }
+                .mapNotNull { it.exceptionOrNull() }
+                .filterNot { (it as? PackageParser.PackageParserException)?.error ==
+                        PackageManager.INSTALL_PARSE_FAILED_SKIPPED }
+
+        if (exceptions.isEmpty()) return
+
+        throw AssertionError("verify failed with ${exceptions.size} errors:\n" +
+                exceptions.joinToString(separator = "\n") { it.message.orEmpty() })
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 48e22f6..2d45f9e 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -63,6 +63,7 @@
 import android.appwidget.AppWidgetManager;
 import android.content.Context;
 import android.content.ContextWrapper;
+import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -107,6 +108,10 @@
     private static final int UID_1 = 10000;
     private static final String PACKAGE_EXEMPTED_1 = "com.android.exempted";
     private static final int UID_EXEMPTED_1 = 10001;
+    private static final String PACKAGE_SYSTEM_HEADFULL = "com.example.system.headfull";
+    private static final int UID_SYSTEM_HEADFULL = 10002;
+    private static final String PACKAGE_SYSTEM_HEADLESS = "com.example.system.headless";
+    private static final int UID_SYSTEM_HEADLESS = 10003;
     private static final int USER_ID = 0;
     private static final int USER_ID2 = 10;
     private static final UserHandle USER_HANDLE_USER2 = new UserHandle(USER_ID2);
@@ -305,18 +310,33 @@
         pie.packageName = PACKAGE_EXEMPTED_1;
         packages.add(pie);
 
+        PackageInfo pis = new PackageInfo();
+        pis.activities = new ActivityInfo[]{mock(ActivityInfo.class)};
+        pis.applicationInfo = new ApplicationInfo();
+        pis.applicationInfo.uid = UID_SYSTEM_HEADFULL;
+        pis.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+        pis.packageName = PACKAGE_SYSTEM_HEADFULL;
+        packages.add(pis);
+
+        PackageInfo pish = new PackageInfo();
+        pish.applicationInfo = new ApplicationInfo();
+        pish.applicationInfo.uid = UID_SYSTEM_HEADLESS;
+        pish.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+        pish.packageName = PACKAGE_SYSTEM_HEADLESS;
+        packages.add(pish);
+
         doReturn(packages).when(mockPm).getInstalledPackagesAsUser(anyInt(), anyInt());
         try {
-            doReturn(UID_1).when(mockPm).getPackageUidAsUser(eq(PACKAGE_1), anyInt());
-            doReturn(UID_1).when(mockPm).getPackageUidAsUser(eq(PACKAGE_1), anyInt(), anyInt());
-            doReturn(UID_EXEMPTED_1).when(mockPm).getPackageUidAsUser(eq(PACKAGE_EXEMPTED_1),
-                    anyInt());
-            doReturn(UID_EXEMPTED_1).when(mockPm).getPackageUidAsUser(eq(PACKAGE_EXEMPTED_1),
-                    anyInt(), anyInt());
-            doReturn(pi.applicationInfo).when(mockPm).getApplicationInfo(eq(pi.packageName),
-                    anyInt());
-            doReturn(pie.applicationInfo).when(mockPm).getApplicationInfo(eq(pie.packageName),
-                    anyInt());
+            for (int i = 0; i < packages.size(); ++i) {
+                PackageInfo pkg = packages.get(i);
+
+                doReturn(pkg.applicationInfo.uid).when(mockPm)
+                        .getPackageUidAsUser(eq(pkg.packageName), anyInt());
+                doReturn(pkg.applicationInfo.uid).when(mockPm)
+                        .getPackageUidAsUser(eq(pkg.packageName), anyInt(), anyInt());
+                doReturn(pkg.applicationInfo).when(mockPm)
+                        .getApplicationInfo(eq(pkg.packageName), anyInt());
+            }
         } catch (PackageManager.NameNotFoundException nnfe) {}
     }
 
@@ -367,7 +387,7 @@
     @Test
     public void testBoundWidgetPackageExempt() throws Exception {
         assumeTrue(mInjector.getContext().getSystemService(AppWidgetManager.class) != null);
-        assertEquals(STANDBY_BUCKET_EXEMPTED,
+        assertEquals(STANDBY_BUCKET_ACTIVE,
                 mController.getAppStandbyBucket(PACKAGE_EXEMPTED_1, USER_ID,
                         mInjector.mElapsedRealtime, false));
     }
@@ -514,7 +534,11 @@
     }
 
     private void assertBucket(int bucket) {
-        assertEquals(bucket, getStandbyBucket(mController, PACKAGE_1));
+        assertBucket(bucket, PACKAGE_1);
+    }
+
+    private void assertBucket(int bucket, String pkg) {
+        assertEquals(bucket, getStandbyBucket(mController, pkg));
     }
 
     private void assertNotBucket(int bucket) {
@@ -1462,6 +1486,32 @@
         assertBucket(STANDBY_BUCKET_RESTRICTED);
     }
 
+    @Test
+    public void testSystemHeadlessAppElevated() {
+        reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
+        reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime,
+                PACKAGE_SYSTEM_HEADFULL);
+        reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime,
+                PACKAGE_SYSTEM_HEADLESS);
+        mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD;
+
+
+        mController.setAppStandbyBucket(PACKAGE_SYSTEM_HEADFULL, USER_ID, STANDBY_BUCKET_RARE,
+                REASON_MAIN_TIMEOUT);
+        assertBucket(STANDBY_BUCKET_RARE, PACKAGE_SYSTEM_HEADFULL);
+
+        // Make sure headless system apps don't get lowered.
+        mController.setAppStandbyBucket(PACKAGE_SYSTEM_HEADLESS, USER_ID, STANDBY_BUCKET_RARE,
+                REASON_MAIN_TIMEOUT);
+        assertBucket(STANDBY_BUCKET_ACTIVE, PACKAGE_SYSTEM_HEADLESS);
+
+        // Package 1 doesn't have activities and is headless, but is not a system app, so it can
+        // be lowered.
+        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
+                REASON_MAIN_TIMEOUT);
+        assertBucket(STANDBY_BUCKET_RARE, PACKAGE_1);
+    }
+
     private String getAdminAppsStr(int userId) {
         return getAdminAppsStr(userId, mController.getActiveAdminAppsForTest(userId));
     }
diff --git a/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java b/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java
index 5d849c1..2be3f1e8 100644
--- a/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java
@@ -19,6 +19,7 @@
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
 
 import android.app.usage.UsageEvents;
 import android.content.res.Configuration;
@@ -26,9 +27,12 @@
 
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.util.ArrayUtils;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.lang.reflect.Field;
 import java.util.Locale;
 
 @RunWith(AndroidJUnit4.class)
@@ -191,4 +195,27 @@
         assertTrue(intervalStats.events.size() > NUMBER_OF_EVENTS - NUMBER_OF_EVENTS_PER_PACKAGE);
         assertEquals(intervalStats.packageStats.size(), NUMBER_OF_PACKAGES);
     }
+
+    // All fields in this list are defined in IntervalStats and persisted - please ensure they're
+    // defined correctly in both usagestatsservice.proto and usagestatsservice_v2.proto
+    private static final String[] INTERVALSTATS_PERSISTED_FIELDS = {"beginTime", "endTime",
+            "mStringCache", "majorVersion", "minorVersion", "interactiveTracker",
+            "nonInteractiveTracker", "keyguardShownTracker", "keyguardHiddenTracker",
+            "packageStats", "configurations", "activeConfiguration", "events"};
+    // All fields in this list are defined in IntervalStats but not persisted
+    private static final String[] INTERVALSTATS_IGNORED_FIELDS = {"lastTimeSaved",
+            "packageStatsObfuscated", "CURRENT_MAJOR_VERSION", "CURRENT_MINOR_VERSION", "TAG"};
+
+    @Test
+    public void testIntervalStatsFieldsAreKnown() {
+        final IntervalStats stats = new IntervalStats();
+        final Field[] fields = stats.getClass().getDeclaredFields();
+        for (Field field : fields) {
+            if (!(ArrayUtils.contains(INTERVALSTATS_PERSISTED_FIELDS, field.getName())
+                    || ArrayUtils.contains(INTERVALSTATS_IGNORED_FIELDS, field.getName()))) {
+                fail("Found an unknown field: " + field.getName() + ". Please correctly update "
+                        + "either INTERVALSTATS_PERSISTED_FIELDS or INTERVALSTATS_IGNORED_FIELDS.");
+            }
+        }
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 289933e..ced7804 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -6557,7 +6557,7 @@
         when(si.getPackage()).thenReturn(PKG_P);
         when(si.getId()).thenReturn("convo");
         when(si.getUserId()).thenReturn(USER_SYSTEM);
-        when(si.getShortLabel()).thenReturn("Hello");
+        when(si.getLabel()).thenReturn("Hello");
         when(si.isLongLived()).thenReturn(true);
         when(si.isEnabled()).thenReturn(true);
         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
@@ -6591,7 +6591,7 @@
         when(si.getPackage()).thenReturn(PKG_P);
         when(si.getId()).thenReturn("convo");
         when(si.getUserId()).thenReturn(USER_SYSTEM);
-        when(si.getShortLabel()).thenReturn("Hello");
+        when(si.getLabel()).thenReturn("Hello");
         when(si.isLongLived()).thenReturn(false);
         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(Arrays.asList(si));
 
@@ -6650,18 +6650,14 @@
                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
         waitForIdle();
 
-        assertTrue(mBinderService.hasSentMessage(PKG, mUid));
+        assertTrue(mBinderService.isInInvalidMsgState(PKG, mUid));
     }
 
     @Test
     public void testRecordMessages_validMsg() throws RemoteException {
-        // Messaging notification with shortcut info
-        Notification.BubbleMetadata metadata =
-                new Notification.BubbleMetadata.Builder("id").build();
         Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
                 null /* groupKey */, false /* isSummary */);
-        nb.setShortcutId("id");
-        nb.setBubbleMetadata(metadata);
+        nb.setShortcutId(null);
         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
                 "testRecordMessages_validMsg", mUid, 0, nb.build(), new UserHandle(mUid), null, 0);
         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
@@ -6670,7 +6666,43 @@
                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
         waitForIdle();
 
-        assertFalse(mBinderService.hasSentMessage(PKG, mUid));
+        assertTrue(mBinderService.isInInvalidMsgState(PKG, mUid));
+
+        nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
+                "testRecordMessages_validMsg");
+
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
+                nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
+        waitForIdle();
+
+        assertFalse(mBinderService.isInInvalidMsgState(PKG, mUid));
+    }
+
+    @Test
+    public void testRecordMessages_invalidMsg_afterValidMsg() throws RemoteException {
+        NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
+                "testRecordMessages_invalidMsg_afterValidMsg_1");
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
+                nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
+        waitForIdle();
+        assertTrue(mService.getNotificationRecord(nr.getKey()).isConversation());
+
+        mBinderService.cancelAllNotifications(PKG, mUid);
+        waitForIdle();
+
+        Notification.Builder nb = getMessageStyleNotifBuilder(false /* addDefaultMetadata */,
+                null /* groupKey */, false /* isSummary */);
+        nb.setShortcutId(null);
+        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
+                "testRecordMessages_invalidMsg_afterValidMsg_2", mUid, 0, nb.build(),
+                new UserHandle(mUid), null, 0);
+         nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
+                nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
+        waitForIdle();
+
+        assertFalse(mService.getNotificationRecord(nr.getKey()).isConversation());
     }
 
     @Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
index b03596a..6df3c7b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
@@ -1137,6 +1137,26 @@
     }
 
     @Test
+    public void testIsConversation_noShortcut_appHasPreviousSentFullConversation() {
+        StatusBarNotification sbn = getMessagingStyleNotification();
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        record.setShortcutInfo(null);
+        record.setHasSentValidMsg(true);
+
+        assertFalse(record.isConversation());
+    }
+
+    @Test
+    public void testIsConversation_noShortcut_userDemotedApp() {
+        StatusBarNotification sbn = getMessagingStyleNotification();
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        record.setShortcutInfo(null);
+        record.userDemotedAppFromConvoSpace(true);
+
+        assertFalse(record.isConversation());
+    }
+
+    @Test
     public void testIsConversation_noShortcut_targetsR() {
         StatusBarNotification sbn = getMessagingStyleNotification(PKG_R);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 4320f1c..078c21e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -81,6 +81,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Pair;
+import android.util.StatsEvent;
 import android.util.Xml;
 
 import androidx.test.InstrumentationRegistry;
@@ -89,6 +90,7 @@
 import com.android.internal.util.FastXmlSerializer;
 import com.android.server.UiServiceTestCase;
 
+
 import org.json.JSONArray;
 import org.json.JSONObject;
 import org.junit.Before;
@@ -454,7 +456,9 @@
         mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false);
 
         mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true);
-        mHelper.setMessageSent(PKG_P, UID_P);
+        mHelper.setInvalidMessageSent(PKG_P, UID_P);
+        mHelper.setValidMessageSent(PKG_P, UID_P);
+        mHelper.setInvalidMsgAppDemoted(PKG_P, UID_P, true);
 
         mHelper.setImportance(PKG_O, UID_O, IMPORTANCE_NONE);
 
@@ -470,8 +474,10 @@
 
         assertEquals(IMPORTANCE_NONE, mHelper.getImportance(PKG_O, UID_O));
         assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1));
-        assertTrue(mHelper.hasSentMessage(PKG_P, UID_P));
-        assertFalse(mHelper.hasSentMessage(PKG_N_MR1, UID_N_MR1));
+        assertTrue(mHelper.hasSentInvalidMsg(PKG_P, UID_P));
+        assertFalse(mHelper.hasSentInvalidMsg(PKG_N_MR1, UID_N_MR1));
+        assertTrue(mHelper.hasSentValidMsg(PKG_P, UID_P));
+        assertTrue(mHelper.didUserEverDemoteInvalidMsgApp(PKG_P, UID_P));
         assertEquals(channel1,
                 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false));
         compareChannels(channel2,
@@ -2992,6 +2998,31 @@
                 PKG_O, UID_O, parent.getId(), conversationId, false, false), conversationId);
     }
 
+
+    @Test
+    public void testPullConversationNotificationChannel() {
+        String conversationId = "friend";
+
+        NotificationChannel parent =
+                new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false);
+
+        String channelId = String.format(
+                CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), conversationId);
+        NotificationChannel friend = new NotificationChannel(channelId,
+                "messages", IMPORTANCE_DEFAULT);
+        friend.setConversationId(parent.getId(), conversationId);
+        mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false);
+        ArrayList<StatsEvent> events = new ArrayList<>();
+        mHelper.pullPackageChannelPreferencesStats(events);
+        boolean found = false;
+        for (StatsEvent event : events) {
+            // TODO(b/153195691): inspect the content once it is possible to do so
+            found = true;
+        }
+        assertTrue("conversation was not in the pull", found);
+    }
+
     @Test
     public void testGetNotificationChannel_conversationProvidedByNotCustomizedYet() {
         String conversationId = "friend";
@@ -3380,15 +3411,49 @@
     }
 
     @Test
-    public void testMessageSent() {
+    public void testInvalidMessageSent() {
         // create package preferences
         mHelper.canShowBadge(PKG_P, UID_P);
 
         // check default value
-        assertFalse(mHelper.hasSentMessage(PKG_P, UID_P));
+        assertFalse(mHelper.isInInvalidMsgState(PKG_P, UID_P));
 
         // change it
-        mHelper.setMessageSent(PKG_P, UID_P);
-        assertTrue(mHelper.hasSentMessage(PKG_P, UID_P));
+        mHelper.setInvalidMessageSent(PKG_P, UID_P);
+        assertTrue(mHelper.isInInvalidMsgState(PKG_P, UID_P));
+        assertTrue(mHelper.hasSentInvalidMsg(PKG_P, UID_P));
+    }
+
+    @Test
+    public void testValidMessageSent() {
+        // create package preferences
+        mHelper.canShowBadge(PKG_P, UID_P);
+
+        // get into the bad state
+        mHelper.setInvalidMessageSent(PKG_P, UID_P);
+
+        // and then fix it
+        mHelper.setValidMessageSent(PKG_P, UID_P);
+
+        assertTrue(mHelper.hasSentValidMsg(PKG_P, UID_P));
+        assertFalse(mHelper.isInInvalidMsgState(PKG_P, UID_P));
+    }
+
+    @Test
+    public void testUserDemotedInvalidMsgApp() {
+        // create package preferences
+        mHelper.canShowBadge(PKG_P, UID_P);
+
+        // demotion means nothing before msg notif sent
+        mHelper.setInvalidMsgAppDemoted(PKG_P, UID_P, true);
+        assertFalse(mHelper.hasUserDemotedInvalidMsgApp(PKG_P, UID_P));
+
+        // it's valid when incomplete msgs have been sent
+        mHelper.setInvalidMessageSent(PKG_P, UID_P);
+        assertTrue(mHelper.hasUserDemotedInvalidMsgApp(PKG_P, UID_P));
+
+        // and is invalid once complete msgs are sent
+        mHelper.setValidMessageSent(PKG_P, UID_P);
+        assertFalse(mHelper.hasUserDemotedInvalidMsgApp(PKG_P, UID_P));
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 8cfe96f..063568d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -35,6 +35,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
@@ -69,6 +70,7 @@
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.never;
 
+import android.app.ActivityManager.TaskSnapshot;
 import android.app.ActivityOptions;
 import android.app.WindowConfiguration;
 import android.app.servertransaction.ActivityConfigurationChangeItem;
@@ -82,14 +84,18 @@
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.PersistableBundle;
+import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 import android.util.MergedConfiguration;
 import android.util.MutableBoolean;
 import android.view.DisplayInfo;
 import android.view.IRemoteAnimationFinishedCallback;
 import android.view.IRemoteAnimationRunner.Stub;
+import android.view.IWindowSession;
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationTarget;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 
 import androidx.test.filters.MediumTest;
 
@@ -488,6 +494,16 @@
     }
 
     @Test
+    public void testShouldMakeActive_nonTopVisible() {
+        ActivityRecord finishingActivity = new ActivityBuilder(mService).setTask(mTask).build();
+        finishingActivity.finishing = true;
+        ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
+        mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
+
+        assertEquals(false, mActivity.shouldMakeActive(null /* activeActivity */));
+    }
+
+    @Test
     public void testShouldResume_stackVisibility() {
         mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
         spyOn(mStack);
@@ -1389,11 +1405,15 @@
         mActivity.setVisibility(true);
 
         display.rotateInDifferentOrientationIfNeeded(mActivity);
-        display.mFixedRotationLaunchingApp = mActivity;
+        display.setFixedRotationLaunchingAppUnchecked(mActivity);
         displayRotation.updateRotationUnchecked(true /* forceUpdate */);
 
         assertTrue(displayRotation.isRotatingSeamlessly());
 
+        // The launching rotated app should not be cleared when waiting for remote rotation.
+        display.continueUpdateOrientationForDiffOrienLaunchingApp();
+        assertNotNull(display.getFixedRotationLaunchingApp());
+
         // Simulate the rotation has been updated to previous one, e.g. sensor updates before the
         // remote rotation is completed.
         doReturn(originalRotation).when(displayRotation).rotationForOrientation(
@@ -1418,14 +1438,81 @@
         displayRotation.updateRotationUnchecked(true /* forceUpdate */);
         doReturn(false).when(displayRotation).isWaitingForRemoteRotation();
         clearInvocations(mActivity);
-        display.mFixedRotationLaunchingApp = mActivity;
+        display.setFixedRotationLaunchingAppUnchecked(mActivity);
         display.sendNewConfiguration();
 
-        assertNull(display.mFixedRotationLaunchingApp);
+        assertNull(display.getFixedRotationLaunchingApp());
         assertFalse(mActivity.hasFixedRotationTransform());
     }
 
     @Test
+    public void testIsSnapshotCompatible() {
+        mService.mWindowManager.mIsFixedRotationTransformEnabled = true;
+        final TaskSnapshot snapshot = new TaskSnapshotPersisterTestBase.TaskSnapshotBuilder()
+                .setRotation(mActivity.getWindowConfiguration().getRotation())
+                .build();
+
+        assertTrue(mActivity.isSnapshotCompatible(snapshot));
+
+        setRotatedScreenOrientationSilently(mActivity);
+
+        assertFalse(mActivity.isSnapshotCompatible(snapshot));
+    }
+
+    @Test
+    public void testFixedRotationSnapshotStartingWindow() {
+        mService.mWindowManager.mIsFixedRotationTransformEnabled = true;
+        // TaskSnapshotSurface requires a fullscreen opaque window.
+        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+                WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
+        params.width = params.height = WindowManager.LayoutParams.MATCH_PARENT;
+        final WindowTestUtils.TestWindowState w = new WindowTestUtils.TestWindowState(
+                mService.mWindowManager, mock(Session.class), new TestIWindow(), params, mActivity);
+        mActivity.addWindow(w);
+
+        // Assume the activity is launching in different rotation, and there was an available
+        // snapshot accepted by {@link Activity#isSnapshotCompatible}.
+        final TaskSnapshot snapshot = new TaskSnapshotPersisterTestBase.TaskSnapshotBuilder()
+                .setRotation((mActivity.getWindowConfiguration().getRotation() + 1) % 4)
+                .build();
+        setRotatedScreenOrientationSilently(mActivity);
+
+        final IWindowSession session = WindowManagerGlobal.getWindowSession();
+        spyOn(session);
+        try {
+            // Return error to skip unnecessary operation.
+            doReturn(WindowManagerGlobal.ADD_STARTING_NOT_NEEDED).when(session).addToDisplay(
+                    any() /* window */, anyInt() /* seq */, any() /* attrs */,
+                    anyInt() /* viewVisibility */, anyInt() /* displayId */, any() /* outFrame */,
+                    any() /* outContentInsets */, any() /* outStableInsets */,
+                    any() /* outDisplayCutout */, any() /* outInputChannel */,
+                    any() /* outInsetsState */, any() /* outActiveControls */);
+            TaskSnapshotSurface.create(mService.mWindowManager, mActivity, snapshot);
+        } catch (RemoteException ignored) {
+        } finally {
+            reset(session);
+        }
+
+        // Because the rotation of snapshot and the corresponding top activity are different, fixed
+        // rotation should be applied when creating snapshot surface if the display rotation may be
+        // changed according to the activity orientation.
+        assertTrue(mActivity.hasFixedRotationTransform());
+        assertEquals(mActivity, mActivity.mDisplayContent.getFixedRotationLaunchingApp());
+    }
+
+    /**
+     * Sets orientation without notifying the parent to simulate that the display has not applied
+     * the requested orientation yet.
+     */
+    private static void setRotatedScreenOrientationSilently(ActivityRecord r) {
+        final int rotatedOrentation = r.getConfiguration().orientation == ORIENTATION_PORTRAIT
+                ? SCREEN_ORIENTATION_LANDSCAPE
+                : SCREEN_ORIENTATION_PORTRAIT;
+        doReturn(false).when(r).onDescendantOrientationChanged(any(), any());
+        r.setOrientation(rotatedOrentation);
+    }
+
+    @Test
     public void testActivityOnDifferentDisplayUpdatesProcessOverride() {
         final ActivityRecord secondaryDisplayActivity =
                 createActivityOnDisplay(false /* defaultDisplay */, null /* process */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 822cb5a..64e08c6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -76,6 +76,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
 /**
  * Tests for the {@link ActivityStack} class.
  *
@@ -1327,6 +1330,8 @@
 
     @Test
     public void testCheckBehindFullscreenActivity() {
+        final ArrayList<ActivityRecord> occludedActivities = new ArrayList<>();
+        final Consumer<ActivityRecord> handleBehindFullscreenActivity = occludedActivities::add;
         final ActivityRecord bottomActivity =
                 new ActivityBuilder(mService).setStack(mStack).setTask(mTask).build();
         final ActivityRecord topActivity =
@@ -1337,12 +1342,21 @@
         assertFalse(mStack.checkBehindFullscreenActivity(topActivity,
                 null /* handleBehindFullscreenActivity */));
 
+        // Top activity occludes bottom activity.
+        mStack.checkBehindFullscreenActivity(null /* toCheck */, handleBehindFullscreenActivity);
+        assertThat(occludedActivities).containsExactly(bottomActivity);
+
         doReturn(false).when(topActivity).occludesParent();
         assertFalse(mStack.checkBehindFullscreenActivity(bottomActivity,
                 null /* handleBehindFullscreenActivity */));
         assertFalse(mStack.checkBehindFullscreenActivity(topActivity,
                 null /* handleBehindFullscreenActivity */));
 
+        occludedActivities.clear();
+        // Top activity doesn't occlude parent, so the bottom activity is not occluded.
+        mStack.checkBehindFullscreenActivity(null /* toCheck */, handleBehindFullscreenActivity);
+        assertThat(occludedActivities).isEmpty();
+
         final ActivityRecord finishingActivity =
                 new ActivityBuilder(mService).setStack(mStack).setTask(mTask).build();
         finishingActivity.finishing = true;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index fc256b0..702d9d3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -53,6 +53,7 @@
 import com.android.server.am.ActivityManagerService;
 import com.android.server.pm.PackageManagerService;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -161,6 +162,12 @@
         mAInfo.packageName = mAInfo.applicationInfo.packageName = TEST_PACKAGE_NAME;
     }
 
+    @After
+    public void tearDown() {
+        LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+        LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
+    }
+
     @Test
     public void testSuspendedByAdminPackage() {
         // GIVEN the package we're about to launch is currently suspended
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 4b43ceb..bd616a3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -140,6 +140,12 @@
             public void onDisplayRemoved(int displayId) {
                 removed.add(displayId);
             }
+
+            @Override
+            public void onFixedRotationStarted(int displayId, int newRotation) {}
+
+            @Override
+            public void onFixedRotationFinished(int displayId) {}
         };
         mService.mWindowManager.registerDisplayWindowListener(listener);
         // Check that existing displays call added
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 5c21853..07050d9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -52,6 +52,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.res.Configuration;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.view.IWindowManager;
@@ -307,7 +308,7 @@
     public void testCreateRemoveStartingWindow() {
         mActivity.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
-                false, false);
+                false);
         waitUntilHandlersIdle();
         assertHasStartingWindow(mActivity);
         mActivity.removeStartingWindow();
@@ -316,20 +317,16 @@
     }
 
     @Test
-    @FlakyTest(bugId = 130392471)
     public void testAddRemoveRace() {
         // There was once a race condition between adding and removing starting windows
+        final ActivityRecord appToken = mAppWindow.mActivityRecord;
         for (int i = 0; i < 1000; i++) {
-            final ActivityRecord appToken = createIsolatedTestActivityRecord();
-
             appToken.addStartingWindow(mPackageName,
                     android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
-                    false, false);
+                    false);
             appToken.removeStartingWindow();
             waitUntilHandlersIdle();
             assertNoStartingWindow(appToken);
-
-            appToken.getParent().getParent().removeImmediately();
         }
     }
 
@@ -339,11 +336,11 @@
         final ActivityRecord activity2 = createIsolatedTestActivityRecord();
         activity1.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
-                false, false);
+                false);
         waitUntilHandlersIdle();
         activity2.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity1.appToken.asBinder(),
-                true, true, false, true, false, false);
+                true, true, false, true, false);
         waitUntilHandlersIdle();
         assertNoStartingWindow(activity1);
         assertHasStartingWindow(activity2);
@@ -359,11 +356,11 @@
                     activity2.addStartingWindow(mPackageName,
                             android.R.style.Theme, null, "Test", 0, 0, 0, 0,
                             activity1.appToken.asBinder(), true, true, false,
-                            true, false, false);
+                            true, false);
                 });
         activity1.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
-                false, false);
+                false);
         waitUntilHandlersIdle();
         assertNoStartingWindow(activity1);
         assertHasStartingWindow(activity2);
@@ -375,11 +372,11 @@
         final ActivityRecord activity2 = createIsolatedTestActivityRecord();
         activity1.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
-                false, false);
+                false);
         waitUntilHandlersIdle();
         activity2.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity1.appToken.asBinder(),
-                true, true, false, true, false, false);
+                true, true, false, true, false);
         waitUntilHandlersIdle();
         assertNoStartingWindow(activity1);
         assertHasStartingWindow(activity2);
@@ -417,7 +414,7 @@
         // Add a starting window.
         activityTop.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
-                false, false);
+                false);
         waitUntilHandlersIdle();
 
         // Make the top one invisible, and try transferring the starting window from the top to the
@@ -436,20 +433,35 @@
         removeGlobalMinSizeRestriction();
         final Rect stackBounds = new Rect(0, 0, 1000, 600);
         final Rect taskBounds = new Rect(100, 400, 600, 800);
-        mStack.setBounds(stackBounds);
-        mTask.setBounds(taskBounds);
+        // Set the bounds and windowing mode to window configuration directly, otherwise the
+        // testing setups may be discarded by configuration resolving.
+        mStack.getWindowConfiguration().setBounds(stackBounds);
+        mTask.getWindowConfiguration().setBounds(taskBounds);
+        mActivity.getWindowConfiguration().setBounds(taskBounds);
 
         // Check that anim bounds for freeform window match task bounds
-        mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        mTask.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FREEFORM);
         assertEquals(mTask.getBounds(), mActivity.getAnimationBounds(STACK_CLIP_NONE));
 
         // STACK_CLIP_AFTER_ANIM should use task bounds since they will be clipped by
         // bounds animation layer.
-        mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        mTask.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         assertEquals(mTask.getBounds(), mActivity.getAnimationBounds(STACK_CLIP_AFTER_ANIM));
 
+        // Even the activity is smaller than task and it is not aligned to the top-left corner of
+        // task, the animation bounds the same as task and position should be zero because in real
+        // case the letterbox will fill the remaining area in task.
+        final Rect halfBounds = new Rect(taskBounds);
+        halfBounds.scale(0.5f);
+        mActivity.getWindowConfiguration().setBounds(halfBounds);
+        final Point animationPosition = new Point();
+        mActivity.getAnimationPosition(animationPosition);
+
+        assertEquals(taskBounds, mActivity.getAnimationBounds(STACK_CLIP_AFTER_ANIM));
+        assertEquals(new Point(0, 0), animationPosition);
+
         // STACK_CLIP_BEFORE_ANIM should use stack bounds since it won't be clipped later.
-        mTask.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+        mTask.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
         assertEquals(mStack.getBounds(), mActivity.getAnimationBounds(STACK_CLIP_BEFORE_ANIM));
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java
index 6a1f50d..f4b50dc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java
@@ -23,6 +23,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Binder;
 import android.os.RemoteException;
@@ -91,5 +92,11 @@
 
         mDisplayContent.setBounds(new Rect(0, 0, 1000, 1000));
         verify(organizer).onDisplayAreaInfoChanged(any());
+
+        Configuration tmpConfiguration = new Configuration();
+        tmpConfiguration.setTo(mDisplayContent.getRequestedOverrideConfiguration());
+        mDisplayContent.onRequestedOverrideConfigurationChanged(tmpConfiguration);
+        // Ensure it was still only called once if the bounds didn't change
+        verify(organizer).onDisplayAreaInfoChanged(any());
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index d605ab2..27c4e9b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -27,9 +27,7 @@
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
 import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
-import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
 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.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
@@ -40,7 +38,6 @@
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
@@ -50,7 +47,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertThat;
-import static org.junit.Assume.assumeTrue;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.spy;
 import static org.testng.Assert.expectThrows;
@@ -64,18 +60,15 @@
 import android.view.DisplayCutout;
 import android.view.DisplayInfo;
 import android.view.InsetsState;
-import android.view.ViewRootImpl;
 import android.view.WindowInsets.Side;
 import android.view.WindowInsets.Type;
 import android.view.WindowManager;
 
-import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.wm.utils.WmDisplayCutout;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -116,12 +109,6 @@
         updateDisplayFrames();
     }
 
-    @After
-    public void tearDown() {
-        PolicyControl.setFilters("");
-        mWindow.getDisplayContent().mInputMethodTarget = null;
-    }
-
     public void setRotation(int rotation) {
         mRotation = rotation;
         updateDisplayFrames();
@@ -210,8 +197,6 @@
 
     @Test
     public void layoutWindowLw_fitStatusBars() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
-
         mWindow.mAttrs.setFitInsetsTypes(Type.statusBars());
         addWindow(mWindow);
 
@@ -228,8 +213,6 @@
 
     @Test
     public void layoutWindowLw_fitNavigationBars() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
-
         mWindow.mAttrs.setFitInsetsTypes(Type.navigationBars());
         addWindow(mWindow);
 
@@ -246,8 +229,6 @@
 
     @Test
     public void layoutWindowLw_fitAllSides() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
-
         mWindow.mAttrs.setFitInsetsSides(Side.all());
         addWindow(mWindow);
 
@@ -264,8 +245,6 @@
 
     @Test
     public void layoutWindowLw_fitTopOnly() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
-
         mWindow.mAttrs.setFitInsetsSides(Side.TOP);
         addWindow(mWindow);
 
@@ -282,8 +261,6 @@
 
     @Test
     public void layoutWindowLw_fitInsetsIgnoringVisibility() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
-
         final InsetsState state =
                 mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow);
         state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
@@ -304,8 +281,6 @@
 
     @Test
     public void layoutWindowLw_fitInsetsNotIgnoringVisibility() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
-
         final InsetsState state =
                 mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow);
         state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
@@ -326,7 +301,6 @@
 
     @Test
     public void layoutWindowLw_fitDisplayCutout() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
         addDisplayCutout();
 
         mWindow.mAttrs.setFitInsetsTypes(Type.displayCutout());
@@ -683,31 +657,6 @@
     }
 
     @Test
-    public void layoutWindowLw_withForwardInset_SoftInputAdjustResize() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_NONE);
-
-        mWindow.mAttrs.flags =
-                FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-        mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
-        mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
-        addWindow(mWindow);
-
-        final int forwardedInsetBottom = 50;
-        mDisplayPolicy.setForwardedInsets(Insets.of(0, 0, 0, forwardedInsetBottom));
-        mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
-        mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
-
-        assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0);
-        assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-        assertInsetByTopBottom(mWindow.getContentFrameLw(),
-                STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT + forwardedInsetBottom);
-        assertInsetByTopBottom(mWindow.getVisibleFrameLw(),
-                STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT + forwardedInsetBottom);
-        assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0);
-        assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0);
-    }
-
-    @Test
     public void layoutWindowLw_withForwardInset_SoftInputAdjustNothing() {
         mWindow.mAttrs.flags =
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
@@ -728,117 +677,6 @@
         assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0);
     }
 
-    // TODO(b/118118435): remove after removing PolicyControl
-    @FlakyTest(bugId = 129711077)
-    @Test
-    public void layoutWindowLw_withImmersive_SoftInputAdjustResize() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
-
-        synchronized (mWm.mGlobalLock) {
-            mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
-            mWindow.mAttrs.flags = 0;
-            mWindow.mAttrs.systemUiVisibility =
-                    SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
-                            | SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION;
-
-            addWindow(mWindow);
-
-            mWindow.getDisplayContent().mInputMethodTarget = mWindow;
-            mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
-            mFrames.mContent.bottom = mFrames.mVoiceContent.bottom = INPUT_METHOD_WINDOW_TOP;
-            mFrames.mCurrent.bottom = INPUT_METHOD_WINDOW_TOP;
-            mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
-
-            int bottomInset = mFrames.mDisplayHeight - INPUT_METHOD_WINDOW_TOP;
-            assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0);
-            assertInsetByTopBottom(mWindow.getContentFrameLw(), 0, 0);
-            assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, bottomInset);
-        }
-    }
-
-    // TODO(b/118118435): remove after removing PolicyControl
-    @FlakyTest(bugId = 129711077)
-    @Test
-    public void layoutWindowLw_withImmersive_SoftInputAdjustNothing() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
-
-        synchronized (mWm.mGlobalLock) {
-            mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_NOTHING;
-            mWindow.mAttrs.flags = 0;
-            mWindow.mAttrs.systemUiVisibility =
-                    SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
-                            | SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION;
-
-            addWindow(mWindow);
-
-            mWindow.getDisplayContent().mInputMethodTarget = mWindow;
-            mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
-            mFrames.mContent.bottom = mFrames.mVoiceContent.bottom = INPUT_METHOD_WINDOW_TOP;
-            mFrames.mCurrent.bottom = INPUT_METHOD_WINDOW_TOP;
-            mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
-
-            assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0);
-            assertInsetByTopBottom(mWindow.getContentFrameLw(), 0, 0);
-            assertInsetByTopBottom(mWindow.getVisibleFrameLw(), 0, 0);
-        }
-    }
-
-    // TODO(b/118118435): remove after removing PolicyControl
-    @FlakyTest(bugId = 129711077)
-    @Test
-    public void layoutWindowLw_withForceImmersive_fullscreen() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
-
-        synchronized (mWm.mGlobalLock) {
-            mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
-            mWindow.mAttrs.flags = 0;
-            mWindow.mAttrs.systemUiVisibility = 0;
-            PolicyControl.setFilters(PolicyControl.NAME_IMMERSIVE_FULL + "=*");
-
-            addWindow(mWindow);
-
-            mWindow.getDisplayContent().mInputMethodTarget = mWindow;
-            mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
-            mFrames.mContent.bottom = mFrames.mVoiceContent.bottom = INPUT_METHOD_WINDOW_TOP;
-            mFrames.mCurrent.bottom = INPUT_METHOD_WINDOW_TOP;
-            mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
-
-            int bottomInset = mFrames.mDisplayHeight - INPUT_METHOD_WINDOW_TOP;
-            assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0);
-            assertInsetByTopBottom(mWindow.getContentFrameLw(), 0, 0);
-            assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, bottomInset);
-        }
-    }
-
-    // TODO(b/118118435): remove after removing PolicyControl
-    @FlakyTest(bugId = 129711077)
-    @Test
-    public void layoutWindowLw_withForceImmersive_nonFullscreen() {
-        assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
-
-        synchronized (mWm.mGlobalLock) {
-            mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
-            mWindow.mAttrs.flags = 0;
-            mWindow.mAttrs.systemUiVisibility = 0;
-            mWindow.mAttrs.width = DISPLAY_WIDTH / 2;
-            mWindow.mAttrs.height = DISPLAY_HEIGHT / 2;
-            PolicyControl.setFilters(PolicyControl.NAME_IMMERSIVE_FULL + "=*");
-
-            addWindow(mWindow);
-
-            mWindow.getDisplayContent().mInputMethodTarget = mWindow;
-            mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
-            mFrames.mContent.bottom = mFrames.mVoiceContent.bottom = INPUT_METHOD_WINDOW_TOP;
-            mFrames.mCurrent.bottom = INPUT_METHOD_WINDOW_TOP;
-            mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
-
-            int bottomInset = mFrames.mDisplayHeight - INPUT_METHOD_WINDOW_TOP;
-            assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, bottomInset);
-            assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, bottomInset);
-            assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, bottomInset);
-        }
-    }
-
     @Test
     public void layoutHint_appWindow() {
         mWindow.mAttrs.flags =
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index c2db0c0..a3f9b2e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -16,7 +16,9 @@
 
 package com.android.server.wm;
 
+import static android.view.InsetsState.ITYPE_IME;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
+import static android.view.Surface.ROTATION_0;
 import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
@@ -56,7 +58,10 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
+import android.view.DisplayInfo;
+import android.view.InsetsSource;
 import android.view.InsetsState;
+import android.view.WindowInsets.Side;
 import android.view.WindowManager;
 
 import androidx.test.filters.SmallTest;
@@ -352,4 +357,36 @@
         insetsPolicy.updateBarControlTarget(mAppWindow);
         assertNull(displayPolicy.mInputConsumer);
     }
+
+    @Test
+    public void testImeMinimalSourceFrame() {
+        final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
+        final DisplayInfo displayInfo = new DisplayInfo();
+        displayInfo.logicalWidth = 1000;
+        displayInfo.logicalHeight = 2000;
+        displayInfo.rotation = ROTATION_0;
+        mDisplayContent.mDisplayFrames = new DisplayFrames(mDisplayContent.getDisplayId(),
+                displayInfo, null /* displayCutout */);
+
+        displayPolicy.addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs);
+        mNavBarWindow.getControllableInsetProvider().setServerVisible(true);
+
+        mDisplayContent.setInputMethodWindowLocked(mImeWindow);
+        mImeWindow.mAttrs.setFitInsetsSides(Side.all() & ~Side.BOTTOM);
+        mImeWindow.getGivenContentInsetsLw().set(0, displayInfo.logicalHeight, 0, 0);
+        mImeWindow.getControllableInsetProvider().setServerVisible(true);
+
+        displayPolicy.beginLayoutLw(mDisplayContent.mDisplayFrames, 0 /* UI mode */);
+        displayPolicy.layoutWindowLw(mImeWindow, null, mDisplayContent.mDisplayFrames);
+
+        final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
+        final InsetsSource imeSource = state.peekSource(ITYPE_IME);
+        final InsetsSource navBarSource = state.peekSource(ITYPE_NAVIGATION_BAR);
+
+        assertNotNull(imeSource);
+        assertNotNull(navBarSource);
+        assertFalse(imeSource.getFrame().isEmpty());
+        assertFalse(navBarSource.getFrame().isEmpty());
+        assertTrue(imeSource.getFrame().contains(navBarSource.getFrame()));
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 209db62..f330f0f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -343,7 +343,7 @@
 
         initializeRecentsAnimationController(mController, homeActivity);
 
-        assertEquals(homeActivity, mDefaultDisplay.mFixedRotationLaunchingApp);
+        assertEquals(homeActivity, mDefaultDisplay.getFixedRotationLaunchingApp());
 
         // Check that the home app is in portrait
         assertEquals(Configuration.ORIENTATION_PORTRAIT,
@@ -353,7 +353,7 @@
         // top rotated record should be cleared.
         mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
         assertFalse(homeActivity.hasFixedRotationTransform());
-        assertNull(mDefaultDisplay.mFixedRotationLaunchingApp);
+        assertNull(mDefaultDisplay.getFixedRotationLaunchingApp());
     }
 
     @Test
@@ -367,7 +367,7 @@
                 (mDefaultDisplay.getRotation() + 1) % 4);
 
         assertTrue(activity.hasFixedRotationTransform());
-        assertEquals(activity, mDefaultDisplay.mFixedRotationLaunchingApp);
+        assertEquals(activity, mDefaultDisplay.getFixedRotationLaunchingApp());
 
         // Before the transition is done, the recents animation is triggered.
         initializeRecentsAnimationController(mController, homeActivity);
@@ -377,7 +377,7 @@
         mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
         // The rotation transform should be cleared after updating orientation with display.
         assertFalse(activity.hasFixedRotationTransform());
-        assertNull(mDefaultDisplay.mFixedRotationLaunchingApp);
+        assertNull(mDefaultDisplay.getFixedRotationLaunchingApp());
     }
 
     @Test
@@ -436,7 +436,7 @@
         // The transform state should keep because we expect to listen the signal from the
         // transition executed by moving the task to front.
         assertTrue(homeActivity.hasFixedRotationTransform());
-        assertEquals(homeActivity, mDefaultDisplay.mFixedRotationLaunchingApp);
+        assertEquals(homeActivity, mDefaultDisplay.getFixedRotationLaunchingApp());
 
         mDefaultDisplay.mFixedRotationTransitionListener.onAppTransitionFinishedLocked(
                 homeActivity.token);
diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
index 851b052..d7eedd9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
+++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import android.annotation.NonNull;
 import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.graphics.Region;
@@ -265,4 +266,15 @@
     public SurfaceControl.Transaction setShadowRadius(SurfaceControl sc, float shadowRadius) {
         return this;
     }
+
+    @Override
+    public SurfaceControl.Transaction setFixedTransformHint(SurfaceControl sc,
+            @Surface.Rotation int transformHint) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction unsetFixedTransformHint(@NonNull SurfaceControl sc) {
+        return this;
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
index 552c476..79ba175 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -33,6 +33,7 @@
 import static org.mockito.ArgumentMatchers.eq;
 
 import android.platform.test.annotations.Presubmit;
+import android.util.proto.ProtoOutputStream;
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Builder;
 import android.view.SurfaceControl.Transaction;
@@ -52,6 +53,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.io.PrintWriter;
+
 /**
  * Test class for {@link SurfaceAnimatorTest}.
  *
@@ -267,6 +270,27 @@
         assertFalse(mDeferFinishAnimatable.mFinishedCallbackCalled);
     }
 
+    @Test
+    public void testDeferFinishFromAdapter() {
+
+        DeferredFinishAdapter deferredFinishAdapter = new DeferredFinishAdapter();
+        // Start animation
+        mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, deferredFinishAdapter,
+                true /* hidden */,
+                ANIMATION_TYPE_APP_TRANSITION);
+        assertAnimating(mAnimatable);
+        deferredFinishAdapter.mFinishCallback.onAnimationFinished(ANIMATION_TYPE_APP_TRANSITION,
+                deferredFinishAdapter);
+
+        assertAnimating(mAnimatable);
+        assertFalse(mAnimatable.mFinishedCallbackCalled);
+        // Now end defer finishing.
+        deferredFinishAdapter.mEndDeferFinishCallback.run();
+        assertNotAnimating(mAnimatable);
+        assertTrue(mAnimatable.mFinishedCallbackCalled);
+        verify(mTransaction).remove(eq(deferredFinishAdapter.mAnimationLeash));
+    }
+
     private OnAnimationFinishedCallback startDeferFinishAnimatable(AnimationAdapter anim) {
         mDeferFinishAnimatable.mSurfaceAnimator.startAnimation(mTransaction, anim,
                 true /* hidden */, ANIMATION_TYPE_APP_TRANSITION);
@@ -389,4 +413,51 @@
             return true;
         }
     }
+
+    private static class DeferredFinishAdapter implements AnimationAdapter {
+
+        private Runnable mEndDeferFinishCallback;
+        private OnAnimationFinishedCallback mFinishCallback;
+        private SurfaceControl mAnimationLeash;
+
+        @Override
+        public boolean getShowWallpaper() {
+            return true;
+        }
+
+        @Override
+        public void startAnimation(SurfaceControl animationLeash, Transaction t, int type,
+                OnAnimationFinishedCallback finishCallback) {
+            mFinishCallback = finishCallback;
+            mAnimationLeash = animationLeash;
+        }
+
+        @Override
+        public void onAnimationCancelled(SurfaceControl animationLeash) {
+        }
+
+        @Override
+        public long getDurationHint() {
+            return 100;
+        }
+
+        @Override
+        public long getStatusBarTransitionsStartTime() {
+            return 100;
+        }
+
+        @Override
+        public void dump(PrintWriter pw, String prefix) {
+        }
+
+        @Override
+        public void dumpDebug(ProtoOutputStream proto) {
+        }
+
+        @Override
+        public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
+            mEndDeferFinishCallback = endDeferFinishCallback;
+            return true;
+        }
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
index 52a5187..512042c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
@@ -40,6 +40,9 @@
 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.never;
+import static org.mockito.Mockito.verify;
 
 import android.platform.test.annotations.Presubmit;
 
@@ -82,6 +85,25 @@
     }
 
     @Test
+    public void testActivityWithZBoost_taskDisplayAreaDoesNotMoveUp() {
+        final ActivityStack stack = createTaskStackOnDisplay(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent);
+        final Task task = createTaskInStack(stack, 0 /* userId */);
+        final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        task.addChild(activity, 0 /* addPos */);
+        final TaskDisplayArea taskDisplayArea = activity.getDisplayArea();
+        activity.mNeedsAnimationBoundsLayer = true;
+        activity.mNeedsZBoost = true;
+        spyOn(taskDisplayArea.mSurfaceAnimator);
+
+        mDisplayContent.assignChildLayers(mTransaction);
+
+        assertThat(activity.needsZBoost()).isTrue();
+        assertThat(taskDisplayArea.needsZBoost()).isFalse();
+        verify(taskDisplayArea.mSurfaceAnimator, never()).setLayer(eq(mTransaction), anyInt());
+    }
+
+    @Test
     public void testStackPositionChildAt() {
         // Test that always-on-top stack can't be moved to position other than top.
         final ActivityStack stack1 = createTaskStackOnDisplay(mDisplayContent);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 20d9aff..f985a14 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -192,10 +192,18 @@
 
         final ActivityManager.TaskSnapshot.Builder builder =
                 new ActivityManager.TaskSnapshot.Builder();
-        mWm.mTaskSnapshotController.prepareTaskSnapshot(mAppWindow.mActivityRecord.getTask(),
-                PixelFormat.UNKNOWN, builder);
+        boolean success = mWm.mTaskSnapshotController.prepareTaskSnapshot(
+                mAppWindow.mActivityRecord.getTask(), PixelFormat.UNKNOWN, builder);
 
+        assertTrue(success);
         // The pixel format should be selected automatically.
         assertNotEquals(PixelFormat.UNKNOWN, builder.getPixelFormat());
+
+        // Snapshot should not be taken while the rotation of activity and task are different.
+        doReturn(true).when(mAppWindow.mActivityRecord).hasFixedRotationTransform();
+        success = mWm.mTaskSnapshotController.prepareTaskSnapshot(
+                mAppWindow.mActivityRecord.getTask(), PixelFormat.UNKNOWN, builder);
+
+        assertFalse(success);
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index 88de34d..bdcae48 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -24,6 +24,7 @@
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
@@ -39,10 +40,15 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.UserManager;
+import android.os.UserManagerInternal;
 import android.view.Surface;
 
+import com.android.server.LocalServices;
+
 import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 
 import java.io.File;
 import java.util.function.Predicate;
@@ -70,11 +76,26 @@
         mLowResScale = lowResScale;
     }
 
+    @BeforeClass
+    public static void setUpOnce() {
+        final UserManagerInternal userManager = mock(UserManagerInternal.class);
+        LocalServices.addService(UserManagerInternal.class, userManager);
+    }
+
+    @AfterClass
+    public static void tearDownOnce() {
+        LocalServices.removeServiceForTest(UserManagerInternal.class);
+    }
+
     @Before
     public void setUp() {
         final UserManager um = UserManager.get(getInstrumentation().getTargetContext());
         mTestUserId = um.getUserHandle();
 
+        final UserManagerInternal userManagerInternal =
+                LocalServices.getService(UserManagerInternal.class);
+        when(userManagerInternal.isUserUnlocked(mTestUserId)).thenReturn(true);
+
         mContextSpy = spy(new ContextWrapper(mWm.mContext));
         mResourcesSpy = spy(mContextSpy.getResources());
         when(mContextSpy.getResources()).thenReturn(mResourcesSpy);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index 2ea58a0..71dabc5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -758,6 +758,28 @@
     }
 
     @Test
+    public void testBLASTCallbackNoDoubleAdd() {
+        final ActivityStack stackController1 = createStack();
+        final Task task = createTask(stackController1);
+        final ITaskOrganizer organizer = registerMockOrganizer();
+        final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
+        makeWindowVisible(w);
+
+        BLASTSyncEngine bse = new BLASTSyncEngine();
+
+        BLASTSyncEngine.TransactionReadyListener transactionListener =
+                mock(BLASTSyncEngine.TransactionReadyListener.class);
+
+        int id = bse.startSyncSet(transactionListener);
+        assertTrue(bse.addToSyncSet(id, w));
+        assertFalse(bse.addToSyncSet(id, w));
+
+        // Clean-up
+        bse.setReady(id);
+    }
+
+
+    @Test
     public void testBLASTCallbackWithInvisibleWindow() {
         final ActivityStack stackController1 = createStack();
         final Task task = createTask(stackController1);
@@ -836,7 +858,7 @@
         spyOn(record);
         doReturn(true).when(record).checkEnterPictureInPictureState(any(), anyBoolean());
 
-        record.getRootTask().setHasBeenVisible(true);
+        record.getTask().setHasBeenVisible(true);
         return record;
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 65fb2c0..8ce5daa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -22,7 +22,6 @@
 import static android.hardware.camera2.params.OutputConfiguration.ROTATION_90;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.Surface.ROTATION_0;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
@@ -75,17 +74,13 @@
 import android.view.DisplayCutout;
 import android.view.InsetsSource;
 import android.view.SurfaceControl;
-import android.view.ViewRootImpl;
 import android.view.WindowManager;
 
-import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
 import com.android.server.wm.utils.WmDisplayCutout;
 
-import org.junit.AfterClass;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -103,21 +98,6 @@
 @Presubmit
 @RunWith(WindowTestRunner.class)
 public class WindowStateTests extends WindowTestsBase {
-    private static int sPreviousNewInsetsMode;
-
-    @BeforeClass
-    public static void setUpOnce() {
-        // TODO: Make use of SettingsSession when it becomes feasible for this.
-        sPreviousNewInsetsMode = ViewRootImpl.sNewInsetsMode;
-        // To let the insets provider control the insets visibility, the insets mode has to be
-        // NEW_INSETS_MODE_FULL.
-        ViewRootImpl.sNewInsetsMode = NEW_INSETS_MODE_FULL;
-    }
-
-    @AfterClass
-    public static void tearDownOnce() {
-        ViewRootImpl.sNewInsetsMode = sPreviousNewInsetsMode;
-    }
 
     @Before
     public void setUp() {
@@ -290,6 +270,26 @@
     }
 
     @Test
+    public void testCanWindowWithEmbeddedDisplayBeImeTarget() {
+        final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
+        final WindowState imeWindow = createWindow(null, TYPE_INPUT_METHOD, "imeWindow");
+
+        imeWindow.setHasSurface(true);
+        appWindow.setHasSurface(true);
+
+        appWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
+        assertFalse(appWindow.canBeImeTarget());
+
+        DisplayContent secondDisplay = createNewDisplay();
+        final WindowState embeddedWindow = createWindow(null, TYPE_APPLICATION, secondDisplay,
+                "embeddedWindow");
+        appWindow.addEmbeddedDisplayContent(secondDisplay);
+        embeddedWindow.setHasSurface(true);
+        embeddedWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE;
+        assertTrue(appWindow.canBeImeTarget());
+    }
+
+    @Test
     public void testGetWindow() {
         final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
         final WindowState mediaChild = createWindow(root, TYPE_APPLICATION_MEDIA, "mediaChild");
diff --git a/services/usage/java/com/android/server/usage/UsageStatsIdleService.java b/services/usage/java/com/android/server/usage/UsageStatsIdleService.java
index 4468871..3163820 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsIdleService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsIdleService.java
@@ -27,6 +27,8 @@
 
 import com.android.server.LocalServices;
 
+import java.util.concurrent.TimeUnit;
+
 /**
  * JobService used to do any work for UsageStats while the device is idle.
  */
@@ -36,6 +38,11 @@
      * Base job ID for the pruning job - must be unique within the system server uid.
      */
     private static final int PRUNE_JOB_ID = 546357475;
+    /**
+     * Job ID for the update mappings job - must be unique within the system server uid.
+     * Incrementing PRUNE_JOB_ID by 21475 (MAX_USER_ID) to ensure there is no overlap in job ids.
+     */
+    private static final int UPDATE_MAPPINGS_JOB_ID = 546378950;
 
     private static final String USER_ID_KEY = "user_id";
 
@@ -51,35 +58,65 @@
                 .setPersisted(true)
                 .build();
 
+        scheduleJobInternal(context, pruneJob, userJobId);
+    }
+
+    static void scheduleUpdateMappingsJob(Context context) {
+        final ComponentName component = new ComponentName(context.getPackageName(),
+                UsageStatsIdleService.class.getName());
+        final JobInfo updateMappingsJob = new JobInfo.Builder(UPDATE_MAPPINGS_JOB_ID, component)
+                .setPersisted(true)
+                .setMinimumLatency(TimeUnit.DAYS.toMillis(1))
+                .setOverrideDeadline(TimeUnit.DAYS.toMillis(2))
+                .build();
+
+        scheduleJobInternal(context, updateMappingsJob, UPDATE_MAPPINGS_JOB_ID);
+    }
+
+    private static void scheduleJobInternal(Context context, JobInfo pruneJob, int jobId) {
         final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
-        final JobInfo pendingPruneJob = jobScheduler.getPendingJob(userJobId);
+        final JobInfo pendingPruneJob = jobScheduler.getPendingJob(jobId);
         // only schedule a new prune job if one doesn't exist already for this user
         if (!pruneJob.equals(pendingPruneJob)) {
-            jobScheduler.cancel(userJobId); // cancel any previously scheduled prune job
+            jobScheduler.cancel(jobId); // cancel any previously scheduled prune job
             jobScheduler.schedule(pruneJob);
         }
-
     }
 
     static void cancelJob(Context context, int userId) {
-        final int userJobId = PRUNE_JOB_ID + userId; // unique job id per user
+        cancelJobInternal(context, PRUNE_JOB_ID + userId);
+    }
+
+    static void cancelUpdateMappingsJob(Context context) {
+        cancelJobInternal(context, UPDATE_MAPPINGS_JOB_ID);
+    }
+
+    private static void cancelJobInternal(Context context, int jobId) {
         final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
-        jobScheduler.cancel(userJobId);
+        if (jobScheduler != null) {
+            jobScheduler.cancel(jobId);
+        }
     }
 
     @Override
     public boolean onStartJob(JobParameters params) {
         final PersistableBundle bundle = params.getExtras();
         final int userId = bundle.getInt(USER_ID_KEY, -1);
-        if (userId == -1) {
+        if (userId == -1 && params.getJobId() != UPDATE_MAPPINGS_JOB_ID) {
             return false;
         }
 
         AsyncTask.execute(() -> {
             final UsageStatsManagerInternal usageStatsManagerInternal = LocalServices.getService(
                     UsageStatsManagerInternal.class);
-            final boolean pruned = usageStatsManagerInternal.pruneUninstalledPackagesData(userId);
-            jobFinished(params, !pruned); // reschedule if data was not pruned
+            if (params.getJobId() == UPDATE_MAPPINGS_JOB_ID) {
+                final boolean jobFinished = usageStatsManagerInternal.updatePackageMappingsData();
+                jobFinished(params, !jobFinished); // reschedule if data was not updated
+            } else {
+                final boolean jobFinished =
+                        usageStatsManagerInternal.pruneUninstalledPackagesData(userId);
+                jobFinished(params, !jobFinished); // reschedule if data was not pruned
+            }
         });
         return true;
     }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 5b5d57b..060ed51 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -88,6 +88,7 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.DumpUtils;
+import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -332,6 +333,11 @@
     private void onUserUnlocked(int userId) {
         // fetch the installed packages outside the lock so it doesn't block package manager.
         final HashMap<String, Long> installedPackages = getInstalledPackages(userId);
+        // delay updating of package mappings for user 0 since their data is not likely to be stale.
+        // this also makes it less likely for restored data to be erased on unexpected reboots.
+        if (userId == UserHandle.USER_SYSTEM) {
+            UsageStatsIdleService.scheduleUpdateMappingsJob(getContext());
+        }
         synchronized (mLock) {
             // Create a user unlocked event to report
             final Event unlockEvent = new Event(USER_UNLOCKED, SystemClock.elapsedRealtime());
@@ -543,8 +549,8 @@
      * Initializes the given user's usage stats service - this should ideally only be called once,
      * when the user is initially unlocked.
      */
-    private void initializeUserUsageStatsServiceLocked(int userId,
-            long currentTimeMillis, HashMap<String, Long> installedPackages) {
+    private void initializeUserUsageStatsServiceLocked(int userId, long currentTimeMillis,
+            HashMap<String, Long> installedPackages) {
         final File usageStatsDir = new File(Environment.getDataSystemCeDirectory(userId),
                 "usagestats");
         final UserUsageStatsService service = new UserUsageStatsService(getContext(), userId,
@@ -810,6 +816,13 @@
                     } catch (IllegalArgumentException iae) {
                         Slog.e(TAG, "Failed to note usage start", iae);
                     }
+                    FrameworkStatsLog.write(
+                            FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED,
+                            mPackageManagerInternal.getPackageUid(event.mPackage, 0, userId),
+                            event.mPackage,
+                            event.mClass,
+                            FrameworkStatsLog
+                                .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_FOREGROUND);
                     break;
                 case Event.ACTIVITY_PAUSED:
                     if (event.mTaskRootPackage == null) {
@@ -824,6 +837,13 @@
                             event.mTaskRootClass = prevData.mTaskRootClass;
                         }
                     }
+                    FrameworkStatsLog.write(
+                            FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED,
+                            mPackageManagerInternal.getPackageUid(event.mPackage, 0, userId),
+                            event.mPackage,
+                            event.mClass,
+                            FrameworkStatsLog
+                                .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_BACKGROUND);
                     break;
                 case Event.ACTIVITY_DESTROYED:
                     // Treat activity destroys like activity stops.
@@ -931,6 +951,7 @@
         }
         // Cancel any scheduled jobs for this user since the user is being removed.
         UsageStatsIdleService.cancelJob(getContext(), userId);
+        UsageStatsIdleService.cancelUpdateMappingsJob(getContext());
     }
 
     /**
@@ -980,6 +1001,26 @@
     /**
      * Called by the Binder stub.
      */
+    private boolean updatePackageMappingsData() {
+        // fetch the installed packages outside the lock so it doesn't block package manager.
+        final HashMap<String, Long> installedPkgs = getInstalledPackages(UserHandle.USER_SYSTEM);
+        synchronized (mLock) {
+            if (!mUserUnlockedStates.get(UserHandle.USER_SYSTEM)) {
+                return false; // user is no longer unlocked
+            }
+
+            final UserUsageStatsService userService = mUserState.get(UserHandle.USER_SYSTEM);
+            if (userService == null) {
+                return false; // user was stopped or removed
+            }
+
+            return userService.updatePackageMappingsLocked(installedPkgs);
+        }
+    }
+
+    /**
+     * Called by the Binder stub.
+     */
     List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime,
             boolean obfuscateInstantApps) {
         synchronized (mLock) {
@@ -1847,7 +1888,7 @@
             final DevicePolicyManagerInternal dpmInternal = getDpmInternal();
             if (!hasPermissions(callingPackage,
                     Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE)
-                    && (dpmInternal != null && !dpmInternal.isActiveSupervisionApp(callingUid))) {
+                    && (dpmInternal == null || !dpmInternal.isActiveSupervisionApp(callingUid))) {
                 throw new SecurityException("Caller must be the active supervision app or "
                         + "it must have both SUSPEND_APPS and OBSERVE_APP_USAGE permissions");
             }
@@ -1874,7 +1915,7 @@
             final DevicePolicyManagerInternal dpmInternal = getDpmInternal();
             if (!hasPermissions(callingPackage,
                     Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE)
-                    && (dpmInternal != null && !dpmInternal.isActiveSupervisionApp(callingUid))) {
+                    && (dpmInternal == null || !dpmInternal.isActiveSupervisionApp(callingUid))) {
                 throw new SecurityException("Caller must be the active supervision app or "
                         + "it must have both SUSPEND_APPS and OBSERVE_APP_USAGE permissions");
             }
@@ -2137,6 +2178,9 @@
                 }
 
                 // Check to ensure that only user 0's data is b/r for now
+                // Note: if backup and restore is enabled for users other than the system user, the
+                // #onUserUnlocked logic, specifically when the update mappings job is scheduled via
+                // UsageStatsIdleService.scheduleUpdateMappingsJob, will have to be updated.
                 if (user == UserHandle.USER_SYSTEM) {
                     final UserUsageStatsService userStats = getUserUsageStatsServiceLocked(user);
                     if (userStats == null) {
@@ -2229,6 +2273,11 @@
         public boolean pruneUninstalledPackagesData(int userId) {
             return UsageStatsService.this.pruneUninstalledPackagesData(userId);
         }
+
+        @Override
+        public boolean updatePackageMappingsData() {
+            return UsageStatsService.this.updatePackageMappingsData();
+        }
     }
 
     private class MyPackageMonitor extends PackageMonitor {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 4e75b73..26de11a 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -40,6 +40,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -181,19 +182,27 @@
 
     private void readPackageMappingsLocked(HashMap<String, Long> installedPackages) {
         mDatabase.readMappingsLocked();
-        updatePackageMappingsLocked(installedPackages);
+        // Package mappings for the system user are updated after 24 hours via a job scheduled by
+        // UsageStatsIdleService to ensure restored data is not lost on first boot. Additionally,
+        // this makes user service initialization a little quicker on subsequent boots.
+        if (mUserId != UserHandle.USER_SYSTEM) {
+            updatePackageMappingsLocked(installedPackages);
+        }
     }
 
     /**
-     * Queries Job Scheduler for any pending data prune jobs and if any exist, it updates the
-     * package mappings in memory by removing those tokens.
+     * Compares the package mappings on disk with the ones currently installed and removes the
+     * mappings for those packages that have been uninstalled.
      * This will only happen once per device boot, when the user is unlocked for the first time.
+     * If the user is the system user (user 0), this is delayed to ensure data for packages
+     * that were restored isn't removed before the restore is complete.
      *
      * @param installedPackages map of installed packages (package_name:package_install_time)
+     * @return {@code true} on a successful mappings update, {@code false} otherwise.
      */
-    private void updatePackageMappingsLocked(HashMap<String, Long> installedPackages) {
+    boolean updatePackageMappingsLocked(HashMap<String, Long> installedPackages) {
         if (ArrayUtils.isEmpty(installedPackages)) {
-            return;
+            return true;
         }
 
         final long timeNow = System.currentTimeMillis();
@@ -206,7 +215,7 @@
             }
         }
         if (removedPackages.isEmpty()) {
-            return;
+            return true;
         }
 
         // remove packages in the mappings that are no longer installed and persist to disk
@@ -217,7 +226,9 @@
             mDatabase.writeMappingsLocked();
         } catch (Exception e) {
             Slog.w(TAG, "Unable to write updated package mappings file on service initialization.");
+            return false;
         }
+        return true;
     }
 
     boolean pruneUninstalledPackagesData() {
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 42e2bbf..6c13cd7 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -346,12 +346,15 @@
             sEventLogger.log(new SoundTriggerLogger.StringEvent("deleteSoundModel(): id = "
                     + soundModelId));
 
-            // Unload the model if it is loaded.
-            mSoundTriggerHelper.unloadGenericSoundModel(soundModelId.getUuid());
-            mDbHelper.deleteGenericSoundModel(soundModelId.getUuid());
+            if (isInitialized()) {
+                // Unload the model if it is loaded.
+                mSoundTriggerHelper.unloadGenericSoundModel(soundModelId.getUuid());
 
-            // Stop recognition if it is started.
-            mSoundModelStatTracker.onStop(soundModelId.getUuid());
+                // Stop tracking recognition if it is started.
+                mSoundModelStatTracker.onStop(soundModelId.getUuid());
+            }
+
+            mDbHelper.deleteGenericSoundModel(soundModelId.getUuid());
         }
 
         @Override
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index ead90bb..3365ab7 100755
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -22,6 +22,7 @@
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
+import android.content.pm.ServiceInfo;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
@@ -1635,13 +1636,21 @@
 
     /**
      * Instructs Telecom to put the call into the background audio processing state.
-     *
+     * <p>
      * This method can be called either when the call is in {@link #STATE_RINGING} or
      * {@link #STATE_ACTIVE}. After Telecom acknowledges the request by setting the call's state to
      * {@link #STATE_AUDIO_PROCESSING}, your app may setup the audio paths with the audio stack in
      * order to capture and play audio on the call stream.
-     *
+     * <p>
      * This method can only be called by the default dialer app.
+     * <p>
+     * Apps built with SDK version {@link android.os.Build.VERSION_CODES#R} or later which are using
+     * the microphone as part of audio processing should specify the foreground service type using
+     * the attribute {@link android.R.attr#foregroundServiceType} in the {@link InCallService}
+     * service element of the app's manifest file.
+     * The {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} attribute should be specified.
+     * @see <a href="https://developer.android.com/preview/privacy/foreground-service-types">
+     * the Android Developer Site</a> for more information.
      * @hide
      */
     @SystemApi
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index f8722f4..8abab90 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -23,6 +23,7 @@
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.pm.ServiceInfo;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.IBinder;
@@ -281,9 +282,20 @@
              * Sets whether to request background audio processing so that the in-call service can
              * screen the call further. If set to {@code true}, {@link #setDisallowCall} should be
              * called with {@code false}, and all other parameters in this builder will be ignored.
-             *
+             * <p>
              * This request will only be honored if the {@link CallScreeningService} shares the same
              * uid as the default dialer app. Otherwise, the call will go through as usual.
+             * <p>
+             * Apps built with SDK version {@link android.os.Build.VERSION_CODES#R} or later which
+             * are using the microphone as part of audio processing should specify the
+             * foreground service type using the attribute
+             * {@link android.R.attr#foregroundServiceType} in the {@link CallScreeningService}
+             * service element of the app's manifest file.
+             * The {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} attribute should be
+             * specified.
+             * @see
+             * <a href="https://developer.android.com/preview/privacy/foreground-service-types">
+             *     the Android Developer Site</a> for more information.
              *
              * @param shouldScreenCallViaAudioProcessing Whether to request further call screening.
              * @hide
diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index bb6f154..b35b323 100644
--- a/telephony/common/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
@@ -536,13 +536,16 @@
 
         // Assign permission to special system apps
         assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
-                PHONE_PACKAGE_NAME);
+                PHONE_PACKAGE_NAME, true);
         assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
-                BLUETOOTH_PACKAGE_NAME);
+                BLUETOOTH_PACKAGE_NAME, true);
         assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
-                MMS_SERVICE_PACKAGE_NAME);
+                MMS_SERVICE_PACKAGE_NAME, true);
         assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
-                TELEPHONY_PROVIDER_PACKAGE_NAME);
+                TELEPHONY_PROVIDER_PACKAGE_NAME, true);
+        // CellbroadcastReceiver is a mainline module thus skip signature match.
+        assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
+                CellBroadcastUtils.getDefaultCellBroadcastReceiverPackageName(context), false);
 
         // Give AppOps permission to UID 1001 which contains multiple
         // apps, all of them should be able to write to telephony provider.
@@ -744,17 +747,23 @@
      * @param packageManager The package manager instance
      * @param appOps The AppOps manager instance
      * @param packageName The package name of the system app
+     * @param sigatureMatch whether to check signature match
      */
     private static void assignExclusiveSmsPermissionsToSystemApp(Context context,
-            PackageManager packageManager, AppOpsManager appOps, String packageName) {
+            PackageManager packageManager, AppOpsManager appOps, String packageName,
+            boolean sigatureMatch) {
         // First check package signature matches the caller's package signature.
         // Since this class is only used internally by the system, this check makes sure
         // the package signature matches system signature.
-        final int result = packageManager.checkSignatures(context.getPackageName(), packageName);
-        if (result != PackageManager.SIGNATURE_MATCH) {
-            Log.e(LOG_TAG, packageName + " does not have system signature");
-            return;
+        if (sigatureMatch) {
+            final int result = packageManager.checkSignatures(context.getPackageName(),
+                    packageName);
+            if (result != PackageManager.SIGNATURE_MATCH) {
+                Log.e(LOG_TAG, packageName + " does not have system signature");
+                return;
+            }
         }
+
         try {
             PackageInfo info = packageManager.getPackageInfo(packageName, 0);
             int mode = appOps.unsafeCheckOp(AppOpsManager.OPSTR_WRITE_SMS, info.applicationInfo.uid,
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index a28f281..50ff8f4 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1632,6 +1632,12 @@
             "show_precise_failed_cause_bool";
 
     /**
+     * Boolean to decide whether NR is enabled.
+     * @hide
+     */
+    public static final String KEY_NR_ENABLED_BOOL = "nr_enabled_bool";
+
+    /**
      * Boolean to decide whether LTE is enabled.
      */
     public static final String KEY_LTE_ENABLED_BOOL = "lte_enabled_bool";
@@ -4139,6 +4145,7 @@
         sDefaults.putString(KEY_OPERATOR_NAME_FILTER_PATTERN_STRING, "");
         sDefaults.putString(KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING, "");
         sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, true);
+        sDefaults.putBoolean(KEY_NR_ENABLED_BOOL, true);
         sDefaults.putBoolean(KEY_LTE_ENABLED_BOOL, true);
         sDefaults.putBoolean(KEY_SUPPORT_TDSCDMA_BOOL, false);
         sDefaults.putStringArray(KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY, null);
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 3546434..d62cd0a 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -837,20 +837,20 @@
                 + " carrierId=" + mCarrierId + " displayName=" + mDisplayName
                 + " carrierName=" + mCarrierName + " nameSource=" + mNameSource
                 + " iconTint=" + mIconTint
-                + " mNumber=" + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, mNumber)
-                + " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc
-                + " mnc " + mMnc + "mCountryIso=" + mCountryIso + " isEmbedded " + mIsEmbedded
-                + " nativeAccessRules " + Arrays.toString(mNativeAccessRules)
+                + " number=" + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, mNumber)
+                + " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc=" + mMcc
+                + " mnc=" + mMnc + " countryIso=" + mCountryIso + " isEmbedded=" + mIsEmbedded
+                + " nativeAccessRules=" + Arrays.toString(mNativeAccessRules)
                 + " cardString=" + cardStringToPrint + " cardId=" + mCardId
-                + " isOpportunistic=" + mIsOpportunistic + " mGroupUUID=" + mGroupUUID
-                + " mIsGroupDisabled=" + mIsGroupDisabled
+                + " isOpportunistic=" + mIsOpportunistic + " groupUUID=" + mGroupUUID
+                + " isGroupDisabled=" + mIsGroupDisabled
                 + " profileClass=" + mProfileClass
                 + " ehplmns=" + Arrays.toString(mEhplmns)
                 + " hplmns=" + Arrays.toString(mHplmns)
                 + " subscriptionType=" + mSubscriptionType
-                + " mGroupOwner=" + mGroupOwner
+                + " groupOwner=" + mGroupOwner
                 + " carrierConfigAccessRules=" + Arrays.toString(mCarrierConfigAccessRules)
-                + " mAreUiccApplicationsEnabled=" + mAreUiccApplicationsEnabled + "}";
+                + " areUiccApplicationsEnabled=" + mAreUiccApplicationsEnabled + "}";
     }
 
     @Override
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index e85dfbe..f5ed64e 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -7395,6 +7395,29 @@
     }
 
     /**
+     * Unregister a IImsServiceFeatureCallback previously associated with an ImsFeature through
+     * {@link #getImsMmTelFeatureAndListen(int, IImsServiceFeatureCallback)} or
+     * {@link #getImsRcsFeatureAndListen(int, IImsServiceFeatureCallback)}.
+     * @param slotIndex The SIM slot associated with the callback.
+     * @param featureType The {@link android.telephony.ims.feature.ImsFeature.FeatureType}
+     *                    associated with the callback.
+     * @param callback The callback to be unregistered.
+     * @hide
+     */
+    public void unregisterImsFeatureCallback(int slotIndex, int featureType,
+            IImsServiceFeatureCallback callback) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.unregisterImsFeatureCallback(slotIndex, featureType, callback);
+            }
+        } catch (RemoteException e) {
+            Rlog.e(TAG, "unregisterImsFeatureCallback, RemoteException: "
+                    + e.getMessage());
+        }
+    }
+
+    /**
      * @return the {@IImsRegistration} interface that corresponds with the slot index and feature.
      * @param slotIndex The SIM slot corresponding to the ImsService ImsRegistration is active for.
      * @param feature An integer indicating the feature that we wish to get the ImsRegistration for.
@@ -10415,7 +10438,7 @@
      * <p>To recognize a carrier (including MVNO) as a first-class identity, Android assigns each
      * carrier with a canonical integer a.k.a. carrier id. The carrier ID is an Android
      * platform-wide identifier for a carrier. AOSP maintains carrier ID assignments in
-     * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a>
+     * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb">here</a>
      *
      * <p>Apps which have carrier-specific configurations or business logic can use the carrier id
      * as an Android platform-wide identifier for carriers.
@@ -10477,7 +10500,7 @@
      *
      * <p>For carriers without fine-grained specific carrier ids, return {@link #getSimCarrierId()}
      * <p>Specific carrier ids are defined in the same way as carrier id
-     * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a>
+     * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb">here</a>
      * except each with a "parent" id linking to its top-level carrier id.
      *
      * @return Returns fine-grained carrier id of the current subscription.
@@ -10526,7 +10549,7 @@
      * This is used for fallback when configurations/logic for exact carrier id
      * {@link #getSimCarrierId()} are not found.
      *
-     * Android carrier id table <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a>
+     * Android carrier id table <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb">here</a>
      * can be updated out-of-band, its possible a MVNO (Mobile Virtual Network Operator) carrier
      * was not fully recognized and assigned to its MNO (Mobile Network Operator) carrier id
      * by default. After carrier id table update, a new carrier id was assigned. If apps don't
@@ -10553,7 +10576,7 @@
       * used for fallback when configurations/logic for exact carrier id {@link #getSimCarrierId()}
       * are not found.
       *
-      * Android carrier id table <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a>
+      * Android carrier id table <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb">here</a>
       * can be updated out-of-band, its possible a MVNO (Mobile Virtual Network Operator) carrier
       * was not fully recognized and assigned to its MNO (Mobile Network Operator) carrier id
       * by default. After carrier id table update, a new carrier id was assigned. If apps don't
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index ede67dd..94407f1 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -56,14 +56,15 @@
      * Activity Action: Show the opt-in dialog for enabling or disabling RCS contact discovery
      * using User Capability Exchange (UCE).
      * <p>
-     * An application that depends on contact discovery being enabled may send this intent
+     * An application that depends on RCS contact discovery being enabled must send this intent
      * using {@link Context#startActivity(Intent)} to ask the user to opt-in for contacts upload for
-     * capability exchange if it is currently disabled. Whether or not this setting has been enabled
-     * can be queried using {@link RcsUceAdapter#isUceSettingEnabled()}.
+     * capability exchange if it is currently disabled. Whether or not RCS contact discovery has
+     * been enabled by the user can be queried using {@link RcsUceAdapter#isUceSettingEnabled()}.
      * <p>
-     * This intent should only be sent if the carrier supports RCS capability exchange, which can be
-     * queried using the key {@link CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL}. Otherwise, the
-     * setting will not be present.
+     * This intent will always be handled by the system, however the application should only send
+     * this Intent if the carrier supports RCS contact discovery, which can be queried using the key
+     * {@link CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL}. Otherwise, the RCS contact discovery
+     * opt-in dialog will not be shown.
      * <p>
      * Input: A mandatory {@link Settings#EXTRA_SUB_ID} extra containing the subscription that the
      * setting will be be shown for.
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index 05ab6bd..ec11279 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -363,9 +363,10 @@
     /**
      * Change the user’s setting for whether or not UCE is enabled for the associated subscription.
      * <p>
-     * If an application Requires UCE, they may launch an Activity using the Intent
+     * If an application Requires UCE, they will launch an Activity using the Intent
      * {@link ImsRcsManager#ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN}, which will ask the user if
-     * they wish to enable this feature.
+     * they wish to enable this feature. This setting should only be enabled after the user has
+     * opted-in to capability exchange.
      * <p>
      * Note: This setting does not affect whether or not the device publishes its service
      * capabilities if the subscription supports presence publication.
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index f5cd68f..3690200 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -851,6 +851,14 @@
     IImsRcsFeature getRcsFeatureAndListen(int slotId, in IImsServiceFeatureCallback callback);
 
     /**
+     * Unregister a callback that was previously registered through
+     * {@link #getMmTelFeatureAndListen} or {@link #getRcsFeatureAndListen}. This should always be
+     * called when the callback is no longer being used.
+     */
+    void unregisterImsFeatureCallback(int slotId, int featureType,
+            in IImsServiceFeatureCallback callback);
+
+    /**
     * Returns the IImsRegistration associated with the slot and feature specified.
     */
     IImsRegistration getImsRegistration(int slotId, int feature);
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index ff70f8b..29286e8 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -240,5 +240,5 @@
      * two.
      * Type: int
      */
-    static final String PROPERTY_MAX_ACTIVE_MODEMS = "ro.telephony.max.active.modems";
+    static final String PROPERTY_MAX_ACTIVE_MODEMS = "telephony.active_modems.max_count";
 }
diff --git a/test-mock/api/lint-baseline.txt b/test-mock/api/lint-baseline.txt
index c6ba3f5..1411824 100644
--- a/test-mock/api/lint-baseline.txt
+++ b/test-mock/api/lint-baseline.txt
@@ -21,10 +21,6 @@
     Missing nullability on parameter `url` in method `getStreamTypes`
 MissingNullability: android.test.mock.MockContentProvider#getStreamTypes(android.net.Uri, String) parameter #1:
     Missing nullability on parameter `mimeTypeFilter` in method `getStreamTypes`
-MissingNullability: android.test.mock.MockContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean) parameter #0:
-    Missing nullability on parameter `uri` in method `notifyChange`
-MissingNullability: android.test.mock.MockContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean) parameter #1:
-    Missing nullability on parameter `observer` in method `notifyChange`
 MissingNullability: android.test.mock.MockContext#bindIsolatedService(android.content.Intent, int, String, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #0:
     Missing nullability on parameter `service` in method `bindIsolatedService`
 MissingNullability: android.test.mock.MockContext#bindIsolatedService(android.content.Intent, int, String, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #2:
@@ -39,6 +35,10 @@
     Missing nullability on parameter `executor` in method `bindService`
 MissingNullability: android.test.mock.MockContext#bindService(android.content.Intent, int, java.util.concurrent.Executor, android.content.ServiceConnection) parameter #3:
     Missing nullability on parameter `conn` in method `bindService`
+MissingNullability: android.test.mock.MockContext#createWindowContext(int, android.os.Bundle) parameter #1:
+    Missing nullability on parameter `options` in method `createWindowContext`
+MissingNullability: android.test.mock.MockContext#getDisplay():
+    Missing nullability on method `getDisplay` return
 MissingNullability: android.test.mock.MockContext#getMainExecutor():
     Missing nullability on method `getMainExecutor` return
 MissingNullability: android.test.mock.MockContext#sendOrderedBroadcast(android.content.Intent, String, String, android.content.BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle) parameter #0:
diff --git a/tests/NullHomeTest/Android.bp b/tests/NullHomeTest/Android.bp
new file mode 100644
index 0000000..99248bf
--- /dev/null
+++ b/tests/NullHomeTest/Android.bp
@@ -0,0 +1,22 @@
+// Copyright 2020 Google Inc. All Rights Reserved.
+//
+// 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.
+
+android_test {
+    name: "NullHomeTest",
+    srcs: ["src/**/*.java"],
+    certificate: "platform",
+    platform_apis: true,
+    static_libs: ["android-support-test"],
+    test_suites: ["device-tests"],
+}
diff --git a/tests/NullHomeTest/AndroidManifest.xml b/tests/NullHomeTest/AndroidManifest.xml
new file mode 100644
index 0000000..dc6402e
--- /dev/null
+++ b/tests/NullHomeTest/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.test.nullhome"
+    android:sharedUserId="android.uid.system" >
+
+    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.test.nullhome"
+        android:label="Check if no null Home exists/is enabled" />
+
+    <application android:label="Null Home Test">
+        <uses-library android:name="android.test.runner" />
+    </application>
+</manifest>
diff --git a/tests/NullHomeTest/src/com/android/test/nullhome/NullHomeTest.java b/tests/NullHomeTest/src/com/android/test/nullhome/NullHomeTest.java
new file mode 100644
index 0000000..1d77cdc
--- /dev/null
+++ b/tests/NullHomeTest/src/com/android/test/nullhome/NullHomeTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test.nullhome;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.support.test.InstrumentationRegistry;
+import android.util.Log;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+ * Check if NullHome/SystemUserHome activity does not exist/is disabled.
+ *
+ * SystemUserHome is only enabled in bootable CSI (csi_x86, csi_arm64)
+ * products and should not be enabled in other products.
+ *
+ * Shell's NullHome is empty and caused issues in sevaral manual GUI tests
+ * that try to select/use it, and should be removed.
+ *
+ * Settings' FallbackHome is fine because it's specially handled by Settings.
+ *
+ */
+
+@RunWith(JUnit4.class)
+public class NullHomeTest {
+    private static final String TAG = "NullHomeTest";
+    private Context mContext;
+    private PackageManager mPm;
+
+    @Before
+    public void before() {
+        Log.d(TAG, "beforeClass()");
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        mPm = mContext.getPackageManager();
+    }
+
+    @Test
+    public void checkNullHome() {
+        final List<ResolveInfo> homeActivities = new ArrayList<>();
+
+        mPm.getHomeActivities(homeActivities);
+        for (ResolveInfo activity : homeActivities) {
+            Log.d(TAG, "Home activity: " + activity.activityInfo.packageName);
+            Assert.assertNotEquals(activity.activityInfo.packageName,
+                    "com.android.internal.app.SystemUserHomeActivity");
+            Assert.assertNotEquals(activity.activityInfo.packageName,
+                    "com.android.shell");
+        }
+    }
+}
diff --git a/tests/UiBench/src/com/android/test/uibench/ClippedListActivity.java b/tests/UiBench/src/com/android/test/uibench/ClippedListActivity.java
index 2bf6040..e21dec3 100644
--- a/tests/UiBench/src/com/android/test/uibench/ClippedListActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/ClippedListActivity.java
@@ -15,27 +15,24 @@
  */
 package com.android.test.uibench;
 
-import android.os.Bundle;
 import android.view.MenuItem;
 import android.widget.ArrayAdapter;
 import android.widget.ListAdapter;
 
 import androidx.appcompat.app.ActionBarDrawerToggle;
-import androidx.appcompat.app.AppCompatActivity;
 import androidx.appcompat.widget.Toolbar;
 import androidx.core.view.GravityCompat;
 import androidx.drawerlayout.widget.DrawerLayout;
-import androidx.fragment.app.FragmentManager;
-import androidx.fragment.app.ListFragment;
+
+import com.android.test.uibench.listview.CompatListActivity;
 
 import com.google.android.material.navigation.NavigationView;
 
-public class ClippedListActivity extends AppCompatActivity
+public class ClippedListActivity extends CompatListActivity
         implements NavigationView.OnNavigationItemSelectedListener {
 
     @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
+    protected void initializeActivity() {
         setContentView(R.layout.activity_navigation_drawer);
         Toolbar toolbar = findViewById(R.id.toolbar);
         setSupportActionBar(toolbar);
@@ -48,15 +45,17 @@
 
         NavigationView navigationView = findViewById(R.id.nav_view);
         navigationView.setNavigationItemSelectedListener(this);
+    }
 
-        FragmentManager fm = getSupportFragmentManager();
-        if (fm.findFragmentById(android.R.id.content) == null) {
-            ListFragment listFragment = new ListFragment();
-            ListAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,
-                    TextUtils.buildSimpleStringList(40));
-            listFragment.setListAdapter(adapter);
-            fm.beginTransaction().add(R.id.app_bar_layout, listFragment).commit();
-        }
+    @Override
+    protected ListAdapter createListAdapter() {
+        return new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,
+                TextUtils.buildSimpleStringList(40));
+    }
+
+    @Override
+    protected int getListFragmentContainerViewId() {
+        return R.id.app_bar_layout;
     }
 
     @Override
diff --git a/tests/UiBench/src/com/android/test/uibench/MainActivity.java b/tests/UiBench/src/com/android/test/uibench/MainActivity.java
index 0a7aa42..77a6c32 100644
--- a/tests/UiBench/src/com/android/test/uibench/MainActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/MainActivity.java
@@ -19,13 +19,15 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
-import androidx.fragment.app.FragmentManager;
-import androidx.fragment.app.ListFragment;
-import androidx.appcompat.app.AppCompatActivity;
 import android.view.View;
+import android.widget.ListAdapter;
 import android.widget.ListView;
 import android.widget.SimpleAdapter;
 
+import androidx.fragment.app.ListFragment;
+
+import com.android.test.uibench.listview.CompatListActivity;
+
 import java.text.Collator;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -34,10 +36,12 @@
 import java.util.List;
 import java.util.Map;
 
-public class MainActivity extends AppCompatActivity {
+public class MainActivity extends CompatListActivity {
     private static final String EXTRA_PATH = "activity_path";
     private static final String CATEGORY_HWUI_TEST = "com.android.test.uibench.TEST";
 
+    private String mActivityPath = "";
+
     public static class TestListFragment extends ListFragment {
         @Override
         @SuppressWarnings("unchecked")
@@ -56,9 +60,7 @@
     }
 
     @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
+    protected void initializeActivity() {
         Intent intent = getIntent();
         String path = intent.getStringExtra(EXTRA_PATH);
 
@@ -68,15 +70,19 @@
             // not root level, display where we are in the hierarchy
             setTitle(path);
         }
+        mActivityPath = path;
+    }
 
-        FragmentManager fm = getSupportFragmentManager();
-        if (fm.findFragmentById(android.R.id.content) == null) {
-            ListFragment listFragment = new TestListFragment();
-            listFragment.setListAdapter(new SimpleAdapter(this, getData(path),
-                    android.R.layout.simple_list_item_1, new String[] { "title" },
-                    new int[] { android.R.id.text1 }));
-            fm.beginTransaction().add(android.R.id.content, listFragment).commit();
-        }
+    @Override
+    protected ListAdapter createListAdapter() {
+        return new SimpleAdapter(this, getData(mActivityPath),
+                android.R.layout.simple_list_item_1, new String[] { "title" },
+                new int[] { android.R.id.text1 });
+    }
+
+    @Override
+    protected ListFragment createListFragment() {
+        return new TestListFragment();
     }
 
     protected List<Map<String, Object>> getData(String prefix) {
diff --git a/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java b/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java
index af7c65a..d6e1d06 100644
--- a/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java
@@ -16,13 +16,15 @@
 package com.android.test.uibench;
 
 import android.os.Bundle;
-import androidx.fragment.app.FragmentManager;
-import androidx.fragment.app.ListFragment;
-import androidx.appcompat.app.AppCompatActivity;
 import android.view.View;
 import android.widget.ArrayAdapter;
+import android.widget.ListAdapter;
 
-public class ShadowGridActivity extends AppCompatActivity {
+import androidx.fragment.app.ListFragment;
+
+import com.android.test.uibench.listview.CompatListActivity;
+
+public class ShadowGridActivity extends CompatListActivity {
     public static class NoDividerListFragment extends ListFragment {
         @Override
         public void onViewCreated(View view, Bundle savedInstanceState) {
@@ -31,18 +33,14 @@
         }
     };
 
+    @Override
+    protected ListAdapter createListAdapter() {
+        return new ArrayAdapter<>(this, R.layout.card_row, R.id.card_text,
+                TextUtils.buildSimpleStringList());
+    }
 
     @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        FragmentManager fm = getSupportFragmentManager();
-        if (fm.findFragmentById(android.R.id.content) == null) {
-            ListFragment listFragment = new NoDividerListFragment();
-
-            listFragment.setListAdapter(new ArrayAdapter<>(this,
-                    R.layout.card_row, R.id.card_text, TextUtils.buildSimpleStringList()));
-            fm.beginTransaction().add(android.R.id.content, listFragment).commit();
-        }
+    protected ListFragment createListFragment() {
+        return new NoDividerListFragment();
     }
 }
diff --git a/tests/UiBench/src/com/android/test/uibench/listview/CompatListActivity.java b/tests/UiBench/src/com/android/test/uibench/listview/CompatListActivity.java
index 6659558..9a4b527 100644
--- a/tests/UiBench/src/com/android/test/uibench/listview/CompatListActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/listview/CompatListActivity.java
@@ -16,22 +16,29 @@
 package com.android.test.uibench.listview;
 
 import android.os.Bundle;
+import android.widget.ListAdapter;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentManager;
 import androidx.fragment.app.ListFragment;
-import androidx.appcompat.app.AppCompatActivity;
-import android.widget.ListAdapter;
 
 public abstract class CompatListActivity extends AppCompatActivity {
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        initializeActivity();
 
+        int containerViewId = getListFragmentContainerViewId();
         FragmentManager fm = getSupportFragmentManager();
-        if (fm.findFragmentById(android.R.id.content) == null) {
+        Fragment fragment = fm.findFragmentById(containerViewId);
+        if (fragment == null) {
             ListFragment listFragment = createListFragment();
             listFragment.setListAdapter(createListAdapter());
-            fm.beginTransaction().add(android.R.id.content, listFragment).commit();
+            fm.beginTransaction().add(containerViewId, listFragment).commit();
+        } else if (fragment instanceof ListFragment) {
+            ((ListFragment) fragment).setListAdapter(createListAdapter());
         }
     }
 
@@ -40,4 +47,11 @@
     protected ListFragment createListFragment() {
         return new ListFragment();
     }
+
+    protected int getListFragmentContainerViewId() {
+        return android.R.id.content;
+    }
+
+    protected void initializeActivity() {
+    }
 }
diff --git a/tests/UiBench/src/com/android/test/uibench/recyclerview/RvCompatListActivity.java b/tests/UiBench/src/com/android/test/uibench/recyclerview/RvCompatListActivity.java
index bd313ad..2f0d6ab 100644
--- a/tests/UiBench/src/com/android/test/uibench/recyclerview/RvCompatListActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/recyclerview/RvCompatListActivity.java
@@ -17,16 +17,17 @@
 
 import android.content.Context;
 import android.os.Bundle;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentManager;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
 import com.android.test.uibench.R;
 
 public abstract class RvCompatListActivity extends AppCompatActivity {
@@ -51,14 +52,21 @@
         super.onCreate(savedInstanceState);
 
         FragmentManager fm = getSupportFragmentManager();
-        if (fm.findFragmentById(android.R.id.content) == null) {
+        Fragment existingFragment = fm.findFragmentById(android.R.id.content);
+        if (existingFragment == null) {
             RecyclerViewFragment fragment = new RecyclerViewFragment();
-            fragment.layoutManager = createLayoutManager(this);
-            fragment.adapter = createAdapter();
+            initializeRecyclerViewFragment(fragment);
             fm.beginTransaction().add(android.R.id.content, fragment).commit();
+        } else if (existingFragment instanceof RecyclerViewFragment) {
+            initializeRecyclerViewFragment((RecyclerViewFragment) existingFragment);
         }
     }
 
+    private void initializeRecyclerViewFragment(RecyclerViewFragment fragment) {
+        fragment.layoutManager = createLayoutManager(this);
+        fragment.adapter = createAdapter();
+    }
+
     protected RecyclerView.LayoutManager createLayoutManager(Context context) {
         return new LinearLayoutManager(context);
     }
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
index eec3cdbe..8c2de40 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
@@ -52,7 +52,7 @@
         doReturn(mock(IBinder::class.java)).`when`(it).getSystemService(Context.NETD_SERVICE)
     }
 
-    private class TestPermissionChecker : NetworkStackConnector.PermissionChecker() {
+    private class TestPermissionChecker : NetworkStackService.PermissionChecker() {
         override fun enforceNetworkStackCallingPermission() = Unit
     }
 
@@ -62,8 +62,8 @@
         override fun sendNetworkConditionsBroadcast(context: Context, broadcast: Intent) = Unit
     }
 
-    private inner class TestNetworkStackConnector(context: Context) :
-            NetworkStackConnector(context, TestPermissionChecker()) {
+    private inner class TestNetworkStackConnector(context: Context) : NetworkStackConnector(
+            context, TestPermissionChecker(), NetworkStackService.Dependencies()) {
 
         private val network = Network(TEST_NETID)
         private val privateDnsBypassNetwork = TestNetwork(TEST_NETID)
diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
index a35fb40..0ffafd4 100644
--- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -92,6 +92,9 @@
                 break;
             case TRANSPORT_VPN:
                 mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
+                // VPNs deduce the SUSPENDED capability from their underlying networks and there
+                // is no public API to let VPN services set it.
+                mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
                 mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
                 break;
             default:
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index a992778..83ca9b2 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -75,6 +75,7 @@
 import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
 import static android.net.RouteInfo.RTN_UNREACHABLE;
+import static android.os.Process.INVALID_UID;
 import static android.system.OsConstants.IPPROTO_TCP;
 
 import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType;
@@ -5386,8 +5387,6 @@
 
         // Even though the VPN is unvalidated, it becomes the default network for our app.
         callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
-        // TODO: this looks like a spurious callback.
-        callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
         callback.assertNoCallback();
 
         assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
@@ -5417,6 +5416,47 @@
     }
 
     @Test
+    public void testVpnStartsWithUnderlyingCaps() throws Exception {
+        final int uid = Process.myUid();
+
+        final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
+        final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
+                .removeCapability(NET_CAPABILITY_NOT_VPN)
+                .addTransportType(TRANSPORT_VPN)
+                .build();
+        mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
+        vpnNetworkCallback.assertNoCallback();
+
+        // Connect cell. It will become the default network, and in the absence of setting
+        // underlying networks explicitly it will become the sole underlying network for the vpn.
+        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        mCellNetworkAgent.connect(true);
+
+        final TestNetworkAgentWrapper vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN);
+        final ArraySet<UidRange> ranges = new ArraySet<>();
+        ranges.add(new UidRange(uid, uid));
+        mMockVpn.setNetworkAgent(vpnNetworkAgent);
+        mMockVpn.connect();
+        mMockVpn.setUids(ranges);
+        vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
+                false /* isStrictMode */);
+
+        vpnNetworkCallback.expectAvailableCallbacks(vpnNetworkAgent.getNetwork(),
+                false /* suspended */, false /* validated */, false /* blocked */, TIMEOUT_MS);
+        vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent.getNetwork(), TIMEOUT_MS,
+                nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED));
+
+        final NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
+        assertTrue(nc.hasTransport(TRANSPORT_VPN));
+        assertTrue(nc.hasTransport(TRANSPORT_CELLULAR));
+        assertFalse(nc.hasTransport(TRANSPORT_WIFI));
+        assertTrue(nc.hasCapability(NET_CAPABILITY_VALIDATED));
+        assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
+        assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+    }
+
+    @Test
     public void testVpnSetUnderlyingNetworks() throws Exception {
         final int uid = Process.myUid();
 
@@ -5446,9 +5486,12 @@
         assertFalse(nc.hasTransport(TRANSPORT_WIFI));
         // For safety reasons a VPN without underlying networks is considered metered.
         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
+        // A VPN without underlying networks is not suspended.
+        assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
 
         // Connect cell and use it as an underlying network.
         mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
         mCellNetworkAgent.connect(true);
 
         mService.setUnderlyingNetworksForVpn(
@@ -5457,10 +5500,12 @@
         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
+                && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
 
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
         mWiFiNetworkAgent.connect(true);
 
         mService.setUnderlyingNetworksForVpn(
@@ -5469,7 +5514,8 @@
         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
+                && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
 
         // Don't disconnect, but note the VPN is not using wifi any more.
         mService.setUnderlyingNetworksForVpn(
@@ -5478,16 +5524,36 @@
         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
                 && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
+                && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
 
-        // Use Wifi but not cell. Note the VPN is now unmetered.
+        // Remove NOT_SUSPENDED from the only network and observe VPN is now suspended.
+        mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+                (caps) -> caps.hasTransport(TRANSPORT_VPN)
+                && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
+                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
+                && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        vpnNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, vpnNetworkAgent);
+
+        // Add NOT_SUSPENDED again and observe VPN is no longer suspended.
+        mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+                (caps) -> caps.hasTransport(TRANSPORT_VPN)
+                && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
+                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
+                && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, vpnNetworkAgent);
+
+        // Use Wifi but not cell. Note the VPN is now unmetered and not suspended.
         mService.setUnderlyingNetworksForVpn(
                 new Network[] { mWiFiNetworkAgent.getNetwork() });
 
         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
                 && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
-                && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+                && caps.hasCapability(NET_CAPABILITY_NOT_METERED)
+                && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
 
         // Use both again.
         mService.setUnderlyingNetworksForVpn(
@@ -5496,7 +5562,37 @@
         vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
                 (caps) -> caps.hasTransport(TRANSPORT_VPN)
                 && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
-                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
+                && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+
+        // Cell is suspended again. As WiFi is not, this should not cause a callback.
+        mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        vpnNetworkCallback.assertNoCallback();
+
+        // Stop using WiFi. The VPN is suspended again.
+        mService.setUnderlyingNetworksForVpn(
+                new Network[] { mCellNetworkAgent.getNetwork() });
+        vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+                (caps) -> caps.hasTransport(TRANSPORT_VPN)
+                && caps.hasTransport(TRANSPORT_CELLULAR)
+                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
+                && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        // While the SUSPENDED callback should in theory be sent here, it is not. This is
+        // a bug in ConnectivityService, but as the SUSPENDED and RESUMED callbacks have never
+        // been public and are deprecated and slated for removal, there is no sense in spending
+        // resources fixing this bug now.
+
+        // Use both again.
+        mService.setUnderlyingNetworksForVpn(
+                new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
+
+        vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+                (caps) -> caps.hasTransport(TRANSPORT_VPN)
+                && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
+                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
+                && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+        // As above, the RESUMED callback not being sent here is a bug, but not a bug that's
+        // worth anybody's time to fix.
 
         // Disconnect cell. Receive update without even removing the dead network from the
         // underlying networks – it's dead anyway. Not metered any more.
@@ -6945,7 +7041,7 @@
         final NetworkAgentInfo naiWithoutUid =
                 new NetworkAgentInfo(
                         null, null, null, null, null, new NetworkCapabilities(), 0,
-                        mServiceContext, null, null, mService, null, null, null, 0);
+                        mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
 
         mServiceContext.setPermission(
                 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
@@ -6961,7 +7057,7 @@
         final NetworkAgentInfo naiWithoutUid =
                 new NetworkAgentInfo(
                         null, null, null, null, null, new NetworkCapabilities(), 0,
-                        mServiceContext, null, null, mService, null, null, null, 0);
+                        mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
 
         mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
 
@@ -6977,7 +7073,7 @@
         final NetworkAgentInfo naiWithoutUid =
                 new NetworkAgentInfo(
                         null, null, null, null, null, new NetworkCapabilities(), 0,
-                        mServiceContext, null, null, mService, null, null, null, 0);
+                        mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
 
         mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
 
@@ -6994,7 +7090,7 @@
         final NetworkAgentInfo naiWithoutUid =
                 new NetworkAgentInfo(
                         null, null, network, null, null, new NetworkCapabilities(), 0,
-                        mServiceContext, null, null, mService, null, null, null, 0);
+                        mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
 
         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
                 Manifest.permission.ACCESS_FINE_LOCATION);
@@ -7028,7 +7124,7 @@
         final NetworkAgentInfo naiWithUid =
                 new NetworkAgentInfo(
                         null, null, null, null, null, nc, 0, mServiceContext, null, null,
-                        mService, null, null, null, 0);
+                        mService, null, null, null, 0, INVALID_UID);
 
         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
                 Manifest.permission.ACCESS_FINE_LOCATION);
@@ -7050,7 +7146,7 @@
         final NetworkAgentInfo naiWithUid =
                 new NetworkAgentInfo(
                         null, null, null, null, null, nc, 0, mServiceContext, null, null,
-                        mService, null, null, null, 0);
+                        mService, null, null, null, 0, INVALID_UID);
 
         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
                 Manifest.permission.ACCESS_FINE_LOCATION);
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index 23098ec..529d03c 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -547,6 +547,16 @@
 
     @Test
     public void testApplyTransportModeTransform() throws Exception {
+        verifyApplyTransportModeTransformCommon(false);
+    }
+
+    @Test
+    public void testApplyTransportModeTransformReleasedSpi() throws Exception {
+        verifyApplyTransportModeTransformCommon(true);
+    }
+
+    public void verifyApplyTransportModeTransformCommon(
+                boolean closeSpiBeforeApply) throws Exception {
         IpSecConfig ipSecConfig = new IpSecConfig();
         addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
         addAuthAndCryptToIpSecConfig(ipSecConfig);
@@ -554,6 +564,39 @@
         IpSecTransformResponse createTransformResp =
                 mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
 
+        if (closeSpiBeforeApply) {
+            mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
+        }
+
+        Socket socket = new Socket();
+        socket.bind(null);
+        ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket);
+
+        int resourceId = createTransformResp.resourceId;
+        mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId);
+
+        verify(mMockNetd)
+                .ipSecApplyTransportModeTransform(
+                        eq(pfd),
+                        eq(mUid),
+                        eq(IpSecManager.DIRECTION_OUT),
+                        anyString(),
+                        anyString(),
+                        eq(TEST_SPI));
+    }
+
+    @Test
+    public void testApplyTransportModeTransformWithClosedSpi() throws Exception {
+        IpSecConfig ipSecConfig = new IpSecConfig();
+        addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
+        addAuthAndCryptToIpSecConfig(ipSecConfig);
+
+        IpSecTransformResponse createTransformResp =
+                mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
+
+        // Close SPI record
+        mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
+
         Socket socket = new Socket();
         socket.bind(null);
         ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket);
@@ -660,6 +703,15 @@
 
     @Test
     public void testApplyTunnelModeTransform() throws Exception {
+        verifyApplyTunnelModeTransformCommon(false);
+    }
+
+    @Test
+    public void testApplyTunnelModeTransformReleasedSpi() throws Exception {
+        verifyApplyTunnelModeTransformCommon(true);
+    }
+
+    public void verifyApplyTunnelModeTransformCommon(boolean closeSpiBeforeApply) throws Exception {
         IpSecConfig ipSecConfig = new IpSecConfig();
         ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL);
         addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
@@ -670,6 +722,49 @@
         IpSecTunnelInterfaceResponse createTunnelResp =
                 createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
 
+        if (closeSpiBeforeApply) {
+            mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
+        }
+
+        int transformResourceId = createTransformResp.resourceId;
+        int tunnelResourceId = createTunnelResp.resourceId;
+        mIpSecService.applyTunnelModeTransform(tunnelResourceId, IpSecManager.DIRECTION_OUT,
+                transformResourceId, "blessedPackage");
+
+        for (int selAddrFamily : ADDRESS_FAMILIES) {
+            verify(mMockNetd)
+                    .ipSecUpdateSecurityPolicy(
+                            eq(mUid),
+                            eq(selAddrFamily),
+                            eq(IpSecManager.DIRECTION_OUT),
+                            anyString(),
+                            anyString(),
+                            eq(TEST_SPI),
+                            anyInt(), // iKey/oKey
+                            anyInt(), // mask
+                            eq(tunnelResourceId));
+        }
+
+        ipSecConfig.setXfrmInterfaceId(tunnelResourceId);
+        verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
+    }
+
+
+    @Test
+    public void testApplyTunnelModeTransformWithClosedSpi() throws Exception {
+        IpSecConfig ipSecConfig = new IpSecConfig();
+        ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL);
+        addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
+        addAuthAndCryptToIpSecConfig(ipSecConfig);
+
+        IpSecTransformResponse createTransformResp =
+                mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
+        IpSecTunnelInterfaceResponse createTunnelResp =
+                createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage");
+
+        // Close SPI record
+        mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
+
         int transformResourceId = createTransformResp.resourceId;
         int tunnelResourceId = createTunnelResp.resourceId;
         mIpSecService.applyTunnelModeTransform(tunnelResourceId, IpSecManager.DIRECTION_OUT,
diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
index 24a8717..aafa18a 100644
--- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -38,6 +38,7 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkProvider;
+import android.os.Binder;
 import android.os.INetworkManagementService;
 import android.text.format.DateUtils;
 
@@ -354,7 +355,7 @@
         caps.addTransportType(transport);
         NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null,
                 caps, 50, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS,
-                NetworkProvider.ID_NONE);
+                NetworkProvider.ID_NONE, Binder.getCallingUid());
         nai.everValidated = true;
         return nai;
     }
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 1994d1f..f8d8a56 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -25,6 +25,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
@@ -606,6 +607,7 @@
                         .addCapability(NET_CAPABILITY_NOT_METERED)
                         .addCapability(NET_CAPABILITY_NOT_ROAMING)
                         .addCapability(NET_CAPABILITY_NOT_CONGESTED)
+                        .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
                         .setLinkUpstreamBandwidthKbps(20));
         setMockedNetworks(networks);
 
@@ -621,6 +623,7 @@
         assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
+        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
 
         Vpn.applyUnderlyingCapabilities(
                 mConnectivityManager,
@@ -635,6 +638,7 @@
         assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
         assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
+        assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
 
         Vpn.applyUnderlyingCapabilities(
                 mConnectivityManager, new Network[] {wifi}, caps, false /* isAlwaysMetered */);
@@ -646,6 +650,7 @@
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
+        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
 
         Vpn.applyUnderlyingCapabilities(
                 mConnectivityManager, new Network[] {wifi}, caps, true /* isAlwaysMetered */);
@@ -657,6 +662,7 @@
         assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
+        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
 
         Vpn.applyUnderlyingCapabilities(
                 mConnectivityManager,
@@ -671,6 +677,7 @@
         assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
         assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
+        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
     }
 
     /**
diff --git a/tests/testables/src/android/testing/TestableLooper.java b/tests/testables/src/android/testing/TestableLooper.java
index fe0224a..ebe9b57 100644
--- a/tests/testables/src/android/testing/TestableLooper.java
+++ b/tests/testables/src/android/testing/TestableLooper.java
@@ -222,6 +222,10 @@
         return sLoopers.get(test);
     }
 
+    public static void remove(Object test) {
+        sLoopers.remove(test);
+    }
+
     static class LooperFrameworkMethod extends FrameworkMethod {
         private HandlerThread mHandlerThread;
 
diff --git a/tools/validatekeymaps/OWNERS b/tools/validatekeymaps/OWNERS
new file mode 100644
index 0000000..0313a40
--- /dev/null
+++ b/tools/validatekeymaps/OWNERS
@@ -0,0 +1,2 @@
+michaelwr@google.com
+svv@google.com
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index f5b5622..aa3a139 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -524,6 +524,161 @@
      * {@hide}
      */
     public final static int UNSPECIFIED = -1;
+
+    /**
+     * 2.4 GHz band first channel number
+     * @hide
+     */
+    public static final int BAND_24_GHZ_FIRST_CH_NUM = 1;
+    /**
+     * 2.4 GHz band last channel number
+     * @hide
+     */
+    public static final int BAND_24_GHZ_LAST_CH_NUM = 14;
+    /**
+     * 2.4 GHz band frequency of first channel in MHz
+     * @hide
+     */
+    public static final int BAND_24_GHZ_START_FREQ_MHZ = 2412;
+    /**
+     * 2.4 GHz band frequency of last channel in MHz
+     * @hide
+     */
+    public static final int BAND_24_GHZ_END_FREQ_MHZ = 2484;
+
+    /**
+     * 5 GHz band first channel number
+     * @hide
+     */
+    public static final int BAND_5_GHZ_FIRST_CH_NUM = 32;
+    /**
+     * 5 GHz band last channel number
+     * @hide
+     */
+    public static final int BAND_5_GHZ_LAST_CH_NUM = 173;
+    /**
+     * 5 GHz band frequency of first channel in MHz
+     * @hide
+     */
+    public static final int BAND_5_GHZ_START_FREQ_MHZ = 5160;
+    /**
+     * 5 GHz band frequency of last channel in MHz
+     * @hide
+     */
+    public static final int BAND_5_GHZ_END_FREQ_MHZ = 5865;
+
+    /**
+     * 6 GHz band first channel number
+     * @hide
+     */
+    public static final int BAND_6_GHZ_FIRST_CH_NUM = 1;
+    /**
+     * 6 GHz band last channel number
+     * @hide
+     */
+    public static final int BAND_6_GHZ_LAST_CH_NUM = 233;
+    /**
+     * 6 GHz band frequency of first channel in MHz
+     * @hide
+     */
+    public static final int BAND_6_GHZ_START_FREQ_MHZ = 5945;
+    /**
+     * 6 GHz band frequency of last channel in MHz
+     * @hide
+     */
+    public static final int BAND_6_GHZ_END_FREQ_MHZ = 7105;
+
+    /**
+     * Utility function to check if a frequency within 2.4 GHz band
+     * @param freqMhz frequency in MHz
+     * @return true if within 2.4GHz, false otherwise
+     *
+     * @hide
+     */
+    public static boolean is24GHz(int freqMhz) {
+        return freqMhz >= BAND_24_GHZ_START_FREQ_MHZ && freqMhz <= BAND_24_GHZ_END_FREQ_MHZ;
+    }
+
+    /**
+     * Utility function to check if a frequency within 5 GHz band
+     * @param freqMhz frequency in MHz
+     * @return true if within 5GHz, false otherwise
+     *
+     * @hide
+     */
+    public static boolean is5GHz(int freqMhz) {
+        return freqMhz >=  BAND_5_GHZ_START_FREQ_MHZ && freqMhz <= BAND_5_GHZ_END_FREQ_MHZ;
+    }
+
+    /**
+     * Utility function to check if a frequency within 6 GHz band
+     * @param freqMhz
+     * @return true if within 6GHz, false otherwise
+     *
+     * @hide
+     */
+    public static boolean is6GHz(int freqMhz) {
+        return freqMhz >= BAND_6_GHZ_START_FREQ_MHZ && freqMhz <= BAND_6_GHZ_END_FREQ_MHZ;
+    }
+
+    /**
+     * Utility function to convert channel number/band to frequency in MHz
+     * @param channel number to convert
+     * @param band of channel to convert
+     * @return center frequency in Mhz of the channel, {@link UNSPECIFIED} if no match
+     *
+     * @hide
+     */
+    public static int convertChannelToFrequencyMhz(int channel, @WifiScanner.WifiBand int band) {
+        if (band == WifiScanner.WIFI_BAND_24_GHZ) {
+            // Special case
+            if (channel == 14) {
+                return 2484;
+            } else if (channel >= BAND_24_GHZ_FIRST_CH_NUM && channel <= BAND_24_GHZ_LAST_CH_NUM) {
+                return ((channel - BAND_24_GHZ_FIRST_CH_NUM) * 5) + BAND_24_GHZ_START_FREQ_MHZ;
+            } else {
+                return UNSPECIFIED;
+            }
+        }
+        if (band == WifiScanner.WIFI_BAND_5_GHZ) {
+            if (channel >= BAND_5_GHZ_FIRST_CH_NUM && channel <= BAND_5_GHZ_LAST_CH_NUM) {
+                return ((channel - BAND_5_GHZ_FIRST_CH_NUM) * 5) + BAND_5_GHZ_START_FREQ_MHZ;
+            } else {
+                return UNSPECIFIED;
+            }
+        }
+        if (band == WifiScanner.WIFI_BAND_6_GHZ) {
+            if (channel >= BAND_6_GHZ_FIRST_CH_NUM && channel <= BAND_6_GHZ_LAST_CH_NUM) {
+                return ((channel - BAND_6_GHZ_FIRST_CH_NUM) * 5) + BAND_6_GHZ_START_FREQ_MHZ;
+            } else {
+                return UNSPECIFIED;
+            }
+        }
+        return UNSPECIFIED;
+    }
+
+    /**
+     * Utility function to convert frequency in MHz to channel number
+     * @param freqMhz frequency in MHz
+     * @return channel number associated with given frequency, {@link UNSPECIFIED} if no match
+     *
+     * @hide
+     */
+    public static int convertFrequencyMhzToChannel(int freqMhz) {
+        // Special case
+        if (freqMhz == 2484) {
+            return 14;
+        } else if (is24GHz(freqMhz)) {
+            return (freqMhz - BAND_24_GHZ_START_FREQ_MHZ) / 5 + BAND_24_GHZ_FIRST_CH_NUM;
+        } else if (is5GHz(freqMhz)) {
+            return ((freqMhz - BAND_5_GHZ_START_FREQ_MHZ) / 5) + BAND_5_GHZ_FIRST_CH_NUM;
+        } else if (is6GHz(freqMhz)) {
+            return ((freqMhz - BAND_6_GHZ_START_FREQ_MHZ) / 5) + BAND_6_GHZ_FIRST_CH_NUM;
+        }
+
+        return UNSPECIFIED;
+    }
+
     /**
      * @hide
      */
@@ -533,14 +688,6 @@
 
     /**
      * @hide
-     * TODO: makes real freq boundaries
-     */
-    public static boolean is24GHz(int freq) {
-        return freq > 2400 && freq < 2500;
-    }
-
-    /**
-     * @hide
      */
     public boolean is5GHz() {
         return ScanResult.is5GHz(frequency);
@@ -554,21 +701,6 @@
     }
 
     /**
-     * @hide
-     * TODO: makes real freq boundaries
-     */
-    public static boolean is5GHz(int freq) {
-        return freq > 4900 && freq < 5900;
-    }
-
-    /**
-     * @hide
-     */
-    public static boolean is6GHz(int freq) {
-        return freq > 5925 && freq < 7125;
-    }
-
-    /**
      *  @hide
      * anqp lines from supplicant BSS response
      */
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 7d20d0d..5f46cb3 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -817,6 +817,9 @@
     /**
      * Broadcast intent action indicating that the wifi network settings
      * had been reset.
+     *
+     * Note: This intent is sent as a directed broadcast to each manifest registered receiver.
+     * Intent will not be received by dynamically registered receivers.
      * @hide
      */
     @SystemApi
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index d299cdc..94771ac 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -131,10 +131,10 @@
     public @interface WifiBand {}
 
     /**
-     * Max band value
+     * All bands
      * @hide
      */
-    public static final int WIFI_BAND_MAX = 0x10;
+    public static final int WIFI_BAND_ALL = (1 << WIFI_BAND_COUNT) - 1;
 
     /** Minimum supported scanning period */
     public static final int MIN_SCAN_PERIOD_MS = 1000;
@@ -168,6 +168,22 @@
     }
 
     /**
+     * Test if scan is a full scan. i.e. scanning all available bands.
+     * For backward compatibility, since some apps don't include 6GHz in their requests yet,
+     * lacking 6GHz band does not cause the result to be false.
+     *
+     * @param bandScanned bands that are fully scanned
+     * @param excludeDfs when true, DFS band is excluded from the check
+     * @return true if all bands are scanned, false otherwise
+     *
+     * @hide
+     */
+    public static boolean isFullBandScan(@WifiBand int bandScanned, boolean excludeDfs) {
+        return (bandScanned | WIFI_BAND_6_GHZ | (excludeDfs ? WIFI_BAND_5_GHZ_DFS_ONLY : 0))
+                == WIFI_BAND_ALL;
+    }
+
+    /**
      * Returns a list of all the possible channels for the given band(s).
      *
      * @param band one of the WifiScanner#WIFI_BAND_* constants, e.g. {@link #WIFI_BAND_24_GHZ}
diff --git a/wifi/tests/src/android/net/wifi/ScanResultTest.java b/wifi/tests/src/android/net/wifi/ScanResultTest.java
index 6cb8324..5516f43 100644
--- a/wifi/tests/src/android/net/wifi/ScanResultTest.java
+++ b/wifi/tests/src/android/net/wifi/ScanResultTest.java
@@ -46,6 +46,68 @@
             ScanResult.WIFI_STANDARD_11AC;
 
     /**
+     * Frequency to channel map. This include some frequencies used outside the US.
+     * Representing it using a vector (instead of map) for simplification.
+     */
+    private static final int[] FREQUENCY_TO_CHANNEL_MAP = {
+            2412, WifiScanner.WIFI_BAND_24_GHZ, 1,
+            2417, WifiScanner.WIFI_BAND_24_GHZ, 2,
+            2422, WifiScanner.WIFI_BAND_24_GHZ, 3,
+            2427, WifiScanner.WIFI_BAND_24_GHZ, 4,
+            2432, WifiScanner.WIFI_BAND_24_GHZ, 5,
+            2437, WifiScanner.WIFI_BAND_24_GHZ, 6,
+            2442, WifiScanner.WIFI_BAND_24_GHZ, 7,
+            2447, WifiScanner.WIFI_BAND_24_GHZ, 8,
+            2452, WifiScanner.WIFI_BAND_24_GHZ, 9,
+            2457, WifiScanner.WIFI_BAND_24_GHZ, 10,
+            2462, WifiScanner.WIFI_BAND_24_GHZ, 11,
+            /* 12, 13 are only legitimate outside the US. */
+            2467, WifiScanner.WIFI_BAND_24_GHZ, 12,
+            2472, WifiScanner.WIFI_BAND_24_GHZ, 13,
+            /* 14 is for Japan, DSSS and CCK only. */
+            2484, WifiScanner.WIFI_BAND_24_GHZ, 14,
+            /* 34 valid in Japan. */
+            5170, WifiScanner.WIFI_BAND_5_GHZ, 34,
+            5180, WifiScanner.WIFI_BAND_5_GHZ, 36,
+            5190, WifiScanner.WIFI_BAND_5_GHZ, 38,
+            5200, WifiScanner.WIFI_BAND_5_GHZ, 40,
+            5210, WifiScanner.WIFI_BAND_5_GHZ, 42,
+            5220, WifiScanner.WIFI_BAND_5_GHZ, 44,
+            5230, WifiScanner.WIFI_BAND_5_GHZ, 46,
+            5240, WifiScanner.WIFI_BAND_5_GHZ, 48,
+            5260, WifiScanner.WIFI_BAND_5_GHZ, 52,
+            5280, WifiScanner.WIFI_BAND_5_GHZ, 56,
+            5300, WifiScanner.WIFI_BAND_5_GHZ, 60,
+            5320, WifiScanner.WIFI_BAND_5_GHZ, 64,
+            5500, WifiScanner.WIFI_BAND_5_GHZ, 100,
+            5520, WifiScanner.WIFI_BAND_5_GHZ, 104,
+            5540, WifiScanner.WIFI_BAND_5_GHZ, 108,
+            5560, WifiScanner.WIFI_BAND_5_GHZ, 112,
+            5580, WifiScanner.WIFI_BAND_5_GHZ, 116,
+            /* 120, 124, 128 valid in Europe/Japan. */
+            5600, WifiScanner.WIFI_BAND_5_GHZ, 120,
+            5620, WifiScanner.WIFI_BAND_5_GHZ, 124,
+            5640, WifiScanner.WIFI_BAND_5_GHZ, 128,
+            /* 132+ valid in US. */
+            5660, WifiScanner.WIFI_BAND_5_GHZ, 132,
+            5680, WifiScanner.WIFI_BAND_5_GHZ, 136,
+            5700, WifiScanner.WIFI_BAND_5_GHZ, 140,
+            /* 144 is supported by a subset of WiFi chips. */
+            5720, WifiScanner.WIFI_BAND_5_GHZ, 144,
+            5745, WifiScanner.WIFI_BAND_5_GHZ, 149,
+            5765, WifiScanner.WIFI_BAND_5_GHZ, 153,
+            5785, WifiScanner.WIFI_BAND_5_GHZ, 157,
+            5805, WifiScanner.WIFI_BAND_5_GHZ, 161,
+            5825, WifiScanner.WIFI_BAND_5_GHZ, 165,
+            5845, WifiScanner.WIFI_BAND_5_GHZ, 169,
+            5865, WifiScanner.WIFI_BAND_5_GHZ, 173,
+            /* Now some 6GHz channels */
+            5945, WifiScanner.WIFI_BAND_6_GHZ, 1,
+            5960, WifiScanner.WIFI_BAND_6_GHZ, 4,
+            6100, WifiScanner.WIFI_BAND_6_GHZ, 32
+    };
+
+    /**
      * Setup before tests.
      */
     @Before
@@ -184,6 +246,25 @@
     }
 
     /**
+     * verify frequency to channel conversion for all possible frequencies.
+     */
+    @Test
+    public void convertFrequencyToChannel() throws Exception {
+        for (int i = 0; i < FREQUENCY_TO_CHANNEL_MAP.length; i += 3) {
+            assertEquals(FREQUENCY_TO_CHANNEL_MAP[i + 2],
+                    ScanResult.convertFrequencyMhzToChannel(FREQUENCY_TO_CHANNEL_MAP[i]));
+        }
+    }
+
+    /**
+     * Verify frequency to channel conversion failed for an invalid frequency.
+     */
+    @Test
+    public void convertFrequencyToChannelWithInvalidFreq() throws Exception {
+        assertEquals(-1, ScanResult.convertFrequencyMhzToChannel(8000));
+    }
+
+    /**
      * Write the provided {@link ScanResult} to a parcel and deserialize it.
      */
     private static ScanResult parcelReadWrite(ScanResult writeResult) throws Exception {
diff --git a/wifi/tests/src/android/net/wifi/WifiScannerTest.java b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
index 4881200..b68616f 100644
--- a/wifi/tests/src/android/net/wifi/WifiScannerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
@@ -613,4 +613,22 @@
         verify(mExecutor, never()).execute(any());
         verify(mScanListener, never()).onResults(mScanData);
     }
+
+    /**
+     * Tests isFullBandScan() method with and without DFS check
+     */
+    @Test
+    public void testIsFullBandScan() throws Exception {
+        assertFalse(WifiScanner.isFullBandScan(WifiScanner.WIFI_BAND_24_GHZ, true));
+        assertFalse(WifiScanner.isFullBandScan(WifiScanner.WIFI_BAND_5_GHZ, true));
+        assertFalse(WifiScanner.isFullBandScan(WifiScanner.WIFI_BAND_6_GHZ, true));
+        assertFalse(WifiScanner.isFullBandScan(
+                WifiScanner.WIFI_BAND_6_GHZ | WifiScanner.WIFI_BAND_5_GHZ, true));
+        assertTrue(WifiScanner.isFullBandScan(
+                WifiScanner.WIFI_BAND_24_GHZ | WifiScanner.WIFI_BAND_5_GHZ, true));
+        assertFalse(WifiScanner.isFullBandScan(
+                WifiScanner.WIFI_BAND_24_GHZ | WifiScanner.WIFI_BAND_5_GHZ, false));
+        assertTrue(WifiScanner.isFullBandScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, true));
+        assertTrue(WifiScanner.isFullBandScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, false));
+    }
 }