Merge "AudioService: evaluate permissions for min stream index" into rvc-dev
diff --git a/Android.bp b/Android.bp
index ee381a4..557c320 100644
--- a/Android.bp
+++ b/Android.bp
@@ -670,7 +670,7 @@
 
 filegroup {
     name: "framework-ike-shared-srcs",
-    visibility: ["//frameworks/opt/net/ike"],
+    visibility: ["//packages/modules/IPsec"],
     srcs: [
         "core/java/android/annotation/StringDef.java",
         "core/java/android/net/annotations/PolicyDirection.java",
@@ -930,6 +930,8 @@
     srcs: [
         "core/java/android/os/incremental/IIncrementalService.aidl",
         "core/java/android/os/incremental/IncrementalNewFileParams.aidl",
+        "core/java/android/os/incremental/IStorageHealthListener.aidl",
+        "core/java/android/os/incremental/StorageHealthCheckParams.aidl",
     ],
     path: "core/java",
 }
@@ -1223,4 +1225,4 @@
 build = [
     "StubLibraries.bp",
     "ApiDocs.bp",
-]
\ No newline at end of file
+]
diff --git a/ApiDocs.bp b/ApiDocs.bp
index 90df19a..a81342a 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -66,7 +66,7 @@
         ":opt-telephony-srcs",
         ":opt-net-voip-srcs",
         ":art-module-public-api-stubs-source",
-        ":conscrypt.module.public.api.stubs.source",
+        ":conscrypt.module.public.api{.public.stubs.source}",
         ":android_icu4j_public_api_files",
         "test-mock/src/**/*.java",
         "test-runner/src/**/*.java",
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 6e6efe5..c0197c4 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -69,7 +69,7 @@
     name: "metalava-full-api-stubs-default",
     defaults: ["metalava-base-api-stubs-default"],
     srcs: [
-        ":conscrypt.module.public.api.stubs.source",
+        ":conscrypt.module.public.api{.public.stubs.source}",
         ":framework-updatable-sources",
     ],
     sdk_version: "core_platform",
diff --git a/apex/Android.bp b/apex/Android.bp
index de4b24a..c1715a00 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -100,6 +100,8 @@
     // Configure framework module specific metalava options.
     droiddoc_options: [mainline_stubs_args],
 
+    annotations_enabled: true,
+
     // The stub libraries must be visible to frameworks/base so they can be combined
     // into API specific libraries.
     stubs_library_visibility: [
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
index 49b3ec1..cea7fcc 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
@@ -212,7 +212,10 @@
     }
 
     boolean isAccessAllowedForCaller(@NonNull String callingPackage, int callingUid) {
-        // TODO: verify blob is still valid (expiryTime is not elapsed)
+        // Don't allow the blob to be accessed after it's expiry time has passed.
+        if (getBlobHandle().isExpired()) {
+            return false;
+        }
         synchronized (mMetadataLock) {
             // Check if packageName already holds a lease on the blob.
             for (int i = 0, size = mLeasees.size(); i < size; ++i) {
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
index b4a7cd4..9a711d3 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
@@ -18,7 +18,6 @@
 import static android.provider.DeviceConfig.NAMESPACE_BLOBSTORE;
 import static android.text.format.Formatter.FLAG_IEC_UNITS;
 import static android.text.format.Formatter.formatFileSize;
-import static android.util.TimeUtils.formatDuration;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -58,18 +57,24 @@
      * Job Id for idle maintenance job ({@link BlobStoreIdleJobService}).
      */
     public static final int IDLE_JOB_ID = 0xB70B1D7; // 191934935L
-    /**
-     * Max time period (in millis) between each idle maintenance job run.
-     */
-    public static final long IDLE_JOB_PERIOD_MILLIS = TimeUnit.DAYS.toMillis(1);
-
-    /**
-     * Timeout in millis after which sessions with no updates will be deleted.
-     */
-    public static final long SESSION_EXPIRY_TIMEOUT_MILLIS = TimeUnit.DAYS.toMillis(7);
 
     public static class DeviceConfigProperties {
         /**
+         * Denotes the max time period (in millis) between each idle maintenance job run.
+         */
+        public static final String KEY_IDLE_JOB_PERIOD_MS = "idle_job_period_ms";
+        public static final long DEFAULT_IDLE_JOB_PERIOD_MS = TimeUnit.DAYS.toMillis(1);
+        public static long IDLE_JOB_PERIOD_MS = DEFAULT_IDLE_JOB_PERIOD_MS;
+
+        /**
+         * Denotes the timeout in millis after which sessions with no updates will be deleted.
+         */
+        public static final String KEY_SESSION_EXPIRY_TIMEOUT_MS =
+                "session_expiry_timeout_ms";
+        public static final long DEFAULT_SESSION_EXPIRY_TIMEOUT_MS = TimeUnit.DAYS.toMillis(7);
+        public static long SESSION_EXPIRY_TIMEOUT_MS = DEFAULT_SESSION_EXPIRY_TIMEOUT_MS;
+
+        /**
          * Denotes how low the limit for the amount of data, that an app will be allowed to acquire
          * a lease on, can be.
          */
@@ -119,6 +124,13 @@
             }
             properties.getKeyset().forEach(key -> {
                 switch (key) {
+                    case KEY_IDLE_JOB_PERIOD_MS:
+                        IDLE_JOB_PERIOD_MS = properties.getLong(key, DEFAULT_IDLE_JOB_PERIOD_MS);
+                        break;
+                    case KEY_SESSION_EXPIRY_TIMEOUT_MS:
+                        SESSION_EXPIRY_TIMEOUT_MS = properties.getLong(key,
+                                DEFAULT_SESSION_EXPIRY_TIMEOUT_MS);
+                        break;
                     case KEY_TOTAL_BYTES_PER_APP_LIMIT_FLOOR:
                         TOTAL_BYTES_PER_APP_LIMIT_FLOOR = properties.getLong(key,
                                 DEFAULT_TOTAL_BYTES_PER_APP_LIMIT_FLOOR);
@@ -143,6 +155,12 @@
 
         static void dump(IndentingPrintWriter fout, Context context) {
             final String dumpFormat = "%s: [cur: %s, def: %s]";
+            fout.println(String.format(dumpFormat, KEY_IDLE_JOB_PERIOD_MS,
+                    TimeUtils.formatDuration(IDLE_JOB_PERIOD_MS),
+                    TimeUtils.formatDuration(DEFAULT_IDLE_JOB_PERIOD_MS)));
+            fout.println(String.format(dumpFormat, KEY_SESSION_EXPIRY_TIMEOUT_MS,
+                    TimeUtils.formatDuration(SESSION_EXPIRY_TIMEOUT_MS),
+                    TimeUtils.formatDuration(DEFAULT_SESSION_EXPIRY_TIMEOUT_MS)));
             fout.println(String.format(dumpFormat, KEY_TOTAL_BYTES_PER_APP_LIMIT_FLOOR,
                     formatFileSize(context, TOTAL_BYTES_PER_APP_LIMIT_FLOOR, FLAG_IEC_UNITS),
                     formatFileSize(context, DEFAULT_TOTAL_BYTES_PER_APP_LIMIT_FLOOR,
@@ -167,6 +185,22 @@
     }
 
     /**
+     * Returns the max time period (in millis) between each idle maintenance job run.
+     */
+    public static long getIdleJobPeriodMs() {
+        return DeviceConfigProperties.IDLE_JOB_PERIOD_MS;
+    }
+
+    /**
+     * Returns whether a session is expired or not. A session is considered expired if the session
+     * has not been modified in a while (i.e. SESSION_EXPIRY_TIMEOUT_MS).
+     */
+    public static boolean hasSessionExpired(long sessionLastModifiedMs) {
+        return sessionLastModifiedMs
+                < System.currentTimeMillis() - DeviceConfigProperties.SESSION_EXPIRY_TIMEOUT_MS;
+    }
+
+    /**
      * Returns the maximum amount of data that an app can acquire a lease on.
      */
     public static long getAppDataBytesLimit() {
@@ -277,9 +311,6 @@
         fout.println("XML current version: " + XML_VERSION_CURRENT);
 
         fout.println("Idle job ID: " + IDLE_JOB_ID);
-        fout.println("Idle job period: " + formatDuration(IDLE_JOB_PERIOD_MILLIS));
-
-        fout.println("Session expiry timeout: " + formatDuration(SESSION_EXPIRY_TIMEOUT_MILLIS));
 
         fout.println("Total bytes per app limit: " + formatFileSize(context,
                 getAppDataBytesLimit(), FLAG_IEC_UNITS));
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreIdleJobService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreIdleJobService.java
index 460e776..4b0f719 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreIdleJobService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreIdleJobService.java
@@ -16,7 +16,6 @@
 package com.android.server.blob;
 
 import static com.android.server.blob.BlobStoreConfig.IDLE_JOB_ID;
-import static com.android.server.blob.BlobStoreConfig.IDLE_JOB_PERIOD_MILLIS;
 import static com.android.server.blob.BlobStoreConfig.LOGV;
 import static com.android.server.blob.BlobStoreConfig.TAG;
 
@@ -60,7 +59,7 @@
                 new ComponentName(context, BlobStoreIdleJobService.class))
                         .setRequiresDeviceIdle(true)
                         .setRequiresCharging(true)
-                        .setPeriodic(IDLE_JOB_PERIOD_MILLIS)
+                        .setPeriodic(BlobStoreConfig.getIdleJobPeriodMs())
                         .build();
         jobScheduler.schedule(job);
         if (LOGV) {
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 9376198..a2bce31 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -29,10 +29,10 @@
 import static android.os.UserHandle.USER_NULL;
 
 import static com.android.server.blob.BlobStoreConfig.LOGV;
-import static com.android.server.blob.BlobStoreConfig.SESSION_EXPIRY_TIMEOUT_MILLIS;
 import static com.android.server.blob.BlobStoreConfig.TAG;
 import static com.android.server.blob.BlobStoreConfig.XML_VERSION_CURRENT;
 import static com.android.server.blob.BlobStoreConfig.getAdjustedCommitTimeMs;
+import static com.android.server.blob.BlobStoreConfig.hasSessionExpired;
 import static com.android.server.blob.BlobStoreSession.STATE_ABANDONED;
 import static com.android.server.blob.BlobStoreSession.STATE_COMMITTED;
 import static com.android.server.blob.BlobStoreSession.STATE_VERIFIED_INVALID;
@@ -986,9 +986,9 @@
             userSessions.removeIf((sessionId, blobStoreSession) -> {
                 boolean shouldRemove = false;
 
+                // TODO: handle the case where no content has been written to session yet.
                 // Cleanup sessions which haven't been modified in a while.
-                if (blobStoreSession.getSessionFile().lastModified()
-                        < System.currentTimeMillis() - SESSION_EXPIRY_TIMEOUT_MILLIS) {
+                if (hasSessionExpired(blobStoreSession.getSessionFile().lastModified())) {
                     shouldRemove = true;
                 }
 
@@ -1059,6 +1059,18 @@
         }
     }
 
+    boolean isBlobAvailable(long blobId, int userId) {
+        synchronized (mBlobsLock) {
+            final ArrayMap<BlobHandle, BlobMetadata> userBlobs = getUserBlobsLocked(userId);
+            for (BlobMetadata blobMetadata : userBlobs.values()) {
+                if (blobMetadata.getBlobId() == blobId) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
     @GuardedBy("mBlobsLock")
     private void dumpSessionsLocked(IndentingPrintWriter fout, DumpArgs dumpArgs) {
         for (int i = 0, userCount = mSessions.size(); i < userCount; ++i) {
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerShellCommand.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerShellCommand.java
index 72af323..a4a2e80 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerShellCommand.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerShellCommand.java
@@ -46,6 +46,8 @@
                 return runDeleteBlob(pw);
             case "idle-maintenance":
                 return runIdleMaintenance(pw);
+            case "query-blob-existence":
+                return runQueryBlobExistence(pw);
             default:
                 return handleDefaultCommands(cmd);
         }
@@ -91,6 +93,16 @@
         return 0;
     }
 
+    private int runQueryBlobExistence(PrintWriter pw) {
+        final ParsedArgs args = new ParsedArgs();
+        if (parseOptions(pw, args) < 0) {
+            return -1;
+        }
+
+        pw.println(mService.isBlobAvailable(args.blobId, args.userId) ? 1 : 0);
+        return 0;
+    }
+
     @Override
     public void onHelp() {
         final PrintWriter pw = getOutPrintWriter();
@@ -121,6 +133,8 @@
         pw.println("      --tag: Tag of the blob to delete.");
         pw.println("idle-maintenance");
         pw.println("    Run idle maintenance which takes care of removing stale data.");
+        pw.println("query-blob-existence [-b BLOB_ID]");
+        pw.println("    Prints 1 if blob exists, otherwise 0.");
         pw.println();
     }
 
@@ -147,6 +161,9 @@
                 case "--tag":
                     args.tag = getNextArgRequired();
                     break;
+                case "-b":
+                    args.blobId = Long.parseLong(getNextArgRequired());
+                    break;
                 default:
                     pw.println("Error: unknown option '" + opt + "'");
                     return -1;
@@ -166,6 +183,7 @@
         public long expiryTimeMillis;
         public CharSequence label;
         public String tag;
+        public long blobId;
 
         public BlobHandle getBlobHandle() {
             return BlobHandle.create(algorithm, digest, label, expiryTimeMillis, tag);
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 94e5d0b..40328b3 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -1322,6 +1322,8 @@
 
     private void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
             int reason, long elapsedRealtime, boolean resetTimeout) {
+        if (!mAppIdleEnabled) return;
+
         synchronized (mAppIdleLock) {
             // If the package is not installed, don't allow the bucket to be set.
             if (!mInjector.isPackageInstalled(packageName, 0, userId)) {
diff --git a/apex/sdkextensions/Android.bp b/apex/sdkextensions/Android.bp
deleted file mode 100644
index fdb078e..0000000
--- a/apex/sdkextensions/Android.bp
+++ /dev/null
@@ -1,84 +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 {
-    default_visibility: [":__subpackages__"],
-}
-
-apex {
-    name: "com.android.sdkext",
-    defaults: [ "com.android.sdkext-defaults" ],
-    binaries: [ "derive_sdk" ],
-    prebuilts: [ "cur_sdkinfo" ],
-    manifest: "manifest.json",
-    min_sdk_version: "current",
-}
-
-apex_defaults {
-    name: "com.android.sdkext-defaults",
-    updatable: true,
-    min_sdk_version: "R",
-    java_libs: [ "framework-sdkextensions" ],
-    prebuilts: [
-        "derive_sdk.rc",
-    ],
-    key: "com.android.sdkext.key",
-    certificate: ":com.android.sdkext.certificate",
-}
-
-sdk {
-    name: "sdkextensions-sdk",
-    java_sdk_libs: [ "framework-sdkextensions" ],
-}
-
-apex_key {
-    name: "com.android.sdkext.key",
-    public_key: "com.android.sdkext.avbpubkey",
-    private_key: "com.android.sdkext.pem",
-}
-
-android_app_certificate {
-    name: "com.android.sdkext.certificate",
-    certificate: "com.android.sdkext",
-}
-
-python_binary_host {
-    name: "gen_sdkinfo",
-    srcs: [
-        "sdk.proto",
-        "gen_sdkinfo.py",
-    ],
-    proto: {
-        canonical_path_from_root: false,
-    },
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
-}
-
-gensrcs {
-    name: "cur_sdkinfo_src",
-    srcs: [""],
-    tools: [ "gen_sdkinfo" ],
-    cmd: "$(location) -v 0 -o $(out)",
-}
-
-prebuilt_etc {
-    name: "cur_sdkinfo",
-    src: ":cur_sdkinfo_src",
-    filename: "sdkinfo.binarypb",
-    installable: false,
-}
diff --git a/apex/sdkextensions/OWNERS b/apex/sdkextensions/OWNERS
deleted file mode 100644
index a6e5522..0000000
--- a/apex/sdkextensions/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-dariofreni@google.com
-hansson@google.com
diff --git a/apex/sdkextensions/TEST_MAPPING b/apex/sdkextensions/TEST_MAPPING
deleted file mode 100644
index 3dc1b9f..0000000
--- a/apex/sdkextensions/TEST_MAPPING
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "presubmit": [
-    {
-      "name": "CtsSdkExtensionsTestCases"
-    },
-    {
-      "name": "sdkextensions_e2e_tests"
-    }
-  ]
-}
diff --git a/apex/sdkextensions/com.android.sdkext.avbpubkey b/apex/sdkextensions/com.android.sdkext.avbpubkey
deleted file mode 100644
index 8f47741..0000000
--- a/apex/sdkextensions/com.android.sdkext.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/apex/sdkextensions/com.android.sdkext.pem b/apex/sdkextensions/com.android.sdkext.pem
deleted file mode 100644
index 8164601..0000000
--- a/apex/sdkextensions/com.android.sdkext.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEAr72pTSavrziDP54AtQZlRclDxJf9HXRZwFRbYx9hWZ4z7ZtO
-pNBDPvPJCiAOVUsILgCQhBUolz2dyLob25Fd0PVp0n9ibIPEQYjTfHjOK40qb57N
-LhEp2ceGiAfsywPSi0TH1PQ6JgbCe/RM4TefI/sj3gYJPka3ksMvylhMIgUVLgME
-kYizhzwHqlLMspB858SioREZdGwcdZrMMIajGFU69Q9ZRDBzhPvxyKhYoObcOtk1
-uVaiE/fNoi3wKGJz2l2vhUuNrQW7MWlVMag+Qes4YACUTk9LZrOVFEJFjWc8xGUi
-ABtfKGs5JgNr/sWnhvifLn8lJuf0/BJmjD+L5QwXYs2cS7gcZJtTM12J94r0Twgw
-wF2lNmIxAE9sYqj5Rh3dIlTPE5vMUECmQEGjIBB/hzT65VxVqSjU/IlS506JTg3p
-IOQtZ15cUzTBpda4jrvqcq6RNVvgBCu2bV5D8Z4z9FUlPyvD+Zq/6lcoJfLtznAs
-G2463hyPAHTGBIcZ5p5bTuGxoAb6ivyqo4b9Qi4yYA6je9HJmuy8T3Mn5JROoeu9
-BH1K54r/mpT4TQPwuKUvRRtBAV2OPHjo+zp0Gd4Y6rxDYxEIdfEae7pQr/QExSPB
-q/QCr9RhixR1mO373LHuja+MxdAxIxugb2HTS61PQo+PbYrhJMcVuxTwJOECAwEA
-AQKCAgAH7ToRrMkH0ji5SdsmTx+KQkW4PFLCXVke/68PjX7KmAQnl3W4oVwnHr/W
-oROEbVn1GTlre7jU+YaAY0SWZrwgjLE1OWGrG1ZizlUbrCdAd6GOX09J4KROml1L
-DXB0x7tbZMLOrCVjSbLD/ITrM6MN8Gnxvbv0/yOQjxU8vzbP4gLOjHxMRCo001RV
-Ll7lPvcjTQ84zJilU6sE8vJ6zdfVZSK/ou2X0cekG+kP7+fvefo8/UcbEPlGhUrV
-IdVPPQGUu90K2hmN0FBdLi8Vik0klAN68Qu/bHwuKbNzsnmIoztucFFUR+fG3u84
-87aPS0L/J3+mjT2Tv6qhJANUGBmrK/h7MkelpKXlRTCITJLX9xP7hfSbJ4f6aLVq
-ZYPPciGxSBbUDgAwvPtOlMDzccg7YsYyiBBO28wh8MN97rePmc0z6nGmjeXhcbCC
-QktG50VYFCyqp5muKgqQmRfRjHFHLWs8GEqgxMeEL3U3HjYfCYr+6E8Sr5OnOBeH
-3buCi1+zgnNYCvbamgY/OJmW7f9h5O31hxmTplc2E1ZuxUGQZthabt1rN3bmNkyf
-KUmPwnIYkDkWBSV5lzyQExfS3/EVvj0EnHhx8faamimNrGo8xCcfnLT3c0WEFVmo
-yIyVRX3EpXJFM2JkeJ21/IEZXTzHSoNxk12CBG8i8lLSflWSMQKCAQEA2ZqVnOuV
-SZfLCUYUUh8Hvhc5zONstfq7ma1Zsttsdaj9t68nLRiBDvLOGnMjDkYZzoSd4fyl
-oy+YqWGBqcqa5kg1NOCH0I46p9d8RcWAfDnB4sqbLgWh70qsvni6igRijmsMDvkA
-U9HeEdPaLCjQ4UXw7GQvN5rRxuRt+OSqV3tV/Pk9JYyYjz7faC8dmbKDrWHHuOvm
-/9y6Xy+L5IgftykNlUeddSCIoMOAadM7BiRjsrHnOYBQ8xBcn0OYafpIswItrgVi
-IrsPJaBFidx8QYK4MVibyka6U0cm28OocDSPtSk/4jrnCEEhLjFUnWwuMXuBGlrd
-W7wP/muoJqb1VwKCAQEAzsAT90kkOCvAcrfGRE3KkUjwWAsQyP8u2+27JIQPqrpW
-GfWAzJXFt80TSp0Zf/Lrq3/SQ9n4AaL4K9dcMoreedoQN9C9JI7zPtZAWNrJVUcV
-dq2gZjBQ78+oK7uQgvFNWxga5D+Nh+Y+9Tp537fc5HIh0Y13PgsxxPk2OnZJTvLX
-HM5H7Aua9ssmqChsrKihuUsDSPozfBz+H7FNHEdKMqVLqJJSK6m0uMxuLovdVfka
-5S7iBMjEGZc46Iz3ckE0pdOiQLooNqfEQqFe5Uou/KZxxKI1NW25rEEBTVyQWt+2
-BNUCfKP7noZ45u5sUY3eJrgI7BrPEDbNS81WYaLchwKCAQA8Q4mHyd6wYO+EA/qA
-u8NDK9+AFMP4qhXme5HJ7Obetwx9IG7zGEQ1xZy6yoQ84cEn5qZq/bNJvFbFIhHs
-2gWIHRtPJ5e1dI5eCVmLYSUyQjSmAIJ1fm3YfY/VuE3BB3HcC11tkBw9GnQr78YO
-UMd4fAw7C4vgFGpgcMbcFUfvrmKkCsqaaZOeqETq75F9DWlWTSwo1HxHA/RBhENz
-6RcPfLkcTJcY5wevrjUUGcHQ86cAyDBHRngkuLVODkRZpU0Y9lN8TFVfVPre6sIX
-ag6nffJRCD8tB+V2RtBGMKunV4ctHt1oY/Oz34W260aJynoIjjG1ANEpJK4xQdNx
-0O9FAoIBAQCz2AGGKemHswdEwveEkuaSWpA3Bekj7lYkmTchHH9EU7JyAkx3qhDD
-QXB2hxGXawf1tsqAmypQwiJ+gGeCz6mW9UkGRF1DX9XX4yc2I5rew2a4RXAxc/Xz
-pP70i8O5I43Wn7FEusOyY2aAis1Y/eb4EQ+56QTAw5wXa3DwidRbCIJ2XDnT6oRy
-CWUnAYMG7ek/9TB2Wq5OWCn2B5S79IdmZsLZb+5qbMT3u1xcwO1Xy8jJc27IGpv6
-ZsDqCTV1/aJ+XQnWpBg28tiV3Sle6pjUzTRJh5AhWcEZRbKMSOiJI/CBY4k2Qq6t
-xuuEdgFjL7T+mTepqehUglcyiPuLEtAhAoIBAQDDQ5pTFOlunfYzm+CIvvImAgy7
-vrEabJYABATytAbXRMMbrKoEdU2ApEDyEW7PgysDnYLAZ+icObnJlBTYvNdlWFly
-XiviGVfpjFWDT9U/gUwFQu2lfEjoiivoGS92USHUy4UMVHiiznnm20VLLkgd3xna
-HUNSDdHIEgzOTmDsKJwMfA9zGckx23JJimPR5ekv6vr6QllYtECs4lTC1gVQAp2f
-5daxHRbkmO6gw1RgQADLkAnYz3aI1jNuHm5VyAZGt/d3JCtZ3Wwwejll8uJ4J09G
-oEtqyY9RVeHK50bLO4lyAXFiE+J6qqXjsGC20cpxeZYW5llMY/dhA6WV4YXV
------END RSA PRIVATE KEY-----
diff --git a/apex/sdkextensions/com.android.sdkext.pk8 b/apex/sdkextensions/com.android.sdkext.pk8
deleted file mode 100644
index ccc0bf4..0000000
--- a/apex/sdkextensions/com.android.sdkext.pk8
+++ /dev/null
Binary files differ
diff --git a/apex/sdkextensions/com.android.sdkext.x509.pem b/apex/sdkextensions/com.android.sdkext.x509.pem
deleted file mode 100644
index 45d2ade..0000000
--- a/apex/sdkextensions/com.android.sdkext.x509.pem
+++ /dev/null
@@ -1,35 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIGIzCCBAugAwIBAgIUXuDL7QvzQh7S6rihWz2KRvCFVT0wDQYJKoZIhvcNAQEL
-BQAwgZ8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
-DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
-b2lkMRswGQYDVQQDDBJjb20uYW5kcm9pZC5zZGtleHQxIjAgBgkqhkiG9w0BCQEW
-E2FuZHJvaWRAYW5kcm9pZC5jb20wIBcNMTkxMjAyMTQyNDM0WhgPNDc1NzEwMjgx
-NDI0MzRaMIGfMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG
-A1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwH
-QW5kcm9pZDEbMBkGA1UEAwwSY29tLmFuZHJvaWQuc2RrZXh0MSIwIAYJKoZIhvcN
-AQkBFhNhbmRyb2lkQGFuZHJvaWQuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
-MIICCgKCAgEAxFvZZ6ES1oqAu1K74/ZxnC3SOhHnLISLBgJEe7DqtdpuNFAwvdVO
-RL/HULhDbjYlOhpU2x3SavDIZZ2lRfiS9Q+M25WftxTRHVjBcpgwbV77TVxPKlAa
-tVN2lUVOY+s4QAVMNIXjC4kCKK/pCQtacH715EtdV47fWdg/Nx4iP/Aord8k3KGI
-9iI2ZOUjaugTRxu5lKRNDrv0bw5rEzyYmDyMud+kR/iS3/5oog57wPE0ffAkZXWE
-p3L2Cejre3ekCizsvVh6EmH6ForKLtL6f0z5Zir1f4R9+YcENspTlJR3pDhg7y3I
-uTQT/iDCtV0l+g2PjGZPEeAQHND3+kDQR7Sno/WC1Nhws6vcu1MdrC+kIh1ewx4y
-8moy/yqb5M98PJDzTSi/AOTB/OiqLXo/T8rjLBmirs9y3fTT6gJ6qXxOWgt8dle9
-7TBfa84Xi8uVY61c+A+YI0nLal7QDPsP3RPv5sJSQ9x9YnweVfD9Q0EOi52sSNu+
-QuN/kcUrMgPgha20VhfH/CkkPDyIp6aZyHHM69MIl+cYEm8vPa5uy3dosuRomT0f
-I4HOBjULDIuj+rIi+Rg3qHvmpuejwZXI/FBNWIhLEUG3ytgksjMaBoYAYflGdrcj
-BQexuF3EO+j4uo7JGjNcaT7wRoCH9gt29VHckDg2qz6VWXrlpmME4UkCAwEAAaNT
-MFEwHQYDVR0OBBYEFISN2nmUHllgPZMZ62U7mU3ZxzlXMB8GA1UdIwQYMBaAFISN
-2nmUHllgPZMZ62U7mU3ZxzlXMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
-BQADggIBAFHIwyBNIVyHXUsDUdcjxfojXQsF/BCL9ehE3pgdkvDfQanaIREWn0nc
-oCFDFkYMRqaXOGC5TKq4OCjXOLsdfODt8HQ3F9J1B0ghQ5tfOdw7xDugNAszqP/Q
-h7kpvqLTycjrqOeZ5KjxEEYtP/KlUmALgOKcTcSH+XhWyxhjF4j24T9F2yJRr3/A
-r1NGU/djH953bHKC8OpJ2teUpDLA4TxVp/EhslH2eVigF80c/w74QPLEWkD9zv/4
-YeRg/R5N83zHs99NtlWMIeHfK6fUbzMyaSZtvm+jK20tkByQb/OQRed+drk25MtL
-68IRvxqri367qRScdpTZbu0ByLO4X8gFdubRUWr+tcO4pZX+DJRVriExbOkU2xhS
-Vtslq23V/hwTuUNm1CXjR70mPS13BTmHrIQDqLoIw/WTQlGh+vxnlAFRIHM3KB2c
-OdzUBu+NcB4aZEd0KKtct600A0DKPr1MQPb5jDq9wEtPSQYwMF0nRFNnXltbrXMd
-4hhwnhKr74fVMUmb+7eQP56XE/Nk4D+npMO54vv1pav+DI2/nxCND9BOLBweY38p
-Tvd2RjesMok0zXuVXiCIu4GEpwo7WkSnv25xrb0Ey2M8QWnGNnCcX7Kv6ip3RdWy
-HiN0G8RJrs/yNEVSDRx8ZhtwTpXVPQxbARbmhNF4/fnolElkmrMP
------END CERTIFICATE-----
diff --git a/apex/sdkextensions/derive_sdk/Android.bp b/apex/sdkextensions/derive_sdk/Android.bp
deleted file mode 100644
index 41eae09..0000000
--- a/apex/sdkextensions/derive_sdk/Android.bp
+++ /dev/null
@@ -1,55 +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.
-
-cc_defaults {
-    name: "derive_sdk-defaults",
-    srcs: [
-        "derive_sdk.cpp",
-        "sdk.proto",
-    ],
-    proto: {
-        type: "lite",
-        static: true,
-    },
-    min_sdk_version: "current",
-    shared_libs: ["liblog"],
-    // static c++/libbase for smaller size
-    stl: "c++_static",
-    static_libs: ["libbase"],
-}
-
-cc_binary {
-    name: "derive_sdk",
-    defaults: [ "derive_sdk-defaults" ],
-    apex_available: [ "com.android.sdkext" ],
-    visibility: [ "//frameworks/base/apex/sdkextensions" ]
-}
-
-// Work around testing using a 64-bit test suite on 32-bit test device by
-// using a prefer32 version of derive_sdk in testing.
-cc_binary {
-    name: "derive_sdk_prefer32",
-    defaults: [ "derive_sdk-defaults" ],
-    compile_multilib: "prefer32",
-    stem: "derive_sdk",
-    apex_available: [ "test_com.android.sdkext" ],
-    visibility: [ "//frameworks/base/apex/sdkextensions/testing" ],
-    installable: false,
-}
-
-prebuilt_etc {
-    name: "derive_sdk.rc",
-    src: "derive_sdk.rc",
-    installable: false,
-}
diff --git a/apex/sdkextensions/derive_sdk/derive_sdk.cpp b/apex/sdkextensions/derive_sdk/derive_sdk.cpp
deleted file mode 100644
index 900193a..0000000
--- a/apex/sdkextensions/derive_sdk/derive_sdk.cpp
+++ /dev/null
@@ -1,79 +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.
- */
-
-#define LOG_TAG "derive_sdk"
-
-#include <algorithm>
-#include <dirent.h>
-#include <iostream>
-#include <sys/stat.h>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-
-#include "frameworks/base/apex/sdkextensions/derive_sdk/sdk.pb.h"
-
-using com::android::sdkext::proto::SdkVersion;
-
-int main(int, char**) {
-    std::unique_ptr<DIR, decltype(&closedir)> apex(opendir("/apex"), closedir);
-    if (!apex) {
-        LOG(ERROR) << "Could not read /apex";
-        return EXIT_FAILURE;
-    }
-    struct dirent* de;
-    std::vector<std::string> paths;
-    while ((de = readdir(apex.get()))) {
-        std::string name = de->d_name;
-        if (name[0] == '.' || name.find('@') != std::string::npos) {
-            // Skip <name>@<ver> dirs, as they are bind-mounted to <name>
-            continue;
-        }
-        std::string path = "/apex/" + name + "/etc/sdkinfo.binarypb";
-        struct stat statbuf;
-        if (stat(path.c_str(), &statbuf) == 0) {
-            paths.push_back(path);
-        }
-    }
-
-    std::vector<int> versions;
-    for (const auto& path : paths) {
-        std::string contents;
-        if (!android::base::ReadFileToString(path, &contents, true)) {
-            LOG(ERROR) << "failed to read " << path;
-            continue;
-        }
-        SdkVersion sdk_version;
-        if (!sdk_version.ParseFromString(contents)) {
-            LOG(ERROR) << "failed to parse " << path;
-            continue;
-        }
-        LOG(INFO) << "Read version " << sdk_version.version() << " from " << path;
-        versions.push_back(sdk_version.version());
-    }
-    auto itr = std::min_element(versions.begin(), versions.end());
-    std::string prop_value = itr == versions.end() ? "0" : std::to_string(*itr);
-
-    if (!android::base::SetProperty("build.version.extensions.r", prop_value)) {
-        LOG(ERROR) << "failed to set sdk_info prop";
-        return EXIT_FAILURE;
-    }
-
-    LOG(INFO) << "R extension version is " << prop_value;
-    return EXIT_SUCCESS;
-}
diff --git a/apex/sdkextensions/derive_sdk/derive_sdk.rc b/apex/sdkextensions/derive_sdk/derive_sdk.rc
deleted file mode 100644
index 18f021c..0000000
--- a/apex/sdkextensions/derive_sdk/derive_sdk.rc
+++ /dev/null
@@ -1,5 +0,0 @@
-service derive_sdk /apex/com.android.sdkext/bin/derive_sdk
-    user nobody
-    group nobody
-    oneshot
-    disabled
diff --git a/apex/sdkextensions/framework/Android.bp b/apex/sdkextensions/framework/Android.bp
deleted file mode 100644
index b8aad7d..0000000
--- a/apex/sdkextensions/framework/Android.bp
+++ /dev/null
@@ -1,49 +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 {
-    default_visibility: [ ":__pkg__" ]
-}
-
-filegroup {
-    name: "framework-sdkextensions-sources",
-    srcs: [
-        "java/**/*.java",
-    ],
-    path: "java",
-    visibility: [ "//frameworks/base" ] // For the "global" stubs.
-}
-
-java_sdk_library {
-    name: "framework-sdkextensions",
-    srcs: [ ":framework-sdkextensions-sources" ],
-    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,
-    visibility: [
-        "//frameworks/base/apex/sdkextensions",
-        "//frameworks/base/apex/sdkextensions/testing",
-    ],
-    hostdex: true, // for hiddenapi check
-    apex_available: [
-        "com.android.sdkext",
-        "test_com.android.sdkext",
-    ],
-}
diff --git a/apex/sdkextensions/framework/api/current.txt b/apex/sdkextensions/framework/api/current.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/sdkextensions/framework/api/current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/sdkextensions/framework/api/module-lib-current.txt b/apex/sdkextensions/framework/api/module-lib-current.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/sdkextensions/framework/api/module-lib-current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/sdkextensions/framework/api/module-lib-removed.txt b/apex/sdkextensions/framework/api/module-lib-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/sdkextensions/framework/api/module-lib-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/sdkextensions/framework/api/removed.txt b/apex/sdkextensions/framework/api/removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/sdkextensions/framework/api/removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/sdkextensions/framework/api/system-current.txt b/apex/sdkextensions/framework/api/system-current.txt
deleted file mode 100644
index bbff4c5..0000000
--- a/apex/sdkextensions/framework/api/system-current.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-// Signature format: 2.0
-package android.os.ext {
-
-  public class SdkExtensions {
-    method public static int getExtensionVersion(int);
-  }
-
-}
-
diff --git a/apex/sdkextensions/framework/api/system-removed.txt b/apex/sdkextensions/framework/api/system-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/sdkextensions/framework/api/system-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/sdkextensions/framework/java/android/os/ext/SdkExtensions.java b/apex/sdkextensions/framework/java/android/os/ext/SdkExtensions.java
deleted file mode 100644
index 6c25f28..0000000
--- a/apex/sdkextensions/framework/java/android/os/ext/SdkExtensions.java
+++ /dev/null
@@ -1,75 +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 android.os.ext;
-
-import android.annotation.IntDef;
-import android.annotation.SystemApi;
-import android.os.Build.VERSION_CODES;
-import android.os.SystemProperties;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Methods for interacting with the extension SDK.
- *
- * This class provides information about the extension SDK version present
- * on this device. Use the {@link #getExtensionVersion(int) getExtension} to
- * query for the extension version for the given SDK version.
-
- * @hide
- */
-@SystemApi
-public class SdkExtensions {
-
-    private static final int R_EXTENSION_INT;
-    static {
-        // Note: when adding more extension versions, the logic that records current
-        // extension versions when saving a rollback must also be updated.
-        // At the time of writing this is in RollbackManagerServiceImpl#getExtensionVersions()
-        R_EXTENSION_INT = SystemProperties.getInt("build.version.extensions.r", 0);
-    }
-
-    /**
-     * Values suitable as parameters for {@link #getExtensionVersion(int)}.
-     * @hide
-     */
-    @IntDef(value = { VERSION_CODES.R })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface SdkVersion {}
-
-    private SdkExtensions() { }
-
-    /**
-     * Return the version of the extension to the given SDK.
-     *
-     * @param sdk the SDK version to get the extension version of.
-     * @see SdkVersion
-     * @throws IllegalArgumentException if sdk is not an sdk version with extensions
-     */
-    public static int getExtensionVersion(@SdkVersion int sdk) {
-        if (sdk < VERSION_CODES.R) {
-            throw new IllegalArgumentException(String.valueOf(sdk) + " does not have extensions");
-        }
-
-        if (sdk == VERSION_CODES.R) {
-            return R_EXTENSION_INT;
-        }
-        return 0;
-    }
-
-}
diff --git a/apex/sdkextensions/framework/java/android/os/ext/package.html b/apex/sdkextensions/framework/java/android/os/ext/package.html
deleted file mode 100644
index 34c1697..0000000
--- a/apex/sdkextensions/framework/java/android/os/ext/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<HTML>
-<BODY>
-Provides APIs to interface with the SDK extensions.
-</BODY>
-</HTML>
diff --git a/apex/sdkextensions/gen_sdkinfo.py b/apex/sdkextensions/gen_sdkinfo.py
deleted file mode 100644
index 5af478b..0000000
--- a/apex/sdkextensions/gen_sdkinfo.py
+++ /dev/null
@@ -1,19 +0,0 @@
-import sdk_pb2
-import sys
-
-if __name__ == '__main__':
-  argv = sys.argv[1:]
-  if not len(argv) == 4 or sorted([argv[0], argv[2]]) != ['-o', '-v']:
-    print('usage: gen_sdkinfo -v <version> -o <output-file>')
-    sys.exit(1)
-
-  for i in range(len(argv)):
-    if sys.argv[i] == '-o':
-      filename = sys.argv[i+1]
-    if sys.argv[i] == '-v':
-      version = int(sys.argv[i+1])
-
-  proto = sdk_pb2.SdkVersion()
-  proto.version = version
-  with open(filename, 'wb') as f:
-    f.write(proto.SerializeToString())
diff --git a/apex/sdkextensions/manifest.json b/apex/sdkextensions/manifest.json
deleted file mode 100644
index deeb29e..0000000
--- a/apex/sdkextensions/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "com.android.sdkext",
-  "version": 300000000
-}
diff --git a/apex/sdkextensions/sdk.proto b/apex/sdkextensions/sdk.proto
deleted file mode 100644
index d15b935..0000000
--- a/apex/sdkextensions/sdk.proto
+++ /dev/null
@@ -1,25 +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.
- */
-
-syntax = "proto3";
-package com.android.sdkext.proto;
-
-option java_outer_classname = "SdkProto";
-option optimize_for = LITE_RUNTIME;
-
-message SdkVersion {
-  int32 version = 1;
-}
diff --git a/apex/sdkextensions/testing/Android.bp b/apex/sdkextensions/testing/Android.bp
deleted file mode 100644
index f2f5b32..0000000
--- a/apex/sdkextensions/testing/Android.bp
+++ /dev/null
@@ -1,46 +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.
-
-apex_test {
-    name: "test_com.android.sdkext",
-    visibility: [ "//system/apex/tests" ],
-    defaults: ["com.android.sdkext-defaults"],
-    manifest: "test_manifest.json",
-    prebuilts: [ "sdkinfo_45" ],
-    file_contexts: ":com.android.sdkext-file_contexts",
-    installable: false, // Should never be installed on the systemimage
-    multilib: {
-        prefer32: {
-            binaries: ["derive_sdk_prefer32"],
-        },
-    },
-    // The automated test infra ends up building this apex for 64+32-bit and
-    // then installs it on a 32-bit-only device. Work around this weirdness
-    // by preferring 32-bit.
-    compile_multilib: "prefer32",
-}
-
-genrule {
-    name: "sdkinfo_45_src",
-    out: [ "sdkinfo.binarypb" ],
-    tools: [ "gen_sdkinfo" ],
-    cmd: "$(location) -v 45 -o $(out)",
-}
-
-prebuilt_etc {
-    name: "sdkinfo_45",
-    src: ":sdkinfo_45_src",
-    filename: "sdkinfo.binarypb",
-    installable: false,
-}
diff --git a/apex/sdkextensions/testing/test_manifest.json b/apex/sdkextensions/testing/test_manifest.json
deleted file mode 100644
index 1b4a2b0..0000000
--- a/apex/sdkextensions/testing/test_manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "com.android.sdkext",
-  "version": 2147483647
-}
diff --git a/api/test-current.txt b/api/test-current.txt
index 5dc7bdb..a163dea 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1728,6 +1728,15 @@
 
 }
 
+package android.media.tv {
+
+  public final class TvInputManager {
+    method public void addHardwareDevice(int);
+    method public void removeHardwareDevice(int);
+  }
+
+}
+
 package android.metrics {
 
   public class LogMaker {
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index ecb95bd..3bcabe5 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -48,6 +48,7 @@
 #include <ui/Region.h>
 
 #include <gui/ISurfaceComposer.h>
+#include <gui/DisplayEventReceiver.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 
@@ -113,8 +114,8 @@
 // ---------------------------------------------------------------------------
 
 BootAnimation::BootAnimation(sp<Callbacks> callbacks)
-        : Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
-        mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks) {
+        : Thread(false), mClockEnabled(true), mTimeIsAccurate(false), mTimeFormat12Hour(false),
+        mTimeCheckThread(nullptr), mCallbacks(callbacks), mLooper(new Looper(false)) {
     mSession = new SurfaceComposerClient();
 
     std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
@@ -154,8 +155,7 @@
     return mSession;
 }
 
-void BootAnimation::binderDied(const wp<IBinder>&)
-{
+void BootAnimation::binderDied(const wp<IBinder>&) {
     // woah, surfaceflinger died!
     SLOGD("SurfaceFlinger died, exiting...");
 
@@ -219,8 +219,7 @@
     return NO_ERROR;
 }
 
-status_t BootAnimation::initTexture(FileMap* map, int* width, int* height)
-{
+status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) {
     SkBitmap bitmap;
     sk_sp<SkData> data = SkData::MakeWithoutCopy(map->getDataPtr(),
             map->getDataLength());
@@ -278,6 +277,78 @@
     return NO_ERROR;
 }
 
+class BootAnimation::DisplayEventCallback : public LooperCallback {
+    BootAnimation* mBootAnimation;
+
+public:
+    DisplayEventCallback(BootAnimation* bootAnimation) {
+        mBootAnimation = bootAnimation;
+    }
+
+    int handleEvent(int /* fd */, int events, void* /* data */) {
+        if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
+            ALOGE("Display event receiver pipe was closed or an error occurred. events=0x%x",
+                    events);
+            return 0; // remove the callback
+        }
+
+        if (!(events & Looper::EVENT_INPUT)) {
+            ALOGW("Received spurious callback for unhandled poll event.  events=0x%x", events);
+            return 1; // keep the callback
+        }
+
+        constexpr int kBufferSize = 100;
+        DisplayEventReceiver::Event buffer[kBufferSize];
+        ssize_t numEvents;
+        do {
+            numEvents = mBootAnimation->mDisplayEventReceiver->getEvents(buffer, kBufferSize);
+            for (size_t i = 0; i < static_cast<size_t>(numEvents); i++) {
+                const auto& event = buffer[i];
+                if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) {
+                    SLOGV("Hotplug received");
+
+                    if (!event.hotplug.connected) {
+                        // ignore hotplug disconnect
+                        continue;
+                    }
+                    auto token = SurfaceComposerClient::getPhysicalDisplayToken(
+                        event.header.displayId);
+
+                    if (token != mBootAnimation->mDisplayToken) {
+                        // ignore hotplug of a secondary display
+                        continue;
+                    }
+
+                    DisplayConfig displayConfig;
+                    const status_t error = SurfaceComposerClient::getActiveDisplayConfig(
+                        mBootAnimation->mDisplayToken, &displayConfig);
+                    if (error != NO_ERROR) {
+                        SLOGE("Can't get active display configuration.");
+                    }
+                    mBootAnimation->resizeSurface(displayConfig.resolution.getWidth(),
+                        displayConfig.resolution.getHeight());
+                }
+            }
+        } while (numEvents > 0);
+
+        return 1;  // keep the callback
+    }
+};
+
+EGLConfig BootAnimation::getEglConfig(const EGLDisplay& display) {
+    const EGLint attribs[] = {
+        EGL_RED_SIZE,   8,
+        EGL_GREEN_SIZE, 8,
+        EGL_BLUE_SIZE,  8,
+        EGL_DEPTH_SIZE, 0,
+        EGL_NONE
+    };
+    EGLint numConfigs;
+    EGLConfig config;
+    eglChooseConfig(display, attribs, &config, 1, &numConfigs);
+    return config;
+}
+
 status_t BootAnimation::readyToRun() {
     mAssets.addDefaultAssets();
 
@@ -346,25 +417,12 @@
     sp<Surface> s = control->getSurface();
 
     // initialize opengl and egl
-    const EGLint attribs[] = {
-            EGL_RED_SIZE,   8,
-            EGL_GREEN_SIZE, 8,
-            EGL_BLUE_SIZE,  8,
-            EGL_DEPTH_SIZE, 0,
-            EGL_NONE
-    };
-    EGLint w, h;
-    EGLint numConfigs;
-    EGLConfig config;
-    EGLSurface surface;
-    EGLContext context;
-
     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-
     eglInitialize(display, nullptr, nullptr);
-    eglChooseConfig(display, attribs, &config, 1, &numConfigs);
-    surface = eglCreateWindowSurface(display, config, s.get(), nullptr);
-    context = eglCreateContext(display, config, nullptr, nullptr);
+    EGLConfig config = getEglConfig(display);
+    EGLSurface surface = eglCreateWindowSurface(display, config, s.get(), nullptr);
+    EGLContext context = eglCreateContext(display, config, nullptr, nullptr);
+    EGLint w, h;
     eglQuerySurface(display, surface, EGL_WIDTH, &w);
     eglQuerySurface(display, surface, EGL_HEIGHT, &h);
 
@@ -380,9 +438,46 @@
     mFlingerSurface = s;
     mTargetInset = -1;
 
+    // Register a display event receiver
+    mDisplayEventReceiver = std::make_unique<DisplayEventReceiver>();
+    status_t status = mDisplayEventReceiver->initCheck();
+    SLOGE_IF(status != NO_ERROR, "Initialization of DisplayEventReceiver failed with status: %d",
+            status);
+    mLooper->addFd(mDisplayEventReceiver->getFd(), 0, Looper::EVENT_INPUT,
+            new DisplayEventCallback(this), nullptr);
+
     return NO_ERROR;
 }
 
+void BootAnimation::resizeSurface(int newWidth, int newHeight) {
+    // We assume this function is called on the animation thread.
+    if (newWidth == mWidth && newHeight == mHeight) {
+        return;
+    }
+    SLOGV("Resizing the boot animation surface to %d %d", newWidth, newHeight);
+
+    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglDestroySurface(mDisplay, mSurface);
+
+    mWidth = newWidth;
+    mHeight = newHeight;
+
+    SurfaceComposerClient::Transaction t;
+    t.setSize(mFlingerSurfaceControl, mWidth, mHeight);
+    t.apply();
+
+    EGLConfig config = getEglConfig(mDisplay);
+    EGLSurface surface = eglCreateWindowSurface(mDisplay, config, mFlingerSurface.get(), nullptr);
+    if (eglMakeCurrent(mDisplay, surface, surface, mContext) == EGL_FALSE) {
+        SLOGE("Can't make the new surface current. Error %d", eglGetError());
+        return;
+    }
+    glViewport(0, 0, mWidth, mHeight);
+    glScissor(0, 0, mWidth, mHeight);
+
+    mSurface = surface;
+}
+
 bool BootAnimation::preloadAnimation() {
     findBootAnimationFile();
     if (!mZipFileName.isEmpty()) {
@@ -443,15 +538,14 @@
     }
 }
 
-bool BootAnimation::threadLoop()
-{
-    bool r;
+bool BootAnimation::threadLoop() {
+    bool result;
     // We have no bootanimation file, so we use the stock android logo
     // animation.
     if (mZipFileName.isEmpty()) {
-        r = android();
+        result = android();
     } else {
-        r = movie();
+        result = movie();
     }
 
     eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
@@ -462,11 +556,10 @@
     eglTerminate(mDisplay);
     eglReleaseThread();
     IPCThreadState::self()->stopProcess();
-    return r;
+    return result;
 }
 
-bool BootAnimation::android()
-{
+bool BootAnimation::android() {
     SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
             elapsedRealtime());
     initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
@@ -485,19 +578,19 @@
     glEnable(GL_TEXTURE_2D);
     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
-    const GLint xc = (mWidth  - mAndroid[0].w) / 2;
-    const GLint yc = (mHeight - mAndroid[0].h) / 2;
-    const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);
-
-    glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
-            updateRect.height());
-
     // Blend state
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
     const nsecs_t startTime = systemTime();
     do {
+        processDisplayEvents();
+        const GLint xc = (mWidth  - mAndroid[0].w) / 2;
+        const GLint yc = (mHeight - mAndroid[0].h) / 2;
+        const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);
+        glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
+                updateRect.height());
+
         nsecs_t now = systemTime();
         double time = now - startTime;
         float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w;
@@ -612,8 +705,7 @@
 }
 
 
-static bool readFile(ZipFileRO* zip, const char* name, String8& outString)
-{
+static bool readFile(ZipFileRO* zip, const char* name, String8& outString) {
     ZipEntryRO entry = zip->findEntryByName(name);
     SLOGE_IF(!entry, "couldn't find %s", name);
     if (!entry) {
@@ -734,8 +826,7 @@
     drawText(out, font, false, &x, &y);
 }
 
-bool BootAnimation::parseAnimationDesc(Animation& animation)
-{
+bool BootAnimation::parseAnimationDesc(Animation& animation)  {
     String8 desString;
 
     if (!readFile(animation.zip, "desc.txt", desString)) {
@@ -802,8 +893,7 @@
     return true;
 }
 
-bool BootAnimation::preloadZip(Animation& animation)
-{
+bool BootAnimation::preloadZip(Animation& animation) {
     // read all the data structures
     const size_t pcount = animation.parts.size();
     void *cookie = nullptr;
@@ -900,8 +990,7 @@
     return true;
 }
 
-bool BootAnimation::movie()
-{
+bool BootAnimation::movie() {
     if (mAnimation == nullptr) {
         mAnimation = loadAnimation(mZipFileName);
     }
@@ -987,12 +1076,9 @@
     return false;
 }
 
-bool BootAnimation::playAnimation(const Animation& animation)
-{
+bool BootAnimation::playAnimation(const Animation& animation) {
     const size_t pcount = animation.parts.size();
     nsecs_t frameDuration = s2ns(1) / animation.fps;
-    const int animationX = (mWidth - animation.width) / 2;
-    const int animationY = (mHeight - animation.height) / 2;
 
     SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
             elapsedRealtime());
@@ -1023,6 +1109,11 @@
                     1.0f);
 
             for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) {
+                processDisplayEvents();
+
+                const int animationX = (mWidth - animation.width) / 2;
+                const int animationY = (mHeight - animation.height) / 2;
+
                 const Animation::Frame& frame(part.frames[j]);
                 nsecs_t lastFrame = systemTime();
 
@@ -1106,6 +1197,12 @@
     return true;
 }
 
+void BootAnimation::processDisplayEvents() {
+    // This will poll mDisplayEventReceiver and if there are new events it'll call
+    // displayEventCallback synchronously.
+    mLooper->pollOnce(0);
+}
+
 void BootAnimation::handleViewport(nsecs_t timestep) {
     if (mShuttingDown || !mFlingerSurfaceControl || mTargetInset == 0) {
         return;
@@ -1148,8 +1245,7 @@
     mCurrentInset += delta;
 }
 
-void BootAnimation::releaseAnimation(Animation* animation) const
-{
+void BootAnimation::releaseAnimation(Animation* animation) const {
     for (Vector<Animation::Part>::iterator it = animation->parts.begin(),
          e = animation->parts.end(); it != e; ++it) {
         if (it->animation)
@@ -1160,8 +1256,7 @@
     delete animation;
 }
 
-BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn)
-{
+BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) {
     if (mLoadedFiles.indexOf(fn) >= 0) {
         SLOGE("File \"%s\" is already loaded. Cyclic ref is not allowed",
             fn.string());
@@ -1323,5 +1418,4 @@
 
 // ---------------------------------------------------------------------------
 
-}
-; // namespace android
+} // namespace android
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 574d65e..36cd91b 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -18,11 +18,14 @@
 #define ANDROID_BOOTANIMATION_H
 
 #include <vector>
+#include <queue>
 
 #include <stdint.h>
 #include <sys/types.h>
 
 #include <androidfw/AssetManager.h>
+#include <gui/DisplayEventReceiver.h>
+#include <utils/Looper.h>
 #include <utils/Thread.h>
 #include <binder/IBinder.h>
 
@@ -145,6 +148,11 @@
         BootAnimation* mBootAnimation;
     };
 
+    // Display event handling
+    class DisplayEventCallback;
+    int displayEventCallback(int fd, int events, void* data);
+    void processDisplayEvents();
+
     status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
     status_t initTexture(FileMap* map, int* width, int* height);
     status_t initFont(Font* font, const char* fallback);
@@ -161,6 +169,8 @@
     void findBootAnimationFile();
     bool findBootAnimationFileInternal(const std::vector<std::string>& files);
     bool preloadAnimation();
+    EGLConfig getEglConfig(const EGLDisplay&);
+    void resizeSurface(int newWidth, int newHeight);
 
     void checkExit();
 
@@ -189,6 +199,8 @@
     sp<TimeCheckThread> mTimeCheckThread = nullptr;
     sp<Callbacks> mCallbacks;
     Animation* mAnimation = nullptr;
+    std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver;
+    sp<Looper> mLooper;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index f30ed17..3dbe413 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -292,6 +292,7 @@
     name: "statsd_test",
     defaults: ["statsd_defaults"],
     test_suites: ["device-tests", "mts"],
+    test_config: "statsd_test.xml",
 
     //TODO(b/153588990): Remove when the build system properly separates
     //32bit and 64bit architectures.
@@ -299,7 +300,10 @@
     multilib: {
         lib64: {
             suffix: "64",
-        }
+        },
+        lib32: {
+            suffix: "32",
+        },
     },
 
     cflags: [
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 4ffa040..47bab29 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1298,7 +1298,6 @@
     return Status::ok();
 }
 
-
 void StatsService::statsCompanionServiceDied(void* cookie) {
     auto thiz = static_cast<StatsService*>(cookie);
     thiz->statsCompanionServiceDiedImpl();
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index c6e9e01..62e1567 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -6713,11 +6713,11 @@
  * Logs when a data stall event occurs.
  *
  * Log from:
- *     frameworks/base/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+ *     packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
  */
 message DataStallEvent {
     // Data stall evaluation type.
-    // See frameworks/base/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+    // See packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
     // Refer to the definition of DATA_STALL_EVALUATION_TYPE_*.
     optional int32 evaluation_type = 1;
     // See definition in data_stall_event.proto.
@@ -6730,6 +6730,10 @@
     optional com.android.server.connectivity.CellularData cell_info = 5 [(log_mode) = MODE_BYTES];
     // See definition in data_stall_event.proto.
     optional com.android.server.connectivity.DnsEvent dns_event = 6 [(log_mode) = MODE_BYTES];
+    // The tcp packets fail rate from the latest tcp polling.
+    optional int32 tcp_fail_rate = 7;
+    // Number of packets sent since the last received packet.
+    optional int32 tcp_sent_since_last_recv = 8;
 }
 
 /*
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 3d0eeb8..8587e145 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -160,7 +160,7 @@
     static const long kPullerCacheClearIntervalSec = 1;
 
     // Max time to do a pull.
-    static const int64_t kPullMaxDelayNs = 10 * NS_PER_SEC;
+    static const int64_t kPullMaxDelayNs = 30 * NS_PER_SEC;
 
     // Maximum number of pushed atoms statsd stats will track above kMaxPushedAtomId.
     static const int kMaxNonPlatformPushedAtoms = 100;
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index e86fdf0..673f668 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -82,7 +82,9 @@
     DIMENSION_GUARDRAIL_REACHED = 6,
     MULTIPLE_BUCKETS_SKIPPED = 7,
     // Not an invalid bucket case, but the bucket is dropped.
-    BUCKET_TOO_SMALL = 8
+    BUCKET_TOO_SMALL = 8,
+    // Not an invalid bucket case, but the bucket is skipped.
+    NO_DATA = 9
 };
 
 struct Activation {
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index f03ce45..dbec24b 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -108,7 +108,7 @@
       mSkipZeroDiffOutput(metric.skip_zero_diff_output()),
       mUseZeroDefaultBase(metric.use_zero_default_base()),
       mHasGlobalBase(false),
-      mCurrentBucketIsInvalid(false),
+      mCurrentBucketIsSkipped(false),
       mMaxPullDelayNs(metric.max_pull_delay_sec() > 0 ? metric.max_pull_delay_sec() * NS_PER_SEC
                                                       : StatsdStats::kPullMaxDelayNs),
       mSplitBucketForAppUpgrade(metric.split_bucket_for_app_upgrade()),
@@ -383,15 +383,12 @@
 
 void ValueMetricProducer::invalidateCurrentBucketWithoutResetBase(const int64_t dropTimeNs,
                                                                   const BucketDropReason reason) {
-    if (!mCurrentBucketIsInvalid) {
+    if (!mCurrentBucketIsSkipped) {
         // Only report to StatsdStats once per invalid bucket.
         StatsdStats::getInstance().noteInvalidatedBucket(mMetricId);
     }
 
-    if (!maxDropEventsReached()) {
-        mCurrentSkippedBucket.dropEvents.emplace_back(buildDropEvent(dropTimeNs, reason));
-    }
-    mCurrentBucketIsInvalid = true;
+    skipCurrentBucket(dropTimeNs, reason);
 }
 
 void ValueMetricProducer::invalidateCurrentBucket(const int64_t dropTimeNs,
@@ -400,6 +397,14 @@
     resetBase();
 }
 
+void ValueMetricProducer::skipCurrentBucket(const int64_t dropTimeNs,
+                                            const BucketDropReason reason) {
+    if (!maxDropEventsReached()) {
+        mCurrentSkippedBucket.dropEvents.emplace_back(buildDropEvent(dropTimeNs, reason));
+    }
+    mCurrentBucketIsSkipped = true;
+}
+
 void ValueMetricProducer::resetBase() {
     for (auto& slice : mCurrentBaseInfo) {
         for (auto& baseInfo : slice.second) {
@@ -961,12 +966,10 @@
     int64_t conditionTrueDuration = mConditionTimer.newBucketStart(bucketEndTime);
     bool isBucketLargeEnough = bucketEndTime - mCurrentBucketStartTimeNs >= mMinBucketSizeNs;
     if (!isBucketLargeEnough) {
-        if (!maxDropEventsReached()) {
-            mCurrentSkippedBucket.dropEvents.emplace_back(
-                    buildDropEvent(eventTimeNs, BucketDropReason::BUCKET_TOO_SMALL));
-        }
+        skipCurrentBucket(eventTimeNs, BucketDropReason::BUCKET_TOO_SMALL);
     }
-    if (isBucketLargeEnough && !mCurrentBucketIsInvalid) {
+    bool bucketHasData = false;
+    if (!mCurrentBucketIsSkipped) {
         // The current bucket is large enough to keep.
         for (const auto& slice : mCurrentSlicedBucket) {
             ValueBucket bucket = buildPartialBucket(bucketEndTime, slice.second);
@@ -975,14 +978,33 @@
             if (bucket.valueIndex.size() > 0) {
                 auto& bucketList = mPastBuckets[slice.first];
                 bucketList.push_back(bucket);
+                bucketHasData = true;
             }
         }
-    } else {
+    }
+
+    if (!bucketHasData && !mCurrentBucketIsSkipped) {
+        skipCurrentBucket(eventTimeNs, BucketDropReason::NO_DATA);
+    }
+
+    if (mCurrentBucketIsSkipped) {
         mCurrentSkippedBucket.bucketStartTimeNs = mCurrentBucketStartTimeNs;
-        mCurrentSkippedBucket.bucketEndTimeNs = bucketEndTime;
+        // Fill in the gap if we skipped multiple buckets.
+        mCurrentSkippedBucket.bucketEndTimeNs =
+                numBucketsForward > 1 ? nextBucketStartTimeNs : bucketEndTime;
         mSkippedBuckets.emplace_back(mCurrentSkippedBucket);
     }
 
+    // This means that the current bucket was not flushed before a forced bucket split.
+    if (bucketEndTime < nextBucketStartTimeNs && numBucketsForward <= 1) {
+        SkippedBucket bucketInGap;
+        bucketInGap.bucketStartTimeNs = bucketEndTime;
+        bucketInGap.bucketEndTimeNs = nextBucketStartTimeNs;
+        bucketInGap.dropEvents.emplace_back(
+                buildDropEvent(eventTimeNs, BucketDropReason::NO_DATA));
+        mSkippedBuckets.emplace_back(bucketInGap);
+    }
+
     appendToFullBucket(eventTimeNs, fullBucketEndTimeNs);
     initCurrentSlicedBucket(nextBucketStartTimeNs);
     // Update the condition timer again, in case we skipped buckets.
@@ -1036,13 +1058,13 @@
         // TODO: remove mCurrentBaseInfo entries when obsolete
     }
 
-    mCurrentBucketIsInvalid = false;
+    mCurrentBucketIsSkipped = false;
     mCurrentSkippedBucket.reset();
 
     // If we do not have a global base when the condition is true,
     // we will have incomplete bucket for the next bucket.
     if (mUseDiff && !mHasGlobalBase && mCondition) {
-        mCurrentBucketIsInvalid = false;
+        mCurrentBucketIsSkipped = false;
     }
     mCurrentBucketStartTimeNs = nextBucketStartTimeNs;
     VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
@@ -1051,7 +1073,7 @@
 
 void ValueMetricProducer::appendToFullBucket(int64_t eventTimeNs, int64_t fullBucketEndTimeNs) {
     bool isFullBucketReached = eventTimeNs > fullBucketEndTimeNs;
-    if (mCurrentBucketIsInvalid) {
+    if (mCurrentBucketIsSkipped) {
         if (isFullBucketReached) {
             // If the bucket is invalid, we ignore the full bucket since it contains invalid data.
             mCurrentFullBucket.clear();
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 751fef2..bb4a661 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -144,6 +144,10 @@
     void invalidateCurrentBucket(const int64_t dropTimeNs, const BucketDropReason reason);
     void invalidateCurrentBucketWithoutResetBase(const int64_t dropTimeNs,
                                                  const BucketDropReason reason);
+    // Skips the current bucket without notifying StatsdStats of the skipped bucket.
+    // This should only be called from #flushCurrentBucketLocked. Otherwise, a future event that
+    // causes the bucket to be invalidated will not notify StatsdStats.
+    void skipCurrentBucket(const int64_t dropTimeNs, const BucketDropReason reason);
 
     const int mWhatMatcherIndex;
 
@@ -250,11 +254,9 @@
     // diff against.
     bool mHasGlobalBase;
 
-    // Invalid bucket. There was a problem in collecting data in the current bucket so we cannot
-    // trust any of the data in this bucket.
-    //
-    // For instance, one pull failed.
-    bool mCurrentBucketIsInvalid;
+    // This is to track whether or not the bucket is skipped for any of the reasons listed in
+    // BucketDropReason, many of which make the bucket potentially invalid.
+    bool mCurrentBucketIsSkipped;
 
     const int64_t mMaxPullDelayNs;
 
diff --git a/cmds/statsd/src/shell/ShellSubscriber.cpp b/cmds/statsd/src/shell/ShellSubscriber.cpp
index 361b161..fd883c2 100644
--- a/cmds/statsd/src/shell/ShellSubscriber.cpp
+++ b/cmds/statsd/src/shell/ShellSubscriber.cpp
@@ -41,13 +41,8 @@
 
     {
         std::unique_lock<std::mutex> lock(mMutex);
-        if (myToken != mToken) {
-            // Some other subscription has already come in. Stop.
-            return;
-        }
         mSubscriptionInfo = mySubscriptionInfo;
-
-        spawnHelperThreadsLocked(mySubscriptionInfo, myToken);
+        spawnHelperThread(myToken);
         waitForSubscriptionToEndLocked(mySubscriptionInfo, myToken, lock, timeoutSec);
 
         if (mSubscriptionInfo == mySubscriptionInfo) {
@@ -57,14 +52,9 @@
     }
 }
 
-void ShellSubscriber::spawnHelperThreadsLocked(shared_ptr<SubscriptionInfo> myInfo, int myToken) {
-    if (!myInfo->mPulledInfo.empty() && myInfo->mPullIntervalMin > 0) {
-        std::thread puller([this, myToken] { startPull(myToken); });
-        puller.detach();
-    }
-
-    std::thread heartbeatSender([this, myToken] { sendHeartbeats(myToken); });
-    heartbeatSender.detach();
+void ShellSubscriber::spawnHelperThread(int myToken) {
+    std::thread t([this, myToken] { pullAndSendHeartbeats(myToken); });
+    t.detach();
 }
 
 void ShellSubscriber::waitForSubscriptionToEndLocked(shared_ptr<SubscriptionInfo> myInfo,
@@ -114,13 +104,7 @@
         subscriptionInfo->mPushedMatchers.push_back(pushed);
     }
 
-    int minInterval = -1;
     for (const auto& pulled : config.pulled()) {
-        // All intervals need to be multiples of the min interval.
-        if (minInterval < 0 || pulled.freq_millis() < minInterval) {
-            minInterval = pulled.freq_millis();
-        }
-
         vector<string> packages;
         vector<int32_t> uids;
         for (const string& pkg : pulled.packages()) {
@@ -136,18 +120,18 @@
                                                    uids);
         VLOG("adding matcher for pulled atom %d", pulled.matcher().atom_id());
     }
-    subscriptionInfo->mPullIntervalMin = minInterval;
 
     return true;
 }
 
-void ShellSubscriber::startPull(int myToken) {
-    VLOG("ShellSubscriber: pull thread %d starting", myToken);
+void ShellSubscriber::pullAndSendHeartbeats(int myToken) {
+    VLOG("ShellSubscriber: helper thread %d starting", myToken);
     while (true) {
+        int64_t sleepTimeMs = INT_MAX;
         {
             std::lock_guard<std::mutex> lock(mMutex);
             if (!mSubscriptionInfo || mToken != myToken) {
-                VLOG("ShellSubscriber: pulling thread %d done!", myToken);
+                VLOG("ShellSubscriber: helper thread %d done!", myToken);
                 return;
             }
 
@@ -168,11 +152,27 @@
 
                 pullInfo.mPrevPullElapsedRealtimeMs = nowMillis;
             }
+
+            // Send a heartbeat, consisting of a data size of 0, if perfd hasn't recently received
+            // data from statsd. When it receives the data size of 0, perfd will not expect any
+            // atoms and recheck whether the subscription should end.
+            if (nowMillis - mLastWriteMs > kMsBetweenHeartbeats) {
+                attemptWriteToPipeLocked(/*dataSize=*/0);
+            }
+
+            // Determine how long to sleep before doing more work.
+            for (PullInfo& pullInfo : mSubscriptionInfo->mPulledInfo) {
+                int64_t nextPullTime = pullInfo.mPrevPullElapsedRealtimeMs + pullInfo.mInterval;
+                int64_t timeBeforePull = nextPullTime - nowMillis; // guaranteed to be non-negative
+                if (timeBeforePull < sleepTimeMs) sleepTimeMs = timeBeforePull;
+            }
+            int64_t timeBeforeHeartbeat = (mLastWriteMs + kMsBetweenHeartbeats) - nowMillis;
+            if (timeBeforeHeartbeat < sleepTimeMs) sleepTimeMs = timeBeforeHeartbeat;
         }
 
-        VLOG("ShellSubscriber: pulling thread %d sleeping for %d ms", myToken,
-             mSubscriptionInfo->mPullIntervalMin);
-        std::this_thread::sleep_for(std::chrono::milliseconds(mSubscriptionInfo->mPullIntervalMin));
+        VLOG("ShellSubscriber: helper thread %d sleeping for %lld ms", myToken,
+             (long long)sleepTimeMs);
+        std::this_thread::sleep_for(std::chrono::milliseconds(sleepTimeMs));
     }
 }
 
@@ -200,7 +200,7 @@
         }
     }
 
-    if (count > 0) attemptWriteToSocketLocked(mProto.size());
+    if (count > 0) attemptWriteToPipeLocked(mProto.size());
 }
 
 void ShellSubscriber::onLogEvent(const LogEvent& event) {
@@ -214,26 +214,24 @@
                                               util::FIELD_COUNT_REPEATED | FIELD_ID_ATOM);
             event.ToProto(mProto);
             mProto.end(atomToken);
-            attemptWriteToSocketLocked(mProto.size());
+            attemptWriteToPipeLocked(mProto.size());
         }
     }
 }
 
-// Tries to write the atom encoded in mProto to the socket. If the write fails
+// Tries to write the atom encoded in mProto to the pipe. If the write fails
 // because the read end of the pipe has closed, signals to other threads that
 // the subscription should end.
-void ShellSubscriber::attemptWriteToSocketLocked(size_t dataSize) {
-    // First write the payload size.
+void ShellSubscriber::attemptWriteToPipeLocked(size_t dataSize) {
+    // First, write the payload size.
     if (!android::base::WriteFully(mSubscriptionInfo->mOutputFd, &dataSize, sizeof(dataSize))) {
         mSubscriptionInfo->mClientAlive = false;
         mSubscriptionShouldEnd.notify_one();
         return;
     }
 
-    if (dataSize == 0) return;
-
-    // Then, write the payload.
-    if (!mProto.flush(mSubscriptionInfo->mOutputFd)) {
+    // Then, write the payload if this is not just a heartbeat.
+    if (dataSize > 0 && !mProto.flush(mSubscriptionInfo->mOutputFd)) {
         mSubscriptionInfo->mClientAlive = false;
         mSubscriptionShouldEnd.notify_one();
         return;
@@ -242,28 +240,6 @@
     mLastWriteMs = getElapsedRealtimeMillis();
 }
 
-// Send a heartbeat, consisting solely of a data size of 0, if perfd has not
-// recently received any writes from statsd. When it receives the data size of
-// 0, perfd will not expect any data and recheck whether the shell command is
-// still running.
-void ShellSubscriber::sendHeartbeats(int myToken) {
-    while (true) {
-        {
-            std::lock_guard<std::mutex> lock(mMutex);
-            if (!mSubscriptionInfo || myToken != mToken) {
-                VLOG("ShellSubscriber: heartbeat thread %d done!", myToken);
-                return;
-            }
-
-            if (getElapsedRealtimeMillis() - mLastWriteMs > kMsBetweenHeartbeats) {
-                VLOG("ShellSubscriber: sending a heartbeat to perfd");
-                attemptWriteToSocketLocked(/*dataSize=*/0);
-            }
-        }
-        std::this_thread::sleep_for(std::chrono::milliseconds(kMsBetweenHeartbeats));
-    }
-}
-
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/shell/ShellSubscriber.h b/cmds/statsd/src/shell/ShellSubscriber.h
index 26c8a2a..4c05fa7 100644
--- a/cmds/statsd/src/shell/ShellSubscriber.h
+++ b/cmds/statsd/src/shell/ShellSubscriber.h
@@ -92,7 +92,6 @@
         int mOutputFd;
         std::vector<SimpleAtomMatcher> mPushedMatchers;
         std::vector<PullInfo> mPulledInfo;
-        int mPullIntervalMin;
         bool mClientAlive;
     };
 
@@ -100,27 +99,25 @@
 
     bool readConfig(std::shared_ptr<SubscriptionInfo> subscriptionInfo);
 
-    void spawnHelperThreadsLocked(std::shared_ptr<SubscriptionInfo> myInfo, int myToken);
+    void spawnHelperThread(int myToken);
 
     void waitForSubscriptionToEndLocked(std::shared_ptr<SubscriptionInfo> myInfo,
                                         int myToken,
                                         std::unique_lock<std::mutex>& lock,
                                         int timeoutSec);
 
-    void startPull(int myToken);
+    // Helper thread that pulls atoms at a regular frequency and sends
+    // heartbeats to perfd if statsd hasn't recently sent any data. Statsd must
+    // send heartbeats for perfd to escape a blocking read call and recheck if
+    // the user has terminated the subscription.
+    void pullAndSendHeartbeats(int myToken);
 
     void writePulledAtomsLocked(const vector<std::shared_ptr<LogEvent>>& data,
                                 const SimpleAtomMatcher& matcher);
 
     void getUidsForPullAtom(vector<int32_t>* uids, const PullInfo& pullInfo);
 
-    void attemptWriteToSocketLocked(size_t dataSize);
-
-    // Send ocassional heartbeats for two reasons: (a) for statsd to detect when
-    // the read end of the pipe has closed and (b) for perfd to escape a
-    // blocking read call and recheck if the user has terminated the
-    // subscription.
-    void sendHeartbeats(int myToken);
+    void attemptWriteToPipeLocked(size_t dataSize);
 
     sp<UidMap> mUidMap;
 
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 1121392..6bfa267 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -212,6 +212,8 @@
       MULTIPLE_BUCKETS_SKIPPED = 7;
       // Not an invalid bucket case, but the bucket is dropped.
       BUCKET_TOO_SMALL = 8;
+      // Not an invalid bucket case, but the bucket is skipped.
+      NO_DATA = 9;
   };
 
   message DropEvent {
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 2e6043d..72decf2 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -278,7 +278,7 @@
 
   optional int64 max_num_gauge_atoms_per_bucket = 11 [default = 10];
 
-  optional int32 max_pull_delay_sec = 13 [default = 10];
+  optional int32 max_pull_delay_sec = 13 [default = 30];
 
   optional bool split_bucket_for_app_upgrade = 14 [default = true];
 }
@@ -328,7 +328,7 @@
 
   optional bool skip_zero_diff_output = 14 [default = true];
 
-  optional int32 max_pull_delay_sec = 16 [default = 10];
+  optional int32 max_pull_delay_sec = 16 [default = 30];
 
   optional bool split_bucket_for_app_upgrade = 17 [default = true];
 
diff --git a/cmds/statsd/statsd_test.xml b/cmds/statsd/statsd_test.xml
new file mode 100644
index 0000000..8f9bb1c
--- /dev/null
+++ b/cmds/statsd/statsd_test.xml
@@ -0,0 +1,37 @@
+<?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.
+-->
+<configuration description="Runs statsd_test.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+    <option name="test-suite-tag" value="mts" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+       <option name="cleanup" value="true" />
+       <option name="push" value="statsd_test->/data/local/tmp/statsd_test" />
+       <option name="append-bitness" value="true" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="statsd_test" />
+    </test>
+
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <option name="mainline-module-package-name" value="com.google.android.os.statsd" />
+    </object>
+</configuration>
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 474aa22..14246cab 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -1115,13 +1115,21 @@
     EXPECT_EQ(false, curInterval.hasValue);
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs},
                                     {bucket2StartTimeNs}, {bucket3StartTimeNs});
+    // The 1st bucket is dropped because of no data
     // The 3rd bucket is dropped due to multiple buckets being skipped.
-    ASSERT_EQ(1, valueProducer->mSkippedBuckets.size());
-    EXPECT_EQ(bucket3StartTimeNs, valueProducer->mSkippedBuckets[0].bucketStartTimeNs);
-    EXPECT_EQ(bucket4StartTimeNs, valueProducer->mSkippedBuckets[0].bucketEndTimeNs);
+    ASSERT_EQ(2, valueProducer->mSkippedBuckets.size());
+
+    EXPECT_EQ(bucketStartTimeNs, valueProducer->mSkippedBuckets[0].bucketStartTimeNs);
+    EXPECT_EQ(bucket2StartTimeNs, valueProducer->mSkippedBuckets[0].bucketEndTimeNs);
     ASSERT_EQ(1, valueProducer->mSkippedBuckets[0].dropEvents.size());
-    EXPECT_EQ(MULTIPLE_BUCKETS_SKIPPED, valueProducer->mSkippedBuckets[0].dropEvents[0].reason);
-    EXPECT_EQ(bucket6StartTimeNs, valueProducer->mSkippedBuckets[0].dropEvents[0].dropTimeNs);
+    EXPECT_EQ(NO_DATA, valueProducer->mSkippedBuckets[0].dropEvents[0].reason);
+    EXPECT_EQ(bucket2StartTimeNs, valueProducer->mSkippedBuckets[0].dropEvents[0].dropTimeNs);
+
+    EXPECT_EQ(bucket3StartTimeNs, valueProducer->mSkippedBuckets[1].bucketStartTimeNs);
+    EXPECT_EQ(bucket6StartTimeNs, valueProducer->mSkippedBuckets[1].bucketEndTimeNs);
+    ASSERT_EQ(1, valueProducer->mSkippedBuckets[1].dropEvents.size());
+    EXPECT_EQ(MULTIPLE_BUCKETS_SKIPPED, valueProducer->mSkippedBuckets[1].dropEvents[0].reason);
+    EXPECT_EQ(bucket6StartTimeNs, valueProducer->mSkippedBuckets[1].dropEvents[0].dropTimeNs);
 }
 
 /*
@@ -2214,7 +2222,7 @@
     valueProducer->mCondition = ConditionState::kFalse;
 
     valueProducer->onConditionChanged(true, bucketStartTimeNs + 2);
-    EXPECT_EQ(true, valueProducer->mCurrentBucketIsInvalid);
+    EXPECT_EQ(true, valueProducer->mCurrentBucketIsSkipped);
     ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
     ASSERT_EQ(0UL, valueProducer->mSkippedBuckets.size());
 
@@ -2629,13 +2637,17 @@
 
     vector<shared_ptr<LogEvent>> allData;
     allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 4));
+    // Pull fails and arrives late.
     valueProducer->onDataPulled(allData, /** fails */ false, bucket3StartTimeNs + 1);
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9},
                                     {partialBucketSplitTimeNs - bucketStartTimeNs},
                                     {bucketStartTimeNs}, {partialBucketSplitTimeNs});
     ASSERT_EQ(1, valueProducer->mSkippedBuckets.size());
+    ASSERT_EQ(2, valueProducer->mSkippedBuckets[0].dropEvents.size());
+    EXPECT_EQ(PULL_FAILED, valueProducer->mSkippedBuckets[0].dropEvents[0].reason);
+    EXPECT_EQ(MULTIPLE_BUCKETS_SKIPPED, valueProducer->mSkippedBuckets[0].dropEvents[1].reason);
     EXPECT_EQ(partialBucketSplitTimeNs, valueProducer->mSkippedBuckets[0].bucketStartTimeNs);
-    EXPECT_EQ(bucket2StartTimeNs, valueProducer->mSkippedBuckets[0].bucketEndTimeNs);
+    EXPECT_EQ(bucket3StartTimeNs, valueProducer->mSkippedBuckets[0].bucketEndTimeNs);
     ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
 }
 
@@ -3464,26 +3476,41 @@
     // Condition change event that skips forward by three buckets.
     valueProducer->onConditionChanged(false, bucket4StartTimeNs + 10);
 
+    int64_t dumpTimeNs = bucket4StartTimeNs + 1000;
+
     // Check dump report.
     ProtoOutputStream output;
     std::set<string> strSet;
-    valueProducer->onDumpReport(bucket4StartTimeNs + 1000, true /* include recent buckets */, true,
+    valueProducer->onDumpReport(dumpTimeNs, true /* include current buckets */, true,
                                 NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
 
     StatsLogReport report = outputStreamToProto(&output);
     EXPECT_TRUE(report.has_value_metrics());
     ASSERT_EQ(0, report.value_metrics().data_size());
-    ASSERT_EQ(1, report.value_metrics().skipped_size());
+    ASSERT_EQ(2, report.value_metrics().skipped_size());
 
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
               report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+    EXPECT_EQ(NanoToMillis(bucket4StartTimeNs),
               report.value_metrics().skipped(0).end_bucket_elapsed_millis());
     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());
     EXPECT_EQ(NanoToMillis(bucket4StartTimeNs + 10), dropEvent.drop_time_millis());
+
+    // This bucket is skipped because a dumpReport with include current buckets is called.
+    // This creates a new bucket from bucket4StartTimeNs to dumpTimeNs in which we have no data
+    // since the condition is false for the entire bucket interval.
+    EXPECT_EQ(NanoToMillis(bucket4StartTimeNs),
+              report.value_metrics().skipped(1).start_bucket_elapsed_millis());
+    EXPECT_EQ(NanoToMillis(dumpTimeNs),
+              report.value_metrics().skipped(1).end_bucket_elapsed_millis());
+    ASSERT_EQ(1, report.value_metrics().skipped(1).drop_event_size());
+
+    dropEvent = report.value_metrics().skipped(1).drop_event(0);
+    EXPECT_EQ(BucketDropReason::NO_DATA, dropEvent.drop_reason());
+    EXPECT_EQ(NanoToMillis(dumpTimeNs), dropEvent.drop_time_millis());
 }
 
 /*
@@ -3544,6 +3571,89 @@
 }
 
 /*
+ * Test that NO_DATA dump reason is logged when a flushed bucket contains no data.
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenDataUnavailable) {
+    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+    sp<ValueMetricProducer> valueProducer =
+            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+    // Check dump report.
+    ProtoOutputStream output;
+    std::set<string> strSet;
+    int64_t dumpReportTimeNs = bucketStartTimeNs + 10000000000; // 10 seconds
+    valueProducer->onDumpReport(dumpReportTimeNs, true /* include current bucket */, true,
+                                NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+
+    StatsLogReport report = outputStreamToProto(&output);
+    EXPECT_TRUE(report.has_value_metrics());
+    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());
+    ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+    EXPECT_EQ(BucketDropReason::NO_DATA, dropEvent.drop_reason());
+    EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
+}
+
+/*
+ * Test that a skipped bucket is logged when a forced bucket split occurs when the previous bucket
+ * was not flushed in time.
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenForceBucketSplitBeforeBucketFlush) {
+    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+    sp<ValueMetricProducer> valueProducer =
+            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+    // App update event.
+    int64_t appUpdateTimeNs = bucket2StartTimeNs + 1000;
+    valueProducer->notifyAppUpgrade(appUpdateTimeNs);
+
+    // Check dump report.
+    ProtoOutputStream output;
+    std::set<string> strSet;
+    int64_t dumpReportTimeNs = bucket2StartTimeNs + 10000000000; // 10 seconds
+    valueProducer->onDumpReport(dumpReportTimeNs, false /* include current buckets */, true,
+                                NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+
+    StatsLogReport report = outputStreamToProto(&output);
+    EXPECT_TRUE(report.has_value_metrics());
+    ASSERT_EQ(0, report.value_metrics().data_size());
+    ASSERT_EQ(2, 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());
+    ASSERT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+    EXPECT_EQ(BucketDropReason::NO_DATA, dropEvent.drop_reason());
+    EXPECT_EQ(NanoToMillis(appUpdateTimeNs), dropEvent.drop_time_millis());
+
+    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+              report.value_metrics().skipped(1).start_bucket_elapsed_millis());
+    EXPECT_EQ(NanoToMillis(appUpdateTimeNs),
+              report.value_metrics().skipped(1).end_bucket_elapsed_millis());
+    ASSERT_EQ(1, report.value_metrics().skipped(1).drop_event_size());
+
+    dropEvent = report.value_metrics().skipped(1).drop_event(0);
+    EXPECT_EQ(BucketDropReason::NO_DATA, dropEvent.drop_reason());
+    EXPECT_EQ(NanoToMillis(appUpdateTimeNs), dropEvent.drop_time_millis());
+}
+
+/*
  * Test multiple bucket drop events in the same bucket.
  */
 TEST(ValueMetricProducerTest_BucketDrop, TestMultipleBucketDropEvents) {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 8e43ca3..cffa59c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -604,11 +604,8 @@
                     throw new IllegalStateException(
                             "Received config update for non-existing activity");
                 }
-                // Given alwaysReportChange=false because the configuration is from view root, the
-                // activity may not be able to handle the changes. In that case the activity will be
-                // relaunched immediately, then Activity#onConfigurationChanged shouldn't be called.
                 activity.mMainThread.handleActivityConfigurationChanged(token, overrideConfig,
-                        newDisplayId, false /* alwaysReportChange */);
+                        newDisplayId);
             };
         }
 
@@ -4520,8 +4517,7 @@
         // simply finishing, and we are not starting another activity.
         if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
             if (r.newConfig != null) {
-                performConfigurationChangedForActivity(r, r.newConfig,
-                        false /* alwaysReportChange */);
+                performConfigurationChangedForActivity(r, r.newConfig);
                 if (DEBUG_CONFIGURATION) {
                     Slog.v(TAG, "Resuming activity " + r.activityInfo.name + " with newConfig "
                             + r.activity.mCurrentConfig);
@@ -4841,8 +4837,7 @@
                     }
                 }
                 if (r.newConfig != null) {
-                    performConfigurationChangedForActivity(r, r.newConfig,
-                            false /* alwaysReportChange */);
+                    performConfigurationChangedForActivity(r, r.newConfig);
                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
                             + r.activityInfo.name + " with new config "
                             + r.activity.mCurrentConfig);
@@ -5510,12 +5505,11 @@
      * @param r ActivityClientRecord representing the Activity.
      * @param newBaseConfig The new configuration to use. This may be augmented with
      *                      {@link ActivityClientRecord#overrideConfig}.
-     * @param alwaysReportChange If the configuration is changed, always report to activity.
      */
     private void performConfigurationChangedForActivity(ActivityClientRecord r,
-            Configuration newBaseConfig, boolean alwaysReportChange) {
+            Configuration newBaseConfig) {
         performConfigurationChangedForActivity(r, newBaseConfig, r.activity.getDisplayId(),
-                false /* movedToDifferentDisplay */, alwaysReportChange);
+                false /* movedToDifferentDisplay */);
     }
 
     /**
@@ -5528,19 +5522,16 @@
      *                      {@link ActivityClientRecord#overrideConfig}.
      * @param displayId The id of the display where the Activity currently resides.
      * @param movedToDifferentDisplay Indicates if the activity was moved to different display.
-     * @param alwaysReportChange If the configuration is changed, always report to activity.
      * @return {@link Configuration} instance sent to client, null if not sent.
      */
     private Configuration performConfigurationChangedForActivity(ActivityClientRecord r,
-            Configuration newBaseConfig, int displayId, boolean movedToDifferentDisplay,
-            boolean alwaysReportChange) {
+            Configuration newBaseConfig, int displayId, boolean movedToDifferentDisplay) {
         r.tmpConfig.setTo(newBaseConfig);
         if (r.overrideConfig != null) {
             r.tmpConfig.updateFrom(r.overrideConfig);
         }
         final Configuration reportedConfig = performActivityConfigurationChanged(r.activity,
-                r.tmpConfig, r.overrideConfig, displayId, movedToDifferentDisplay,
-                alwaysReportChange);
+                r.tmpConfig, r.overrideConfig, displayId, movedToDifferentDisplay);
         freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
         return reportedConfig;
     }
@@ -5596,12 +5587,11 @@
      *                         ActivityManager.
      * @param displayId Id of the display where activity currently resides.
      * @param movedToDifferentDisplay Indicates if the activity was moved to different display.
-     * @param alwaysReportChange If the configuration is changed, always report to activity.
      * @return Configuration sent to client, null if no changes and not moved to different display.
      */
     private Configuration performActivityConfigurationChanged(Activity activity,
             Configuration newConfig, Configuration amOverrideConfig, int displayId,
-            boolean movedToDifferentDisplay, boolean alwaysReportChange) {
+            boolean movedToDifferentDisplay) {
         if (activity == null) {
             throw new IllegalArgumentException("No activity provided.");
         }
@@ -5614,31 +5604,27 @@
         // callback, see also PinnedStackTests#testConfigurationChangeOrderDuringTransition
         handleWindowingModeChangeIfNeeded(activity, newConfig);
 
-        boolean shouldChangeConfig = false;
+        boolean shouldReportChange = false;
         if (activity.mCurrentConfig == null) {
-            shouldChangeConfig = true;
+            shouldReportChange = true;
         } else {
             // If the new config is the same as the config this Activity is already running with and
             // the override config also didn't change, then don't bother calling
             // onConfigurationChanged.
             final int diff = activity.mCurrentConfig.diffPublicOnly(newConfig);
-
-            if (diff != 0 || !mResourcesManager.isSameResourcesOverrideConfig(activityToken,
+            if (diff == 0 && !movedToDifferentDisplay
+                    && mResourcesManager.isSameResourcesOverrideConfig(activityToken,
                     amOverrideConfig)) {
-                // Always send the task-level config changes. For system-level configuration, if
-                // this activity doesn't handle any of the config changes, then don't bother
-                // calling onConfigurationChanged as we're going to destroy it.
-                if (alwaysReportChange
-                        || (~activity.mActivityInfo.getRealConfigChanged() & diff) == 0
-                        || !REPORT_TO_ACTIVITY) {
-                    shouldChangeConfig = true;
-                }
+                // Nothing significant, don't proceed with updating and reporting.
+                return null;
+            } else if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0
+                    || !REPORT_TO_ACTIVITY) {
+                // If this activity doesn't handle any of the config changes, then don't bother
+                // calling onConfigurationChanged. Otherwise, report to the activity for the
+                // changes.
+                shouldReportChange = true;
             }
         }
-        if (!shouldChangeConfig && !movedToDifferentDisplay) {
-            // Nothing significant, don't proceed with updating and reporting.
-            return null;
-        }
 
         // Propagate the configuration change to ResourcesManager and Activity.
 
@@ -5675,7 +5661,7 @@
             activity.dispatchMovedToDisplay(displayId, configToReport);
         }
 
-        if (shouldChangeConfig) {
+        if (shouldReportChange) {
             activity.mCalled = false;
             activity.onConfigurationChanged(configToReport);
             if (!activity.mCalled) {
@@ -5792,7 +5778,7 @@
                     // config and avoid onConfigurationChanged if it hasn't changed.
                     Activity a = (Activity) cb;
                     performConfigurationChangedForActivity(mActivities.get(a.getActivityToken()),
-                            config, false /* alwaysReportChange */);
+                            config);
                 } else if (!equivalent) {
                     performConfigurationChanged(cb, config);
                 } else {
@@ -5943,18 +5929,6 @@
         }
     }
 
-    @Override
-    public void handleActivityConfigurationChanged(IBinder activityToken,
-            @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
-                // has confirmed the activity should handle the configuration instead of relaunch.
-                // If Activity#onConfigurationChanged is called unexpectedly, then we can know it is
-                // something wrong from server side.
-                true /* alwaysReportChange */);
-    }
-
     /**
      * 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
@@ -5964,10 +5938,10 @@
      * @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,
-            @NonNull Configuration overrideConfig, int displayId, boolean alwaysReportChange) {
+    @Override
+    public void handleActivityConfigurationChanged(IBinder activityToken,
+            @NonNull Configuration overrideConfig, int displayId) {
         ActivityClientRecord r = mActivities.get(activityToken);
         // Check input params.
         if (r == null || r.activity == null) {
@@ -6010,15 +5984,14 @@
                     + ", config=" + overrideConfig);
 
             final Configuration reportedConfig = performConfigurationChangedForActivity(r,
-                    mCompatConfiguration, displayId, true /* movedToDifferentDisplay */,
-                    alwaysReportChange);
+                    mCompatConfiguration, displayId, true /* movedToDifferentDisplay */);
             if (viewRoot != null) {
                 viewRoot.onMovedToDisplay(displayId, reportedConfig);
             }
         } else {
             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
                     + r.activityInfo.name + ", config=" + overrideConfig);
-            performConfigurationChangedForActivity(r, mCompatConfiguration, alwaysReportChange);
+            performConfigurationChangedForActivity(r, mCompatConfiguration);
         }
         // Notify the ViewRootImpl instance about configuration changes. It may have initiated this
         // update to make sure that resources are updated before updating itself.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 90206b6..e8ce92d 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3614,6 +3614,7 @@
          * <li>Directional conversations where there is an active speaker and many passive
          * individuals</li>
          * <li>Stream / posting updates from other individuals</li>
+         * <li>Email, document comments, or other conversation types that are not real-time</li>
          * </ul>
          * </p>
          *
diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java
index 01cf2b94a..5806876 100644
--- a/core/java/android/app/PropertyInvalidatedCache.java
+++ b/core/java/android/app/PropertyInvalidatedCache.java
@@ -188,6 +188,17 @@
     private static final boolean DEBUG = false;
     private static final boolean VERIFY = false;
 
+    // Per-Cache performance counters. As some cache instances are declared static,
+    @GuardedBy("mLock")
+    private long mHits = 0;
+
+    @GuardedBy("mLock")
+    private long mMisses = 0;
+
+    // Most invalidation is done in a static context, so the counters need to be accessible.
+    @GuardedBy("sCorkLock")
+    private static final HashMap<String, Long> sInvalidates = new HashMap<>();
+
     /**
      * If sEnabled is false then all cache operations are stubbed out.  Set
      * it to false inside test processes.
@@ -265,6 +276,7 @@
             };
         synchronized (sCorkLock) {
             sCaches.put(this, null);
+            sInvalidates.put(propertyName, (long) 0);
         }
     }
 
@@ -365,6 +377,8 @@
             synchronized (mLock) {
                 if (currentNonce == mLastSeenNonce) {
                     cachedResult = mCache.get(query);
+
+                    if (cachedResult != null) mHits++;
                 } else {
                     if (DEBUG) {
                         Log.d(TAG,
@@ -428,6 +442,7 @@
                 if (mLastSeenNonce == currentNonce && result != null) {
                     mCache.put(query, result);
                 }
+                mMisses++;
             }
             return maybeCheckConsistency(query, result);
         }
@@ -531,6 +546,8 @@
                             newValueString));
         }
         SystemProperties.set(name, newValueString);
+        long invalidateCount = sInvalidates.getOrDefault(name, (long) 0);
+        sInvalidates.put(name, ++invalidateCount);
     }
 
     /**
@@ -758,8 +775,16 @@
     }
 
     private void dumpContents(PrintWriter pw, String[] args) {
+        long invalidateCount;
+
+        synchronized (sCorkLock) {
+            invalidateCount = sInvalidates.getOrDefault(mPropertyName, (long) 0);
+        }
+
         synchronized (mLock) {
             pw.println(String.format("  Cache Property Name: %s", cacheName()));
+            pw.println(String.format("    Hits: %d, Misses: %d, Invalidates: %d",
+                    mHits, mMisses, invalidateCount));
             pw.println(String.format("    Last Observed Nonce: %d", mLastSeenNonce));
             pw.println(String.format("    Current Size: %d, Max Size: %d",
                     mCache.entrySet().size(), mMaxEntries));
diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING
index ab86860..8ad33db 100644
--- a/core/java/android/app/TEST_MAPPING
+++ b/core/java/android/app/TEST_MAPPING
@@ -50,7 +50,7 @@
             "file_patterns": ["INotificationManager\\.aidl"]
         },
         {
-            "name": "FrameworksInstantAppResolverTests",
+            "name": "CtsInstantAppTests",
             "file_patterns": ["(/|^)InstantAppResolve[^/]*"]
         }
     ],
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index aa29040..389458b 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -99,9 +99,9 @@
             in IShortcutChangeCallback callback);
 
     void cacheShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
-            in UserHandle user);
+            in UserHandle user, int cacheFlags);
     void uncacheShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
-            in UserHandle user);
+            in UserHandle user, int cacheFlags);
 
     String getShortcutIconUri(String callingPackage, String packageName, String shortcutId,
             int userId);
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 4299e80..bd1ee27 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -155,6 +155,26 @@
     public static final String EXTRA_PIN_ITEM_REQUEST =
             "android.content.pm.extra.PIN_ITEM_REQUEST";
 
+    /**
+     * Cache shortcuts which are used in notifications.
+     * @hide
+     */
+    public static final int FLAG_CACHE_NOTIFICATION_SHORTCUTS = 0;
+
+    /**
+     * Cache shortcuts which are used in bubbles.
+     * @hide
+     */
+    public static final int FLAG_CACHE_BUBBLE_SHORTCUTS = 1;
+
+    /** @hide */
+    @IntDef(flag = false, prefix = { "FLAG_CACHE_" }, value = {
+            FLAG_CACHE_NOTIFICATION_SHORTCUTS,
+            FLAG_CACHE_BUBBLE_SHORTCUTS,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ShortcutCacheFlags {}
+
     private final Context mContext;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final ILauncherApps mService;
@@ -1109,6 +1129,11 @@
      * @param packageName The target package name.
      * @param shortcutIds The IDs of the shortcut to be cached.
      * @param user The UserHandle of the profile.
+     * @param cacheFlags One of the values in:
+     * <ul>
+     *     <li>{@link #FLAG_CACHE_NOTIFICATION_SHORTCUTS}
+     *     <li>{@link #FLAG_CACHE_BUBBLE_SHORTCUTS}
+     * </ul>
      * @throws IllegalStateException when the user is locked, or when the {@code user} user
      * is locked or not running.
      *
@@ -1118,10 +1143,11 @@
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_SHORTCUTS)
     public void cacheShortcuts(@NonNull String packageName, @NonNull List<String> shortcutIds,
-            @NonNull UserHandle user) {
+            @NonNull UserHandle user, @ShortcutCacheFlags int cacheFlags) {
         logErrorForInvalidProfileAccess(user);
         try {
-            mService.cacheShortcuts(mContext.getPackageName(), packageName, shortcutIds, user);
+            mService.cacheShortcuts(
+                    mContext.getPackageName(), packageName, shortcutIds, user, cacheFlags);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1133,6 +1159,11 @@
      * @param packageName The target package name.
      * @param shortcutIds The IDs of the shortcut to be uncached.
      * @param user The UserHandle of the profile.
+     * @param cacheFlags One of the values in:
+     * <ul>
+     *     <li>{@link #FLAG_CACHE_NOTIFICATION_SHORTCUTS}
+     *     <li>{@link #FLAG_CACHE_BUBBLE_SHORTCUTS}
+     * </ul>
      * @throws IllegalStateException when the user is locked, or when the {@code user} user
      * is locked or not running.
      *
@@ -1142,10 +1173,11 @@
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_SHORTCUTS)
     public void uncacheShortcuts(@NonNull String packageName, @NonNull List<String> shortcutIds,
-            @NonNull UserHandle user) {
+            @NonNull UserHandle user, @ShortcutCacheFlags int cacheFlags) {
         logErrorForInvalidProfileAccess(user);
         try {
-            mService.uncacheShortcuts(mContext.getPackageName(), packageName, shortcutIds, user);
+            mService.uncacheShortcuts(
+                    mContext.getPackageName(), packageName, shortcutIds, user, cacheFlags);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 2f488cd..c577d0e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2032,8 +2032,16 @@
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device's main front and back cameras can stream
-     * concurrently as described in  {@link
-     * android.hardware.camera2.CameraManager#getConcurrentCameraIds()}
+     * concurrently as described in {@link
+     * android.hardware.camera2.CameraManager#getConcurrentCameraIds()}.
+     * </p>
+     * <p>While {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds()} and
+     * associated APIs are only available on API level 30 or newer, this feature flag may be
+     * advertised by devices on API levels below 30. If present on such a device, the same
+     * guarantees hold: The main front and main back camera can be used at the same time, with
+     * guaranteed stream configurations as defined in the table for concurrent streaming at
+     * {@link android.hardware.camera2.CameraDevice#createCaptureSession(android.hardware.camera2.params.SessionConfiguration)}.
+     * </p>
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_CAMERA_CONCURRENT = "android.hardware.camera.concurrent";
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index dcc6cb2..1b3c46f 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -119,12 +119,27 @@
     /** @hide */
     public static final int FLAG_LONG_LIVED = 1 << 13;
 
-    /** @hide */
-    public static final int FLAG_CACHED = 1 << 14;
+    /**
+     * TODO(b/155135057): This is a quick and temporary fix for b/155135890. ShortcutService doesn't
+     *  need to be aware of the outside world. Replace this with a more extensible solution.
+     * @hide
+     */
+    public static final int FLAG_CACHED_NOTIFICATIONS = 1 << 14;
 
     /** @hide */
     public static final int FLAG_HAS_ICON_URI = 1 << 15;
 
+
+    /**
+     * TODO(b/155135057): This is a quick and temporary fix for b/155135890. ShortcutService doesn't
+     *  need to be aware of the outside world. Replace this with a more extensible solution.
+     * @hide
+     */
+    public static final int FLAG_CACHED_BUBBLES = 1 << 30;
+
+    /** @hide */
+    public static final int FLAG_CACHED_ALL = FLAG_CACHED_NOTIFICATIONS | FLAG_CACHED_BUBBLES;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "FLAG_" }, value = {
             FLAG_DYNAMIC,
@@ -141,8 +156,9 @@
             FLAG_ICON_FILE_PENDING_SAVE,
             FLAG_SHADOW,
             FLAG_LONG_LIVED,
-            FLAG_CACHED,
             FLAG_HAS_ICON_URI,
+            FLAG_CACHED_NOTIFICATIONS,
+            FLAG_CACHED_BUBBLES,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ShortcutFlags {}
@@ -1707,13 +1723,13 @@
     }
 
     /** @hide */
-    public void setCached() {
-        addFlags(FLAG_CACHED);
+    public void setCached(@ShortcutFlags int cacheFlag) {
+        addFlags(cacheFlag);
     }
 
     /** Return whether a shortcut is cached. */
     public boolean isCached() {
-        return hasFlags(FLAG_CACHED);
+        return (getFlags() & FLAG_CACHED_ALL) != 0;
     }
 
     /** Return whether a shortcut is dynamic. */
@@ -1807,7 +1823,7 @@
     /** @hide */
     public boolean isAlive() {
         return hasFlags(FLAG_PINNED) || hasFlags(FLAG_DYNAMIC) || hasFlags(FLAG_MANIFEST)
-                || hasFlags(FLAG_CACHED);
+                || isCached();
     }
 
     /** @hide */
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index eee91ce..c62767e 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -92,10 +92,10 @@
 
     public abstract void cacheShortcuts(int launcherUserId,
             @NonNull String callingPackage, @NonNull String packageName,
-            @NonNull List<String> shortcutIds, int userId);
+            @NonNull List<String> shortcutIds, int userId, int cacheFlags);
     public abstract void uncacheShortcuts(int launcherUserId,
             @NonNull String callingPackage, @NonNull String packageName,
-            @NonNull List<String> shortcutIds, int userId);
+            @NonNull List<String> shortcutIds, int userId, int cacheFlags);
 
     /**
      * Retrieves all of the direct share targets that match the given IntentFilter for the specified
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index 6f30ecd..e404fee 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -12,7 +12,7 @@
   ],
   "presubmit": [
     {
-      "name": "FrameworksInstantAppResolverTests",
+      "name": "CtsInstantAppTests",
       "file_patterns": ["(/|^)InstantApp[^/]*"]
     }
   ],
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 6bf754f..0a76a9c 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -498,7 +498,7 @@
                 || type == Sensor.TYPE_TILT_DETECTOR || type == Sensor.TYPE_WAKE_GESTURE
                 || type == Sensor.TYPE_GLANCE_GESTURE || type == Sensor.TYPE_PICK_UP_GESTURE
                 || type == Sensor.TYPE_WRIST_TILT_GESTURE
-                || type == Sensor.TYPE_DYNAMIC_SENSOR_META) {
+                || type == Sensor.TYPE_DYNAMIC_SENSOR_META || type == Sensor.TYPE_HINGE_ANGLE) {
             wakeUpSensor = true;
         }
 
diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java
index 9086d49..275e38c 100644
--- a/core/java/android/net/ConnectivityDiagnosticsManager.java
+++ b/core/java/android/net/ConnectivityDiagnosticsManager.java
@@ -437,7 +437,7 @@
          */
         private long mReportTimestamp;
 
-        /** The detection method used to identify the suspected data stall */
+        /** A bitmask of the detection methods used to identify the suspected data stall */
         @DetectionMethod private final int mDetectionMethod;
 
         /** LinkProperties available on the Network at the reported timestamp */
@@ -499,9 +499,9 @@
         }
 
         /**
-         * Returns the detection method used to identify this suspected data stall.
+         * Returns the bitmask of detection methods used to identify this suspected data stall.
          *
-         * @return The detection method used to identify the suspected data stall
+         * @return The bitmask of detection methods used to identify the suspected data stall
          */
         public int getDetectionMethod() {
             return mDetectionMethod;
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index 836624b..407ff04 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -101,6 +101,7 @@
     private final boolean mIsBypassable; // Defaults in builder
     private final boolean mIsMetered; // Defaults in builder
     private final int mMaxMtu; // Defaults in builder
+    private final boolean mIsRestrictedToTestNetworks;
 
     private Ikev2VpnProfile(
             int type,
@@ -116,7 +117,8 @@
             @NonNull List<String> allowedAlgorithms,
             boolean isBypassable,
             boolean isMetered,
-            int maxMtu) {
+            int maxMtu,
+            boolean restrictToTestNetworks) {
         super(type);
 
         checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address");
@@ -140,6 +142,7 @@
         mIsBypassable = isBypassable;
         mIsMetered = isMetered;
         mMaxMtu = maxMtu;
+        mIsRestrictedToTestNetworks = restrictToTestNetworks;
 
         validate();
     }
@@ -329,6 +332,15 @@
         return mMaxMtu;
     }
 
+    /**
+     * Returns whether or not this VPN profile is restricted to test networks.
+     *
+     * @hide
+     */
+    public boolean isRestrictedToTestNetworks() {
+        return mIsRestrictedToTestNetworks;
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(
@@ -345,7 +357,8 @@
                 mAllowedAlgorithms,
                 mIsBypassable,
                 mIsMetered,
-                mMaxMtu);
+                mMaxMtu,
+                mIsRestrictedToTestNetworks);
     }
 
     @Override
@@ -368,7 +381,8 @@
                 && Objects.equals(mAllowedAlgorithms, other.mAllowedAlgorithms)
                 && mIsBypassable == other.mIsBypassable
                 && mIsMetered == other.mIsMetered
-                && mMaxMtu == other.mMaxMtu;
+                && mMaxMtu == other.mMaxMtu
+                && mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks;
     }
 
     /**
@@ -381,7 +395,8 @@
      */
     @NonNull
     public VpnProfile toVpnProfile() throws IOException, GeneralSecurityException {
-        final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */);
+        final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */,
+                mIsRestrictedToTestNetworks);
         profile.type = mType;
         profile.server = mServerAddr;
         profile.ipsecIdentifier = mUserIdentity;
@@ -449,6 +464,9 @@
         builder.setBypassable(profile.isBypassable);
         builder.setMetered(profile.isMetered);
         builder.setMaxMtu(profile.maxMtu);
+        if (profile.isRestrictedToTestNetworks) {
+            builder.restrictToTestNetworks();
+        }
 
         switch (profile.type) {
             case TYPE_IKEV2_IPSEC_USER_PASS:
@@ -621,6 +639,7 @@
         private boolean mIsBypassable = false;
         private boolean mIsMetered = true;
         private int mMaxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT;
+        private boolean mIsRestrictedToTestNetworks = false;
 
         /**
          * Creates a new builder with the basic parameters of an IKEv2/IPsec VPN.
@@ -842,6 +861,21 @@
         }
 
         /**
+         * Restricts this profile to use test networks (only).
+         *
+         * <p>This method is for testing only, and must not be used by apps. Calling
+         * provisionVpnProfile() with a profile where test-network usage is enabled will require the
+         * MANAGE_TEST_NETWORKS permission.
+         *
+         * @hide
+         */
+        @NonNull
+        public Builder restrictToTestNetworks() {
+            mIsRestrictedToTestNetworks = true;
+            return this;
+        }
+
+        /**
          * Validates, builds and provisions the VpnProfile.
          *
          * @throws IllegalArgumentException if any of the required keys or values were invalid
@@ -862,7 +896,8 @@
                     mAllowedAlgorithms,
                     mIsBypassable,
                     mIsMetered,
-                    mMaxMtu);
+                    mMaxMtu,
+                    mIsRestrictedToTestNetworks);
         }
     }
 }
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index b7fb280..34e48eb 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -16,8 +16,6 @@
 
 package android.net;
 
-import static android.os.Process.CLAT_UID;
-
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -1047,73 +1045,54 @@
     }
 
     /**
-     * Calculate and apply adjustments to captured statistics for 464xlat traffic counted twice.
+     * Calculate and apply adjustments to captured statistics for 464xlat traffic.
      *
-     * <p>This mutates both base and stacked traffic stats, to account respectively for
-     * double-counted traffic and IPv4/IPv6 header size difference.
+     * <p>This mutates stacked traffic stats, to account for IPv4/IPv6 header size difference.
      *
-     * <p>For 464xlat traffic, xt_qtaguid sees every IPv4 packet twice, once as a native IPv4
-     * packet on the stacked interface, and once as translated to an IPv6 packet on the
-     * base interface. For correct stats accounting on the base interface, if using xt_qtaguid,
-     * every rx 464xlat packet needs to be subtracted from the root UID on the base interface
-     * (http://b/12249687, http:/b/33681750), and every tx 464xlat packet which was counted onto
-     * clat uid should be ignored.
+     * <p>UID stats, which are only accounted on the stacked interface, need to be increased
+     * by 20 bytes/packet to account for translation overhead.
      *
-     * As for eBPF, the per uid stats is collected by different hook, the rx packets on base
-     * interface will not be counted. Thus, the adjustment on root uid is not needed. However, the
-     * tx traffic counted in the same way xt_qtaguid does, so the traffic on clat uid still
-     * needs to be ignored.
+     * <p>The potential additional overhead of 8 bytes/packet for ip fragments is ignored.
+     *
+     * <p>Interface stats need to sum traffic on both stacked and base interface because:
+     *   - eBPF offloaded packets appear only on the stacked interface
+     *   - Non-offloaded ingress packets appear only on the stacked interface
+     *     (due to iptables raw PREROUTING drop rules)
+     *   - Non-offloaded egress packets appear only on the stacked interface
+     *     (due to ignoring traffic from clat daemon by uid match)
+     * (and of course the 20 bytes/packet overhead needs to be applied to stacked interface stats)
      *
      * <p>This method will behave fine if {@code stackedIfaces} is an non-synchronized but add-only
      * {@code ConcurrentHashMap}
      * @param baseTraffic Traffic on the base interfaces. Will be mutated.
      * @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated.
      * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both.
-     * @param useBpfStats True if eBPF is in use.
      * @hide
      */
     public static void apply464xlatAdjustments(NetworkStats baseTraffic,
-            NetworkStats stackedTraffic, Map<String, String> stackedIfaces, boolean useBpfStats) {
-        // Total 464xlat traffic to subtract from uid 0 on all base interfaces.
-        // stackedIfaces may grow afterwards, but NetworkStats will just be resized automatically.
-        final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size());
-
+            NetworkStats stackedTraffic, Map<String, String> stackedIfaces) {
         // For recycling
         Entry entry = null;
-        Entry adjust = new NetworkStats.Entry(IFACE_ALL, 0, 0, 0, 0, 0, 0, 0L, 0L, 0L, 0L, 0L);
-
         for (int i = 0; i < stackedTraffic.size; i++) {
             entry = stackedTraffic.getValues(i, entry);
-            if (entry.iface == null || !entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) {
-                continue;
-            }
-            final String baseIface = stackedIfaces.get(entry.iface);
-            if (baseIface == null) {
-                continue;
-            }
-            // Subtract xt_qtaguid 464lat rx traffic seen for the root UID on the current base
-            // interface. As for eBPF, the per uid stats is collected by different hook, the rx
-            // packets on base interface will not be counted.
-            adjust.iface = baseIface;
-            if (!useBpfStats) {
-                adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA);
-                adjust.rxPackets = -entry.rxPackets;
-            }
-            adjustments.combineValues(adjust);
+            if (entry == null) continue;
+            if (entry.iface == null) continue;
+            if (!entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) continue;
 
             // For 464xlat traffic, per uid stats only counts the bytes of the native IPv4 packet
             // sent on the stacked interface with prefix "v4-" and drops the IPv6 header size after
             // unwrapping. To account correctly for on-the-wire traffic, add the 20 additional bytes
             // difference for all packets (http://b/12249687, http:/b/33681750).
+            //
+            // Note: this doesn't account for LRO/GRO/GSO/TSO (ie. >mtu) traffic correctly, nor
+            // does it correctly account for the 8 extra bytes in the IPv6 fragmentation header.
+            //
+            // While the ebpf code path does try to simulate proper post segmentation packet
+            // counts, we have nothing of the sort of xt_qtaguid stats.
             entry.rxBytes += entry.rxPackets * IPV4V6_HEADER_DELTA;
             entry.txBytes += entry.txPackets * IPV4V6_HEADER_DELTA;
             stackedTraffic.setValues(i, entry);
         }
-
-        // Traffic on clat uid is v6 tx traffic that is already counted with app uid on the stacked
-        // v4 interface, so it needs to be removed to avoid double-counting.
-        baseTraffic.removeUids(new int[] {CLAT_UID});
-        baseTraffic.combineAllValues(adjustments);
     }
 
     /**
@@ -1125,8 +1104,8 @@
      * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both.
      * @hide
      */
-    public void apply464xlatAdjustments(Map<String, String> stackedIfaces, boolean useBpfStats) {
-        apply464xlatAdjustments(this, this, stackedIfaces, useBpfStats);
+    public void apply464xlatAdjustments(Map<String, String> stackedIfaces) {
+        apply464xlatAdjustments(this, this, stackedIfaces);
     }
 
     /**
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index ebf4cc5..7845200 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -230,13 +230,14 @@
     public static final String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
 
     /**
-     * Specifies if a user is disallowed from changing Wi-Fi
-     * access points. The default value is <code>false</code>.
-     * <p>
-     * Device owner and profile owner can set this restriction, although the restriction has no
-     * effect in a managed profile. When it is set by the profile owner of an organization-owned
-     * managed profile on the parent profile, it will disallow the personal user from changing
-     * Wi-Fi access points.
+     * Specifies if a user is disallowed from changing Wi-Fi access points via Settings.
+     *
+     * <p>A device owner and a profile owner can set this restriction, although the restriction has
+     * no effect in a managed profile. When it is set by a device owner, a profile owner on the
+     * primary user or by a profile owner of an organization-owned managed profile on the parent
+     * profile, it disallows the primary user from changing Wi-Fi access points.
+     *
+     * <p>The default value is <code>false</code>.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -285,14 +286,16 @@
 
     /**
      * Specifies if a user is disallowed from turning on location sharing.
-     * The default value is <code>false</code>.
-     * <p>
-     * In a managed profile, location sharing always reflects the primary user's setting, but
+     *
+     * <p>In a managed profile, location sharing by default reflects the primary user's setting, but
      * can be overridden and forced off by setting this restriction to true in the managed profile.
-     * <p>
-     * Device owner and profile owner can set this restriction. When it is set by the profile
-     * owner of an organization-owned managed profile on the parent profile, it will prevent the
-     * user from turning on location sharing in the personal profile.
+     *
+     * <p>A device owner and a profile owner can set this restriction. When it is set by a device
+     * owner, a profile owner on the primary user or by a profile owner of an organization-owned
+     * managed profile on the parent profile, it prevents the primary user from turning on
+     * location sharing.
+     *
+     * <p>The default value is <code>false</code>.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -304,12 +307,13 @@
 
     /**
      * Specifies if airplane mode is disallowed on the device.
-     * <p>
-     * This restriction can only be set by the device owner, the profile owner on the primary user
-     * or the profile owner of an organization-owned managed profile on the parent profile, and it
-     * applies globally - i.e. it disables airplane mode on the entire device.
-     * <p>
-     * The default value is <code>false</code>.
+     *
+     * <p>This restriction can only be set by a device owner, a profile owner on the primary
+     * user or a profile owner of an organization-owned managed profile on the parent profile.
+     * When it is set by any of these owners, it applies globally - i.e., it disables airplane mode
+     * on the entire device.
+     *
+     * <p>The default value is <code>false</code>.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -397,17 +401,18 @@
             "no_install_unknown_sources_globally";
 
     /**
-     * Specifies if a user is disallowed from configuring bluetooth.
-     * This does <em>not</em> restrict the user from turning bluetooth on or off.
-     * The default value is <code>false</code>.
-     * <p>
-     * This restriction doesn't prevent the user from using bluetooth. For disallowing usage of
+     * Specifies if a user is disallowed from configuring bluetooth via Settings. This does
+     * <em>not</em> restrict the user from turning bluetooth on or off.
+     *
+     * <p>This restriction doesn't prevent the user from using bluetooth. For disallowing usage of
      * bluetooth completely on the device, use {@link #DISALLOW_BLUETOOTH}.
-     * <p>
-     * Device owner and profile owner can set this restriction, although the restriction has no
-     * effect in a managed profile. When it is set by the profile owner of an organization-owned
-     * managed profile on the parent profile, it will disallow the personal user from configuring
-     * bluetooth.
+     *
+     * <p>A device owner and a profile owner can set this restriction, although the restriction has
+     * no effect in a managed profile. When it is set by a device owner, a profile owner on the
+     * primary user or by a profile owner of an organization-owned managed profile on the parent
+     * profile, it disallows the primary user from configuring bluetooth.
+     *
+     * <p>The default value is <code>false</code>.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -418,13 +423,19 @@
     public static final String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
 
     /**
-     * Specifies if bluetooth is disallowed on the device.
+     * Specifies if bluetooth is disallowed on the device. If bluetooth is disallowed on the device,
+     * bluetooth cannot be turned on or configured via Settings.
      *
-     * <p> This restriction can only be set by the device owner, the profile owner on the
-     * primary user or the profile owner of an organization-owned managed profile on the
-     * parent profile and it applies globally - i.e. it disables bluetooth on the entire
-     * device.
+     * <p>This restriction can only be set by a device owner, a profile owner on the primary
+     * user or a profile owner of an organization-owned managed profile on the parent profile.
+     * When it is set by a device owner, it applies globally - i.e., it disables bluetooth on
+     * the entire device and all users will be affected. When it is set by a profile owner on the
+     * primary user or by a profile owner of an organization-owned managed profile on the parent
+     * profile, it disables the primary user from using bluetooth and configuring bluetooth
+     * in Settings.
+     *
      * <p>The default value is <code>false</code>.
+     *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
@@ -434,14 +445,17 @@
     public static final String DISALLOW_BLUETOOTH = "no_bluetooth";
 
     /**
-     * Specifies if outgoing bluetooth sharing is disallowed on the device. Device owner and profile
-     * owner can set this restriction. When it is set by device owner or the profile owner of an
-     * organization-owned managed profile on the parent profile, all users on this device will be
-     * affected.
+     * Specifies if outgoing bluetooth sharing is disallowed.
      *
-     * <p>Default is <code>true</code> for managed profiles and false for otherwise. When a device
-     * upgrades to {@link android.os.Build.VERSION_CODES#O}, the system sets it for all existing
-     * managed profiles.
+     * <p>A device owner and a profile owner can set this restriction. When it is set by a device
+     * owner, it applies globally. When it is set by a profile owner on the primary user or by a
+     * profile owner of an organization-owned managed profile on the parent profile, it disables
+     * the primary user from any outgoing bluetooth sharing.
+     *
+     * <p>Default is <code>true</code> for managed profiles and false otherwise.
+     *
+     * <p>When a device upgrades to {@link android.os.Build.VERSION_CODES#O}, the system sets it
+     * for all existing managed profiles.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -452,10 +466,17 @@
     public static final String DISALLOW_BLUETOOTH_SHARING = "no_bluetooth_sharing";
 
     /**
-     * Specifies if a user is disallowed from transferring files over
-     * USB. This can only be set by device owners, profile owners on the primary user or
-     * profile owners of organization-owned managed profiles on the parent profile.
-     * The default value is <code>false</code>.
+     * Specifies if a user is disallowed from transferring files over USB.
+     *
+     * <p>This restriction can only be set by a device owner, a profile owner on the primary
+     * user or a profile owner of an organization-owned managed profile on the parent profile.
+     * When it is set by a device owner, it applies globally. When it is set by a profile owner
+     * on the primary user or by a profile owner of an organization-owned managed profile on
+     * the parent profile, it disables the primary user from transferring files over USB. No other
+     * user on the device is able to use file transfer over USB because the UI for file transfer
+     * is always associated with the primary user.
+     *
+     * <p>The default value is <code>false</code>.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -512,13 +533,16 @@
     public static final String DISALLOW_REMOVE_MANAGED_PROFILE = "no_remove_managed_profile";
 
     /**
-     * Specifies if a user is disallowed from enabling or accessing debugging features. When set on
-     * the primary user or by the profile owner of an organization-owned managed profile on the
-     * parent profile, disables debugging features altogether, including USB debugging. When set on
-     * a managed profile or a secondary user, blocks debugging for that user only, including
-     * starting activities, making service calls, accessing content providers, sending broadcasts,
-     * installing/uninstalling packages, clearing user data, etc.
-     * The default value is <code>false</code>.
+     * Specifies if a user is disallowed from enabling or accessing debugging features.
+     *
+     * <p>A device owner and a profile owner can set this restriction. When it is set by a device
+     * owner, a profile owner on the primary user or by a profile owner of an organization-owned
+     * managed profile on the parent profile, it disables debugging features altogether, including
+     * USB debugging. When set on a managed profile or a secondary user, it blocks debugging for
+     * that user only, including starting activities, making service calls, accessing content
+     * providers, sending broadcasts, installing/uninstalling packages, clearing user data, etc.
+     *
+     * <p>The default value is <code>false</code>.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -546,19 +570,18 @@
 
     /**
      * Specifies if a user is disallowed from enabling or disabling location providers. As a
-     * result, user is disallowed from turning on or off location.
+     * result, user is disallowed from turning on or off location via Settings.
      *
-     * <p>
-     * In a managed profile, location sharing is forced off when it is turned off on the primary
-     * user or by the profile owner of an organization-owned managed profile on the parent profile.
-     * The user can still turn off location sharing on a managed profile when the restriction is
-     * set by the profile owner on a managed profile.
-     * <p>
-     * This user restriction is different from {@link #DISALLOW_SHARE_LOCATION},
-     * as the device owner or profile owner can still enable or disable location mode via
+     * <p>A device owner and a profile owner can set this restriction. When it is set by a device
+     * owner, a profile owner on the primary user or by a profile owner of an organization-owned
+     * managed profile on the parent profile, it disallows the primary user from turning location
+     * on or off.
+     *
+     * <p>The default value is <code>false</code>.
+     *
+     * <p>This user restriction is different from {@link #DISALLOW_SHARE_LOCATION},
+     * as a device owner or a profile owner can still enable or disable location mode via
      * {@link DevicePolicyManager#setLocationEnabled} when this restriction is on.
-     * <p>
-     * The default value is <code>false</code>.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -570,15 +593,18 @@
     public static final String DISALLOW_CONFIG_LOCATION = "no_config_location";
 
     /**
-     * Specifies if date, time and timezone configuring is disallowed.
+     * Specifies configuring date, time and timezone is disallowed via Settings.
      *
-     * <p>When restriction is set by device owners or profile owners of organization-owned
-     * managed profiles on the parent profile, it applies globally - i.e., it disables date,
-     * time and timezone setting on the entire device and all users will be affected. When it's set
-     * by profile owners, it's only applied to the managed user.
+     * <p>A device owner and a profile owner can set this restriction, although the restriction has
+     * no effect in a managed profile. When it is set by a device owner or by a profile owner of an
+     * organization-owned managed profile on the parent profile, it applies globally - i.e.,
+     * it disables date, time and timezone setting on the entire device and all users are affected.
+     * When it is set by a profile owner on the primary user, it disables the primary user
+     * from configuring date, time and timezone and disables all configuring of date, time and
+     * timezone in Settings.
+     *
      * <p>The default value is <code>false</code>.
      *
-     * <p>This user restriction has no effect on managed profiles.
      * <p>Key for user restrictions.
      * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
@@ -588,10 +614,18 @@
     public static final String DISALLOW_CONFIG_DATE_TIME = "no_config_date_time";
 
     /**
-     * Specifies if a user is disallowed from configuring Tethering
-     * & portable hotspots. This can only be set by device owners, profile owners on the
-     * primary user or profile owners of organization-owned managed profiles on the parent profile.
-     * The default value is <code>false</code>.
+     * Specifies if a user is disallowed from configuring Tethering and portable hotspots
+     * via Settings.
+     *
+     * <p>This restriction can only be set by a device owner, a profile owner on the primary
+     * user or a profile owner of an organization-owned managed profile on the parent profile.
+     * When it is set by a device owner, it applies globally. When it is set by a profile owner
+     * on the primary user or by a profile owner of an organization-owned managed profile on
+     * the parent profile, it disables the primary user from using Tethering and hotspots and
+     * disables all configuring of Tethering and hotspots in Settings.
+     *
+     * <p>The default value is <code>false</code>.
+     *
      * <p>In Android 9.0 or higher, if tethering is enabled when this restriction is set,
      * tethering will be automatically turned off.
      *
@@ -685,10 +719,16 @@
     public static final String ENSURE_VERIFY_APPS = "ensure_verify_apps";
 
     /**
-     * Specifies if a user is disallowed from configuring cell
-     * broadcasts. This can only be set by device owners, profile owners on the primary user or
-     * profile owners of organization-owned managed profiles on the parent profile.
-     * The default value is <code>false</code>.
+     * Specifies if a user is disallowed from configuring cell broadcasts.
+     *
+     * <p>This restriction can only be set by a device owner, a profile owner on the primary
+     * user or a profile owner of an organization-owned managed profile on the parent profile.
+     * When it is set by a device owner, it applies globally. When it is set by a profile owner
+     * on the primary user or by a profile owner of an organization-owned managed profile on
+     * the parent profile, it disables the primary user from configuring cell broadcasts.
+     *
+     * <p>The default value is <code>false</code>.
+     *
      * <p>This restriction has no effect on secondary users and managed profiles since only the
      * primary user can configure cell broadcasts.
      *
@@ -701,10 +741,16 @@
     public static final String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
 
     /**
-     * Specifies if a user is disallowed from configuring mobile
-     * networks. This can only be set by device owners, profile owners on the primary user or
-     * profile owners of organization-owned managed profiles on the parent profile.
-     * The default value is <code>false</code>.
+     * Specifies if a user is disallowed from configuring mobile networks.
+     *
+     * <p>This restriction can only be set by a device owner, a profile owner on the primary
+     * user or a profile owner of an organization-owned managed profile on the parent profile.
+     * When it is set by a device owner, it applies globally. When it is set by a profile owner
+     * on the primary user or by a profile owner of an organization-owned managed profile on
+     * the parent profile, it disables the primary user from configuring mobile networks.
+     *
+     * <p>The default value is <code>false</code>.
+     *
      * <p>This restriction has no effect on secondary users and managed profiles since only the
      * primary user can configure mobile networks.
      *
@@ -747,11 +793,14 @@
 
     /**
      * Specifies if a user is disallowed from mounting physical external media.
-     * <p>
-     * This restriction can only be set by the device owner, the profile owner on the primary user
-     * or the profile owner of an organization-owned managed profile on the parent profile.
-     * <p>
-     * The default value is <code>false</code>.
+     *
+     * <p>This restriction can only be set by a device owner, a profile owner on the primary
+     * user or a profile owner of an organization-owned managed profile on the parent profile.
+     * When it is set by a device owner, it applies globally. When it is set by a profile owner
+     * on the primary user or by a profile owner of an organization-owned managed profile on
+     * the parent profile, it disables the primary user from mounting physical external media.
+     *
+     * <p>The default value is <code>false</code>.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -764,13 +813,14 @@
     /**
      * Specifies if a user is disallowed from adjusting microphone volume. If set, the microphone
      * will be muted.
-     * <p>
-     * The default value is <code>false</code>.
-     * <p>
-     * Device owner and profile owner can set this restriction, although the restriction has no
-     * effect in a managed profile. When it is set by the profile owner of an organization-owned
-     * managed profile on the parent profile, it will disallow the personal user from adjusting the
-     * microphone volume.
+     *
+     * <p>A device owner and a profile owner can set this restriction, although the restriction has
+     * no effect in a managed profile. When it is set by a device owner, it applies globally. When
+     * it is set by a profile owner on the primary user or by a profile owner of an
+     * organization-owned managed profile on the parent profile, it will disallow the primary user
+     * from adjusting the microphone volume.
+     *
+     * <p>The default value is <code>false</code>.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -800,13 +850,13 @@
     /**
      * Specifies that the user is not allowed to make outgoing phone calls. Emergency calls are
      * still permitted.
-     * <p>
-     * The default value is <code>false</code>.
-     * <p>
-     * Device owner and profile owner can set this restriction, although the restriction has no
-     * effect in a managed profile. When it is set by the profile owner of an organization-owned
-     * managed profile on the parent profile, it will disallow the personal user from making
-     * outgoing phone calls.
+     *
+     * <p>A device owner and a profile owner can set this restriction, although the restriction has
+     * no effect in a managed profile. When it is set by a device owner, a profile owner on the
+     * primary user or by a profile owner of an organization-owned managed profile on the parent
+     * profile, it disallows the primary user from making outgoing phone calls.
+     *
+     * <p>The default value is <code>false</code>.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -817,12 +867,15 @@
     public static final String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
 
     /**
-     * Specifies that the user is not allowed to send or receive
-     * SMS messages. The default value is <code>false</code>.
-     * <p>
-     * Device owner and profile owner can set this restriction. When it is set by the
-     * profile owner of an organization-owned managed profile on the parent profile,
-     * it will disable SMS in the personal profile.
+     * Specifies that the user is not allowed to send or receive SMS messages.
+     *
+     * <p>This restriction can only be set by a device owner, a profile owner on the primary
+     * user or a profile owner of an organization-owned managed profile on the parent profile.
+     * When it is set by a device owner, it applies globally. When it is set by a profile owner
+     * on the primary user or by a profile owner of an organization-owned managed profile on
+     * the parent profile, it disables the primary user from sending or receiving SMS messages.
+     *
+     * <p>The default value is <code>false</code>.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -941,9 +994,15 @@
 
     /**
      * Specifies if the user is not allowed to reboot the device into safe boot mode.
-     * This can only be set by device owners, profile owners on the primary user or profile
-     * owners of organization-owned managed profiles on the parent profile.
-     * The default value is <code>false</code>.
+     *
+     * <p>This restriction can only be set by a device owner, a profile owner on the primary
+     * user or a profile owner of an organization-owned managed profile on the parent profile.
+     * When it is set by a device owner, it applies globally. When it is set by a profile owner
+     * on the primary user or by a profile owner of an organization-owned managed profile on
+     * the parent profile, it disables the primary user from rebooting the device into safe
+     * boot mode.
+     *
+     * <p>The default value is <code>false</code>.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -981,12 +1040,14 @@
 
     /**
      * Specifies if a user is not allowed to use the camera.
-     * <p>
-     * Device owner and profile owner can set this restriction. When the restriction is set by
-     * the device owner or the profile owner of an organization-owned managed profile on the
-     * parent profile, it is applied globally.
-     * <p>
-     * The default value is <code>false</code>.
+     *
+     * <p>A device owner and a profile owner can set this restriction. When it is set by a
+     * device owner, it applies globally - i.e., it disables the use of camera on the entire device
+     * and all users are affected. When it is set by a profile owner on the primary user or by a
+     * profile owner of an organization-owned managed profile on the parent profile, it disables
+     * the primary user from using camera.
+     *
+     * <p>The default value is <code>false</code>.
      *
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
@@ -1006,9 +1067,15 @@
     public static final String DISALLOW_UNMUTE_DEVICE = "disallow_unmute_device";
 
     /**
-     * Specifies if a user is not allowed to use cellular data when roaming. This can only be set by
-     * device owners or profile owners of organization-owned managed profiles on the parent profile.
-     * The default value is <code>false</code>.
+     * Specifies if a user is not allowed to use cellular data when roaming.
+     *
+     * <p>This restriction can only be set by a device owner, a profile owner on the primary
+     * user or a profile owner of an organization-owned managed profile on the parent profile.
+     * When it is set by a device owner, it applies globally. When it is set by a profile owner
+     * on the primary user or by a profile owner of an organization-owned managed profile on
+     * the parent profile, it disables the primary user from using cellular data when roaming.
+     *
+     * <p>The default value is <code>false</code>.
      *
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
@@ -1103,9 +1170,10 @@
      * Specifies if the contents of a user's screen is not allowed to be captured for artificial
      * intelligence purposes.
      *
-     * <p>Device owner and profile owner can set this restriction. When it is set by the
-     * device owner or the profile owner of an organization-owned managed profile on the parent
-     * profile, only the target user will be affected.
+     * <p>A device owner and a profile owner can set this restriction. When it is set by a device
+     * owner, a profile owner on the primary user or by a profile owner of an organization-owned
+     * managed profile on the parent profile, it disables the primary user's screen from being
+     * captured for artificial intelligence purposes.
      *
      * <p>The default value is <code>false</code>.
      *
@@ -1119,9 +1187,10 @@
      * Specifies if the current user is able to receive content suggestions for selections based on
      * the contents of their screen.
      *
-     * <p>Device owner and profile owner can set this restriction. When it is set by the
-     * device owner or the profile owner of an organization-owned managed profile on the parent
-     * profile, only the target user will be affected.
+     * <p>A device owner and a profile owner can set this restriction. When it is set by a device
+     * owner, a profile owner on the primary user or by a profile owner of an organization-owned
+     * managed profile on the parent profile, it disables the primary user from receiving content
+     * suggestions for selections based on the contents of their screen.
      *
      * <p>The default value is <code>false</code>.
      *
@@ -1185,10 +1254,11 @@
     /**
      * Specifies whether the user is allowed to modify private DNS settings.
      *
-     * <p>The default value is <code>false</code>.
+     * <p>This restriction can only be set by a device owner or a profile owner of an
+     * organization-owned managed profile on the parent profile. When it is set by either of these
+     * owners, it applies globally.
      *
-     * <p>This user restriction can only be applied by the device owner or the profile owner
-     * of an organization-owned managed profile on the parent profile.
+     * <p>The default value is <code>false</code>.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -2216,6 +2286,20 @@
                 }
             };
 
+    // Uses IS_USER_UNLOCKED_PROPERTY for invalidation as the APIs have the same dependencies.
+    private final PropertyInvalidatedCache<Integer, Boolean> mIsUserUnlockingOrUnlockedCache =
+            new PropertyInvalidatedCache<Integer, Boolean>(
+                32, CACHE_KEY_IS_USER_UNLOCKED_PROPERTY) {
+                @Override
+                protected Boolean recompute(Integer query) {
+                    try {
+                        return mService.isUserUnlockingOrUnlocked(query);
+                    } catch (RemoteException re) {
+                        throw re.rethrowFromSystemServer();
+                    }
+                }
+            };
+
     /** {@hide} */
     @UnsupportedAppUsage
     @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
@@ -2227,6 +2311,7 @@
     /** {@hide} */
     public void disableIsUserUnlockedCache() {
         mIsUserUnlockedCache.disableLocal();
+        mIsUserUnlockingOrUnlockedCache.disableLocal();
     }
 
     /** {@hide} */
@@ -2263,11 +2348,7 @@
     @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
             Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
     public boolean isUserUnlockingOrUnlocked(@UserIdInt int userId) {
-        try {
-            return mService.isUserUnlockingOrUnlocked(userId);
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
+        return mIsUserUnlockingOrUnlockedCache.query(userId);
     }
 
     /**
@@ -4021,12 +4102,25 @@
     }
 
     /**
-     * Returns true if the user switcher should be shown, this will be if device supports multi-user
-     * and there are at least 2 users available that are not managed profiles.
-     * @hide
+     * Returns true if the user switcher should be shown.
+     * I.e., returns whether the user switcher is enabled and there is something actionable to show.
+     *
      * @return true if user switcher should be shown.
+     * @hide
      */
     public boolean isUserSwitcherEnabled() {
+        return isUserSwitcherEnabled(false);
+    }
+
+    /**
+     * Returns true if the user switcher should be shown.
+     *
+     * @param showEvenIfNotActionable value to return if the feature is enabled but there is nothing
+     *                                actionable for the user to do anyway
+     * @return true if user switcher should be shown.
+     * @hide
+     */
+    public boolean isUserSwitcherEnabled(boolean showEvenIfNotActionable) {
         if (!supportsMultipleUsers()) {
             return false;
         }
@@ -4037,15 +4131,26 @@
         if (isDeviceInDemoMode(mContext)) {
             return false;
         }
-        // If user disabled this feature, don't show switcher
-        final boolean userSwitcherEnabled = Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.USER_SWITCHER_ENABLED, 1) != 0;
-        if (!userSwitcherEnabled) {
+        // Check the Settings.Global.USER_SWITCHER_ENABLED that the user can toggle on/off.
+        final boolean userSwitcherSettingOn = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.USER_SWITCHER_ENABLED,
+                Resources.getSystem().getBoolean(R.bool.config_showUserSwitcherByDefault) ? 1 : 0)
+                != 0;
+        if (!userSwitcherSettingOn) {
             return false;
         }
-        List<UserInfo> users = getUsers(true);
+
+        // The feature is enabled. But is it worth showing?
+        return showEvenIfNotActionable
+                || areThereUsersToWhichToSwitch() // There are switchable users.
+                || !hasUserRestriction(UserManager.DISALLOW_ADD_USER); // New users can be added.
+    }
+
+    /** Returns whether there are any users (other than the current user) to which to switch. */
+    private boolean areThereUsersToWhichToSwitch() {
+        final List<UserInfo> users = getUsers(true);
         if (users == null) {
-           return false;
+            return false;
         }
         int switchableUserCount = 0;
         for (UserInfo user : users) {
@@ -4053,9 +4158,7 @@
                 ++switchableUserCount;
             }
         }
-        final boolean guestEnabled = !mContext.getSystemService(DevicePolicyManager.class)
-                .getGuestUserDisabled(null);
-        return switchableUserCount > 1 || guestEnabled;
+        return switchableUserCount > 1;
     }
 
     /**
diff --git a/core/java/android/os/incremental/IIncrementalService.aidl b/core/java/android/os/incremental/IIncrementalService.aidl
index 25cb040..220ce22 100644
--- a/core/java/android/os/incremental/IIncrementalService.aidl
+++ b/core/java/android/os/incremental/IIncrementalService.aidl
@@ -19,6 +19,8 @@
 import android.content.pm.DataLoaderParamsParcel;
 import android.content.pm.IDataLoaderStatusListener;
 import android.os.incremental.IncrementalNewFileParams;
+import android.os.incremental.IStorageHealthListener;
+import android.os.incremental.StorageHealthCheckParams;
 
 /** @hide */
 interface IIncrementalService {
@@ -34,7 +36,10 @@
      * Opens or creates a storage given a target path and data loader params. Returns the storage ID.
      */
     int openStorage(in @utf8InCpp String path);
-    int createStorage(in @utf8InCpp String path, in DataLoaderParamsParcel params, in IDataLoaderStatusListener listener, int createMode);
+    int createStorage(in @utf8InCpp String path, in DataLoaderParamsParcel params, int createMode,
+                      in IDataLoaderStatusListener statusListener,
+                      in StorageHealthCheckParams healthCheckParams,
+                      in IStorageHealthListener healthListener);
     int createLinkedStorage(in @utf8InCpp String path, int otherStorageId, int createMode);
 
     /**
@@ -106,9 +111,9 @@
     void deleteStorage(int storageId);
 
     /**
-     * Setting up native library directories and extract native libs onto a storage.
+     * Setting up native library directories and extract native libs onto a storage if needed.
      */
-    boolean configureNativeBinaries(int storageId, in @utf8InCpp String apkFullPath, in @utf8InCpp String libDirRelativePath, in @utf8InCpp String abi);
+    boolean configureNativeBinaries(int storageId, in @utf8InCpp String apkFullPath, in @utf8InCpp String libDirRelativePath, in @utf8InCpp String abi, boolean extractNativeLibs);
 
     /**
      * Waits until all native library extraction is done for the storage
diff --git a/core/java/android/os/incremental/IStorageHealthListener.aidl b/core/java/android/os/incremental/IStorageHealthListener.aidl
new file mode 100644
index 0000000..9f93ede
--- /dev/null
+++ b/core/java/android/os/incremental/IStorageHealthListener.aidl
@@ -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.
+ */
+
+package android.os.incremental;
+
+/** @hide */
+oneway interface IStorageHealthListener {
+    /** OK status, no pending reads. */
+    const int HEALTH_STATUS_OK = 0;
+    /* Statuses depend on timeouts defined in StorageHealthCheckParams. */
+    /** Pending reads detected, waiting for params.blockedTimeoutMs to confirm blocked state. */
+    const int HEALTH_STATUS_READS_PENDING = 1;
+    /** There are reads pending for params.blockedTimeoutMs, waiting till
+    *   params.unhealthyTimeoutMs to confirm unhealthy state. */
+    const int HEALTH_STATUS_BLOCKED = 2;
+    /** There are reads pending for params.unhealthyTimeoutMs>,
+    *   marking storage as unhealthy. */
+    const int HEALTH_STATUS_UNHEALTHY = 3;
+
+    /** Health status callback. */
+    void onHealthStatus(in int storageId, in int status);
+}
diff --git a/core/java/android/os/incremental/IncrementalFileStorages.java b/core/java/android/os/incremental/IncrementalFileStorages.java
index 958c7fb..863d86ef 100644
--- a/core/java/android/os/incremental/IncrementalFileStorages.java
+++ b/core/java/android/os/incremental/IncrementalFileStorages.java
@@ -65,7 +65,9 @@
     public static IncrementalFileStorages initialize(Context context,
             @NonNull File stageDir,
             @NonNull DataLoaderParams dataLoaderParams,
-            @Nullable IDataLoaderStatusListener dataLoaderStatusListener,
+            @Nullable IDataLoaderStatusListener statusListener,
+            @Nullable StorageHealthCheckParams healthCheckParams,
+            @Nullable IStorageHealthListener healthListener,
             List<InstallationFileParcel> addedFiles) throws IOException {
         // TODO(b/136132412): sanity check if session should not be incremental
         IncrementalManager incrementalManager = (IncrementalManager) context.getSystemService(
@@ -75,9 +77,9 @@
             throw new IOException("Failed to obtain incrementalManager.");
         }
 
-        final IncrementalFileStorages result =
-                new IncrementalFileStorages(stageDir, incrementalManager, dataLoaderParams,
-                                            dataLoaderStatusListener);
+        final IncrementalFileStorages result = new IncrementalFileStorages(stageDir,
+                incrementalManager, dataLoaderParams, statusListener, healthCheckParams,
+                healthListener);
         for (InstallationFileParcel file : addedFiles) {
             if (file.location == LOCATION_DATA_APP) {
                 try {
@@ -100,7 +102,9 @@
     private IncrementalFileStorages(@NonNull File stageDir,
             @NonNull IncrementalManager incrementalManager,
             @NonNull DataLoaderParams dataLoaderParams,
-            @Nullable IDataLoaderStatusListener dataLoaderStatusListener) throws IOException {
+            @Nullable IDataLoaderStatusListener statusListener,
+            @Nullable StorageHealthCheckParams healthCheckParams,
+            @Nullable IStorageHealthListener healthListener) throws IOException {
         try {
             mStageDir = stageDir;
             mIncrementalManager = incrementalManager;
@@ -117,10 +121,9 @@
                 mDefaultStorage.bind(stageDir.getAbsolutePath());
             } else {
                 mDefaultStorage = mIncrementalManager.createStorage(stageDir.getAbsolutePath(),
-                        dataLoaderParams,
-                        dataLoaderStatusListener,
-                        IncrementalManager.CREATE_MODE_CREATE
-                                | IncrementalManager.CREATE_MODE_TEMPORARY_BIND, false);
+                        dataLoaderParams, IncrementalManager.CREATE_MODE_CREATE
+                                | IncrementalManager.CREATE_MODE_TEMPORARY_BIND, false,
+                        statusListener, healthCheckParams, healthListener);
                 if (mDefaultStorage == null) {
                     throw new IOException(
                             "Couldn't create incremental storage at " + stageDir);
diff --git a/core/java/android/os/incremental/IncrementalManager.java b/core/java/android/os/incremental/IncrementalManager.java
index 916edfa..c7f50c9 100644
--- a/core/java/android/os/incremental/IncrementalManager.java
+++ b/core/java/android/os/incremental/IncrementalManager.java
@@ -110,11 +110,15 @@
      */
     @Nullable
     public IncrementalStorage createStorage(@NonNull String path,
-            @NonNull DataLoaderParams params, @Nullable IDataLoaderStatusListener listener,
+            @NonNull DataLoaderParams params,
             @CreateMode int createMode,
-            boolean autoStartDataLoader) {
+            boolean autoStartDataLoader,
+            @Nullable IDataLoaderStatusListener statusListener,
+            @Nullable StorageHealthCheckParams healthCheckParams,
+            @Nullable IStorageHealthListener healthListener) {
         try {
-            final int id = mService.createStorage(path, params.getData(), listener, createMode);
+            final int id = mService.createStorage(path, params.getData(), createMode,
+                    statusListener, healthCheckParams, healthListener);
             if (id < 0) {
                 return null;
             }
diff --git a/core/java/android/os/incremental/IncrementalStorage.java b/core/java/android/os/incremental/IncrementalStorage.java
index 70ebbaa..6200a38 100644
--- a/core/java/android/os/incremental/IncrementalStorage.java
+++ b/core/java/android/os/incremental/IncrementalStorage.java
@@ -469,12 +469,15 @@
      * @param apkFullPath Source APK to extract native libs from.
      * @param libDirRelativePath Target dir to put lib files, e.g., "lib" or "lib/arm".
      * @param abi Target ABI of the native lib files. Only extract native libs of this ABI.
+     * @param extractNativeLibs If true, extract native libraries; otherwise just setup directories
+     *                          without extracting.
      * @return Success of not.
      */
     public boolean configureNativeBinaries(String apkFullPath, String libDirRelativePath,
-            String abi) {
+            String abi, boolean extractNativeLibs) {
         try {
-            return mService.configureNativeBinaries(mId, apkFullPath, libDirRelativePath, abi);
+            return mService.configureNativeBinaries(mId, apkFullPath, libDirRelativePath, abi,
+                    extractNativeLibs);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
             return false;
diff --git a/core/java/android/os/incremental/StorageHealthCheckParams.aidl b/core/java/android/os/incremental/StorageHealthCheckParams.aidl
new file mode 100644
index 0000000..6839317
--- /dev/null
+++ b/core/java/android/os/incremental/StorageHealthCheckParams.aidl
@@ -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.
+ */
+
+package android.os.incremental;
+
+/**
+ * @hide
+ */
+parcelable StorageHealthCheckParams {
+    /** Timeouts of the oldest pending read.
+    *   Valid values 0ms < blockedTimeoutMs < unhealthyTimeoutMs < storage page read timeout.
+    *   Invalid values will disable health checking. */
+
+    /** To consider storage "blocked". */
+    int blockedTimeoutMs;
+    /** To consider storage "unhealthy". */
+    int unhealthyTimeoutMs;
+
+    /** After storage is marked "unhealthy", how often to check if it recovered.
+    *   Valid value 1000ms < unhealthyMonitoringMs. */
+    int unhealthyMonitoringMs;
+}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e0bc764..1b19e12 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -14363,6 +14363,21 @@
          * @hide
          */
         public static final String ADVANCED_BATTERY_USAGE_AMOUNT = "advanced_battery_usage_amount";
+
+        /**
+         * For 5G NSA capable devices, determines whether NR tracking indications are on
+         * when the screen is off.
+         *
+         * Values are:
+         * 0: off - All 5G NSA tracking indications are off when the screen is off.
+         * 1: extended - All 5G NSA tracking indications are on when the screen is off as long as
+         *    the device is camped on 5G NSA (5G icon is showing in status bar).
+         *    If the device is not camped on 5G NSA, tracking indications are off.
+         * 2: always on - All 5G NSA tracking indications are on whether the screen is on or off.
+         * @hide
+         */
+        public static final String NR_NSA_TRACKING_SCREEN_OFF_MODE =
+                "nr_nsa_tracking_screen_off_mode";
     }
 
     /**
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index 05abc60..cd56ca9 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import static android.view.InsetsController.AnimationType;
+import static android.view.InsetsController.DEBUG;
 import static android.view.InsetsState.ISIDE_BOTTOM;
 import static android.view.InsetsState.ISIDE_FLOATING;
 import static android.view.InsetsState.ISIDE_LEFT;
@@ -30,6 +31,7 @@
 import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.util.ArraySet;
+import android.util.Log;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.util.SparseSetArray;
@@ -52,6 +54,8 @@
 public class InsetsAnimationControlImpl implements WindowInsetsAnimationController,
         InsetsAnimationControlRunner {
 
+    private static final String TAG = "InsetsAnimationCtrlImpl";
+
     private final Rect mTmpFrame = new Rect();
 
     private final WindowInsetsAnimationControlListener mListener;
@@ -165,6 +169,7 @@
      */
     public boolean applyChangeInsets(InsetsState state) {
         if (mCancelled) {
+            if (DEBUG) Log.d(TAG, "applyChangeInsets canceled");
             return false;
         }
         final Insets offset = Insets.subtract(mShownInsets, mPendingInsets);
@@ -186,9 +191,13 @@
         mCurrentAlpha = mPendingAlpha;
         mAnimation.setAlpha(mPendingAlpha);
         if (mFinished) {
+            if (DEBUG) Log.d(TAG, String.format(
+                    "notifyFinished shown: %s, currentAlpha: %f, currentInsets: %s",
+                    mShownOnFinish, mCurrentAlpha, mCurrentInsets));
             mController.notifyFinished(this, mShownOnFinish);
             releaseLeashes();
         }
+        if (DEBUG) Log.d(TAG, "Animation finished abruptly.");
         return mFinished;
     }
 
@@ -203,12 +212,15 @@
     @Override
     public void finish(boolean shown) {
         if (mCancelled || mFinished) {
+            if (DEBUG) Log.d(TAG, "Animation already canceled or finished, not notifying.");
             return;
         }
         mShownOnFinish = shown;
         mFinished = true;
         setInsetsAndAlpha(shown ? mShownInsets : mHiddenInsets, 1f /* alpha */, 1f /* fraction */,
                 true /* allowWhenFinished */);
+
+        if (DEBUG) Log.d(TAG, "notify control request finished for types: " + mTypes);
         mListener.onFinished(this);
     }
 
@@ -225,6 +237,7 @@
         }
         mCancelled = true;
         mListener.onCancelled(mReadyDispatched ? this : null);
+        if (DEBUG) Log.d(TAG, "notify Control request cancelled for types: " + mTypes);
 
         releaseLeashes();
     }
diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java
index 3215b7c..0e71b76 100644
--- a/core/java/android/view/InsetsAnimationThreadControlRunner.java
+++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java
@@ -16,12 +16,14 @@
 
 package android.view;
 
+import static android.view.InsetsController.DEBUG;
 import static android.view.SyncRtSurfaceTransactionApplier.applyParams;
 
 import android.annotation.UiThread;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.Trace;
+import android.util.Log;
 import android.util.SparseArray;
 import android.view.InsetsController.AnimationType;
 import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
@@ -37,6 +39,7 @@
  */
 public class InsetsAnimationThreadControlRunner implements InsetsAnimationControlRunner {
 
+    private static final String TAG = "InsetsAnimThreadRunner";
     private final InsetsAnimationControlImpl mControl;
     private final InsetsAnimationControlCallbacks mOuterCallbacks;
     private final Handler mMainThreadHandler;
@@ -71,6 +74,7 @@
 
         @Override
         public void applySurfaceParams(SurfaceParams... params) {
+            if (DEBUG) Log.d(TAG, "applySurfaceParams");
             SurfaceControl.Transaction t = new SurfaceControl.Transaction();
             for (int i = params.length - 1; i >= 0; i--) {
                 SyncRtSurfaceTransactionApplier.SurfaceParams surfaceParams = params[i];
@@ -82,6 +86,7 @@
 
         @Override
         public void releaseSurfaceControlFromRt(SurfaceControl sc) {
+            if (DEBUG) Log.d(TAG, "releaseSurfaceControlFromRt");
             // Since we don't push the SurfaceParams to the RT we can release directly
             sc.release();
         }
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 758062f..ef9edc6c 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -37,6 +37,7 @@
 import android.os.Handler;
 import android.os.Trace;
 import android.util.ArraySet;
+import android.util.Log;
 import android.util.Pair;
 import android.util.SparseArray;
 import android.view.InsetsSourceConsumer.ShowResult;
@@ -69,6 +70,8 @@
  */
 public class InsetsController implements WindowInsetsController, InsetsAnimationControlCallbacks {
 
+    private int mTypesBeingCancelled;
+
     public interface Host {
 
         Handler getHandler();
@@ -152,8 +155,16 @@
          * Obtains {@link InputMethodManager} instance from host.
          */
         InputMethodManager getInputMethodManager();
+
+        /**
+         * @return title of the rootView, if it has one.
+         * Note: this method is for debugging purposes only.
+         */
+        @Nullable
+        String getRootViewTitle();
     }
 
+    private static final String TAG = "InsetsController";
     private static final int ANIMATION_DURATION_SHOW_MS = 275;
     private static final int ANIMATION_DURATION_HIDE_MS = 340;
 
@@ -171,6 +182,9 @@
     private static final Interpolator FAST_OUT_LINEAR_IN_INTERPOLATOR =
             new PathInterpolator(0.4f, 0f, 1f, 1f);
 
+    static final boolean DEBUG = false;
+    static final boolean WARN = false;
+
     /**
      * Layout mode during insets animation: The views should be laid out as if the changing inset
      * types are fully shown. Before starting the animation, {@link View#onApplyWindowInsets} will
@@ -268,6 +282,7 @@
         @Override
         public void onReady(WindowInsetsAnimationController controller, int types) {
             mController = controller;
+            if (DEBUG) Log.d(TAG, "default animation onReady types: " + types);
 
             mAnimator = ValueAnimator.ofFloat(0f, 1f);
             mAnimator.setDuration(mDurationMs);
@@ -290,6 +305,8 @@
                         sEvaluator.evaluate(insetsFraction, start, end),
                         alphaInterpolator.getInterpolation(alphaFraction),
                         rawFraction);
+                if (DEBUG) Log.d(TAG, "Default animation setInsetsAndAlpha fraction: "
+                        + insetsFraction);
             });
             mAnimator.addListener(new AnimatorListenerAdapter() {
 
@@ -306,6 +323,8 @@
 
         @Override
         public void onFinished(WindowInsetsAnimationController controller) {
+            if (DEBUG) Log.d(TAG, "InternalAnimationControlListener onFinished types:"
+                    + Type.toString(mRequestedTypes));
         }
 
         @Override
@@ -314,6 +333,8 @@
             if (mAnimator != null) {
                 mAnimator.cancel();
             }
+            if (DEBUG) Log.d(TAG, "InternalAnimationControlListener onCancelled types:"
+                    + mRequestedTypes);
         }
 
         Interpolator getInterpolator() {
@@ -348,6 +369,7 @@
 
         protected void onAnimationFinish() {
             mController.finish(mShow);
+            if (DEBUG) Log.d(TAG, "onAnimationFinish showOnFinish: " + mShow);
         }
 
         /**
@@ -420,8 +442,6 @@
         final boolean useInsetsAnimationThread;
     }
 
-    private final String TAG = "InsetsControllerImpl";
-
     /** The local state */
     private final InsetsState mState = new InsetsState();
 
@@ -494,6 +514,7 @@
             InsetsState state = new InsetsState(mState, true /* copySources */);
             for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
                 RunningAnimation runningAnimation = mRunningAnimations.get(i);
+                if (DEBUG) Log.d(TAG, "Running animation type: " + runningAnimation.type);
                 InsetsAnimationControlRunner runner = runningAnimation.runner;
                 if (runner instanceof InsetsAnimationControlImpl) {
                     InsetsAnimationControlImpl control = (InsetsAnimationControlImpl) runner;
@@ -516,6 +537,12 @@
                     mLastDisplayCutout, mLastLegacySoftInputMode, mLastLegacySystemUiFlags,
                     null /* typeSideMap */);
             mHost.dispatchWindowInsetsAnimationProgress(insets, mUnmodifiableTmpRunningAnims);
+            if (DEBUG) {
+                for (WindowInsetsAnimation anim : mUnmodifiableTmpRunningAnims) {
+                    Log.d(TAG, String.format("Running animation type: %d, progress: %f",
+                            anim.getTypeMask(), anim.getInterpolatedFraction()));
+                }
+            }
 
             for (int i = mTmpFinishedControls.size() - 1; i >= 0; i--) {
                 dispatchAnimationEnd(mTmpFinishedControls.get(i).getAnimation());
@@ -553,13 +580,16 @@
         if (!localStateChanged && mLastDispatchedState.equals(state)) {
             return false;
         }
+        if (DEBUG) Log.d(TAG, "onStateChanged: " + state);
         updateState(state);
         mLastDispatchedState.set(state, true /* copySources */);
         applyLocalVisibilityOverride();
         if (localStateChanged) {
+            if (DEBUG) Log.d(TAG, "onStateChanged, notifyInsetsChanged");
             mHost.notifyInsetsChanged();
         }
         if (!mState.equals(mLastDispatchedState, true /* excludingCaptionInsets */)) {
+            if (DEBUG) Log.d(TAG, "onStateChanged, send state to WM: " + mState);
             updateRequestedState();
         }
         return true;
@@ -683,7 +713,6 @@
 
     @VisibleForTesting
     public void show(@InsetsType int types, boolean fromIme) {
-
         // Handle pending request ready in case there was one set.
         if (fromIme && mPendingImeControlRequest != null) {
             PendingControlRequest pendingRequest = mPendingImeControlRequest;
@@ -711,10 +740,18 @@
                     || animationType == ANIMATION_TYPE_SHOW) {
                 // no-op: already shown or animating in (because window visibility is
                 // applied before starting animation).
+                if (DEBUG) Log.d(TAG, String.format(
+                        "show ignored for type: %d animType: %d requestedVisible: %s",
+                        consumer.getType(), animationType, consumer.isRequestedVisible()));
+                continue;
+            }
+            if (fromIme && animationType == ANIMATION_TYPE_USER) {
+                // App is already controlling the IME, don't cancel it.
                 continue;
             }
             typesReady |= InsetsState.toPublicType(consumer.getType());
         }
+        if (DEBUG) Log.d(TAG, "show typesReady: " + typesReady);
         applyAnimation(typesReady, true /* show */, fromIme);
     }
 
@@ -778,12 +815,20 @@
             @AnimationType int animationType,
             @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation,
             boolean useInsetsAnimationThread) {
+        if ((types & mTypesBeingCancelled) != 0) {
+            throw new IllegalStateException("Cannot start a new insets animation of "
+                    + Type.toString(types)
+                    + " while an existing " + Type.toString(mTypesBeingCancelled)
+                    + " is being cancelled.");
+        }
         if (types == 0) {
             // nothing to animate.
             listener.onCancelled(null);
+            if (DEBUG) Log.d(TAG, "no types to animate in controlAnimationUnchecked");
             return;
         }
         cancelExistingControllers(types);
+        if (DEBUG) Log.d(TAG, "controlAnimation types: " + types);
         mLastStartedAnimTypes |= types;
 
         final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types);
@@ -793,6 +838,8 @@
                 fromIme, internalTypes, controls, animationType);
         int typesReady = typesReadyPair.first;
         boolean imeReady = typesReadyPair.second;
+        if (DEBUG) Log.d(TAG, String.format(
+                "controlAnimationUnchecked, typesReady: %s imeReady: %s", typesReady, imeReady));
         if (!imeReady) {
             // IME isn't ready, all requested types will be animated once IME is ready
             abortPendingImeControlRequest();
@@ -802,9 +849,12 @@
                     useInsetsAnimationThread);
             mPendingImeControlRequest = request;
             mHandler.postDelayed(mPendingControlTimeout, PENDING_CONTROL_TIMEOUT_MS);
+            if (DEBUG) Log.d(TAG, "Ime not ready. Create pending request");
             if (cancellationSignal != null) {
                 cancellationSignal.setOnCancelListener(() -> {
                     if (mPendingImeControlRequest == request) {
+                        if (DEBUG) Log.d(TAG,
+                                "Cancellation signal abortPendingImeControlRequest");
                         abortPendingImeControlRequest();
                     }
                 });
@@ -813,6 +863,7 @@
         }
 
         if (typesReady == 0) {
+            if (DEBUG) Log.d(TAG, "No types ready. onCancelled()");
             listener.onCancelled(null);
             return;
         }
@@ -826,8 +877,12 @@
                         frame, mState, listener, typesReady, this, durationMs, interpolator,
                         animationType);
         mRunningAnimations.add(new RunningAnimation(runner, animationType));
+        if (DEBUG) Log.d(TAG, "Animation added to runner. useInsetsAnimationThread: "
+                + useInsetsAnimationThread);
         if (cancellationSignal != null) {
-            cancellationSignal.setOnCancelListener(runner::cancel);
+            cancellationSignal.setOnCancelListener(() -> {
+                cancelAnimation(runner, true /* invokeCallback */);
+            });
         }
         if (layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN) {
             showDirectly(types);
@@ -857,8 +912,11 @@
                         break;
                     case ShowResult.IME_SHOW_DELAYED:
                         imeReady = false;
+                        if (DEBUG) Log.d(TAG, "requestShow IME_SHOW_DELAYED");
                         break;
                     case ShowResult.IME_SHOW_FAILED:
+                        if (WARN) Log.w(TAG, "requestShow IME_SHOW_FAILED. fromIme: "
+                                + fromIme);
                         // IME cannot be shown (since it didn't have focus), proceed
                         // with animation of other types.
                         break;
@@ -873,6 +931,9 @@
                 canRun = true;
             }
             if (!canRun) {
+                if (WARN) Log.w(TAG, String.format(
+                        "collectSourceControls can't continue show for type: %s fromIme: %b",
+                        InsetsState.typeToString(consumer.getType()), fromIme));
                 continue;
             }
             final InsetsSourceControl control = consumer.getControl();
@@ -880,7 +941,8 @@
                 controls.put(consumer.getType(), new InsetsSourceControl(control));
                 typesReady |= toPublicType(consumer.getType());
             } else if (animationType == ANIMATION_TYPE_SHOW) {
-
+                if (DEBUG) Log.d(TAG, "collectSourceControls no control for show(). fromIme: "
+                        + fromIme);
                 // We don't have a control at the moment. However, we still want to update requested
                 // visibility state such that in case we get control, we can apply show animation.
                 consumer.show(fromIme);
@@ -915,14 +977,20 @@
     }
 
     private void cancelExistingControllers(@InsetsType int types) {
-        for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
-            InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
-            if ((control.getTypes() & types) != 0) {
-                cancelAnimation(control, true /* invokeCallback */);
+        final int originalmTypesBeingCancelled = mTypesBeingCancelled;
+        mTypesBeingCancelled |= types;
+        try {
+            for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
+                InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
+                if ((control.getTypes() & types) != 0) {
+                    cancelAnimation(control, true /* invokeCallback */);
+                }
             }
-        }
-        if ((types & ime()) != 0) {
-            abortPendingImeControlRequest();
+            if ((types & ime()) != 0) {
+                abortPendingImeControlRequest();
+            }
+        } finally {
+            mTypesBeingCancelled = originalmTypesBeingCancelled;
         }
     }
 
@@ -931,6 +999,7 @@
             mPendingImeControlRequest.listener.onCancelled(null);
             mPendingImeControlRequest = null;
             mHandler.removeCallbacks(mPendingControlTimeout);
+            if (DEBUG) Log.d(TAG, "abortPendingImeControlRequest");
         }
     }
 
@@ -938,6 +1007,7 @@
     @Override
     public void notifyFinished(InsetsAnimationControlRunner runner, boolean shown) {
         cancelAnimation(runner, false /* invokeCallback */);
+        if (DEBUG) Log.d(TAG, "notifyFinished. shown: " + shown);
         if (shown) {
             showDirectly(runner.getTypes());
         } else {
@@ -964,6 +1034,8 @@
     }
 
     private void cancelAnimation(InsetsAnimationControlRunner control, boolean invokeCallback) {
+        if (DEBUG) Log.d(TAG, String.format("cancelAnimation of types: %d, animType: %d",
+                control.getTypes(), control.getAnimationType()));
         if (invokeCallback) {
             control.cancel();
         }
@@ -977,6 +1049,9 @@
                         mHost.notifyInsetsChanged();
                     }
                 }
+                if (invokeCallback && runningAnimation.startDispatched) {
+                    dispatchAnimationEnd(runningAnimation.runner.getAnimation());
+                }
                 break;
             }
         }
@@ -1088,6 +1163,7 @@
     public void applyAnimation(@InsetsType final int types, boolean show, boolean fromIme) {
         if (types == 0) {
             // nothing to animate.
+            if (DEBUG) Log.d(TAG, "applyAnimation, nothing to animate");
             return;
         }
 
@@ -1142,6 +1218,7 @@
         mHost.dispatchWindowInsetsAnimationPrepare(animation);
         mHost.addOnPreDrawRunnable(() -> {
             if (controller.isCancelled()) {
+                if (WARN) Log.w(TAG, "startAnimation canceled before preDraw");
                 return;
             }
             Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW,
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index df3ac87..3869484 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -19,11 +19,13 @@
 import static android.view.InsetsController.ANIMATION_TYPE_NONE;
 import static android.view.InsetsController.AnimationType;
 import static android.view.InsetsState.getDefaultVisibility;
+import static android.view.InsetsController.DEBUG;
 import static android.view.InsetsState.toPublicType;
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.graphics.Rect;
+import android.util.Log;
 import android.view.InsetsState.InternalInsetsType;
 import android.view.SurfaceControl.Transaction;
 import android.view.WindowInsets.Type.InsetsType;
@@ -64,6 +66,7 @@
     protected final InsetsState mState;
     protected final @InternalInsetsType int mType;
 
+    private static final String TAG = "InsetsSourceConsumer";
     private final Supplier<Transaction> mTransactionSupplier;
     private @Nullable InsetsSourceControl mSourceControl;
     private boolean mHasWindowFocus;
@@ -103,7 +106,11 @@
 
         final InsetsSourceControl lastControl = mSourceControl;
         mSourceControl = control;
-
+        if (control != null) {
+            if (DEBUG) Log.d(TAG, String.format("setControl -> %s on %s",
+                    InsetsState.typeToString(control.getType()),
+                    mController.getHost().getRootViewTitle()));
+        }
         // We are loosing control
         if (mSourceControl == null) {
             mController.notifyControlRevoked(this);
@@ -118,6 +125,8 @@
             final boolean requestedVisible = isRequestedVisibleAwaitingControl();
             final boolean needAnimation = requestedVisible != mState.getSource(mType).isVisible();
             if (control.getLeash() != null && (needAnimation || mIsAnimationPending)) {
+                if (DEBUG) Log.d(TAG, String.format("Gaining control in %s, requestedVisible: %b",
+                        mController.getHost().getRootViewTitle(), requestedVisible));
                 if (requestedVisible) {
                     showTypes[0] |= toPublicType(getType());
                 } else {
@@ -170,11 +179,15 @@
 
     @VisibleForTesting
     public void show(boolean fromIme) {
+        if (DEBUG) Log.d(TAG, String.format("Call show() for type: %s fromIme: %b ",
+                InsetsState.typeToString(mType), fromIme));
         setRequestedVisible(true);
     }
 
     @VisibleForTesting
     public void hide() {
+        if (DEBUG) Log.d(TAG, String.format("Call hide for %s on %s",
+                InsetsState.typeToString(mType), mController.getHost().getRootViewTitle()));
         setRequestedVisible(false);
     }
 
@@ -212,11 +225,16 @@
 
         // If we don't have control, we are not able to change the visibility.
         if (!hasControl) {
+            if (DEBUG) Log.d(TAG, "applyLocalVisibilityOverride: No control in "
+                    + mController.getHost().getRootViewTitle()
+                    + " requestedVisible " + mRequestedVisible);
             return false;
         }
         if (isVisible == mRequestedVisible) {
             return false;
         }
+        if (DEBUG) Log.d(TAG, String.format("applyLocalVisibilityOverride: %s requestedVisible: %b",
+                mController.getHost().getRootViewTitle(), mRequestedVisible));
         mState.getSource(mType).setVisible(mRequestedVisible);
         return true;
     }
@@ -271,6 +289,7 @@
         newSource.setFrame(source.getFrame());
         newSource.setVisibleFrame(source.getVisibleFrame());
         mState.addSource(newSource);
+        if (DEBUG) Log.d(TAG, "updateSource: " + newSource);
     }
 
     boolean notifyAnimationFinished() {
@@ -293,6 +312,7 @@
         if (mRequestedVisible != requestedVisible) {
             mRequestedVisible = requestedVisible;
             mIsAnimationPending = false;
+            if (DEBUG) Log.d(TAG, "setRequestedVisible: " + requestedVisible);
         }
         if (applyLocalVisibilityOverride()) {
             mController.notifyVisibilityChanged();
@@ -305,6 +325,7 @@
         }
 
         final Transaction t = mTransactionSupplier.get();
+        if (DEBUG) Log.d(TAG, "applyHiddenToControl: " + mRequestedVisible);
         if (mRequestedVisible) {
             t.show(mSourceControl.getLeash());
         } else {
diff --git a/core/java/android/view/InsetsSourceControl.java b/core/java/android/view/InsetsSourceControl.java
index e001b66..2c2ecd5 100644
--- a/core/java/android/view/InsetsSourceControl.java
+++ b/core/java/android/view/InsetsSourceControl.java
@@ -22,6 +22,7 @@
 import android.os.Parcelable;
 import android.view.InsetsState.InternalInsetsType;
 
+import java.io.PrintWriter;
 import java.util.function.Consumer;
 
 /**
@@ -101,6 +102,14 @@
         }
     }
 
+    public void dump(String prefix, PrintWriter pw) {
+        pw.print(prefix);
+        pw.print("InsetsSourceControl type="); pw.print(InsetsState.typeToString(mType));
+        pw.print(" mLeash="); pw.print(mLeash);
+        pw.print(" mSurfacePosition="); pw.print(mSurfacePosition);
+        pw.println();
+    }
+
     public static final @android.annotation.NonNull Creator<InsetsSourceControl> CREATOR
             = new Creator<InsetsSourceControl>() {
         public InsetsSourceControl createFromParcel(Parcel in) {
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 9896aa4..3822ee5 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -51,6 +51,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
+import java.util.StringJoiner;
 
 /**
  * Holder for state of system windows that cause window insets for all other windows in the system.
@@ -78,7 +79,9 @@
             ITYPE_TOP_DISPLAY_CUTOUT,
             ITYPE_RIGHT_DISPLAY_CUTOUT,
             ITYPE_BOTTOM_DISPLAY_CUTOUT,
-            ITYPE_IME
+            ITYPE_IME,
+            ITYPE_CLIMATE_BAR,
+            ITYPE_EXTRA_NAVIGATION_BAR
     })
     public @interface InternalInsetsType {}
 
@@ -109,7 +112,11 @@
     /** Input method window. */
     public static final int ITYPE_IME = 13;
 
-    static final int LAST_TYPE = ITYPE_IME;
+    /** Additional system decorations inset type. */
+    public static final int ITYPE_CLIMATE_BAR = 14;
+    public static final int ITYPE_EXTRA_NAVIGATION_BAR = 15;
+
+    static final int LAST_TYPE = ITYPE_EXTRA_NAVIGATION_BAR;
 
     // Derived types
 
@@ -417,8 +424,10 @@
     public static @Type.InsetsType int toPublicType(@InternalInsetsType int type) {
         switch (type) {
             case ITYPE_STATUS_BAR:
+            case ITYPE_CLIMATE_BAR:
                 return Type.STATUS_BARS;
             case ITYPE_NAVIGATION_BAR:
+            case ITYPE_EXTRA_NAVIGATION_BAR:
                 return Type.NAVIGATION_BARS;
             case ITYPE_CAPTION_BAR:
                 return Type.CAPTION_BAR;
@@ -497,6 +506,10 @@
                 return "ITYPE_BOTTOM_DISPLAY_CUTOUT";
             case ITYPE_IME:
                 return "ITYPE_IME";
+            case ITYPE_CLIMATE_BAR:
+                return "ITYPE_CLIMATE_BAR";
+            case ITYPE_EXTRA_NAVIGATION_BAR:
+                return "ITYPE_EXTRA_NAVIGATION_BAR";
             default:
                 return "ITYPE_UNKNOWN_" + type;
         }
@@ -600,10 +613,16 @@
 
     @Override
     public String toString() {
+        StringJoiner joiner = new StringJoiner(", ");
+        for (InsetsSource source : mSources.values()) {
+            if (source != null) {
+                joiner.add(source.toString());
+            }
+        }
         return "InsetsState: {"
                 + "mDisplayFrame=" + mDisplayFrame
-                + ", mSources=" + mSources
-                + "}";
+                + ", mSources= { " + joiner
+                + " }";
     }
 }
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7935eb1..e3362aa 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -7298,7 +7298,8 @@
         boolean isOptionalFitSystemWindows = (mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
                 || isFrameworkOptionalFitsSystemWindows();
         if (isOptionalFitSystemWindows && mAttachInfo != null
-                && mAttachInfo.mContentOnApplyWindowInsetsListener != null) {
+                && mAttachInfo.mContentOnApplyWindowInsetsListener != null
+                && (getWindowSystemUiVisibility() & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
             return false;
         }
 
@@ -7322,7 +7323,8 @@
                 || isFrameworkOptionalFitsSystemWindows();
         if (isOptionalFitSystemWindows && mAttachInfo != null
                 && getListenerInfo().mWindowInsetsAnimationCallback == null
-                && mAttachInfo.mContentOnApplyWindowInsetsListener != null) {
+                && mAttachInfo.mContentOnApplyWindowInsetsListener != null
+                && (getWindowSystemUiVisibility() & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
             mInsetsAnimationDispatchMode = DISPATCH_MODE_STOP;
             return;
         }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 511e755..8b5d033 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4990,6 +4990,11 @@
                     break;
                 }
                 case MSG_SHOW_INSETS: {
+                    if (mView == null) {
+                        Log.e(TAG,
+                                String.format("Calling showInsets(%d,%b) on window that no longer"
+                                        + " has views.", msg.arg1, msg.arg2 == 1));
+                    }
                     mInsetsController.show(msg.arg1, msg.arg2 == 1);
                     break;
                 }
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index 9674a80..686d561 100644
--- a/core/java/android/view/ViewRootInsetsControllerHost.java
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import static android.view.InsetsController.DEBUG;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CONTROLLED;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
 
@@ -84,6 +85,7 @@
         if (mViewRoot.mView == null) {
             return null;
         }
+        if (DEBUG) Log.d(TAG, "windowInsetsAnimation started");
         return mViewRoot.mView.dispatchWindowInsetsAnimationStart(animation, bounds);
     }
 
@@ -94,11 +96,18 @@
             // The view has already detached from window.
             return null;
         }
+        if (DEBUG) {
+            for (WindowInsetsAnimation anim : runningAnimations) {
+                Log.d(TAG, "windowInsetsAnimation progress: "
+                        + anim.getInterpolatedFraction());
+            }
+        }
         return mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets, runningAnimations);
     }
 
     @Override
     public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
+        if (DEBUG) Log.d(TAG, "windowInsetsAnimation ended");
         mViewRoot.mView.dispatchWindowInsetsAnimationEnd(animation);
     }
 
@@ -212,4 +221,12 @@
     public InputMethodManager getInputMethodManager() {
         return mViewRoot.mContext.getSystemService(InputMethodManager.class);
     }
+
+    @Override
+    public String getRootViewTitle() {
+        if (mViewRoot == null) {
+            return null;
+        }
+        return mViewRoot.getTitle().toString();
+    }
 }
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index d20ffb3..9b5b882 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -136,6 +136,7 @@
         final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession)
                 .setParent(mRootSurface)
                 .setFormat(attrs.format)
+                .setBufferSize(getSurfaceWidth(attrs), getSurfaceHeight(attrs))
                 .setName(attrs.getTitle().toString());
         final SurfaceControl sc = b.build();
 
@@ -242,13 +243,8 @@
         WindowManager.LayoutParams attrs = state.mParams;
 
         if (viewFlags == View.VISIBLE) {
-            final Rect surfaceInsets = attrs.surfaceInsets;
-            int width = surfaceInsets != null
-                    ? attrs.width + surfaceInsets.left + surfaceInsets.right : attrs.width;
-            int height = surfaceInsets != null
-                    ? attrs.height + surfaceInsets.top + surfaceInsets.bottom : attrs.height;
-
-            t.setBufferSize(sc, width, height).setOpaque(sc, isOpaque(attrs)).show(sc).apply();
+            t.setBufferSize(sc, getSurfaceWidth(attrs), getSurfaceHeight(attrs))
+                    .setOpaque(sc, isOpaque(attrs)).show(sc).apply();
             outSurfaceControl.copyFrom(sc);
         } else {
             t.hide(sc).apply();
@@ -444,4 +440,15 @@
     public android.os.IBinder asBinder() {
         return null;
     }
+
+    private int getSurfaceWidth(WindowManager.LayoutParams attrs) {
+      final Rect surfaceInsets = attrs.surfaceInsets;
+      return surfaceInsets != null
+          ? attrs.width + surfaceInsets.left + surfaceInsets.right : attrs.width;
+    }
+    private int getSurfaceHeight(WindowManager.LayoutParams attrs) {
+      final Rect surfaceInsets = attrs.surfaceInsets;
+      return surfaceInsets != null
+          ? attrs.height + surfaceInsets.top + surfaceInsets.bottom : attrs.height;
+    }
 }
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 0807f41..7042f29 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -202,9 +202,9 @@
      * <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.
+     * <p>Note that if the {@link WebChromeClient} is set to be {@code null},
+     * or if {@link WebChromeClient} is not set at all, 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.
@@ -236,9 +236,10 @@
      * <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.
+     * <p>Note that if the {@link WebChromeClient} is set to be {@code null},
+     * or if {@link WebChromeClient} is not set at all, 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.
@@ -269,9 +270,10 @@
      * <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.
+     * <p>Note that if the {@link WebChromeClient} is set to be {@code null},
+     * or if {@link WebChromeClient} is not set at all, 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.
@@ -288,20 +290,32 @@
     }
 
     /**
-     * Tell the client to display a dialog to confirm navigation away from the
-     * current page. This is the result of the onbeforeunload javascript event.
-     * 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 {@code false}, a default value of {@code true} will be returned to
-     * javascript to accept navigation away from the current page. The default
-     * behavior is to return {@code false}. Setting the JsResult to {@code true} will navigate
-     * away from the current page, {@code false} will cancel the navigation.
+     * Notify the host application that the web page wants to confirm navigation
+     * from JavaScript {@code onbeforeunload}.
+     * <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 continue the navigation if the user confirms the navigation, and
+     * will stop the navigation if the user wants to stay on the current page.
+     * <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. When the custom dialog is dismissed, the
+     * app should call {@code JsResult.confirm()} to continue the navigation or,
+     * {@code JsResult.cancel()} to stay on the current page.
+     * <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 set to be {@code null},
+     * or if {@link WebChromeClient} is not set at all, the default dialog will
+     * be suppressed and the navigation will be resumed 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 onJsBeforeUnload(WebView view, String url, String message,
             JsResult result) {
diff --git a/core/java/com/android/internal/app/AbstractResolverComparator.java b/core/java/com/android/internal/app/AbstractResolverComparator.java
index 28c9464..ea3f1b1 100644
--- a/core/java/com/android/internal/app/AbstractResolverComparator.java
+++ b/core/java/com/android/internal/app/AbstractResolverComparator.java
@@ -54,8 +54,6 @@
 
     // True if the current share is a link.
     private final boolean mHttp;
-    // can be null if mHttp == false or current user has no default browser package
-    private final String mDefaultBrowserPackageName;
 
     // message types
     static final int RANKER_SERVICE_RESULT = 0;
@@ -102,9 +100,6 @@
         getContentAnnotations(intent);
         mPm = context.getPackageManager();
         mUsm = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
-        mDefaultBrowserPackageName = mHttp
-                ? mPm.getDefaultBrowserPackageNameAsUser(UserHandle.myUserId())
-                : null;
         mAzComparator = new AzInfoComparator(context);
     }
 
@@ -157,17 +152,6 @@
         }
 
         if (mHttp) {
-            // Special case: we want filters that match URI paths/schemes to be
-            // ordered before others.  This is for the case when opening URIs,
-            // to make native apps go above browsers - except for 1 even more special case
-            // which is the default browser, as we want that to go above them all.
-            if (isDefaultBrowser(lhs)) {
-                return -1;
-            }
-
-            if (isDefaultBrowser(rhs)) {
-                return 1;
-            }
             final boolean lhsSpecific = ResolverActivity.isSpecificUriMatch(lhs.match);
             final boolean rhsSpecific = ResolverActivity.isSpecificUriMatch(rhs.match);
             if (lhsSpecific != rhsSpecific) {
@@ -272,21 +256,6 @@
         mAfterCompute = null;
     }
 
-    private boolean isDefaultBrowser(ResolveInfo ri) {
-        // It makes sense to prefer the default browser
-        // only if the targeted user is the current user
-        if (ri.targetUserId != UserHandle.USER_CURRENT) {
-            return false;
-        }
-
-        if (ri.activityInfo.packageName != null
-                    && ri.activityInfo.packageName.equals(mDefaultBrowserPackageName)) {
-            return true;
-        }
-        return false;
-    }
-
-
     /**
      * Sort intents alphabetically based on package name.
      */
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index f041ad9..7a033bc 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -101,6 +101,7 @@
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
+import android.view.ViewTreeObserver;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.Button;
@@ -170,17 +171,6 @@
     public static final String EXTRA_PRIVATE_RETAIN_IN_ON_STOP
             = "com.android.internal.app.ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP";
 
-    /**
-     * Integer extra to indicate which profile should be automatically selected.
-     * <p>Can only be used if there is a work profile.
-     * <p>Possible values can be either {@link #PROFILE_PERSONAL} or {@link #PROFILE_WORK}.
-     */
-    static final String EXTRA_SELECTED_PROFILE =
-            "com.android.internal.app.ChooserActivity.EXTRA_SELECTED_PROFILE";
-
-    static final int PROFILE_PERSONAL = AbstractMultiProfilePagerAdapter.PROFILE_PERSONAL;
-    static final int PROFILE_WORK = AbstractMultiProfilePagerAdapter.PROFILE_WORK;
-
     private static final String PREF_NUM_SHEET_EXPANSIONS = "pref_num_sheet_expansions";
 
     private static final String CHIP_LABEL_METADATA_KEY = "android.service.chooser.chip_label";
@@ -885,7 +875,6 @@
                 initialIntents,
                 rList,
                 filterLastUsed,
-                mUseLayoutForBrowsables,
                 /* userHandle */ UserHandle.of(UserHandle.myUserId()));
         return new ChooserMultiProfilePagerAdapter(
                 /* context */ this,
@@ -906,7 +895,6 @@
                 selectedProfile == PROFILE_PERSONAL ? initialIntents : null,
                 rList,
                 filterLastUsed,
-                mUseLayoutForBrowsables,
                 /* userHandle */ getPersonalProfileUserHandle());
         ChooserGridAdapter workAdapter = createChooserGridAdapter(
                 /* context */ this,
@@ -914,7 +902,6 @@
                 selectedProfile == PROFILE_WORK ? initialIntents : null,
                 rList,
                 filterLastUsed,
-                mUseLayoutForBrowsables,
                 /* userHandle */ getWorkProfileUserHandle());
         return new ChooserMultiProfilePagerAdapter(
                 /* context */ this,
@@ -927,15 +914,8 @@
     }
 
     private int findSelectedProfile() {
-        int selectedProfile;
-        if (getIntent().hasExtra(EXTRA_SELECTED_PROFILE)) {
-            selectedProfile = getIntent().getIntExtra(EXTRA_SELECTED_PROFILE, /* defValue = */ -1);
-            if (selectedProfile != PROFILE_PERSONAL && selectedProfile != PROFILE_WORK) {
-                throw new IllegalArgumentException(EXTRA_SELECTED_PROFILE + " has invalid value "
-                        + selectedProfile + ". Must be either ChooserActivity.PROFILE_PERSONAL or "
-                        + "ChooserActivity.PROFILE_WORK.");
-            }
-        } else {
+        int selectedProfile = getSelectedProfileExtra();
+        if (selectedProfile == -1) {
             selectedProfile = getProfileForUser(getUser());
         }
         return selectedProfile;
@@ -2503,10 +2483,10 @@
     @VisibleForTesting
     public ChooserGridAdapter createChooserGridAdapter(Context context,
             List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
-            boolean filterLastUsed, boolean useLayoutForBrowsables, UserHandle userHandle) {
+            boolean filterLastUsed, UserHandle userHandle) {
         ChooserListAdapter chooserListAdapter = createChooserListAdapter(context, payloadIntents,
                 initialIntents, rList, filterLastUsed,
-                useLayoutForBrowsables, createListController(userHandle));
+                createListController(userHandle));
         AppPredictor.Callback appPredictorCallback = createAppPredictorCallback(chooserListAdapter);
         AppPredictor appPredictor = setupAppPredictorForUser(userHandle, appPredictorCallback);
         chooserListAdapter.setAppPredictor(appPredictor);
@@ -2517,11 +2497,10 @@
     @VisibleForTesting
     public ChooserListAdapter createChooserListAdapter(Context context,
             List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
-            boolean filterLastUsed, boolean useLayoutForBrowsables,
-            ResolverListController resolverListController) {
+            boolean filterLastUsed, ResolverListController resolverListController) {
         return new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
-                filterLastUsed, resolverListController, useLayoutForBrowsables,
-                this, this, context.getPackageManager());
+                filterLastUsed, resolverListController, this,
+                this, context.getPackageManager());
     }
 
     @VisibleForTesting
@@ -2777,6 +2756,7 @@
     @Override
     public void onListRebuilt(ResolverListAdapter listAdapter) {
         setupScrollListener();
+        maybeSetupGlobalLayoutListener();
 
         ChooserListAdapter chooserListAdapter = (ChooserListAdapter) listAdapter;
         if (chooserListAdapter.getUserHandle()
@@ -2858,6 +2838,28 @@
                 });
     }
 
+    private void maybeSetupGlobalLayoutListener() {
+        if (shouldShowTabs()) {
+            return;
+        }
+        final View recyclerView = mChooserMultiProfilePagerAdapter.getActiveAdapterView();
+        recyclerView.getViewTreeObserver()
+                .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        // Fixes an issue were the accessibility border disappears on list creation.
+                        recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                        final TextView titleView = findViewById(R.id.title);
+                        if (titleView != null) {
+                            titleView.setFocusable(true);
+                            titleView.setFocusableInTouchMode(true);
+                            titleView.requestFocus();
+                            titleView.requestAccessibilityFocus();
+                        }
+                    }
+                });
+    }
+
     @Override // ChooserListCommunicator
     public boolean isSendAction(Intent targetIntent) {
         if (targetIntent == null) {
diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java
index f1b7161..a87f847 100644
--- a/core/java/com/android/internal/app/ChooserListAdapter.java
+++ b/core/java/com/android/internal/app/ChooserListAdapter.java
@@ -120,15 +120,13 @@
     public ChooserListAdapter(Context context, List<Intent> payloadIntents,
             Intent[] initialIntents, List<ResolveInfo> rList,
             boolean filterLastUsed, ResolverListController resolverListController,
-            boolean useLayoutForBrowsables,
             ChooserListCommunicator chooserListCommunicator,
             SelectableTargetInfo.SelectableTargetInfoCommunicator selectableTargetInfoCommunicator,
             PackageManager packageManager) {
         // Don't send the initial intents through the shared ResolverActivity path,
         // we want to separate them into a different section.
         super(context, payloadIntents, null, rList, filterLastUsed,
-                resolverListController, useLayoutForBrowsables,
-                chooserListCommunicator, false);
+                resolverListController, chooserListCommunicator, false);
 
         createPlaceHolders();
         mMaxShortcutTargetsPerApp =
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index fca156a..e65d1fe 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -18,6 +18,8 @@
 
 import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
 
+import static com.android.internal.app.ResolverActivity.EXTRA_SELECTED_PROFILE;
+
 import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.app.Activity;
@@ -26,6 +28,7 @@
 import android.app.AppGlobals;
 import android.app.admin.DevicePolicyManager;
 import android.compat.annotation.UnsupportedAppUsage;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -74,6 +77,9 @@
 
     private static final String TEL_SCHEME = "tel";
 
+    private static final ComponentName RESOLVER_COMPONENT_NAME =
+            new ComponentName("android", ResolverActivity.class.getName());
+
     private Injector mInjector;
 
     private MetricsLogger mMetricsLogger;
@@ -136,21 +142,50 @@
         }
 
         newIntent.prepareToLeaveUser(callingUserId);
-        maybeShowDisclosureAsync(intentReceived, newIntent, targetUserId, userMessageId);
-        CompletableFuture.runAsync(() ->
-                        startActivityAsCaller(newIntent, targetUserId), mExecutorService)
-                .thenAcceptAsync(result -> finish(), getApplicationContext().getMainExecutor());
+        final CompletableFuture<ResolveInfo> targetResolveInfoFuture =
+                mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY, targetUserId);
+        targetResolveInfoFuture
+                .thenApplyAsync(targetResolveInfo -> {
+                    if (isResolverActivityResolveInfo(targetResolveInfo)) {
+                        launchResolverActivityWithCorrectTab(intentReceived, className, newIntent,
+                                callingUserId, targetUserId);
+                        return targetResolveInfo;
+                    }
+                    startActivityAsCaller(newIntent, targetUserId);
+                    return targetResolveInfo;
+                }, mExecutorService)
+                .thenAcceptAsync(result -> {
+                    maybeShowDisclosure(intentReceived, result, userMessageId);
+                    finish();
+                }, getApplicationContext().getMainExecutor());
     }
 
-    private void maybeShowDisclosureAsync(
-            Intent intentReceived, Intent newIntent, int userId, int messageId) {
-        final CompletableFuture<ResolveInfo> resolveInfoFuture =
-                mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY, userId);
-        resolveInfoFuture.thenAcceptAsync(ri -> {
-            if (shouldShowDisclosure(ri, intentReceived)) {
-                mInjector.showToast(messageId, Toast.LENGTH_LONG);
-            }
-        }, getApplicationContext().getMainExecutor());
+    private boolean isIntentForwarderResolveInfo(ResolveInfo resolveInfo) {
+        if (resolveInfo == null) {
+            return false;
+        }
+        ActivityInfo activityInfo = resolveInfo.activityInfo;
+        if (activityInfo == null) {
+            return false;
+        }
+        if (!"android".equals(activityInfo.packageName)) {
+            return false;
+        }
+        return activityInfo.name.equals(FORWARD_INTENT_TO_PARENT)
+                || activityInfo.name.equals(FORWARD_INTENT_TO_MANAGED_PROFILE);
+    }
+
+    private boolean isResolverActivityResolveInfo(@Nullable ResolveInfo resolveInfo) {
+        return resolveInfo != null
+                && resolveInfo.activityInfo != null
+                && RESOLVER_COMPONENT_NAME.equals(resolveInfo.activityInfo.getComponentName());
+    }
+
+    private void maybeShowDisclosure(
+            Intent intentReceived, ResolveInfo resolveInfo, int messageId) {
+        if (shouldShowDisclosure(resolveInfo, intentReceived)) {
+            mInjector.showToast(messageId, Toast.LENGTH_LONG);
+        }
     }
 
     private void startActivityAsCaller(Intent newIntent, int userId) {
@@ -185,7 +220,7 @@
         // when cross-profile intents are disabled.
         int selectedProfile = findSelectedProfile(className);
         sanitizeIntent(intentReceived);
-        intentReceived.putExtra(ChooserActivity.EXTRA_SELECTED_PROFILE, selectedProfile);
+        intentReceived.putExtra(EXTRA_SELECTED_PROFILE, selectedProfile);
         Intent innerIntent = intentReceived.getParcelableExtra(Intent.EXTRA_INTENT);
         if (innerIntent == null) {
             Slog.wtf(TAG, "Cannot start a chooser intent with no extra " + Intent.EXTRA_INTENT);
@@ -196,6 +231,25 @@
         finish();
     }
 
+    private void launchResolverActivityWithCorrectTab(Intent intentReceived, String className,
+            Intent newIntent, int callingUserId, int targetUserId) {
+        // When showing the intent resolver, instead of forwarding to the other profile,
+        // we launch it in the current user and select the other tab. This fixes b/155874820.
+        //
+        // In the case when there are 0 targets in the current profile and >1 apps in the other
+        // profile, the package manager launches the intent resolver in the other profile.
+        // If that's the case, we launch the resolver in the target user instead (other profile).
+        ResolveInfo callingResolveInfo = mInjector.resolveActivityAsUser(
+                newIntent, MATCH_DEFAULT_ONLY, callingUserId).join();
+        int userId = isIntentForwarderResolveInfo(callingResolveInfo)
+                ? targetUserId : callingUserId;
+        int selectedProfile = findSelectedProfile(className);
+        sanitizeIntent(intentReceived);
+        intentReceived.putExtra(EXTRA_SELECTED_PROFILE, selectedProfile);
+        startActivityAsCaller(intentReceived, null, null, false, userId);
+        finish();
+    }
+
     private int findSelectedProfile(String className) {
         if (className.equals(FORWARD_INTENT_TO_PARENT)) {
             return ChooserActivity.PROFILE_PERSONAL;
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 182c7f2..ff8fd50 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -133,9 +133,6 @@
     private CharSequence mTitle;
     private int mDefaultTitleResId;
 
-    @VisibleForTesting
-    protected boolean mUseLayoutForBrowsables;
-
     // Whether or not this activity supports choosing a default handler for the intent.
     @VisibleForTesting
     protected boolean mSupportsAlwaysUseOption;
@@ -179,6 +176,17 @@
     // Intent extra for connected audio devices
     public static final String EXTRA_IS_AUDIO_CAPTURE_DEVICE = "is_audio_capture_device";
 
+    /**
+     * Integer extra to indicate which profile should be automatically selected.
+     * <p>Can only be used if there is a work profile.
+     * <p>Possible values can be either {@link #PROFILE_PERSONAL} or {@link #PROFILE_WORK}.
+     */
+    static final String EXTRA_SELECTED_PROFILE =
+            "com.android.internal.app.ResolverActivity.EXTRA_SELECTED_PROFILE";
+
+    static final int PROFILE_PERSONAL = AbstractMultiProfilePagerAdapter.PROFILE_PERSONAL;
+    static final int PROFILE_WORK = AbstractMultiProfilePagerAdapter.PROFILE_WORK;
+
     private BroadcastReceiver mWorkProfileStateReceiver;
     private UserHandle mHeaderCreatorUser;
 
@@ -353,10 +361,6 @@
         mTitle = title;
         mDefaultTitleResId = defaultTitleRes;
 
-        mUseLayoutForBrowsables = getTargetIntent() == null
-                ? false
-                : isHttpSchemeAndViewAction(getTargetIntent());
-
         mSupportsAlwaysUseOption = supportsAlwaysUseOption;
         mWorkProfileUserHandle = fetchWorkProfileUserProfile();
 
@@ -450,7 +454,6 @@
                 initialIntents,
                 rList,
                 filterLastUsed,
-                mUseLayoutForBrowsables,
                 /* userHandle */ UserHandle.of(UserHandle.myUserId()));
         return new ResolverMultiProfilePagerAdapter(
                 /* context */ this,
@@ -475,6 +478,10 @@
                 selectedProfile = PROFILE_WORK;
             }
         }
+        int selectedProfileExtra = getSelectedProfileExtra();
+        if (selectedProfileExtra != -1) {
+            selectedProfile = selectedProfileExtra;
+        }
         // We only show the default app for the profile of the current user. The filterLastUsed
         // flag determines whether to show a default app and that app is not shown in the
         // resolver list. So filterLastUsed should be false for the other profile.
@@ -485,7 +492,6 @@
                 rList,
                 (filterLastUsed && UserHandle.myUserId()
                         == getPersonalProfileUserHandle().getIdentifier()),
-                mUseLayoutForBrowsables,
                 /* userHandle */ getPersonalProfileUserHandle());
         UserHandle workProfileUserHandle = getWorkProfileUserHandle();
         ResolverListAdapter workAdapter = createResolverListAdapter(
@@ -495,7 +501,6 @@
                 rList,
                 (filterLastUsed && UserHandle.myUserId()
                         == workProfileUserHandle.getIdentifier()),
-                mUseLayoutForBrowsables,
                 /* userHandle */ workProfileUserHandle);
         return new ResolverMultiProfilePagerAdapter(
                 /* context */ this,
@@ -512,6 +517,25 @@
     }
 
     /**
+     * Returns {@link #PROFILE_PERSONAL} or {@link #PROFILE_WORK} if the {@link
+     * #EXTRA_SELECTED_PROFILE} extra was supplied, or {@code -1} if no extra was supplied.
+     * @throws IllegalArgumentException if the value passed to the {@link #EXTRA_SELECTED_PROFILE}
+     * extra is not {@link #PROFILE_PERSONAL} or {@link #PROFILE_WORK}
+     */
+    int getSelectedProfileExtra() {
+        int selectedProfile = -1;
+        if (getIntent().hasExtra(EXTRA_SELECTED_PROFILE)) {
+            selectedProfile = getIntent().getIntExtra(EXTRA_SELECTED_PROFILE, /* defValue = */ -1);
+            if (selectedProfile != PROFILE_PERSONAL && selectedProfile != PROFILE_WORK) {
+                throw new IllegalArgumentException(EXTRA_SELECTED_PROFILE + " has invalid value "
+                        + selectedProfile + ". Must be either ResolverActivity.PROFILE_PERSONAL or "
+                        + "ResolverActivity.PROFILE_WORK.");
+            }
+        }
+        return selectedProfile;
+    }
+
+    /**
      * 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()},
      * as there are edge cases when the intent resolver is launched in the other profile.
@@ -741,26 +765,6 @@
                 mMultiProfilePagerAdapter.getActiveListAdapter().getFilteredPosition() >= 0;
         if (title == ActionTitle.DEFAULT && defaultTitleRes != 0) {
             return getString(defaultTitleRes);
-        } else if (isHttpSchemeAndViewAction(intent)) {
-            // If the Intent's scheme is http(s) then we need to warn the user that
-            // they're giving access for the activity to open URLs from this specific host
-            String dialogTitle = null;
-            if (named && !mUseLayoutForBrowsables) {
-                dialogTitle = getString(ActionTitle.BROWSABLE_APP_TITLE_RES,
-                        mMultiProfilePagerAdapter.getActiveListAdapter().getFilteredItem()
-                                .getDisplayLabel());
-            } else if (named && mUseLayoutForBrowsables) {
-                dialogTitle = getString(ActionTitle.BROWSABLE_HOST_APP_TITLE_RES,
-                        intent.getData().getHost(),
-                        mMultiProfilePagerAdapter.getActiveListAdapter().getFilteredItem()
-                                .getDisplayLabel());
-            } else if (mMultiProfilePagerAdapter.getActiveListAdapter().areAllTargetsBrowsers()) {
-                dialogTitle = getString(ActionTitle.BROWSABLE_TITLE_RES);
-            } else {
-                dialogTitle = getString(ActionTitle.BROWSABLE_HOST_TITLE_RES,
-                        intent.getData().getHost());
-            }
-            return dialogTitle;
         } else {
             return named
                     ? getString(title.namedTitleRes, mMultiProfilePagerAdapter
@@ -873,12 +877,6 @@
         mMultiProfilePagerAdapter.clearInactiveProfileCache();
     }
 
-    private boolean isHttpSchemeAndViewAction(Intent intent) {
-        return (IntentFilter.SCHEME_HTTP.equals(intent.getScheme())
-                || IntentFilter.SCHEME_HTTPS.equals(intent.getScheme()))
-                && Intent.ACTION_VIEW.equals(intent.getAction());
-    }
-
     private boolean hasManagedProfile() {
         UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
         if (userManager == null) {
@@ -929,13 +927,9 @@
             } else {
                 enabled = true;
             }
-            if (mUseLayoutForBrowsables && !ri.handleAllWebDataURI) {
-                mAlwaysButton.setText(getResources()
-                        .getString(R.string.activity_resolver_set_always));
-            } else {
-                mAlwaysButton.setText(getResources()
-                        .getString(R.string.activity_resolver_use_always));
-            }
+
+            mAlwaysButton.setText(getResources()
+                    .getString(R.string.activity_resolver_use_always));
         }
 
         if (ri != null) {
@@ -965,31 +959,7 @@
                 ? currentListAdapter.getFilteredPosition()
                 : listView.getCheckedItemPosition();
         boolean hasIndexBeenFiltered = !currentListAdapter.hasFilteredItem();
-        ResolveInfo ri = currentListAdapter.resolveInfoForPosition(which, hasIndexBeenFiltered);
-        if (mUseLayoutForBrowsables
-                && !ri.handleAllWebDataURI && id == R.id.button_always) {
-            showSettingsForSelected(ri);
-        } else {
-            startSelected(which, id == R.id.button_always, hasIndexBeenFiltered);
-        }
-    }
-
-    private void showSettingsForSelected(ResolveInfo ri) {
-        Intent intent = new Intent();
-
-        final String packageName = ri.activityInfo.packageName;
-        Bundle showFragmentArgs = new Bundle();
-        showFragmentArgs.putString(EXTRA_FRAGMENT_ARG_KEY, OPEN_LINKS_COMPONENT_KEY);
-        showFragmentArgs.putString("package", packageName);
-
-        // For regular apps, we open the Open by Default page
-        intent.setAction(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS)
-                .setData(Uri.fromParts("package", packageName, null))
-                .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
-                .putExtra(EXTRA_FRAGMENT_ARG_KEY, OPEN_LINKS_COMPONENT_KEY)
-                .putExtra(EXTRA_SHOW_FRAGMENT_ARGS, showFragmentArgs);
-
-        startActivity(intent);
+        startSelected(which, id == R.id.button_always, hasIndexBeenFiltered);
     }
 
     public void startSelected(int which, boolean always, boolean hasIndexBeenFiltered) {
@@ -1381,12 +1351,12 @@
     @VisibleForTesting
     protected ResolverListAdapter createResolverListAdapter(Context context,
             List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
-            boolean filterLastUsed, boolean useLayoutForBrowsables, UserHandle userHandle) {
+            boolean filterLastUsed, UserHandle userHandle) {
         Intent startIntent = getIntent();
         boolean isAudioCaptureDevice =
                 startIntent.getBooleanExtra(EXTRA_IS_AUDIO_CAPTURE_DEVICE, false);
         return new ResolverListAdapter(context, payloadIntents, initialIntents, rList,
-                filterLastUsed, createListController(userHandle), useLayoutForBrowsables, this,
+                filterLastUsed, createListController(userHandle), this,
                 isAudioCaptureDevice);
     }
 
@@ -1760,7 +1730,7 @@
         listView.setOnItemClickListener(listener);
         listView.setOnItemLongClickListener(listener);
 
-        if (mSupportsAlwaysUseOption || mUseLayoutForBrowsables) {
+        if (mSupportsAlwaysUseOption) {
             listView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
         }
     }
@@ -1801,7 +1771,7 @@
     }
 
     protected void resetButtonBar() {
-        if (!mSupportsAlwaysUseOption && !mUseLayoutForBrowsables) {
+        if (!mSupportsAlwaysUseOption) {
             return;
         }
         final ViewGroup buttonLayout = findViewById(R.id.button_bar);
diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java
index d942e85..97f43d27 100644
--- a/core/java/com/android/internal/app/ResolverListAdapter.java
+++ b/core/java/com/android/internal/app/ResolverListAdapter.java
@@ -69,13 +69,11 @@
     private final PackageManager mPm;
     protected final Context mContext;
     private final ColorMatrixColorFilter mSuspendedMatrixColorFilter;
-    private final boolean mUseLayoutForBrowsables;
     private final int mIconDpi;
     protected ResolveInfo mLastChosen;
     private DisplayResolveInfo mOtherProfile;
     ResolverListController mResolverListController;
     private int mPlaceholderCount;
-    private boolean mAllTargetsAreBrowsers = false;
 
     protected final LayoutInflater mInflater;
 
@@ -94,7 +92,6 @@
             Intent[] initialIntents, List<ResolveInfo> rList,
             boolean filterLastUsed,
             ResolverListController resolverListController,
-            boolean useLayoutForBrowsables,
             ResolverListCommunicator resolverListCommunicator,
             boolean isAudioCaptureDevice) {
         mContext = context;
@@ -107,7 +104,6 @@
         mFilterLastUsed = filterLastUsed;
         mResolverListController = resolverListController;
         mSuspendedMatrixColorFilter = createSuspendedColorMatrix();
-        mUseLayoutForBrowsables = useLayoutForBrowsables;
         mResolverListCommunicator = resolverListCommunicator;
         mIsAudioCaptureDevice = isAudioCaptureDevice;
         final ActivityManager am = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE);
@@ -183,14 +179,6 @@
     }
 
     /**
-     * @return true if all items in the display list are defined as browsers by
-     *         ResolveInfo.handleAllWebDataURI
-     */
-    public boolean areAllTargetsBrowsers() {
-        return mAllTargetsAreBrowsers;
-    }
-
-    /**
      * Rebuild the list of resolvers. In some cases some parts will need some asynchronous work
      * to complete.
      *
@@ -207,7 +195,6 @@
         mOtherProfile = null;
         mLastChosen = null;
         mLastChosenPosition = -1;
-        mAllTargetsAreBrowsers = false;
         mDisplayList.clear();
         mIsTabLoaded = false;
 
@@ -322,8 +309,6 @@
             boolean doPostProcessing) {
         int n;
         if (sortedComponents != null && (n = sortedComponents.size()) != 0) {
-            mAllTargetsAreBrowsers = mUseLayoutForBrowsables;
-
             // First put the initial items at the top.
             if (mInitialIntents != null) {
                 for (int i = 0; i < mInitialIntents.length; i++) {
@@ -353,7 +338,6 @@
                         ri.noResourceId = true;
                         ri.icon = 0;
                     }
-                    mAllTargetsAreBrowsers &= ri.handleAllWebDataURI;
 
                     addResolveInfo(new DisplayResolveInfo(ii, ri,
                             ri.loadLabel(mPm), null, ii, makePresentationGetter(ri)));
@@ -364,7 +348,6 @@
             for (ResolvedComponentInfo rci : sortedComponents) {
                 final ResolveInfo ri = rci.getResolveInfoAt(0);
                 if (ri != null) {
-                    mAllTargetsAreBrowsers &= ri.handleAllWebDataURI;
                     addResolveInfoWithAlternates(rci);
                 }
             }
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index 02cf25a..476198b 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -506,7 +506,8 @@
         }
 
         for (int i = 0; i < apkPaths.length; i++) {
-            if (!incrementalStorage.configureNativeBinaries(apkPaths[i], libRelativeDir, abi)) {
+            if (!incrementalStorage.configureNativeBinaries(apkPaths[i], libRelativeDir, abi,
+                    handle.extractNativeLibs)) {
                 return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
             }
         }
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index 829bd8a..8ea5aa8 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -136,13 +136,19 @@
     public boolean isMetered = false;                            // 21
     public int maxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT;      // 22
     public boolean areAuthParamsInline = false;                  // 23
+    public final boolean isRestrictedToTestNetworks;             // 24
 
     // Helper fields.
     @UnsupportedAppUsage
     public transient boolean saveLogin = false;
 
     public VpnProfile(String key) {
+        this(key, false);
+    }
+
+    public VpnProfile(String key, boolean isRestrictedToTestNetworks) {
         this.key = key;
+        this.isRestrictedToTestNetworks = isRestrictedToTestNetworks;
     }
 
     @UnsupportedAppUsage
@@ -171,6 +177,7 @@
         isMetered = in.readBoolean();
         maxMtu = in.readInt();
         areAuthParamsInline = in.readBoolean();
+        isRestrictedToTestNetworks = in.readBoolean();
     }
 
     /**
@@ -220,6 +227,7 @@
         out.writeBoolean(isMetered);
         out.writeInt(maxMtu);
         out.writeBoolean(areAuthParamsInline);
+        out.writeBoolean(isRestrictedToTestNetworks);
     }
 
     /**
@@ -237,12 +245,21 @@
             String[] values = new String(value, StandardCharsets.UTF_8).split(VALUE_DELIMITER, -1);
             // Acceptable numbers of values are:
             // 14-19: Standard profile, with option for serverCert, proxy
-            // 24: Standard profile with serverCert, proxy and platform-VPN parameters.
-            if ((values.length < 14 || values.length > 19) && values.length != 24) {
+            // 24: Standard profile with serverCert, proxy and platform-VPN parameters
+            // 25: Standard profile with platform-VPN parameters and isRestrictedToTestNetworks
+            if ((values.length < 14 || values.length > 19)
+                    && values.length != 24 && values.length != 25) {
                 return null;
             }
 
-            VpnProfile profile = new VpnProfile(key);
+            final boolean isRestrictedToTestNetworks;
+            if (values.length >= 25) {
+                isRestrictedToTestNetworks = Boolean.parseBoolean(values[24]);
+            } else {
+                isRestrictedToTestNetworks = false;
+            }
+
+            VpnProfile profile = new VpnProfile(key, isRestrictedToTestNetworks);
             profile.name = values[0];
             profile.type = Integer.parseInt(values[1]);
             if (profile.type < 0 || profile.type > TYPE_MAX) {
@@ -283,6 +300,8 @@
                 profile.areAuthParamsInline = Boolean.parseBoolean(values[23]);
             }
 
+            // isRestrictedToTestNetworks (values[24]) assigned as part of the constructor
+
             profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty();
             return profile;
         } catch (Exception e) {
@@ -330,6 +349,7 @@
         builder.append(VALUE_DELIMITER).append(isMetered);
         builder.append(VALUE_DELIMITER).append(maxMtu);
         builder.append(VALUE_DELIMITER).append(areAuthParamsInline);
+        builder.append(VALUE_DELIMITER).append(isRestrictedToTestNetworks);
 
         return builder.toString().getBytes(StandardCharsets.UTF_8);
     }
@@ -421,7 +441,8 @@
         return Objects.hash(
             key, type, server, username, password, dnsServers, searchDomains, routes, mppe,
             l2tpSecret, ipsecIdentifier, ipsecSecret, ipsecUserCert, ipsecCaCert, ipsecServerCert,
-            proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline);
+            proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline,
+            isRestrictedToTestNetworks);
     }
 
     /** Checks VPN profiles for interior equality. */
@@ -453,7 +474,8 @@
                 && isBypassable == other.isBypassable
                 && isMetered == other.isMetered
                 && maxMtu == other.maxMtu
-                && areAuthParamsInline == other.areAuthParamsInline;
+                && areAuthParamsInline == other.areAuthParamsInline
+                && isRestrictedToTestNetworks == other.isRestrictedToTestNetworks;
     }
 
     @NonNull
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 415e210..5a1af84 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -9875,6 +9875,10 @@
         mPlatformIdleStateCallback = cb;
         mRailEnergyDataCallback = railStatsCb;
         mUserInfoProvider = userInfoProvider;
+
+        // Notify statsd that the system is initially not in doze.
+        mDeviceIdleMode = DEVICE_IDLE_MODE_OFF;
+        FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mDeviceIdleMode);
     }
 
     @UnsupportedAppUsage
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 762895b..023197b 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -695,6 +695,8 @@
     }
     optional Notification notification = 82;
 
+    optional SettingProto nr_nsa_tracking_screen_off_mode = 153 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
     optional SettingProto nsd_on = 83 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
     message Ntp {
@@ -1060,5 +1062,5 @@
 
     // Please insert fields in alphabetical order and group them into messages
     // if possible (to avoid reaching the method limit).
-    // Next tag = 153;
+    // Next tag = 154;
 }
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index cb65f7c..1379ea7 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1091,7 +1091,7 @@
     <string name="elapsed_time_short_format_h_mm_ss" msgid="2302144714803345056">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
     <string name="selectAll" msgid="1532369154488982046">"အားလုံးရွေးရန်"</string>
     <string name="cut" msgid="2561199725874745819">"ဖြတ်ခြင်း"</string>
-    <string name="copy" msgid="5472512047143665218">"ကူးခြင်း"</string>
+    <string name="copy" msgid="5472512047143665218">"ကူးရန်"</string>
     <string name="failed_to_copy_to_clipboard" msgid="725919885138539875">"ကလစ်ဘုတ်သို့ မိတ္တူကူးခြင်း မအောင်မြင်ပါ"</string>
     <string name="paste" msgid="461843306215520225">"Paste"</string>
     <string name="paste_as_plain_text" msgid="7664800665823182587">"စာသားအတိုင်း ကူးထည့်ပါ"</string>
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index 368e307..34b6a54 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -48,5 +48,8 @@
 
     <!-- Set to true to enable the user switcher on the keyguard. -->
     <bool name="config_keyguardUserSwitcher">true</bool>
+
+    <!-- If true, show multiuser switcher by default unless the user specifically disables it. -->
+    <bool name="config_showUserSwitcherByDefault">true</bool>
 </resources>
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a205fcf..2cad9e6 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -42,7 +42,6 @@
         <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>
@@ -97,7 +96,6 @@
     <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
@@ -4311,6 +4309,10 @@
     (default 2MB) -->
     <integer name="config_notificationStripRemoteViewSizeBytes">5000000</integer>
 
+    <!-- List of packages that can use the Conversation space for their category messages
+    notifications until they target R -->
+    <string-array name="config_notificationMsgPkgsAllowedAsConvos" translatable="false"/>
+
     <!-- Contains a blacklist of apps that should not get pre-installed carrier app permission
          grants, even if the UICC claims that the app should be privileged. See b/138150105 -->
     <string-array name="config_restrictedPreinstalledCarrierApps" translatable="false"/>
@@ -4444,6 +4446,9 @@
     <!-- Set to true to enable the user switcher on the keyguard. -->
     <bool name="config_keyguardUserSwitcher">false</bool>
 
+    <!-- If true, show multiuser switcher by default unless the user specifically disables it. -->
+    <bool name="config_showUserSwitcherByDefault">false</bool>
+
     <!-- Set to true to make assistant show in front of the dream/screensaver. -->
     <bool name="config_assistantOnTopOfDream">false</bool>
 
@@ -4451,4 +4456,11 @@
     <bool name="config_pdp_reject_enable_retry">false</bool>
     <!-- pdp data reject retry delay in ms -->
     <integer name="config_pdp_reject_retry_delay_ms">-1</integer>
+
+    <!-- Package name that is recognized as an actor for the packages listed in
+         @array/config_overlayableConfiguratorTargets. If an overlay targeting one of the listed
+         targets is signed with the same signature as the configurator, the overlay will be granted
+         the "actor" policy. -->
+    <string name="config_overlayableConfigurator" translatable="false" />
+    <string-array name="config_overlayableConfiguratorTargets" translatable="false" />
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 233f72ea..dc21e87 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -456,12 +456,12 @@
         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.
+        <xliff:g id="time" example="5:20 PM">%2$s</xliff:g>. Your IT admin doesn\u2019t allow your
+        work profile to 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>
+    <string name="personal_apps_suspended_turn_profile_on">Turn on</string>
 
     <!-- Display name for any time a piece of data refers to the owner of the phone. For example, this could be used in place of the phone's phone number. -->
     <string name="me">Me</string>
@@ -4138,17 +4138,9 @@
     <string name="activity_resolver_use_always">Always</string>
 
     <!-- Title for a button to choose the currently selected activity
-         as the default in the activity resolver. [CHAR LIMIT=50] -->
-    <string name="activity_resolver_set_always">Set to always open</string>
-
-    <!-- Title for a button to choose the currently selected activity
          from the activity resolver to use just this once. [CHAR LIMIT=25] -->
     <string name="activity_resolver_use_once">Just once</string>
 
-    <!-- Title for a button to choose to go to
-          'Open by Default' app settings. [CHAR LIMIT=25] -->
-    <string name="activity_resolver_app_settings">Settings</string>
-
     <!-- Text for the toast that is shown when the user clicks on a launcher that
          doesn't support the work profile. [CHAR LIMIT=100] -->
     <string name="activity_resolver_work_profiles_support">%1$s doesn\'t support work profile</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 758a4f7..2c0959b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2552,7 +2552,6 @@
   <java-symbol type="bool" name="config_allow_ussd_over_ims" />
   <java-symbol type="attr" name="touchscreenBlocksFocus" />
   <java-symbol type="layout" name="resolver_list_with_default" />
-  <java-symbol type="string" name="activity_resolver_set_always" />
   <java-symbol type="string" name="activity_resolver_use_always" />
   <java-symbol type="string" name="whichApplicationNamed" />
   <java-symbol type="string" name="whichApplicationLabel" />
@@ -2916,7 +2915,6 @@
   <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" />
@@ -4006,6 +4004,9 @@
   <!-- Set to true to enable the user switcher on the keyguard. -->
   <java-symbol type="bool" name="config_keyguardUserSwitcher" />
 
+  <!-- If true, show multiuser switcher by default unless the user specifically disables it. -->
+  <java-symbol type="bool" name="config_showUserSwitcherByDefault" />
+
   <!-- Set to true to make assistant show in front of the dream/screensaver. -->
   <java-symbol type="bool" name="config_assistantOnTopOfDream"/>
 
@@ -4025,4 +4026,8 @@
   <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" />
 
+  <java-symbol type="string" name="config_overlayableConfigurator" />
+  <java-symbol type="array" name="config_overlayableConfiguratorTargets" />
+
+  <java-symbol type="array" name="config_notificationMsgPkgsAllowedAsConvos" />
 </resources>
diff --git a/core/tests/InstantAppResolverTests/Android.bp b/core/tests/InstantAppResolverTests/Android.bp
deleted file mode 100644
index 7b01010..0000000
--- a/core/tests/InstantAppResolverTests/Android.bp
+++ /dev/null
@@ -1,32 +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.
-//
-
-android_test {
-    name: "FrameworksInstantAppResolverTests",
-    srcs: [ "src/**/*.kt" ],
-    libs: [
-        "android.test.runner",
-        "android.test.base",
-    ],
-    platform_apis: true,
-    static_libs: [
-        "androidx.test.ext.junit",
-        "androidx.test.rules",
-        "mockito-target-minus-junit4",
-        "truth-prebuilt",
-    ],
-    test_suites: ["device-tests"],
-}
diff --git a/core/tests/InstantAppResolverTests/AndroidManifest.xml b/core/tests/InstantAppResolverTests/AndroidManifest.xml
deleted file mode 100644
index f95978b..0000000
--- a/core/tests/InstantAppResolverTests/AndroidManifest.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.
-  -->
-
-<manifest
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.app.instantapp.resolver.test"
-    >
-
-    <application>
-        <uses-library android:name="android.test.runner"/>
-    </application>
-
-    <instrumentation
-        android:name="androidx.test.runner.AndroidJUnitRunner"
-        android:label="InstantAppResolverTests"
-        android:targetPackage="android.app.instantapp.resolver.test"
-        />
-
-</manifest>
diff --git a/core/tests/InstantAppResolverTests/AndroidTest.xml b/core/tests/InstantAppResolverTests/AndroidTest.xml
deleted file mode 100644
index fcc6344..0000000
--- a/core/tests/InstantAppResolverTests/AndroidTest.xml
+++ /dev/null
@@ -1,29 +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.
-  -->
-
-<configuration description="Test module config for InstantAppResolverTests">
-    <option name="test-tag" value="InstantAppResolverTests" />
-
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
-        <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="FrameworksInstantAppResolverTests.apk" />
-    </target_preparer>
-
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
-        <option name="package" value="android.app.instantapp.resolver.test" />
-    </test>
-</configuration>
diff --git a/core/tests/InstantAppResolverTests/src/android/app/instantapp/resolver/test/ResolverServiceMethodFallbackTest.kt b/core/tests/InstantAppResolverTests/src/android/app/instantapp/resolver/test/ResolverServiceMethodFallbackTest.kt
deleted file mode 100644
index 2a17ef2..0000000
--- a/core/tests/InstantAppResolverTests/src/android/app/instantapp/resolver/test/ResolverServiceMethodFallbackTest.kt
+++ /dev/null
@@ -1,174 +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 android.app.instantapp.resolver.test
-
-import android.app.InstantAppResolverService
-import android.app.InstantAppResolverService.InstantAppResolutionCallback
-import android.content.Intent
-import android.content.pm.InstantAppRequestInfo
-import android.net.Uri
-import android.os.Bundle
-import android.os.IRemoteCallback
-import android.os.UserHandle
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.rules.ExpectedException
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-import org.mockito.Answers
-import org.mockito.Mock
-import org.mockito.Mockito.doNothing
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyNoMoreInteractions
-import org.mockito.MockitoAnnotations
-import java.util.UUID
-import kotlin.random.Random
-
-private typealias Method = InstantAppResolverService.(InstantAppRequestInfo) -> Unit
-
-@Suppress("max-line-length")
-@RunWith(Parameterized::class)
-class ResolverServiceMethodFallbackTest @Suppress("UNUSED_PARAMETER") constructor(
-    private val version: Int,
-    private val methodList: List<Method>,
-    private val info: InstantAppRequestInfo,
-    // Remaining only used to print human-readable test name
-    name: String,
-    isWebIntent: Boolean
-) {
-
-    companion object {
-        // Since the resolution callback class is final, mock the IRemoteCallback and have it throw
-        // a unique exception to indicate it was called.
-        class TestRemoteCallbackException : Exception()
-
-        private val testIntentWeb = Intent(Intent.ACTION_VIEW,
-                Uri.parse("https://${this::class.java.canonicalName}.com"))
-        private val testIntentNotWeb = Intent(Intent.ACTION_VIEW,
-                Uri.parse("content://${this::class.java.canonicalName}"))
-
-        private val testRemoteCallback = object : IRemoteCallback {
-            override fun sendResult(data: Bundle?) = throw TestRemoteCallbackException()
-            override fun asBinder() = throw UnsupportedOperationException()
-        }
-        private val testResolutionCallback = InstantAppResolutionCallback(0, testRemoteCallback)
-        private val testArray = IntArray(10) { Random.nextInt() }
-        private val testToken = UUID.randomUUID().toString()
-        private val testUser = UserHandle(Integer.MAX_VALUE)
-        private val testInfoWeb = InstantAppRequestInfo(testIntentWeb, testArray, testUser,
-                false, testToken)
-        private val testInfoNotWeb = InstantAppRequestInfo(testIntentNotWeb, testArray, testUser,
-                false, testToken)
-
-        // Each section defines methods versions with later definitions falling back to
-        // earlier definitions. Each block receives an [InstantAppResolverService] and invokes
-        // the appropriate version with the test data defined above.
-        private val infoOne: Method = { onGetInstantAppResolveInfo(testArray, testToken,
-                testResolutionCallback) }
-        private val infoTwo: Method = { onGetInstantAppResolveInfo(it.intent, testArray, testToken,
-                testResolutionCallback) }
-        private val infoThree: Method = { onGetInstantAppResolveInfo(it.intent, testArray, testUser,
-                testToken, testResolutionCallback) }
-        private val infoFour: Method = { onGetInstantAppResolveInfo(it, testResolutionCallback) }
-
-        private val filterOne: Method = { onGetInstantAppIntentFilter(testArray, testToken,
-                testResolutionCallback) }
-        private val filterTwo: Method = { onGetInstantAppIntentFilter(it.intent, testArray,
-                testToken, testResolutionCallback) }
-        private val filterThree: Method = { onGetInstantAppIntentFilter(it.intent, testArray,
-                testUser, testToken, testResolutionCallback) }
-        private val filterFour: Method = { onGetInstantAppIntentFilter(it, testResolutionCallback) }
-
-        private val infoList = listOf(infoOne, infoTwo, infoThree, infoFour)
-        private val filterList = listOf(filterOne, filterTwo, filterThree, filterFour)
-
-        @JvmStatic
-        @Parameterized.Parameters(name = "{3} version {0}, isWeb = {4}")
-        fun parameters(): Array<Array<*>> {
-            // Sanity check that web intent logic hasn't changed
-            assertThat(testInfoWeb.intent.isWebIntent).isTrue()
-            assertThat(testInfoNotWeb.intent.isWebIntent).isFalse()
-
-            // Declare all the possible params
-            val versions = Array(5) { it }
-            val methods = arrayOf("ResolveInfo" to infoList, "IntentFilter" to filterList)
-            val infos = arrayOf(testInfoWeb, testInfoNotWeb)
-
-            // FlatMap params into every possible combination
-            return infos.flatMap { info ->
-                methods.flatMap { (name, methods) ->
-                    versions.map { version ->
-                        arrayOf(version, methods, info, name, info.intent.isWebIntent)
-                    }
-                }
-            }.toTypedArray()
-        }
-    }
-
-    @field:Mock(answer = Answers.CALLS_REAL_METHODS)
-    lateinit var mockService: InstantAppResolverService
-
-    @get:Rule
-    val expectedException = ExpectedException.none()
-
-    @Before
-    fun setUpMocks() {
-        MockitoAnnotations.initMocks(this)
-    }
-
-    @Test
-    fun onGetInstantApp() {
-        if (version == 0) {
-            // No version of the API was implemented, so expect terminal case
-            if (info.intent.isWebIntent) {
-                // If web intent, terminal is total failure
-                expectedException.expect(IllegalStateException::class.java)
-            } else {
-                // Otherwise, terminal is a fail safe by calling [testRemoteCallback]
-                expectedException.expect(TestRemoteCallbackException::class.java)
-            }
-        } else if (version < 2 && !info.intent.isWebIntent) {
-            // Starting from v2, if resolving a non-web intent and a v2+ method isn't implemented,
-            // it fails safely by calling [testRemoteCallback]
-            expectedException.expect(TestRemoteCallbackException::class.java)
-        }
-
-        // Version 1 is the first method (index 0)
-        val methodIndex = version - 1
-
-        // Implement a method if necessary
-        methodList.getOrNull(methodIndex)?.invoke(doNothing().`when`(mockService), info)
-
-        // Call the latest API
-        methodList.last().invoke(mockService, info)
-
-        // Check all methods before implemented method are never called
-        (0 until methodIndex).forEach {
-            methodList[it].invoke(verify(mockService, never()), info)
-        }
-
-        // Check all methods from implemented method are called
-        (methodIndex until methodList.size).forEach {
-            methodList[it].invoke(verify(mockService), info)
-        }
-
-        verifyNoMoreInteractions(mockService)
-    }
-}
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 2884777..daaf31a 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -20,6 +20,8 @@
 import static android.view.InsetsState.ISIDE_TOP;
 import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES;
 import static android.view.InsetsState.ITYPE_CAPTION_BAR;
+import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
+import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_IME;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
@@ -183,6 +185,38 @@
     }
 
     @Test
+    public void testCalculateInsets_extraNavRightStatusTop() throws Exception {
+        try (InsetsModeSession session =
+                     new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+            mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+            mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
+            mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
+            mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setVisible(true);
+            WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
+                    false, DisplayCutout.NO_CUTOUT, 0, 0, null);
+            assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
+            assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars()));
+            assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars()));
+        }
+    }
+
+    @Test
+    public void testCalculateInsets_navigationRightClimateTop() throws Exception {
+        try (InsetsModeSession session =
+                     new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+            mState.getSource(ITYPE_CLIMATE_BAR).setFrame(new Rect(0, 0, 100, 100));
+            mState.getSource(ITYPE_CLIMATE_BAR).setVisible(true);
+            mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
+            mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
+            WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
+                    false, DisplayCutout.NO_CUTOUT, 0, 0, null);
+            assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
+            assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars()));
+            assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars()));
+        }
+    }
+
+    @Test
     public void testStripForDispatch() {
         mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
         mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index 071b225..749b0e5 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -61,12 +61,12 @@
     @Override
     public ChooserListAdapter createChooserListAdapter(Context context, List<Intent> payloadIntents,
             Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed,
-            boolean useLayoutForBrowsables, ResolverListController resolverListController) {
+            ResolverListController resolverListController) {
         PackageManager packageManager =
                 sOverrides.packageManager == null ? context.getPackageManager()
                         : sOverrides.packageManager;
         return new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
-                filterLastUsed, resolverListController, useLayoutForBrowsables,
+                filterLastUsed, resolverListController,
                 this, this, packageManager);
     }
 
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
index 2087104..0c009a0 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
@@ -42,9 +42,9 @@
     @Override
     public ResolverListAdapter createResolverListAdapter(Context context,
             List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
-            boolean filterLastUsed, boolean useLayoutForBrowsables, UserHandle userHandle) {
+            boolean filterLastUsed, UserHandle userHandle) {
         return new ResolverWrapperAdapter(context, payloadIntents, initialIntents, rList,
-                filterLastUsed, createListController(userHandle), useLayoutForBrowsables, this);
+                filterLastUsed, createListController(userHandle), this);
     }
 
     @Override
@@ -166,4 +166,4 @@
             };
         }
     }
-}
\ No newline at end of file
+}
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java
index a2191b5..56a7070 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java
@@ -35,11 +35,10 @@
             List<Intent> payloadIntents,
             Intent[] initialIntents,
             List<ResolveInfo> rList, boolean filterLastUsed,
-            ResolverListController resolverListController, boolean useLayoutForBrowsables,
+            ResolverListController resolverListController,
             ResolverListCommunicator resolverListCommunicator) {
         super(context, payloadIntents, initialIntents, rList, filterLastUsed,
-                resolverListController,
-                useLayoutForBrowsables, resolverListCommunicator, false);
+                resolverListController, resolverListCommunicator, false);
     }
 
     public CountingIdlingResource getLabelIdlingResource() {
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 9cd7cc6..cf31216 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -249,6 +249,7 @@
     <allow-in-data-usage-save package="com.android.providers.downloads" />
 
     <!-- This is a core platform component that needs to freely run in the background -->
+    <allow-in-power-save package="com.android.cellbroadcastreceiver.module" />
     <allow-in-power-save package="com.android.cellbroadcastreceiver" />
     <allow-in-power-save package="com.android.shell" />
 
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index bdb6bcc..16851cf 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -40,7 +40,7 @@
         <permission name="android.permission.CRYPT_KEEPER"/>
     </privapp-permissions>
 
-    <privapp-permissions package="com.android.cellbroadcastreceiver">
+    <privapp-permissions package="com.android.cellbroadcastreceiver.module">
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.MANAGE_USERS"/>
         <permission name="android.permission.MODIFY_PHONE_STATE"/>
@@ -409,6 +409,8 @@
         <permission name="android.permission.ACCESS_TV_DESCRAMBLER" />
         <permission name="android.permission.ACCESS_TV_TUNER" />
         <permission name="android.permission.TUNER_RESOURCE_ACCESS" />
+        <!-- Permissions required for CTS test - TVInputManagerTest -->
+        <permission name="android.permission.TV_INPUT_HARDWARE" />
     </privapp-permissions>
 
     <privapp-permissions package="com.android.statementservice">
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index b5c19a8..bfc623f 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -253,6 +253,12 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/DisplayRotation.java"
     },
+    "-1554521902": {
+      "message": "showInsets(ime) was requested by different window: %s ",
+      "level": "WARN",
+      "group": "WM_DEBUG_IME",
+      "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java"
+    },
     "-1545962566": {
       "message": "View server did not start",
       "level": "WARN",
@@ -367,6 +373,12 @@
       "group": "WM_DEBUG_STARTING_WINDOW",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
+    "-1312861660": {
+      "message": "notifyInsetsControlChanged for %s ",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_IME",
+      "at": "com\/android\/server\/wm\/WindowState.java"
+    },
     "-1292329638": {
       "message": "Added starting %s: startingWindow=%s startingView=%s",
       "level": "VERBOSE",
@@ -817,6 +829,12 @@
       "group": "WM_DEBUG_STARTING_WINDOW",
       "at": "com\/android\/server\/wm\/TaskSnapshotSurface.java"
     },
+    "-395922585": {
+      "message": "InsetsSource setWin %s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_IME",
+      "at": "com\/android\/server\/wm\/InsetsSourceProvider.java"
+    },
     "-393505149": {
       "message": "unable to update pointer icon",
       "level": "WARN",
@@ -859,6 +877,12 @@
       "group": "WM_SHOW_TRANSACTIONS",
       "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
     },
+    "-322743468": {
+      "message": "setInputMethodInputTarget %s",
+      "level": "INFO",
+      "group": "WM_DEBUG_IME",
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
     "-322035974": {
       "message": "App freeze timeout expired.",
       "level": "WARN",
@@ -925,6 +949,12 @@
       "group": "WM_DEBUG_SCREEN_ON",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-112805366": {
+      "message": "InsetsSource updateVisibility serverVisible: %s clientVisible: %s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_IME",
+      "at": "com\/android\/server\/wm\/InsetsSourceProvider.java"
+    },
     "-106400104": {
       "message": "Preload recents with %s",
       "level": "DEBUG",
@@ -1003,6 +1033,12 @@
       "group": "WM_DEBUG_RECENTS_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
     },
+    "29780972": {
+      "message": "InsetsSource Control %s for target %s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_IME",
+      "at": "com\/android\/server\/wm\/InsetsSourceProvider.java"
+    },
     "38267433": {
       "message": "Attempted to reset replacing window on non-existing app token %s",
       "level": "WARN",
@@ -1027,6 +1063,18 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "73987756": {
+      "message": "ControlAdapter onAnimationCancelled mSource: %s mControlTarget: %s",
+      "level": "INFO",
+      "group": "WM_DEBUG_IME",
+      "at": "com\/android\/server\/wm\/InsetsSourceProvider.java"
+    },
+    "75707221": {
+      "message": "ControlAdapter startAnimation mSource: %s controlTarget: %s",
+      "level": "INFO",
+      "group": "WM_DEBUG_IME",
+      "at": "com\/android\/server\/wm\/InsetsSourceProvider.java"
+    },
     "83950285": {
       "message": "removeAnimation(%d)",
       "level": "DEBUG",
@@ -1285,12 +1333,6 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "438102669": {
-      "message": "call showInsets(ime) on %s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_IME",
-      "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java"
-    },
     "457951957": {
       "message": "\tNot visible=%s",
       "level": "DEBUG",
@@ -1369,6 +1411,12 @@
       "group": "WM_SHOW_TRANSACTIONS",
       "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
     },
+    "585839596": {
+      "message": "call showInsets(ime) on %s",
+      "level": "INFO",
+      "group": "WM_DEBUG_IME",
+      "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java"
+    },
     "594260577": {
       "message": "createWallpaperAnimations()",
       "level": "DEBUG",
@@ -1873,6 +1921,12 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
+    "1533154777": {
+      "message": "notifyInsetsChanged for %s ",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_IME",
+      "at": "com\/android\/server\/wm\/WindowState.java"
+    },
     "1563755163": {
       "message": "Permission Denial: %s from pid=%d, uid=%d requires %s",
       "level": "WARN",
@@ -1897,6 +1951,12 @@
       "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
       "at": "com\/android\/server\/wm\/AppTransition.java"
     },
+    "1591969812": {
+      "message": "updateImeControlTarget %s",
+      "level": "INFO",
+      "group": "WM_DEBUG_IME",
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
     "1628345525": {
       "message": "Now opening app %s",
       "level": "VERBOSE",
@@ -1927,6 +1987,12 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
+    "1658605381": {
+      "message": "onImeControlTargetChanged %s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_IME",
+      "at": "com\/android\/server\/wm\/InsetsStateController.java"
+    },
     "1671994402": {
       "message": "Nulling last startingData",
       "level": "VERBOSE",
@@ -2173,6 +2239,12 @@
       "group": "WM_DEBUG_ADD_REMOVE",
       "at": "com\/android\/server\/wm\/WindowState.java"
     },
+    "2119122320": {
+      "message": "setInputMethodTarget %s",
+      "level": "INFO",
+      "group": "WM_DEBUG_IME",
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
     "2128604122": {
       "message": "findFocusedWindow: No focusable windows.",
       "level": "VERBOSE",
diff --git a/data/sounds/AudioTv.mk b/data/sounds/AudioTv.mk
index 2a31e4c..fd53aff 100644
--- a/data/sounds/AudioTv.mk
+++ b/data/sounds/AudioTv.mk
@@ -16,6 +16,7 @@
 
 PRODUCT_COPY_FILES += \
     $(LOCAL_PATH)/Alarm_Beep_01.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/alarms/Alarm_Beep_02.ogg \
+    $(LOCAL_PATH)/effects/ogg/Effect_Tick_48k.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/Effect_Tick.ogg \
     $(LOCAL_PATH)/effects/ogg/KeypressDelete_120_48k.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/KeypressDelete.ogg \
     $(LOCAL_PATH)/effects/ogg/KeypressInvalid_120_48k.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/KeypressInvalid.ogg \
     $(LOCAL_PATH)/effects/ogg/KeypressReturn_120_48k.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/KeypressReturn.ogg \
diff --git a/graphics/java/android/graphics/pdf/PdfDocument.java b/graphics/java/android/graphics/pdf/PdfDocument.java
index 1b8336f..58421ab 100644
--- a/graphics/java/android/graphics/pdf/PdfDocument.java
+++ b/graphics/java/android/graphics/pdf/PdfDocument.java
@@ -46,8 +46,8 @@
  * // create a new document
  * PdfDocument document = new PdfDocument();
  *
- * // crate a page description
- * PageInfo pageInfo = new PageInfo.Builder(new Rect(0, 0, 100, 100), 1).create();
+ * // create a page description
+ * PageInfo pageInfo = new PageInfo.Builder(100, 100, 1).create();
  *
  * // start a page
  * Page page = document.startPage(pageInfo);
diff --git a/libs/hwui/jni/android_graphics_Canvas.cpp b/libs/hwui/jni/android_graphics_Canvas.cpp
index 4aff3e5..b6c6cd0 100644
--- a/libs/hwui/jni/android_graphics_Canvas.cpp
+++ b/libs/hwui/jni/android_graphics_Canvas.cpp
@@ -113,7 +113,7 @@
     get_canvas(canvasHandle)->restoreUnclippedLayer(saveCount, *paint);
 }
 
-static bool restore(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle) {
+static jboolean restore(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle) {
     Canvas* canvas = get_canvas(canvasHandle);
     if (canvas->getSaveCount() <= 1) {
         return false; // cannot restore anymore
diff --git a/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp b/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp
index 8a26296..9cffceb 100644
--- a/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -102,7 +102,7 @@
 /**
  * Draw
  */
-static int draw(JNIEnv* env, jobject, jlong treePtr, jlong canvasPtr,
+static jint draw(JNIEnv* env, jobject, jlong treePtr, jlong canvasPtr,
         jlong colorFilterPtr, jobject jrect, jboolean needsMirroring, jboolean canReuseCache) {
     VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
     Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
diff --git a/libs/hwui/jni/android_util_PathParser.cpp b/libs/hwui/jni/android_util_PathParser.cpp
index df5e9cd..72995ef 100644
--- a/libs/hwui/jni/android_util_PathParser.cpp
+++ b/libs/hwui/jni/android_util_PathParser.cpp
@@ -39,18 +39,18 @@
     }
 }
 
-static long createEmptyPathData(JNIEnv*, jobject) {
+static jlong createEmptyPathData(JNIEnv*, jobject) {
     PathData* pathData = new PathData();
     return reinterpret_cast<jlong>(pathData);
 }
 
-static long createPathData(JNIEnv*, jobject, jlong pathDataPtr) {
+static jlong createPathData(JNIEnv*, jobject, jlong pathDataPtr) {
     PathData* pathData = reinterpret_cast<PathData*>(pathDataPtr);
     PathData* newPathData = new PathData(*pathData);
     return reinterpret_cast<jlong>(newPathData);
 }
 
-static long createPathDataFromStringPath(JNIEnv* env, jobject, jstring inputStr, jint strLength) {
+static jlong createPathDataFromStringPath(JNIEnv* env, jobject, jstring inputStr, jint strLength) {
     const char* pathString = env->GetStringUTFChars(inputStr, NULL);
     PathData* pathData = new PathData();
     PathParser::ParseResult result;
@@ -65,7 +65,7 @@
     }
 }
 
-static bool interpolatePathData(JNIEnv*, jobject, jlong outPathDataPtr, jlong fromPathDataPtr,
+static jboolean interpolatePathData(JNIEnv*, jobject, jlong outPathDataPtr, jlong fromPathDataPtr,
         jlong toPathDataPtr, jfloat fraction) {
     PathData* outPathData = reinterpret_cast<PathData*>(outPathDataPtr);
     PathData* fromPathData = reinterpret_cast<PathData*>(fromPathDataPtr);
@@ -79,7 +79,7 @@
     delete pathData;
 }
 
-static bool canMorphPathData(JNIEnv*, jobject, jlong fromPathDataPtr, jlong toPathDataPtr) {
+static jboolean canMorphPathData(JNIEnv*, jobject, jlong fromPathDataPtr, jlong toPathDataPtr) {
     PathData* fromPathData = reinterpret_cast<PathData*>(fromPathDataPtr);
     PathData* toPathData = reinterpret_cast<PathData*>(toPathDataPtr);
     return VectorDrawableUtils::canMorph(*fromPathData, *toPathData);
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index 508a46f4..1fbb672 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -111,4 +111,8 @@
     // For preview channels and programs
     void sendTvInputNotifyIntent(in Intent intent, int userId);
     void requestChannelBrowsable(in Uri channelUri, int userId);
+
+    // For CTS purpose only. Add/remove a TvInputHardware device
+    void addHardwareDevice(in int deviceId);
+    void removeHardwareDevice(in int deviceId);
 }
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index e701055..98a01a4 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -23,6 +23,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Rect;
@@ -1801,6 +1802,40 @@
                 executor, callback);
     }
 
+    /**
+     * API to add a hardware device in the TvInputHardwareManager for CTS testing
+     * purpose.
+     *
+     * @param deviceId Id of the adding hardware device.
+     *
+     * @hide
+     */
+    @TestApi
+    public void addHardwareDevice(int deviceId) {
+        try {
+            mService.addHardwareDevice(deviceId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * API to remove a hardware device in the TvInputHardwareManager for CTS testing
+     * purpose.
+     *
+     * @param deviceId Id of the removing hardware device.
+     *
+     * @hide
+     */
+    @TestApi
+    public void removeHardwareDevice(int deviceId) {
+        try {
+            mService.removeHardwareDevice(deviceId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     private Hardware acquireTvInputHardwareInternal(int deviceId, TvInputInfo info,
             String tvInputSessionId, int priorityHint,
             Executor executor, final HardwareCallback callback) {
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index a458b16..8bf688d 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -447,7 +447,7 @@
     private native DvrRecorder nativeOpenDvrRecorder(long bufferSize);
     private native DvrPlayback nativeOpenDvrPlayback(long bufferSize);
 
-    private static native DemuxCapabilities nativeGetDemuxCapabilities();
+    private native DemuxCapabilities nativeGetDemuxCapabilities();
 
     private native int nativeCloseDemux(int handle);
     private native int nativeCloseFrontend(int handle);
@@ -939,8 +939,7 @@
         Filter filter = nativeOpenFilter(
                 mainType, TunerUtils.getFilterSubtype(mainType, subType), bufferSize);
         if (filter != null) {
-            filter.setMainType(mainType);
-            filter.setSubtype(subType);
+            filter.setType(mainType, subType);
             filter.setCallback(cb, executor);
             if (mHandler == null) {
                 mHandler = createEventHandler();
@@ -1147,8 +1146,11 @@
     }
 
     /* package */ void releaseLnb() {
-        mTunerResourceManager.releaseLnb(mLnbHandle, mClientId);
-        mLnbHandle = null;
+        if (mLnbHandle != null) {
+            // LNB handle can be null if it's opened by name.
+            mTunerResourceManager.releaseLnb(mLnbHandle, mClientId);
+            mLnbHandle = null;
+        }
         mLnb = null;
     }
 }
diff --git a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
index 9971c84..68071b0 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
@@ -105,28 +105,33 @@
 
 
     /**
-     * Attaches a filter to DVR interface for recording.
+     * Attaches a filter to DVR interface for playback.
      *
-     * <p>There can be multiple filters attached. Attached filters are independent, so the order
-     * doesn't matter.
+     * <p>This method will be deprecated. Now it's a no-op.
+     * <p>Filters opened by {@link Tuner#openFilter} are used for DVR playback.
      *
      * @param filter the filter to be attached.
      * @return result status of the operation.
      */
     @Result
     public int attachFilter(@NonNull Filter filter) {
-        return nativeAttachFilter(filter);
+        // no-op
+        return Tuner.RESULT_UNAVAILABLE;
     }
 
     /**
      * Detaches a filter from DVR interface.
      *
+     * <p>This method will be deprecated. Now it's a no-op.
+     * <p>Filters opened by {@link Tuner#openFilter} are used for DVR playback.
+     *
      * @param filter the filter to be detached.
      * @return result status of the operation.
      */
     @Result
     public int detachFilter(@NonNull Filter filter) {
-        return nativeDetachFilter(filter);
+        // no-op
+        return Tuner.RESULT_UNAVAILABLE;
     }
 
     /**
diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java
index cc932da..f0015b7 100644
--- a/media/java/android/media/tv/tuner/filter/Filter.java
+++ b/media/java/android/media/tv/tuner/filter/Filter.java
@@ -221,12 +221,9 @@
     }
 
     /** @hide */
-    public void setMainType(@Type int mainType) {
+    public void setType(@Type int mainType, @Subtype int subtype) {
         mMainType = mainType;
-    }
-    /** @hide */
-    public void setSubtype(@Subtype int subtype) {
-        mSubtype = subtype;
+        mSubtype = TunerUtils.getFilterSubtype(mainType, subtype);
     }
 
     /** @hide */
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index fb8c276..7e72140 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -2975,7 +2975,7 @@
     jbyte *dst = env->GetByteArrayElements(buffer, &isCopy);
     ALOGD("copyData, isCopy=%d", isCopy);
     if (dst == nullptr) {
-        ALOGD("Failed to GetByteArrayElements");
+        jniThrowRuntimeException(env, "Failed to GetByteArrayElements");
         return 0;
     }
 
@@ -2983,7 +2983,7 @@
         env->ReleaseByteArrayElements(buffer, dst, 0);
         flag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
     } else {
-        ALOGD("Failed to read FMQ");
+        jniThrowRuntimeException(env, "Failed to read FMQ");
         env->ReleaseByteArrayElements(buffer, dst, 0);
         return 0;
     }
diff --git a/media/jni/soundpool/Android.bp b/media/jni/soundpool/Android.bp
index aa32793..6141308 100644
--- a/media/jni/soundpool/Android.bp
+++ b/media/jni/soundpool/Android.bp
@@ -1,5 +1,92 @@
+tidy_errors = [
+    // https://clang.llvm.org/extra/clang-tidy/checks/list.html
+    // For many categories, the checks are too many to specify individually.
+    // Feel free to disable as needed - as warnings are generally ignored,
+    // we treat warnings as errors.
+    "android-*",
+    "bugprone-*",
+    "cert-*",
+    "clang-analyzer-security*",
+    "google-*",
+    "misc-*",
+    //"modernize-*",  // explicitly list the modernize as they can be subjective.
+    "modernize-avoid-bind",
+    //"modernize-avoid-c-arrays", // std::array<> can be verbose
+    "modernize-concat-nested-namespaces",
+    //"modernize-deprecated-headers", // C headers still ok even if there is C++ equivalent.
+    "modernize-deprecated-ios-base-aliases",
+    "modernize-loop-convert",
+    "modernize-make-shared",
+    "modernize-make-unique",
+    "modernize-pass-by-value",
+    "modernize-raw-string-literal",
+    "modernize-redundant-void-arg",
+    "modernize-replace-auto-ptr",
+    "modernize-replace-random-shuffle",
+    "modernize-return-braced-init-list",
+    "modernize-shrink-to-fit",
+    "modernize-unary-static-assert",
+    "modernize-use-auto",  // debatable - auto can obscure type
+    "modernize-use-bool-literals",
+    "modernize-use-default-member-init",
+    "modernize-use-emplace",
+    "modernize-use-equals-default",
+    "modernize-use-equals-delete",
+    "modernize-use-nodiscard",
+    "modernize-use-noexcept",
+    "modernize-use-nullptr",
+    "modernize-use-override",
+    //"modernize-use-trailing-return-type", // not necessarily more readable
+    "modernize-use-transparent-functors",
+    "modernize-use-uncaught-exceptions",
+    "modernize-use-using",
+    "performance-*",
+
+    // Remove some pedantic stylistic requirements.
+    "-google-readability-casting", // C++ casts not always necessary and may be verbose
+    "-google-readability-todo",    // do not require TODO(info)
+    "-google-build-using-namespace", // Reenable and fix later.
+]
+
+cc_defaults {
+    name: "soundpool_flags_defaults",
+    // https://clang.llvm.org/docs/UsersManual.html#command-line-options
+    // https://clang.llvm.org/docs/DiagnosticsReference.html
+    cflags: [
+        "-Wall",
+        "-Wdeprecated",
+        "-Werror",
+        "-Werror=implicit-fallthrough",
+        "-Werror=sometimes-uninitialized",
+        //"-Werror=conditional-uninitialized",
+        "-Wextra",
+        "-Wredundant-decls",
+        "-Wshadow",
+        "-Wstrict-aliasing",
+        "-fstrict-aliasing",
+        "-Wthread-safety",
+        //"-Wthread-safety-negative", // experimental - looks broken in R.
+        "-Wunreachable-code",
+        "-Wunreachable-code-break",
+        "-Wunreachable-code-return",
+        "-Wunused",
+        "-Wused-but-marked-unused",
+    ],
+    // https://clang.llvm.org/extra/clang-tidy/
+    tidy: true,
+    tidy_checks: tidy_errors,
+    tidy_checks_as_errors: tidy_errors,
+    tidy_flags: [
+      "-format-style='file'",
+      "--header-filter='frameworks/base/media/jni/soundpool'",
+    ],
+}
+
 cc_library_shared {
     name: "libsoundpool",
+    defaults: [
+        "soundpool_flags_defaults",
+    ],
 
     srcs: [
         "android_media_SoundPool.cpp",
diff --git a/media/jni/soundpool/Sound.cpp b/media/jni/soundpool/Sound.cpp
index 0bbc3e4..c3abdc2 100644
--- a/media/jni/soundpool/Sound.cpp
+++ b/media/jni/soundpool/Sound.cpp
@@ -31,7 +31,7 @@
 
 Sound::Sound(int32_t soundID, int fd, int64_t offset, int64_t length)
     : mSoundID(soundID)
-    , mFd(dup(fd))
+    , mFd(fcntl(fd, F_DUPFD_CLOEXEC)) // like dup(fd) but closes on exec to prevent leaks.
     , mOffset(offset)
     , mLength(length)
 {
@@ -47,7 +47,7 @@
 
 static status_t decode(int fd, int64_t offset, int64_t length,
         uint32_t *rate, int32_t *channelCount, audio_format_t *audioFormat,
-        audio_channel_mask_t *channelMask, sp<MemoryHeapBase> heap,
+        audio_channel_mask_t *channelMask, const sp<MemoryHeapBase>& heap,
         size_t *sizeInBytes) {
     ALOGV("%s(fd=%d, offset=%lld, length=%lld, ...)",
             __func__, fd, (long long)offset, (long long)length);
@@ -81,7 +81,7 @@
 
             bool sawInputEOS = false;
             bool sawOutputEOS = false;
-            uint8_t* writePos = static_cast<uint8_t*>(heap->getBase());
+            auto writePos = static_cast<uint8_t*>(heap->getBase());
             size_t available = heap->getSize();
             size_t written = 0;
             format.reset(AMediaCodec_getOutputFormat(codec.get())); // update format.
@@ -204,7 +204,7 @@
         int32_t channelCount;
         audio_format_t format;
         audio_channel_mask_t channelMask;
-        status_t status = decode(mFd.get(), mOffset, mLength, &sampleRate, &channelCount, &format,
+        status = decode(mFd.get(), mOffset, mLength, &sampleRate, &channelCount, &format,
                         &channelMask, mHeap, &mSizeInBytes);
         ALOGV("%s: close(%d)", __func__, mFd.get());
         mFd.reset();  // close
diff --git a/media/jni/soundpool/SoundDecoder.cpp b/media/jni/soundpool/SoundDecoder.cpp
index 12200ef..6614fdb 100644
--- a/media/jni/soundpool/SoundDecoder.cpp
+++ b/media/jni/soundpool/SoundDecoder.cpp
@@ -57,7 +57,7 @@
     mThreadPool->quit();
 }
 
-void SoundDecoder::run(int32_t id __unused /* ALOGV only */)
+void SoundDecoder::run(int32_t id)
 {
     ALOGV("%s(%d): entering", __func__, id);
     std::unique_lock lock(mLock);
diff --git a/media/jni/soundpool/SoundDecoder.h b/media/jni/soundpool/SoundDecoder.h
index 1288943..7b62114 100644
--- a/media/jni/soundpool/SoundDecoder.h
+++ b/media/jni/soundpool/SoundDecoder.h
@@ -30,21 +30,22 @@
 public:
     SoundDecoder(SoundManager* soundManager, size_t threads);
     ~SoundDecoder();
-    void loadSound(int32_t soundID);
+    void loadSound(int32_t soundID) NO_THREAD_SAFETY_ANALYSIS; // uses unique_lock
     void quit();
 
 private:
-    void run(int32_t id);                       // The decode thread function.
+    // The decode thread function.
+    void run(int32_t id) NO_THREAD_SAFETY_ANALYSIS; // uses unique_lock
 
     SoundManager* const     mSoundManager;      // set in constructor, has own lock
     std::unique_ptr<ThreadPool> mThreadPool;    // set in constructor, has own lock
 
     std::mutex              mLock;
-    std::condition_variable mQueueSpaceAvailable;
-    std::condition_variable mQueueDataAvailable;
+    std::condition_variable mQueueSpaceAvailable GUARDED_BY(mLock);
+    std::condition_variable mQueueDataAvailable GUARDED_BY(mLock);
 
-    std::deque<int32_t>     mSoundIDs;            // GUARDED_BY(mLock);
-    bool                    mQuit = false;        // GUARDED_BY(mLock);
+    std::deque<int32_t>     mSoundIDs GUARDED_BY(mLock);
+    bool                    mQuit GUARDED_BY(mLock) = false;
 };
 
 } // end namespace android::soundpool
diff --git a/media/jni/soundpool/SoundManager.cpp b/media/jni/soundpool/SoundManager.cpp
index 3c625bf..5b16174 100644
--- a/media/jni/soundpool/SoundManager.cpp
+++ b/media/jni/soundpool/SoundManager.cpp
@@ -43,7 +43,7 @@
     mSounds.clear();
 }
 
-int32_t SoundManager::load(int fd, int64_t offset, int64_t length, int32_t priority __unused)
+int32_t SoundManager::load(int fd, int64_t offset, int64_t length, int32_t priority)
 {
     ALOGV("%s(fd=%d, offset=%lld, length=%lld, priority=%d)",
             __func__, fd, (long long)offset, (long long)length, priority);
diff --git a/media/jni/soundpool/SoundManager.h b/media/jni/soundpool/SoundManager.h
index 9201e78..4a4e3b8 100644
--- a/media/jni/soundpool/SoundManager.h
+++ b/media/jni/soundpool/SoundManager.h
@@ -21,6 +21,8 @@
 #include <mutex>
 #include <unordered_map>
 
+#include <android-base/thread_annotations.h>
+
 namespace android {
 
 class SoundPool;
@@ -91,20 +93,21 @@
         }
     private:
         mutable std::recursive_mutex  mCallbackLock; // allow mCallback to setCallback().
+                                          // No thread-safety checks in R for recursive_mutex.
         SoundPool*          mSoundPool = nullptr; // GUARDED_BY(mCallbackLock)
         SoundPoolCallback*  mCallback = nullptr;  // GUARDED_BY(mCallbackLock)
         void*               mUserData = nullptr;  // GUARDED_BY(mCallbackLock)
     };
 
-    std::shared_ptr<Sound> findSound_l(int32_t soundID) const;
+    std::shared_ptr<Sound> findSound_l(int32_t soundID) const REQUIRES(mSoundManagerLock);
 
     // The following variables are initialized in constructor and can be accessed anytime.
-    CallbackHandler         mCallbackHandler;              // has its own lock
-    const std::unique_ptr<SoundDecoder> mDecoder;          // has its own lock
+    CallbackHandler mCallbackHandler;              // has its own lock
+    const std::unique_ptr<SoundDecoder> mDecoder;  // has its own lock
 
-    mutable std::mutex      mSoundManagerLock;
-    std::unordered_map<int, std::shared_ptr<Sound>> mSounds; // GUARDED_BY(mSoundManagerLock)
-    int32_t                 mNextSoundID = 0;    // GUARDED_BY(mSoundManagerLock)
+    mutable std::mutex mSoundManagerLock;
+    std::unordered_map<int, std::shared_ptr<Sound>> mSounds GUARDED_BY(mSoundManagerLock);
+    int32_t mNextSoundID GUARDED_BY(mSoundManagerLock) = 0;
 };
 
 } // namespace android::soundpool
diff --git a/media/jni/soundpool/Stream.cpp b/media/jni/soundpool/Stream.cpp
index e3152d6..a6d9758 100644
--- a/media/jni/soundpool/Stream.cpp
+++ b/media/jni/soundpool/Stream.cpp
@@ -105,7 +105,7 @@
     if (streamID == mStreamID) {
         mRate = rate;
         if (mAudioTrack != nullptr && mSound != nullptr) {
-            const uint32_t sampleRate = uint32_t(float(mSound->getSampleRate()) * rate + 0.5);
+            const auto sampleRate = (uint32_t)lround(double(mSound->getSampleRate()) * rate);
             mAudioTrack->setSampleRate(sampleRate);
         }
     }
@@ -214,8 +214,11 @@
 
 void Stream::clearAudioTrack()
 {
+    sp<AudioTrack> release;  // release outside of lock.
+    std::lock_guard lock(mLock);
     // This will invoke the destructor which waits for the AudioTrack thread to join,
     // and is currently the only safe way to ensure there are no callbacks afterwards.
+    release = mAudioTrack;  // or std::swap if we had move semantics.
     mAudioTrack.clear();
 }
 
@@ -288,7 +291,7 @@
         const audio_stream_type_t streamType =
                 AudioSystem::attributesToStreamType(*mStreamManager->getAttributes());
         const int32_t channelCount = sound->getChannelCount();
-        const uint32_t sampleRate = uint32_t(float(sound->getSampleRate()) * rate + 0.5);
+        const auto sampleRate = (uint32_t)lround(double(sound->getSampleRate()) * rate);
         size_t frameCount = 0;
 
         if (loop) {
@@ -307,7 +310,7 @@
                         __func__, mAudioTrack.get(), sound->getSoundID());
             }
         }
-        if (newTrack == 0) {
+        if (newTrack == nullptr) {
             // mToggle toggles each time a track is started on a given stream.
             // The toggle is concatenated with the Stream address and passed to AudioTrack
             // as callback user data. This enables the detection of callbacks received from the old
@@ -380,9 +383,9 @@
 /* static */
 void Stream::staticCallback(int event, void* user, void* info)
 {
-    const uintptr_t userAsInt = (uintptr_t)user;
-    Stream* stream = reinterpret_cast<Stream*>(userAsInt & ~1);
-    stream->callback(event, info, userAsInt & 1, 0 /* tries */);
+    const auto userAsInt = (uintptr_t)user;
+    auto stream = reinterpret_cast<Stream*>(userAsInt & ~1);
+    stream->callback(event, info, int(userAsInt & 1), 0 /* tries */);
 }
 
 void Stream::callback(int event, void* info, int toggle, int tries)
diff --git a/media/jni/soundpool/Stream.h b/media/jni/soundpool/Stream.h
index 82d2690..fd92921 100644
--- a/media/jni/soundpool/Stream.h
+++ b/media/jni/soundpool/Stream.h
@@ -18,6 +18,7 @@
 
 #include "Sound.h"
 
+#include <android-base/thread_annotations.h>
 #include <audio_utils/clock.h>
 #include <media/AudioTrack.h>
 
@@ -104,47 +105,55 @@
 
     // The following getters are not locked and have weak consistency.
     // These are considered advisory only - being stale is of nuisance.
-    int32_t getPriority() const { return mPriority; }
-    int32_t getPairPriority() const { return getPairStream()->getPriority(); }
-    int64_t getStopTimeNs() const { return mStopTimeNs; }
+    int32_t getPriority() const NO_THREAD_SAFETY_ANALYSIS { return mPriority; }
+    int32_t getPairPriority() const NO_THREAD_SAFETY_ANALYSIS {
+        return getPairStream()->getPriority();
+    }
+    int64_t getStopTimeNs() const NO_THREAD_SAFETY_ANALYSIS { return mStopTimeNs; }
 
-    int32_t getStreamID() const { return mStreamID; }  // Can change with setPlay()
-    int32_t getSoundID() const { return mSoundID; }    // Can change with play_l()
-    bool hasSound() const { return mSound.get() != nullptr; }
+    // Can change with setPlay()
+    int32_t getStreamID() const NO_THREAD_SAFETY_ANALYSIS { return mStreamID; }
 
-    Stream* getPairStream() const;  // this never changes.  See top of header.
+    // Can change with play_l()
+    int32_t getSoundID() const NO_THREAD_SAFETY_ANALYSIS { return mSoundID; }
+
+    bool hasSound() const NO_THREAD_SAFETY_ANALYSIS { return mSound.get() != nullptr; }
+
+    // This never changes.  See top of header.
+    Stream* getPairStream() const;
 
 private:
     void play_l(const std::shared_ptr<Sound>& sound, int streamID,
             float leftVolume, float rightVolume, int priority, int loop, float rate,
-            sp<AudioTrack> releaseTracks[2]);
-    void stop_l();
-    void setVolume_l(float leftVolume, float rightVolume);
+            sp<AudioTrack> releaseTracks[2]) REQUIRES(mLock);
+    void stop_l() REQUIRES(mLock);
+    void setVolume_l(float leftVolume, float rightVolume) REQUIRES(mLock);
 
     // For use with AudioTrack callback.
     static void staticCallback(int event, void* user, void* info);
-    void callback(int event, void* info, int toggle, int tries);
+    void callback(int event, void* info, int toggle, int tries)
+            NO_THREAD_SAFETY_ANALYSIS; // uses unique_lock
 
     // StreamManager should be set on construction and not changed.
     // release mLock before calling into StreamManager
     StreamManager*     mStreamManager = nullptr;
 
     mutable std::mutex  mLock;
-    std::atomic_int32_t mStreamID = 0;          // Note: valid streamIDs are always positive.
-    int                 mState = IDLE;
-    std::shared_ptr<Sound> mSound;              // Non-null if playing.
-    int32_t             mSoundID = 0;           // The sound ID associated with the AudioTrack.
-    float               mLeftVolume = 0.f;
-    float               mRightVolume = 0.f;
-    int32_t             mPriority = INT32_MIN;
-    int32_t             mLoop = 0;
-    float               mRate = 0.f;
-    bool                mAutoPaused = false;
-    bool                mMuted = false;
+    std::atomic_int32_t mStreamID GUARDED_BY(mLock) = 0; // Valid streamIDs are always positive.
+    int                 mState GUARDED_BY(mLock) = IDLE;
+    std::shared_ptr<Sound> mSound GUARDED_BY(mLock);    // Non-null if playing.
+    int32_t             mSoundID GUARDED_BY(mLock) = 0; // SoundID associated with AudioTrack.
+    float               mLeftVolume GUARDED_BY(mLock) = 0.f;
+    float               mRightVolume GUARDED_BY(mLock) = 0.f;
+    int32_t             mPriority GUARDED_BY(mLock) = INT32_MIN;
+    int32_t             mLoop GUARDED_BY(mLock) = 0;
+    float               mRate GUARDED_BY(mLock) = 0.f;
+    bool                mAutoPaused GUARDED_BY(mLock) = false;
+    bool                mMuted GUARDED_BY(mLock) = false;
 
-    sp<AudioTrack>      mAudioTrack;
-    int                 mToggle = 0;
-    int64_t             mStopTimeNs = 0;        // if nonzero, time to wait for stop.
+    sp<AudioTrack>      mAudioTrack GUARDED_BY(mLock);
+    int                 mToggle GUARDED_BY(mLock) = 0;
+    int64_t             mStopTimeNs GUARDED_BY(mLock) = 0;  // if nonzero, time to wait for stop.
 };
 
 } // namespace android::soundpool
diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp
index c612218..9ff4254 100644
--- a/media/jni/soundpool/StreamManager.cpp
+++ b/media/jni/soundpool/StreamManager.cpp
@@ -55,7 +55,7 @@
         streams = 1;
     }
     mStreamPoolSize = streams * 2;
-    mStreamPool.reset(new Stream[mStreamPoolSize]);
+    mStreamPool = std::make_unique<Stream[]>(mStreamPoolSize); // create array of streams.
     // we use a perfect hash table with 2x size to map StreamIDs to Stream pointers.
     mPerfectHash = std::make_unique<PerfectHash<int32_t, Stream *>>(roundup(mStreamPoolSize * 2));
 }
@@ -69,7 +69,7 @@
 size_t StreamMap::streamPosition(const Stream* stream) const
 {
     ptrdiff_t index = stream - mStreamPool.get();
-    LOG_ALWAYS_FATAL_IF(index < 0 || index >= mStreamPoolSize,
+    LOG_ALWAYS_FATAL_IF(index < 0 || (size_t)index >= mStreamPoolSize,
             "%s: stream position out of range: %td", __func__, index);
     return (size_t)index;
 }
@@ -92,6 +92,11 @@
 
 ////////////
 
+// Thread safety analysis is supposed to be disabled for constructors and destructors
+// but clang in R seems to have a bug.  We use pragma to disable.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wthread-safety-analysis"
+
 StreamManager::StreamManager(
         int32_t streams, size_t threads, const audio_attributes_t* attributes)
     : StreamMap(streams)
@@ -110,6 +115,8 @@
             "SoundPool_");
 }
 
+#pragma clang diagnostic pop
+
 StreamManager::~StreamManager()
 {
     ALOGV("%s", __func__);
diff --git a/media/jni/soundpool/StreamManager.h b/media/jni/soundpool/StreamManager.h
index 30ad220..59ae2f9 100644
--- a/media/jni/soundpool/StreamManager.h
+++ b/media/jni/soundpool/StreamManager.h
@@ -183,9 +183,9 @@
     std::atomic_size_t      mActiveThreadCount = 0;
 
     std::mutex              mThreadLock;
-    bool                    mQuit = false;           // GUARDED_BY(mThreadLock)
-    int32_t                 mNextThreadId = 0;       // GUARDED_BY(mThreadLock)
-    std::list<std::unique_ptr<JavaThread>> mThreads; // GUARDED_BY(mThreadLock)
+    bool                    mQuit GUARDED_BY(mThreadLock) = false;
+    int32_t                 mNextThreadId GUARDED_BY(mThreadLock) = 0;
+    std::list<std::unique_ptr<JavaThread>> mThreads GUARDED_BY(mThreadLock);
 };
 
 /**
@@ -263,7 +263,7 @@
     mutable std::mutex          mHashLock;
     const size_t                mHashCapacity; // size of mK2V no lock needed.
     std::unique_ptr<std::atomic<V>[]> mK2V;    // no lock needed for read access.
-    K                           mNextKey{};    // GUARDED_BY(mHashLock)
+    K                           mNextKey GUARDED_BY(mHashLock) {};
 };
 
 /**
@@ -392,7 +392,8 @@
     // Returns positive streamID on success, 0 on failure.  This is locked.
     int32_t queueForPlay(const std::shared_ptr<Sound> &sound,
             int32_t soundID, float leftVolume, float rightVolume,
-            int32_t priority, int32_t loop, float rate);
+            int32_t priority, int32_t loop, float rate)
+            NO_THREAD_SAFETY_ANALYSIS; // uses unique_lock
 
     ///////////////////////////////////////////////////////////////////////
     // Called from soundpool::Stream
@@ -407,11 +408,11 @@
 
 private:
 
-    void run(int32_t id);                        // worker thread, takes lock internally.
+    void run(int32_t id) NO_THREAD_SAFETY_ANALYSIS; // worker thread, takes unique_lock.
     void dump() const;                           // no lock needed
 
     // returns true if more worker threads are needed.
-    bool needMoreThreads_l() {
+    bool needMoreThreads_l() REQUIRES(mStreamManagerLock) {
         return mRestartStreams.size() > 0 &&
                 (mThreadPool->getActiveThreadCount() == 0
                 || std::distance(mRestartStreams.begin(),
@@ -420,14 +421,16 @@
     }
 
     // returns true if the stream was added.
-    bool moveToRestartQueue_l(Stream* stream, int32_t activeStreamIDToMatch = 0);
+    bool moveToRestartQueue_l(
+            Stream* stream, int32_t activeStreamIDToMatch = 0) REQUIRES(mStreamManagerLock);
     // returns number of queues the stream was removed from (should be 0 or 1);
     // a special code of -1 is returned if activeStreamIDToMatch is > 0 and
     // the stream wasn't found on the active queue.
-    ssize_t removeFromQueues_l(Stream* stream, int32_t activeStreamIDToMatch = 0);
-    void addToRestartQueue_l(Stream *stream);
-    void addToActiveQueue_l(Stream *stream);
-    void sanityCheckQueue_l() const;
+    ssize_t removeFromQueues_l(
+            Stream* stream, int32_t activeStreamIDToMatch = 0) REQUIRES(mStreamManagerLock);
+    void addToRestartQueue_l(Stream *stream) REQUIRES(mStreamManagerLock);
+    void addToActiveQueue_l(Stream *stream) REQUIRES(mStreamManagerLock);
+    void sanityCheckQueue_l() const REQUIRES(mStreamManagerLock);
 
     const audio_attributes_t mAttributes;
     std::unique_ptr<ThreadPool> mThreadPool;                  // locked internally
@@ -436,9 +439,9 @@
     // 4 stream queues by the Manager Thread or by the user initiated play().
     // A stream pair has exactly one stream on exactly one of the queues.
     std::mutex                  mStreamManagerLock;
-    std::condition_variable     mStreamManagerCondition;
+    std::condition_variable     mStreamManagerCondition GUARDED_BY(mStreamManagerLock);
 
-    bool                        mQuit = false;      // GUARDED_BY(mStreamManagerLock)
+    bool                        mQuit GUARDED_BY(mStreamManagerLock) = false;
 
     // There are constructor arg "streams" pairs of streams, only one of each
     // pair on the 4 stream queues below.  The other stream in the pair serves as
@@ -452,24 +455,24 @@
     // The paired stream may be active (but with no AudioTrack), and will be restarted
     // with an active AudioTrack when the current stream is stopped.
     std::multimap<int64_t /* stopTimeNs */, Stream*>
-                                mRestartStreams;    // GUARDED_BY(mStreamManagerLock)
+                                mRestartStreams GUARDED_BY(mStreamManagerLock);
 
     // 2) mActiveStreams: Streams that are active.
     // The paired stream will be inactive.
     // This is in order of specified by kStealActiveStream_OldestFirst
-    std::list<Stream*>          mActiveStreams;     // GUARDED_BY(mStreamManagerLock)
+    std::list<Stream*>          mActiveStreams GUARDED_BY(mStreamManagerLock);
 
     // 3) mAvailableStreams: Streams that are inactive.
     // The paired stream will also be inactive.
     // No particular order.
-    std::unordered_set<Stream*> mAvailableStreams;  // GUARDED_BY(mStreamManagerLock)
+    std::unordered_set<Stream*> mAvailableStreams GUARDED_BY(mStreamManagerLock);
 
     // 4) mProcessingStreams: Streams that are being processed by the ManagerThreads
     // When on this queue, the stream and its pair are not available for stealing.
     // Each ManagerThread will have at most one stream on the mProcessingStreams queue.
     // The paired stream may be active or restarting.
     // No particular order.
-    std::unordered_set<Stream*> mProcessingStreams; // GUARDED_BY(mStreamManagerLock)
+    std::unordered_set<Stream*> mProcessingStreams GUARDED_BY(mStreamManagerLock);
 };
 
 } // namespace android::soundpool
diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp
index f670636..8f6df3d 100644
--- a/media/jni/soundpool/android_media_SoundPool.cpp
+++ b/media/jni/soundpool/android_media_SoundPool.cpp
@@ -52,7 +52,7 @@
 {
     ALOGV("android_media_SoundPool_load_FD");
     SoundPool *ap = MusterSoundPool(env, thiz);
-    if (ap == NULL) return 0;
+    if (ap == nullptr) return 0;
     return (jint) ap->load(jniGetFDFromFileDescriptor(env, fileDescriptor),
             int64_t(offset), int64_t(length), int(priority));
 }
@@ -61,7 +61,7 @@
 android_media_SoundPool_unload(JNIEnv *env, jobject thiz, jint sampleID) {
     ALOGV("android_media_SoundPool_unload\n");
     SoundPool *ap = MusterSoundPool(env, thiz);
-    if (ap == NULL) return JNI_FALSE;
+    if (ap == nullptr) return JNI_FALSE;
     return ap->unload(sampleID) ? JNI_TRUE : JNI_FALSE;
 }
 
@@ -72,7 +72,7 @@
 {
     ALOGV("android_media_SoundPool_play\n");
     SoundPool *ap = MusterSoundPool(env, thiz);
-    if (ap == NULL) return 0;
+    if (ap == nullptr) return 0;
     return (jint) ap->play(sampleID, leftVolume, rightVolume, priority, loop, rate);
 }
 
@@ -81,7 +81,7 @@
 {
     ALOGV("android_media_SoundPool_pause");
     SoundPool *ap = MusterSoundPool(env, thiz);
-    if (ap == NULL) return;
+    if (ap == nullptr) return;
     ap->pause(channelID);
 }
 
@@ -90,7 +90,7 @@
 {
     ALOGV("android_media_SoundPool_resume");
     SoundPool *ap = MusterSoundPool(env, thiz);
-    if (ap == NULL) return;
+    if (ap == nullptr) return;
     ap->resume(channelID);
 }
 
@@ -99,7 +99,7 @@
 {
     ALOGV("android_media_SoundPool_autoPause");
     SoundPool *ap = MusterSoundPool(env, thiz);
-    if (ap == NULL) return;
+    if (ap == nullptr) return;
     ap->autoPause();
 }
 
@@ -108,7 +108,7 @@
 {
     ALOGV("android_media_SoundPool_autoResume");
     SoundPool *ap = MusterSoundPool(env, thiz);
-    if (ap == NULL) return;
+    if (ap == nullptr) return;
     ap->autoResume();
 }
 
@@ -117,7 +117,7 @@
 {
     ALOGV("android_media_SoundPool_stop");
     SoundPool *ap = MusterSoundPool(env, thiz);
-    if (ap == NULL) return;
+    if (ap == nullptr) return;
     ap->stop(channelID);
 }
 
@@ -127,7 +127,7 @@
 {
     ALOGV("android_media_SoundPool_setVolume");
     SoundPool *ap = MusterSoundPool(env, thiz);
-    if (ap == NULL) return;
+    if (ap == nullptr) return;
     ap->setVolume(channelID, (float) leftVolume, (float) rightVolume);
 }
 
@@ -136,7 +136,7 @@
 {
     ALOGV("android_media_SoundPool_mute(%d)", muting);
     SoundPool *ap = MusterSoundPool(env, thiz);
-    if (ap == NULL) return;
+    if (ap == nullptr) return;
     ap->mute(muting == JNI_TRUE);
 }
 
@@ -146,7 +146,7 @@
 {
     ALOGV("android_media_SoundPool_setPriority");
     SoundPool *ap = MusterSoundPool(env, thiz);
-    if (ap == NULL) return;
+    if (ap == nullptr) return;
     ap->setPriority(channelID, (int) priority);
 }
 
@@ -156,7 +156,7 @@
 {
     ALOGV("android_media_SoundPool_setLoop");
     SoundPool *ap = MusterSoundPool(env, thiz);
-    if (ap == NULL) return;
+    if (ap == nullptr) return;
     ap->setLoop(channelID, loop);
 }
 
@@ -166,7 +166,7 @@
 {
     ALOGV("android_media_SoundPool_setRate");
     SoundPool *ap = MusterSoundPool(env, thiz);
-    if (ap == NULL) return;
+    if (ap == nullptr) return;
     ap->setRate(channelID, (float) rate);
 }
 
@@ -174,24 +174,26 @@
 {
     ALOGV("callback: (%d, %d, %d, %p, %p)", event.mMsg, event.mArg1, event.mArg2, soundPool, user);
     JNIEnv *env = AndroidRuntime::getJNIEnv();
-    env->CallStaticVoidMethod(fields.mSoundPoolClass, fields.mPostEvent, user, event.mMsg, event.mArg1, event.mArg2, NULL);
+    env->CallStaticVoidMethod(
+            fields.mSoundPoolClass, fields.mPostEvent, user, event.mMsg, event.mArg1, event.mArg2,
+            nullptr /* object */);
 }
 
 static jint
 android_media_SoundPool_native_setup(JNIEnv *env, jobject thiz, jobject weakRef,
         jint maxChannels, jobject jaa)
 {
-    if (jaa == 0) {
+    if (jaa == nullptr) {
         ALOGE("Error creating SoundPool: invalid audio attributes");
         return -1;
     }
 
-    audio_attributes_t *paa = NULL;
+    audio_attributes_t *paa = nullptr;
     // read the AudioAttributes values
     paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
-    const jstring jtags =
+    const auto jtags =
             (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags);
-    const char* tags = env->GetStringUTFChars(jtags, NULL);
+    const char* tags = env->GetStringUTFChars(jtags, nullptr);
     // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
     strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
     env->ReleaseStringUTFChars(jtags, tags);
@@ -201,8 +203,8 @@
     paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
 
     ALOGV("android_media_SoundPool_native_setup");
-    SoundPool *ap = new SoundPool(maxChannels, paa);
-    if (ap == NULL) {
+    auto *ap = new SoundPool(maxChannels, paa);
+    if (ap == nullptr) {
         return -1;
     }
 
@@ -224,12 +226,12 @@
 {
     ALOGV("android_media_SoundPool_release");
     SoundPool *ap = MusterSoundPool(env, thiz);
-    if (ap != NULL) {
+    if (ap != nullptr) {
 
         // release weak reference and clear callback
-        jobject weakRef = (jobject) ap->getUserData();
-        ap->setCallback(NULL, NULL);
-        if (weakRef != NULL) {
+        auto weakRef = (jobject) ap->getUserData();
+        ap->setCallback(nullptr /* callback */, nullptr /* user */);
+        if (weakRef != nullptr) {
             env->DeleteGlobalRef(weakRef);
         }
 
@@ -309,7 +311,7 @@
 
 jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
 {
-    JNIEnv* env = NULL;
+    JNIEnv* env = nullptr;
     jint result = -1;
     jclass clazz;
 
@@ -317,23 +319,23 @@
         ALOGE("ERROR: GetEnv failed\n");
         return result;
     }
-    assert(env != NULL);
+    assert(env != nullptr);
 
     clazz = env->FindClass(kClassPathName);
-    if (clazz == NULL) {
+    if (clazz == nullptr) {
         ALOGE("Can't find %s", kClassPathName);
         return result;
     }
 
     fields.mNativeContext = env->GetFieldID(clazz, "mNativeContext", "J");
-    if (fields.mNativeContext == NULL) {
+    if (fields.mNativeContext == nullptr) {
         ALOGE("Can't find SoundPool.mNativeContext");
         return result;
     }
 
     fields.mPostEvent = env->GetStaticMethodID(clazz, "postEventFromNative",
                                                "(Ljava/lang/Object;IIILjava/lang/Object;)V");
-    if (fields.mPostEvent == NULL) {
+    if (fields.mPostEvent == nullptr) {
         ALOGE("Can't find android/media/SoundPool.postEventFromNative");
         return result;
     }
@@ -342,16 +344,18 @@
     // since it's a static object.
     fields.mSoundPoolClass = (jclass) env->NewGlobalRef(clazz);
 
-    if (AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)) < 0)
+    if (AndroidRuntime::registerNativeMethods(
+                env, kClassPathName, gMethods, NELEM(gMethods)) < 0) {
         return result;
+    }
 
     // Get the AudioAttributes class and fields
     jclass audioAttrClass = env->FindClass(kAudioAttributesClassPathName);
-    if (audioAttrClass == NULL) {
+    if (audioAttrClass == nullptr) {
         ALOGE("Can't find %s", kAudioAttributesClassPathName);
         return result;
     }
-    jclass audioAttributesClassRef = (jclass)env->NewGlobalRef(audioAttrClass);
+    auto audioAttributesClassRef = (jclass)env->NewGlobalRef(audioAttrClass);
     javaAudioAttrFields.fieldUsage = env->GetFieldID(audioAttributesClassRef, "mUsage", "I");
     javaAudioAttrFields.fieldContentType
                                    = env->GetFieldID(audioAttributesClassRef, "mContentType", "I");
@@ -359,9 +363,10 @@
     javaAudioAttrFields.fieldFormattedTags =
             env->GetFieldID(audioAttributesClassRef, "mFormattedTags", "Ljava/lang/String;");
     env->DeleteGlobalRef(audioAttributesClassRef);
-    if (javaAudioAttrFields.fieldUsage == NULL || javaAudioAttrFields.fieldContentType == NULL
-            || javaAudioAttrFields.fieldFlags == NULL
-            || javaAudioAttrFields.fieldFormattedTags == NULL) {
+    if (javaAudioAttrFields.fieldUsage == nullptr
+            || javaAudioAttrFields.fieldContentType == nullptr
+            || javaAudioAttrFields.fieldFlags == nullptr
+            || javaAudioAttrFields.fieldFormattedTags == nullptr) {
         ALOGE("Can't initialize AudioAttributes fields");
         return result;
     }
diff --git a/packages/CarSystemUI/AndroidManifest.xml b/packages/CarSystemUI/AndroidManifest.xml
index 1dd0291..c0482e1 100644
--- a/packages/CarSystemUI/AndroidManifest.xml
+++ b/packages/CarSystemUI/AndroidManifest.xml
@@ -25,6 +25,11 @@
     <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" />
+    <!-- These permissions are required to implement icons based on role holders. -->
+    <uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS"/>
+    <uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS"/>
+    <!-- This permission is required to access app information from other users. -->
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS"/>
     <!-- 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_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_navigation_bar.xml
index 1418bf8..2a715d0 100644
--- a/packages/CarSystemUI/res/layout/car_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_navigation_bar.xml
@@ -125,6 +125,7 @@
             android:id="@+id/assist"
             style="@style/NavigationBarButton"
             systemui:icon="@drawable/ic_mic_white"
+            systemui:useDefaultAppIconForRole="true"
         />
 
     </LinearLayout>
diff --git a/packages/CarSystemUI/res/layout/car_navigation_button.xml b/packages/CarSystemUI/res/layout/car_navigation_button.xml
index 837252b..ca4e76e 100644
--- a/packages/CarSystemUI/res/layout/car_navigation_button.xml
+++ b/packages/CarSystemUI/res/layout/car_navigation_button.xml
@@ -29,12 +29,14 @@
 
         <com.android.keyguard.AlphaOptimizedImageButton
             android:id="@+id/car_nav_button_icon_image"
-            android:layout_height="wrap_content"
+            android:layout_height="@dimen/car_navigation_button_icon_height"
             android:layout_width="match_parent"
             android:layout_gravity="center"
             android:animateLayoutChanges="true"
             android:background="@android:color/transparent"
             android:scaleType="fitCenter"
+            android:tintMode="src_in"
+            android:tint="@color/car_nav_icon_fill_color"
             android:clickable="false"
         />
 
@@ -48,6 +50,7 @@
             android:background="@android:color/transparent"
             android:scaleType="fitCenter"
             android:clickable="false"
+            android:visibility="gone"
         />
 
         <ImageView
diff --git a/packages/CarSystemUI/res/values/attrs.xml b/packages/CarSystemUI/res/values/attrs.xml
index a586763..7883764 100644
--- a/packages/CarSystemUI/res/values/attrs.xml
+++ b/packages/CarSystemUI/res/values/attrs.xml
@@ -65,6 +65,10 @@
         <attr name="showMoreWhenSelected" format="boolean" />
         <!-- whether to highlight the button when selected. Defaults false -->
         <attr name="highlightWhenSelected" format="boolean" />
+        <!-- whether to show the icon of the app currently associated this button's role. Only
+             relevant for buttons associated to specific roles (e.g.: AssistantButton).
+             Defaults false -->
+        <attr name="useDefaultAppIconForRole" format="boolean"/>
     </declare-styleable>
 
     <!-- Custom attributes to configure hvac values -->
diff --git a/packages/CarSystemUI/res/values/colors.xml b/packages/CarSystemUI/res/values/colors.xml
index 0e84d51..d20ab49 100644
--- a/packages/CarSystemUI/res/values/colors.xml
+++ b/packages/CarSystemUI/res/values/colors.xml
@@ -21,7 +21,7 @@
     <color name="car_user_switcher_name_text_color">@*android:color/car_body1_light</color>
     <color name="car_user_switcher_add_user_background_color">#131313</color>
     <color name="car_user_switcher_add_user_add_sign_color">@*android:color/car_body1_light</color>
-    <color name="car_nav_icon_fill_color">#8Fffffff</color>
+    <color name="car_nav_icon_fill_color">#8F8F8F</color>
     <color name="car_nav_icon_fill_color_selected">#ffffff</color>
     <!-- colors for seekbar -->
     <color name="car_seekbar_track_background">#131315</color>
diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml
index ed0b485..cb321cd 100644
--- a/packages/CarSystemUI/res/values/dimens.xml
+++ b/packages/CarSystemUI/res/values/dimens.xml
@@ -175,6 +175,7 @@
     <dimen name="car_user_switcher_margin_top">@*android:dimen/car_padding_4</dimen>
 
     <dimen name="car_navigation_button_width">64dp</dimen>
+    <dimen name="car_navigation_button_icon_height">44dp</dimen>
     <dimen name="car_navigation_bar_width">760dp</dimen>
     <dimen name="car_left_navigation_bar_width">96dp</dimen>
     <dimen name="car_right_navigation_bar_width">96dp</dimen>
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/AssitantButton.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/AssitantButton.java
index 69ec78e..ede4696 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/AssitantButton.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/AssitantButton.java
@@ -18,6 +18,7 @@
 
 import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE;
 
+import android.app.role.RoleManager;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.os.Bundle;
@@ -31,7 +32,6 @@
  * AssitantButton is a ui component that will trigger the Voice Interaction Service.
  */
 public class AssitantButton extends CarNavigationButton {
-
     private static final String TAG = "AssistantButton";
     private final AssistUtils mAssistUtils;
     private IVoiceInteractionSessionShowCallback mShowCallback =
@@ -50,9 +50,7 @@
     public AssitantButton(Context context, AttributeSet attrs) {
         super(context, attrs);
         mAssistUtils = new AssistUtils(context);
-        setOnClickListener(v -> {
-            showAssistant();
-        });
+        setOnClickListener(v -> showAssistant());
     }
 
     private void showAssistant() {
@@ -65,4 +63,9 @@
     protected void setUpIntents(TypedArray typedArray) {
         // left blank because for the assistant button Intent will not be passed from the layout.
     }
+
+    @Override
+    protected String getRoleName() {
+        return RoleManager.ROLE_ASSISTANT;
+    }
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonRoleHolderController.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonRoleHolderController.java
new file mode 100644
index 0000000..5c83c02
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonRoleHolderController.java
@@ -0,0 +1,142 @@
+/*
+ * 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.navigationbar;
+
+import android.annotation.Nullable;
+import android.app.role.OnRoleHoldersChangedListener;
+import android.app.role.RoleManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.car.CarDeviceProvisionedController;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Some CarNavigationButtons can be associated to a {@link RoleManager} role. When they are, it is
+ * possible to have them display the icon of the default application (role holder) for the given
+ * role.
+ *
+ * This class monitors the current role holders for each role type and updates the button icon for
+ * this buttons with have this feature enabled.
+ */
+@Singleton
+public class ButtonRoleHolderController {
+    private static final String TAG = "ButtonRoleHolderController";
+
+    private final Context mContext;
+    private final PackageManager mPackageManager;
+    private final RoleManager mRoleManager;
+    private final CarDeviceProvisionedController mDeviceController;
+    private final Map<String, CarNavigationButton> mButtonMap = new HashMap<>();
+    private final OnRoleHoldersChangedListener mListener = this::onRoleChanged;
+    private boolean mRegistered;
+
+    @Inject
+    public ButtonRoleHolderController(Context context, PackageManager packageManager,
+            RoleManager roleManager, CarDeviceProvisionedController deviceController) {
+        mContext = context;
+        mPackageManager = packageManager;
+        mRoleManager = roleManager;
+        mDeviceController = deviceController;
+    }
+
+    /**
+     * Iterate through a view looking for CarNavigationButton and add it to this controller if it
+     * opted to be associated with a {@link RoleManager} role type.
+     *
+     * @param v the View that may contain CarFacetButtons
+     */
+    void addAllButtonsWithRoleName(View v) {
+        if (v instanceof CarNavigationButton) {
+            CarNavigationButton button = (CarNavigationButton) v;
+            String roleName = button.getRoleName();
+            if (roleName != null && button.isDefaultAppIconForRoleEnabled()) {
+                addButtonWithRoleName(button, roleName);
+            }
+        } else if (v instanceof ViewGroup) {
+            ViewGroup viewGroup = (ViewGroup) v;
+            for (int i = 0; i < viewGroup.getChildCount(); i++) {
+                addAllButtonsWithRoleName(viewGroup.getChildAt(i));
+            }
+        }
+    }
+
+    private void addButtonWithRoleName(CarNavigationButton button, String roleName) {
+        mButtonMap.put(roleName, button);
+        updateIcon(roleName);
+        if (!mRegistered) {
+            mRoleManager.addOnRoleHoldersChangedListenerAsUser(mContext.getMainExecutor(),
+                    mListener, UserHandle.ALL);
+            mRegistered = true;
+        }
+    }
+
+    void removeAll() {
+        mButtonMap.clear();
+        if (mRegistered) {
+            mRoleManager.removeOnRoleHoldersChangedListenerAsUser(mListener, UserHandle.ALL);
+            mRegistered = false;
+        }
+    }
+
+    @VisibleForTesting
+    void onRoleChanged(String roleName, UserHandle user) {
+        if (RoleManager.ROLE_ASSISTANT.equals(roleName)
+                && user.getIdentifier() == mDeviceController.getCurrentUser()) {
+            updateIcon(roleName);
+        }
+    }
+
+    private void updateIcon(String roleName) {
+        CarNavigationButton button = mButtonMap.get(roleName);
+        if (button == null) {
+            return;
+        }
+        List<String> holders = mRoleManager.getRoleHoldersAsUser(button.getRoleName(),
+                UserHandle.of(mDeviceController.getCurrentUser()));
+        if (holders == null || holders.isEmpty()) {
+            button.setAppIcon(null);
+        } else {
+            button.setAppIcon(loadIcon(holders.get(0)));
+        }
+    }
+
+    @Nullable
+    private Drawable loadIcon(String packageName) {
+        try {
+            ApplicationInfo appInfo = mPackageManager.getApplicationInfo(packageName,
+                    PackageManager.MATCH_ANY_USER);
+            return appInfo.loadIcon(mPackageManager);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(ButtonRoleHolderController.TAG, "Package not found: " + packageName, e);
+            return 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 5c6472e..4c720ab 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java
@@ -87,7 +87,6 @@
     private final Executor mUiBgExecutor;
     private final IStatusBarService mBarService;
     private final Lazy<KeyguardStateController> mKeyguardStateControllerLazy;
-    private final ButtonSelectionStateController mButtonSelectionStateController;
     private final Lazy<PhoneStatusBarPolicy> mIconPolicyLazy;
     private final Lazy<StatusBarIconController> mIconControllerLazy;
 
@@ -139,7 +138,6 @@
             @UiBackground Executor uiBgExecutor,
             IStatusBarService barService,
             Lazy<KeyguardStateController> keyguardStateControllerLazy,
-            ButtonSelectionStateController buttonSelectionStateController,
             Lazy<PhoneStatusBarPolicy> iconPolicyLazy,
             Lazy<StatusBarIconController> iconControllerLazy
     ) {
@@ -156,7 +154,6 @@
         mUiBgExecutor = uiBgExecutor;
         mBarService = barService;
         mKeyguardStateControllerLazy = keyguardStateControllerLazy;
-        mButtonSelectionStateController = buttonSelectionStateController;
         mIconPolicyLazy = iconPolicyLazy;
         mIconControllerLazy = iconControllerLazy;
 
@@ -280,10 +277,9 @@
      * before and after the device is provisioned. . Also for change of density and font size.
      */
     private void restartNavBars() {
-        // remove and reattach all hvac components such that we don't keep a reference to unused
-        // ui elements
-        mCarNavigationBarController.removeAllFromHvac();
-        mButtonSelectionStateController.removeAll();
+        // remove and reattach all components such that we don't keep a reference to unused ui
+        // elements
+        mCarNavigationBarController.removeAll();
 
         if (mTopNavigationBarWindow != null) {
             mTopNavigationBarWindow.removeAllViews();
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java
index 288e5cf..ca780ae 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java
@@ -37,6 +37,7 @@
     private final Context mContext;
     private final NavigationBarViewFactory mNavigationBarViewFactory;
     private final ButtonSelectionStateController mButtonSelectionStateController;
+    private final ButtonRoleHolderController mButtonRoleHolderController;
     private final Lazy<HvacController> mHvacControllerLazy;
 
     private boolean mShowTop;
@@ -59,11 +60,13 @@
     public CarNavigationBarController(Context context,
             NavigationBarViewFactory navigationBarViewFactory,
             ButtonSelectionStateController buttonSelectionStateController,
-            Lazy<HvacController> hvacControllerLazy) {
+            Lazy<HvacController> hvacControllerLazy,
+            ButtonRoleHolderController buttonRoleHolderController) {
         mContext = context;
         mNavigationBarViewFactory = navigationBarViewFactory;
         mButtonSelectionStateController = buttonSelectionStateController;
         mHvacControllerLazy = hvacControllerLazy;
+        mButtonRoleHolderController = buttonRoleHolderController;
 
         // Read configuration.
         mShowTop = mContext.getResources().getBoolean(R.bool.config_enableTopNavigationBar);
@@ -101,9 +104,11 @@
         mHvacControllerLazy.get().connectToCarService();
     }
 
-    /** Clean up hvac. */
-    public void removeAllFromHvac() {
+    /** Clean up */
+    public void removeAll() {
         mHvacControllerLazy.get().removeAllComponents();
+        mButtonSelectionStateController.removeAll();
+        mButtonRoleHolderController.removeAll();
     }
 
     /** Gets the top window if configured to do so. */
@@ -211,6 +216,7 @@
         view.setStatusBarWindowTouchListener(statusBarTouchListener);
         view.setNotificationsPanelController(notifShadeController);
         mButtonSelectionStateController.addAllButtonsWithSelectionState(view);
+        mButtonRoleHolderController.addAllButtonsWithRoleName(view);
         mHvacControllerLazy.get().addTemperatureViewToController(view);
     }
 
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationButton.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationButton.java
index 5f4ac2d..5e113d6 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationButton.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationButton.java
@@ -17,9 +17,11 @@
 package com.android.systemui.car.navigationbar;
 
 import android.app.ActivityOptions;
+import android.app.role.RoleManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.UserHandle;
 import android.util.AttributeSet;
@@ -29,6 +31,7 @@
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.keyguard.AlphaOptimizedImageButton;
 import com.android.systemui.R;
 
@@ -62,6 +65,8 @@
     private float mUnselectedAlpha;
     private int mSelectedIconResourceId;
     private int mIconResourceId;
+    private Drawable mAppIcon;
+    private boolean mIsDefaultAppIconForRoleEnabled;
     private String[] mComponentNames;
     /** App categories that are to be used with this widget */
     private String[] mButtonCategories;
@@ -92,7 +97,9 @@
         super.setSelected(selected);
         mSelected = selected;
         if (mHighlightWhenSelected) {
-            setAlpha(mSelected ? mSelectedAlpha : mUnselectedAlpha);
+            // Always apply selected alpha if the button does not toggle alpha based on selection
+            // state.
+            setAlpha(!mHighlightWhenSelected || mSelected ? mSelectedAlpha : mUnselectedAlpha);
         }
         if (mShowMoreWhenSelected && mMoreIcon != null) {
             mMoreIcon.setVisibility(selected ? VISIBLE : GONE);
@@ -108,6 +115,20 @@
         updateImage();
     }
 
+    /**
+     * Sets the current icon of the default application associated with this button.
+     */
+    public void setAppIcon(Drawable appIcon) {
+        mAppIcon = appIcon;
+        updateImage();
+    }
+
+    /** Gets the icon of the app currently associated to the role of this button. */
+    @VisibleForTesting
+    protected Drawable getAppIcon() {
+        return mAppIcon;
+    }
+
     /** Gets whether the icon is in an unseen state. */
     public boolean getUnseen() {
         return mHasUnseen;
@@ -144,6 +165,22 @@
     }
 
     /**
+     * Subclasses should override this method to return the {@link RoleManager} role associated
+     * with this button.
+     */
+    protected String getRoleName() {
+        return null;
+    }
+
+    /**
+     * @return true if this button should show the icon of the default application for the
+     * role returned by {@link #getRoleName()}.
+     */
+    protected boolean isDefaultAppIconForRoleEnabled() {
+        return mIsDefaultAppIconForRoleEnabled;
+    }
+
+    /**
      * @return The id of the display the button is on or Display.INVALID_DISPLAY if it's not yet on
      * a display.
      */
@@ -240,7 +277,6 @@
         };
     }
 
-
     /**
      * Initializes view-related aspects of the button.
      */
@@ -256,28 +292,27 @@
                 R.styleable.CarNavigationButton_showMoreWhenSelected,
                 mShowMoreWhenSelected);
 
-        mSelectedIconResourceId = typedArray.getResourceId(
-                R.styleable.CarNavigationButton_selectedIcon, mIconResourceId);
         mIconResourceId = typedArray.getResourceId(
                 R.styleable.CarNavigationButton_icon, 0);
-
+        mSelectedIconResourceId = typedArray.getResourceId(
+                R.styleable.CarNavigationButton_selectedIcon, mIconResourceId);
+        mIsDefaultAppIconForRoleEnabled = typedArray.getBoolean(
+                R.styleable.CarNavigationButton_useDefaultAppIconForRole, false);
         mIcon = findViewById(R.id.car_nav_button_icon_image);
-        mIcon.setScaleType(ImageView.ScaleType.CENTER);
         // Always apply selected alpha if the button does not toggle alpha based on selection state.
         mIcon.setAlpha(mHighlightWhenSelected ? mUnselectedAlpha : mSelectedAlpha);
-        mIcon.setImageResource(mIconResourceId);
-
         mMoreIcon = findViewById(R.id.car_nav_button_more_icon);
         mMoreIcon.setAlpha(mSelectedAlpha);
-        mMoreIcon.setVisibility(GONE);
-
         mUnseenIcon = findViewById(R.id.car_nav_button_unseen_icon);
-
-        mUnseenIcon.setVisibility(mHasUnseen ? VISIBLE : GONE);
+        updateImage();
     }
 
     private void updateImage() {
-        mIcon.setImageResource(mSelected ? mSelectedIconResourceId : mIconResourceId);
+        if (mIsDefaultAppIconForRoleEnabled && mAppIcon != null) {
+            mIcon.setImageDrawable(mAppIcon);
+        } else {
+            mIcon.setImageResource(mSelected ? mSelectedIconResourceId : mIconResourceId);
+        }
         mUnseenIcon.setVisibility(mHasUnseen ? VISIBLE : GONE);
     }
 
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 d18eadd..d692487 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBar.java
@@ -45,7 +45,6 @@
 import com.android.systemui.car.navigationbar.CarNavigationBarController;
 import com.android.systemui.classifier.FalsingLog;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
@@ -173,7 +172,6 @@
             DisplayMetrics displayMetrics,
             MetricsLogger metricsLogger,
             @UiBackground Executor uiBgExecutor,
-            @Main Executor mainExecutor,
             NotificationMediaManager notificationMediaManager,
             NotificationLockscreenUserManager lockScreenUserManager,
             NotificationRemoteInputManager remoteInputManager,
@@ -254,7 +252,6 @@
                 displayMetrics,
                 metricsLogger,
                 uiBgExecutor,
-                mainExecutor,
                 notificationMediaManager,
                 lockScreenUserManager,
                 remoteInputManager,
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBarModule.java
index 4f6890e..dc2eb04 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBarModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/CarStatusBarModule.java
@@ -33,7 +33,6 @@
 import com.android.systemui.car.CarDeviceProvisionedController;
 import com.android.systemui.car.navigationbar.CarNavigationBarController;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -148,7 +147,6 @@
             DisplayMetrics displayMetrics,
             MetricsLogger metricsLogger,
             @UiBackground Executor uiBgExecutor,
-            @Main Executor mainExecutor,
             NotificationMediaManager notificationMediaManager,
             NotificationLockscreenUserManager lockScreenUserManager,
             NotificationRemoteInputManager remoteInputManager,
@@ -228,7 +226,6 @@
                 displayMetrics,
                 metricsLogger,
                 uiBgExecutor,
-                mainExecutor,
                 notificationMediaManager,
                 lockScreenUserManager,
                 remoteInputManager,
diff --git a/packages/CarSystemUI/tests/res/layout/button_role_holder_controller_test.xml b/packages/CarSystemUI/tests/res/layout/button_role_holder_controller_test.xml
new file mode 100644
index 0000000..25ec2c1
--- /dev/null
+++ b/packages/CarSystemUI/tests/res/layout/button_role_holder_controller_test.xml
@@ -0,0 +1,41 @@
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:id="@id/nav_buttons"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_weight="1"
+    android:paddingStart="20dp"
+    android:paddingEnd="20dp"
+    android:gravity="center">
+
+    <com.android.systemui.car.navigationbar.AssitantButton
+        android:id="@+id/assistant_role_button"
+        style="@style/NavigationBarButton"
+        systemui:icon="@drawable/car_ic_overview"
+        systemui:useDefaultAppIconForRole="true"
+    />
+
+    <com.android.systemui.car.navigationbar.AssitantButton
+        android:id="@+id/assistant_role_disabled_button"
+        style="@style/NavigationBarButton"
+        systemui:icon="@drawable/car_ic_overview"
+    />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/CarSystemUI/tests/res/layout/car_button_selection_state_controller_test.xml b/packages/CarSystemUI/tests/res/layout/car_button_selection_state_controller_test.xml
index f0e0216..a8e83d6 100644
--- a/packages/CarSystemUI/tests/res/layout/car_button_selection_state_controller_test.xml
+++ b/packages/CarSystemUI/tests/res/layout/car_button_selection_state_controller_test.xml
@@ -25,7 +25,7 @@
     android:paddingEnd="20dp"
     android:gravity="center">
 
-    <com.android.systemui.navigationbar.car.CarNavigationButton
+    <com.android.systemui.car.navigationbar.CarNavigationButton
         android:id="@+id/detectable_by_component_name"
         style="@style/NavigationBarButton"
         systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
@@ -34,7 +34,7 @@
         systemui:highlightWhenSelected="true"
     />
 
-    <com.android.systemui.navigationbar.car.CarNavigationButton
+    <com.android.systemui.car.navigationbar.CarNavigationButton
         android:id="@+id/detectable_by_category"
         style="@style/NavigationBarButton"
         systemui:categories="android.intent.category.APP_MAPS"
@@ -43,7 +43,7 @@
         systemui:highlightWhenSelected="true"
     />
 
-    <com.android.systemui.navigationbar.car.CarNavigationButton
+    <com.android.systemui.car.navigationbar.CarNavigationButton
         android:id="@+id/detectable_by_package"
         style="@style/NavigationBarButton"
         systemui:icon="@drawable/car_ic_phone"
diff --git a/packages/CarSystemUI/tests/res/layout/car_navigation_bar_view_test.xml b/packages/CarSystemUI/tests/res/layout/car_navigation_bar_view_test.xml
index b0ca8dc..94edc4b 100644
--- a/packages/CarSystemUI/tests/res/layout/car_navigation_bar_view_test.xml
+++ b/packages/CarSystemUI/tests/res/layout/car_navigation_bar_view_test.xml
@@ -14,7 +14,7 @@
   ~ limitations under the License.
   -->
 
-<com.android.systemui.navigationbar.car.CarNavigationBarView
+<com.android.systemui.car.navigationbar.CarNavigationBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
@@ -32,7 +32,7 @@
         android:paddingEnd="20dp"
         android:gravity="center">
 
-        <com.android.systemui.navigationbar.car.CarNavigationButton
+        <com.android.systemui.car.navigationbar.CarNavigationButton
             android:id="@+id/home"
             style="@style/NavigationBarButton"
             systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
@@ -55,4 +55,4 @@
         android:visibility="gone"
     />
 
-</com.android.systemui.navigationbar.car.CarNavigationBarView>
+</com.android.systemui.car.navigationbar.CarNavigationBarView>
diff --git a/packages/CarSystemUI/tests/res/layout/car_navigation_button_test.xml b/packages/CarSystemUI/tests/res/layout/car_navigation_button_test.xml
index 576928c..44f8340 100644
--- a/packages/CarSystemUI/tests/res/layout/car_navigation_button_test.xml
+++ b/packages/CarSystemUI/tests/res/layout/car_navigation_button_test.xml
@@ -25,7 +25,7 @@
     android:paddingEnd="20dp"
     android:gravity="center">
 
-    <com.android.systemui.navigationbar.car.CarNavigationButton
+    <com.android.systemui.car.navigationbar.CarNavigationButton
         android:id="@+id/default_no_selection_state"
         style="@style/NavigationBarButton"
         systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
@@ -34,7 +34,7 @@
         systemui:selectedIcon="@drawable/car_ic_overview_selected"
     />
 
-    <com.android.systemui.navigationbar.car.CarNavigationButton
+    <com.android.systemui.car.navigationbar.CarNavigationButton
         android:id="@+id/app_grid_activity"
         style="@style/NavigationBarButton"
         systemui:componentNames="com.android.car.carlauncher/.AppGridActivity"
@@ -44,7 +44,7 @@
         systemui:highlightWhenSelected="true"
     />
 
-    <com.android.systemui.navigationbar.car.CarNavigationButton
+    <com.android.systemui.car.navigationbar.CarNavigationButton
         android:id="@+id/long_click_app_grid_activity"
         style="@style/NavigationBarButton"
         systemui:componentNames="com.android.car.carlauncher/.AppGridActivity"
@@ -54,7 +54,7 @@
         systemui:highlightWhenSelected="true"
     />
 
-    <com.android.systemui.navigationbar.car.CarNavigationButton
+    <com.android.systemui.car.navigationbar.CarNavigationButton
         android:id="@+id/broadcast"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
@@ -63,7 +63,7 @@
         systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
     />
 
-    <com.android.systemui.navigationbar.car.CarNavigationButton
+    <com.android.systemui.car.navigationbar.CarNavigationButton
         android:id="@+id/selected_icon_undefined"
         style="@style/NavigationBarButton"
         systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
@@ -71,7 +71,7 @@
         systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
     />
 
-    <com.android.systemui.navigationbar.car.CarNavigationButton
+    <com.android.systemui.car.navigationbar.CarNavigationButton
         android:id="@+id/highlightable_no_more_button"
         style="@style/NavigationBarButton"
         systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
@@ -81,7 +81,7 @@
         systemui:highlightWhenSelected="true"
     />
 
-    <com.android.systemui.navigationbar.car.CarNavigationButton
+    <com.android.systemui.car.navigationbar.CarNavigationButton
         android:id="@+id/not_highlightable_more_button"
         style="@style/NavigationBarButton"
         systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
@@ -91,7 +91,7 @@
         systemui:showMoreWhenSelected="true"
     />
 
-    <com.android.systemui.navigationbar.car.CarNavigationButton
+    <com.android.systemui.car.navigationbar.CarNavigationButton
         android:id="@+id/highlightable_more_button"
         style="@style/NavigationBarButton"
         systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
@@ -102,7 +102,7 @@
         systemui:showMoreWhenSelected="true"
     />
 
-    <com.android.systemui.navigationbar.car.CarNavigationButton
+    <com.android.systemui.car.navigationbar.CarNavigationButton
         android:id="@+id/broadcast"
         style="@style/NavigationBarButton"
         systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
@@ -112,4 +112,13 @@
         systemui:broadcast="true"
     />
 
+    <com.android.systemui.car.navigationbar.AssitantButton
+        android:id="@+id/role_based_button"
+        style="@style/NavigationBarButton"
+        systemui:icon="@drawable/car_ic_overview"
+        systemui:selectedIcon="@drawable/car_ic_overview_selected"
+        systemui:useDefaultAppIconForRole="true"
+        systemui:highlightWhenSelected="true"
+    />
+
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/ButtonRoleHolderControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/ButtonRoleHolderControllerTest.java
new file mode 100644
index 0000000..a57736b
--- /dev/null
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/ButtonRoleHolderControllerTest.java
@@ -0,0 +1,187 @@
+/*
+ * 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.navigationbar;
+
+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.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.when;
+
+import android.app.role.RoleManager;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.LayoutInflater;
+import android.widget.LinearLayout;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.car.CarDeviceProvisionedController;
+import com.android.systemui.tests.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.List;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class ButtonRoleHolderControllerTest extends SysuiTestCase {
+    private static final String TEST_VALID_PACKAGE_NAME = "foo";
+    private static final String TEST_INVALID_PACKAGE_NAME = "bar";
+    private static final UserHandle TEST_CURRENT_USER = UserHandle.of(100);
+    private static final UserHandle TEST_NON_CURRENT_USER = UserHandle.of(101);
+
+    private LinearLayout mTestView;
+    private CarNavigationButton mNavButtonDefaultAppIconForRoleWithEnabled;
+    private CarNavigationButton mNavButtonDefaultAppIconForRoleWithDisabled;
+    private ButtonRoleHolderController mControllerUnderTest;
+    private Drawable mAppIcon;
+
+    @Mock
+    private RoleManager mRoleManager;
+    @Mock
+    private CarDeviceProvisionedController mDeviceProvisionedController;
+    @Mock
+    private PackageManager mPackageManager;
+    @Mock
+    private ApplicationInfo mApplicationInfo;
+
+    @Before
+    public void setUp() throws PackageManager.NameNotFoundException {
+        MockitoAnnotations.initMocks(this);
+
+        mTestView = (LinearLayout) LayoutInflater.from(mContext).inflate(
+                R.layout.button_role_holder_controller_test, /* root= */ null);
+        mNavButtonDefaultAppIconForRoleWithEnabled = mTestView
+                .findViewById(R.id.assistant_role_button);
+        mNavButtonDefaultAppIconForRoleWithDisabled = mTestView
+                .findViewById(R.id.assistant_role_disabled_button);
+        mAppIcon = mContext.getDrawable(R.drawable.car_ic_apps);
+        when(mApplicationInfo.loadIcon(any())).thenReturn(mAppIcon);
+        doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager)
+                .getApplicationInfo(any(), anyInt());
+        doReturn(mApplicationInfo).when(mPackageManager)
+                .getApplicationInfo(eq(TEST_VALID_PACKAGE_NAME), anyInt());
+        when(mDeviceProvisionedController
+                .getCurrentUser())
+                .thenReturn(TEST_CURRENT_USER.getIdentifier());
+        mControllerUnderTest = new ButtonRoleHolderController(mContext,
+                mPackageManager, mRoleManager, mDeviceProvisionedController);
+    }
+
+    @Test
+    public void addAllButtonsWithRoleName_roleAssigned_appIconEnabled_useAssignedAppIcon() {
+        when(mRoleManager.getRoleHoldersAsUser(eq(RoleManager.ROLE_ASSISTANT), any()))
+                .thenReturn(List.of(TEST_VALID_PACKAGE_NAME));
+
+        mControllerUnderTest.addAllButtonsWithRoleName(mTestView);
+
+        assertThat(mNavButtonDefaultAppIconForRoleWithEnabled.getAppIcon()).isEqualTo(mAppIcon);
+    }
+
+    @Test
+    public void addAllButtonsWithRoleName_roleUnassigned_appIconEnabled_useDefaultIcon() {
+        when(mRoleManager.getRoleHoldersAsUser(eq(RoleManager.ROLE_ASSISTANT), any()))
+                .thenReturn(null);
+
+        mControllerUnderTest.addAllButtonsWithRoleName(mTestView);
+
+        assertThat(mNavButtonDefaultAppIconForRoleWithEnabled.getAppIcon()).isNull();
+    }
+
+    @Test
+    public void onRoleChanged_currentUser_appIconEnabled_useAssignedAppIcon() {
+        when(mRoleManager.getRoleHoldersAsUser(eq(RoleManager.ROLE_ASSISTANT), any()))
+                .thenReturn(null);
+        mControllerUnderTest.addAllButtonsWithRoleName(mTestView);
+        when(mRoleManager
+                .getRoleHoldersAsUser(eq(RoleManager.ROLE_ASSISTANT), any()))
+                .thenReturn(List.of(TEST_VALID_PACKAGE_NAME));
+
+        mControllerUnderTest.onRoleChanged(RoleManager.ROLE_ASSISTANT, TEST_CURRENT_USER);
+
+        assertThat(mNavButtonDefaultAppIconForRoleWithEnabled.getAppIcon()).isEqualTo(mAppIcon);
+    }
+
+    @Test
+    public void onRoleChanged_nonCurrentUser_appIconEnabled_iconIsNotUpdated() {
+        when(mRoleManager
+                .getRoleHoldersAsUser(eq(RoleManager.ROLE_ASSISTANT), any()))
+                .thenReturn(null);
+        mControllerUnderTest.addAllButtonsWithRoleName(mTestView);
+        Drawable beforeIcon = mNavButtonDefaultAppIconForRoleWithEnabled.getAppIcon();
+        when(mRoleManager
+                .getRoleHoldersAsUser(eq(RoleManager.ROLE_ASSISTANT), any()))
+                .thenReturn(List.of(TEST_VALID_PACKAGE_NAME));
+
+        mControllerUnderTest.onRoleChanged(RoleManager.ROLE_ASSISTANT, TEST_NON_CURRENT_USER);
+
+        Drawable afterIcon = mNavButtonDefaultAppIconForRoleWithEnabled.getAppIcon();
+        assertThat(afterIcon).isEqualTo(beforeIcon);
+    }
+
+    @Test
+    public void onRoleChanged_invalidPackage_useDefaultIcon() {
+        when(mRoleManager
+                .getRoleHoldersAsUser(eq(RoleManager.ROLE_ASSISTANT), any()))
+                .thenReturn(List.of(TEST_INVALID_PACKAGE_NAME));
+
+        mControllerUnderTest.addAllButtonsWithRoleName(mTestView);
+
+        assertThat(mNavButtonDefaultAppIconForRoleWithEnabled.getAppIcon()).isNull();
+    }
+
+    @Test
+    public void addAllButtonsWithRoleName_appIconDisabled_useDefaultIcon() {
+        when(mRoleManager
+                .getRoleHoldersAsUser(eq(RoleManager.ROLE_ASSISTANT), any()))
+                .thenReturn(List.of(TEST_VALID_PACKAGE_NAME));
+
+        mControllerUnderTest.addAllButtonsWithRoleName(mTestView);
+
+        assertThat(mNavButtonDefaultAppIconForRoleWithDisabled.getAppIcon()).isNull();
+    }
+
+    @Test
+    public void onRoleChanged_roleAssigned_appIconDisabled_useDefaultIcon() {
+        when(mRoleManager
+                .getRoleHoldersAsUser(eq(RoleManager.ROLE_ASSISTANT), any()))
+                .thenReturn(null);
+        mControllerUnderTest.addAllButtonsWithRoleName(mTestView);
+        assertThat(mNavButtonDefaultAppIconForRoleWithDisabled.getAppIcon()).isNull();
+        when(mRoleManager
+                .getRoleHoldersAsUser(eq(RoleManager.ROLE_ASSISTANT), any()))
+                .thenReturn(List.of(TEST_VALID_PACKAGE_NAME));
+
+        mControllerUnderTest.onRoleChanged(RoleManager.ROLE_ASSISTANT, TEST_CURRENT_USER);
+
+        assertThat(mNavButtonDefaultAppIconForRoleWithDisabled.getAppIcon()).isNull();
+    }
+}
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java
index 911f624..e84e42c 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java
@@ -53,6 +53,8 @@
     @Mock
     private ButtonSelectionStateController mButtonSelectionStateController;
     @Mock
+    private ButtonRoleHolderController mButtonRoleHolderController;
+    @Mock
     private HvacController mHvacController;
 
     @Before
@@ -66,10 +68,15 @@
         mDependency.injectMockDependency(StatusBarIconController.class);
     }
 
+    private CarNavigationBarController createNavigationBarController() {
+        return new CarNavigationBarController(mContext, mNavigationBarViewFactory,
+                mButtonSelectionStateController, () -> mHvacController,
+                mButtonRoleHolderController);
+    }
+
     @Test
     public void testConnectToHvac_callsConnect() {
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         mCarNavigationBar.connectToHvac();
 
@@ -77,20 +84,37 @@
     }
 
     @Test
-    public void testRemoveAllFromHvac_callsRemoveAll() {
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+    public void testRemoveAll_callsHvacControllerRemoveAllComponents() {
+        mCarNavigationBar = createNavigationBarController();
 
-        mCarNavigationBar.removeAllFromHvac();
+        mCarNavigationBar.removeAll();
 
         verify(mHvacController).removeAllComponents();
     }
 
+
+    @Test
+    public void testRemoveAll_callsButtonRoleHolderControllerRemoveAll() {
+        mCarNavigationBar = createNavigationBarController();
+
+        mCarNavigationBar.removeAll();
+
+        verify(mButtonRoleHolderController).removeAll();
+    }
+
+    @Test
+    public void testRemoveAll_callsButtonSelectionStateControllerRemoveAll() {
+        mCarNavigationBar = createNavigationBarController();
+
+        mCarNavigationBar.removeAll();
+
+        verify(mButtonSelectionStateController).removeAll();
+    }
+
     @Test
     public void testGetTopWindow_topDisabled_returnsNull() {
         mTestableResources.addOverride(R.bool.config_enableTopNavigationBar, false);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window = mCarNavigationBar.getTopWindow();
 
@@ -100,8 +124,7 @@
     @Test
     public void testGetTopWindow_topEnabled_returnsWindow() {
         mTestableResources.addOverride(R.bool.config_enableTopNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window = mCarNavigationBar.getTopWindow();
 
@@ -111,8 +134,7 @@
     @Test
     public void testGetTopWindow_topEnabled_calledTwice_returnsSameWindow() {
         mTestableResources.addOverride(R.bool.config_enableTopNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window1 = mCarNavigationBar.getTopWindow();
         ViewGroup window2 = mCarNavigationBar.getTopWindow();
@@ -123,8 +145,7 @@
     @Test
     public void testGetBottomWindow_bottomDisabled_returnsNull() {
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, false);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window = mCarNavigationBar.getBottomWindow();
 
@@ -134,8 +155,7 @@
     @Test
     public void testGetBottomWindow_bottomEnabled_returnsWindow() {
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window = mCarNavigationBar.getBottomWindow();
 
@@ -145,8 +165,7 @@
     @Test
     public void testGetBottomWindow_bottomEnabled_calledTwice_returnsSameWindow() {
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window1 = mCarNavigationBar.getBottomWindow();
         ViewGroup window2 = mCarNavigationBar.getBottomWindow();
@@ -157,8 +176,7 @@
     @Test
     public void testGetLeftWindow_leftDisabled_returnsNull() {
         mTestableResources.addOverride(R.bool.config_enableLeftNavigationBar, false);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
         ViewGroup window = mCarNavigationBar.getLeftWindow();
         assertThat(window).isNull();
     }
@@ -166,8 +184,7 @@
     @Test
     public void testGetLeftWindow_leftEnabled_returnsWindow() {
         mTestableResources.addOverride(R.bool.config_enableLeftNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window = mCarNavigationBar.getLeftWindow();
 
@@ -177,8 +194,7 @@
     @Test
     public void testGetLeftWindow_leftEnabled_calledTwice_returnsSameWindow() {
         mTestableResources.addOverride(R.bool.config_enableLeftNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window1 = mCarNavigationBar.getLeftWindow();
         ViewGroup window2 = mCarNavigationBar.getLeftWindow();
@@ -189,8 +205,7 @@
     @Test
     public void testGetRightWindow_rightDisabled_returnsNull() {
         mTestableResources.addOverride(R.bool.config_enableRightNavigationBar, false);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window = mCarNavigationBar.getRightWindow();
 
@@ -200,8 +215,7 @@
     @Test
     public void testGetRightWindow_rightEnabled_returnsWindow() {
         mTestableResources.addOverride(R.bool.config_enableRightNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window = mCarNavigationBar.getRightWindow();
 
@@ -211,8 +225,7 @@
     @Test
     public void testGetRightWindow_rightEnabled_calledTwice_returnsSameWindow() {
         mTestableResources.addOverride(R.bool.config_enableRightNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window1 = mCarNavigationBar.getRightWindow();
         ViewGroup window2 = mCarNavigationBar.getRightWindow();
@@ -223,8 +236,7 @@
     @Test
     public void testSetBottomWindowVisibility_setTrue_isVisible() {
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window = mCarNavigationBar.getBottomWindow();
         mCarNavigationBar.setBottomWindowVisibility(View.VISIBLE);
@@ -235,8 +247,7 @@
     @Test
     public void testSetBottomWindowVisibility_setFalse_isGone() {
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window = mCarNavigationBar.getBottomWindow();
         mCarNavigationBar.setBottomWindowVisibility(View.GONE);
@@ -247,8 +258,7 @@
     @Test
     public void testSetLeftWindowVisibility_setTrue_isVisible() {
         mTestableResources.addOverride(R.bool.config_enableLeftNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window = mCarNavigationBar.getLeftWindow();
         mCarNavigationBar.setLeftWindowVisibility(View.VISIBLE);
@@ -259,8 +269,7 @@
     @Test
     public void testSetLeftWindowVisibility_setFalse_isGone() {
         mTestableResources.addOverride(R.bool.config_enableLeftNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window = mCarNavigationBar.getLeftWindow();
         mCarNavigationBar.setLeftWindowVisibility(View.GONE);
@@ -271,8 +280,7 @@
     @Test
     public void testSetRightWindowVisibility_setTrue_isVisible() {
         mTestableResources.addOverride(R.bool.config_enableRightNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window = mCarNavigationBar.getRightWindow();
         mCarNavigationBar.setRightWindowVisibility(View.VISIBLE);
@@ -283,8 +291,7 @@
     @Test
     public void testSetRightWindowVisibility_setFalse_isGone() {
         mTestableResources.addOverride(R.bool.config_enableRightNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         ViewGroup window = mCarNavigationBar.getRightWindow();
         mCarNavigationBar.setRightWindowVisibility(View.GONE);
@@ -295,8 +302,7 @@
     @Test
     public void testRegisterBottomBarTouchListener_createViewFirst_registrationSuccessful() {
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
         View.OnTouchListener controller = bottomBar.getStatusBarWindowTouchListener();
@@ -310,8 +316,7 @@
     @Test
     public void testRegisterBottomBarTouchListener_registerFirst_registrationSuccessful() {
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         mCarNavigationBar.registerBottomBarTouchListener(mock(View.OnTouchListener.class));
         CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
@@ -323,8 +328,7 @@
     @Test
     public void testRegisterNotificationController_createViewFirst_registrationSuccessful() {
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
         CarNavigationBarController.NotificationsShadeController controller =
@@ -340,8 +344,7 @@
     @Test
     public void testRegisterNotificationController_registerFirst_registrationSuccessful() {
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
 
         mCarNavigationBar.registerNotificationController(
                 mock(CarNavigationBarController.NotificationsShadeController.class));
@@ -355,8 +358,7 @@
     @Test
     public void testShowAllKeyguardButtons_bottomEnabled_bottomKeyguardButtonsVisible() {
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
         CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
         View bottomKeyguardButtons = bottomBar.findViewById(R.id.lock_screen_nav_buttons);
 
@@ -368,8 +370,7 @@
     @Test
     public void testShowAllKeyguardButtons_bottomEnabled_bottomNavButtonsGone() {
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
         CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
         View bottomButtons = bottomBar.findViewById(R.id.nav_buttons);
 
@@ -381,8 +382,7 @@
     @Test
     public void testHideAllKeyguardButtons_bottomEnabled_bottomKeyguardButtonsGone() {
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
         CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
         View bottomKeyguardButtons = bottomBar.findViewById(R.id.lock_screen_nav_buttons);
 
@@ -396,8 +396,7 @@
     @Test
     public void testHideAllKeyguardButtons_bottomEnabled_bottomNavButtonsVisible() {
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
         CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
         View bottomButtons = bottomBar.findViewById(R.id.nav_buttons);
 
@@ -411,8 +410,7 @@
     @Test
     public void testToggleAllNotificationsUnseenIndicator_bottomEnabled_hasUnseen_setCorrectly() {
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
         CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
         CarNavigationButton notifications = bottomBar.findViewById(R.id.notifications);
 
@@ -426,8 +424,7 @@
     @Test
     public void testToggleAllNotificationsUnseenIndicator_bottomEnabled_noUnseen_setCorrectly() {
         mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
-        mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
-                mButtonSelectionStateController, () -> mHvacController);
+        mCarNavigationBar = createNavigationBarController();
         CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
         CarNavigationButton notifications = bottomBar.findViewById(R.id.notifications);
 
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 04e0a73..0caa86f 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
@@ -89,6 +89,8 @@
     @Mock
     private ButtonSelectionStateListener mButtonSelectionStateListener;
     @Mock
+    private ButtonRoleHolderController mButtonRoleHolderController;
+    @Mock
     private IStatusBarService mBarService;
     @Mock
     private KeyguardStateController mKeyguardStateController;
@@ -137,8 +139,8 @@
                 mCarNavigationBarController, mLightBarController, mStatusBarIconController,
                 mWindowManager, mDeviceProvisionedController, new CommandQueue(mContext),
                 mAutoHideController, mButtonSelectionStateListener, mHandler, mUiBgExecutor,
-                mBarService, () -> mKeyguardStateController, mButtonSelectionStateController,
-                () -> mIconPolicy, () -> mIconController);
+                mBarService, () -> mKeyguardStateController, () -> mIconPolicy,
+                () -> mIconController);
     }
 
     @Test
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationButtonTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationButtonTest.java
index 11f2fa4..54282d3 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationButtonTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationButtonTest.java
@@ -180,6 +180,56 @@
     }
 
     @Test
+    public void onUnselected_withAppIcon_showsAppIcon() {
+        CarNavigationButton roleBasedButton = mTestView.findViewById(R.id.role_based_button);
+        Drawable appIcon = getContext().getDrawable(R.drawable.ic_android);
+
+        roleBasedButton.setSelected(false);
+        roleBasedButton.setAppIcon(appIcon);
+
+        Drawable currentDrawable = ((AlphaOptimizedImageButton) roleBasedButton.findViewById(
+                R.id.car_nav_button_icon_image)).getDrawable();
+
+        assertThat(currentDrawable).isEqualTo(appIcon);
+    }
+
+    @Test
+    public void onUnselected_withAppIcon_applyUnselectedAlpha() {
+        CarNavigationButton roleBasedButton = mTestView.findViewById(R.id.role_based_button);
+
+        roleBasedButton.setSelected(false);
+        roleBasedButton.setAppIcon(getContext().getDrawable(R.drawable.ic_android));
+
+        assertThat(roleBasedButton.getAlpha()).isEqualTo(
+                CarNavigationButton.DEFAULT_UNSELECTED_ALPHA);
+    }
+
+    @Test
+    public void onSelected_withAppIcon_showsAppIconWithSelectedAlpha() {
+        CarNavigationButton roleBasedButton = mTestView.findViewById(R.id.role_based_button);
+        Drawable appIcon = getContext().getDrawable(R.drawable.ic_android);
+
+        roleBasedButton.setSelected(true);
+        roleBasedButton.setAppIcon(appIcon);
+
+        Drawable currentDrawable = ((AlphaOptimizedImageButton) roleBasedButton.findViewById(
+                R.id.car_nav_button_icon_image)).getDrawable();
+
+        assertThat(currentDrawable).isEqualTo(appIcon);
+    }
+
+    @Test
+    public void onSelected_withAppIcon_applySelectedAlpha() {
+        CarNavigationButton roleBasedButton = mTestView.findViewById(R.id.role_based_button);
+
+        roleBasedButton.setSelected(true);
+        roleBasedButton.setAppIcon(getContext().getDrawable(R.drawable.ic_android));
+
+        assertThat(roleBasedButton.getAlpha()).isEqualTo(
+                CarNavigationButton.DEFAULT_SELECTED_ALPHA);
+    }
+
+    @Test
     public void onClick_launchesIntentActivity() {
         mDefaultButton.performClick();
 
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index ac4e1ea..5afe2f3d 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -50,6 +50,7 @@
         "SettingsLibAdaptiveIcon",
         "SettingsLibRadioButtonPreference",
         "SettingsLibDisplayDensityUtils",
+        "SettingsLibUtils",
     ],
 }
 
diff --git a/packages/SettingsLib/Utils/Android.bp b/packages/SettingsLib/Utils/Android.bp
new file mode 100644
index 0000000..c5f0ee6
--- /dev/null
+++ b/packages/SettingsLib/Utils/Android.bp
@@ -0,0 +1,15 @@
+android_library {
+    name: "SettingsLibUtils",
+
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+
+    sdk_version: "system_current",
+    min_sdk_version: "21",
+
+    apex_available: [
+
+        "//apex_available:platform",
+        "com.android.permission",
+    ],
+}
diff --git a/packages/SettingsLib/Utils/AndroidManifest.xml b/packages/SettingsLib/Utils/AndroidManifest.xml
new file mode 100644
index 0000000..fd89676
--- /dev/null
+++ b/packages/SettingsLib/Utils/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.settingslib.utils">
+
+    <uses-sdk android:minSdkVersion="21" />
+
+</manifest>
diff --git a/packages/SettingsLib/Utils/res/values/strings.xml b/packages/SettingsLib/Utils/res/values/strings.xml
new file mode 100644
index 0000000..035e7f2
--- /dev/null
+++ b/packages/SettingsLib/Utils/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- 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>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/Utils/src/com/android/settingslib/utils/applications/AppUtils.java b/packages/SettingsLib/Utils/src/com/android/settingslib/utils/applications/AppUtils.java
new file mode 100644
index 0000000..6125b85
--- /dev/null
+++ b/packages/SettingsLib/Utils/src/com/android/settingslib/utils/applications/AppUtils.java
@@ -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.settingslib.utils.applications;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.UserManager;
+import android.util.Log;
+
+import com.android.settingslib.utils.R;
+
+public class AppUtils {
+
+    private static final String TAG = AppUtils.class.getSimpleName();
+
+    /** Returns the label for a given package. */
+    public static CharSequence getApplicationLabel(
+            PackageManager packageManager, String packageName) {
+        try {
+            final ApplicationInfo appInfo =
+                    packageManager.getApplicationInfo(
+                            packageName,
+                            PackageManager.MATCH_DISABLED_COMPONENTS
+                                    | PackageManager.MATCH_ANY_USER);
+            return appInfo.loadLabel(packageManager);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.w(TAG, "Unable to find info for package: " + packageName);
+        }
+        return null;
+    }
+
+    /**
+     * Returns a content description of an app name which distinguishes a personal app from a
+     * work app for accessibility purpose.
+     * If the app is in a work profile, then add a "work" prefix to the app name.
+     */
+    public static String getAppContentDescription(Context context, String packageName,
+            int userId) {
+        final CharSequence appLabel = getApplicationLabel(context.getPackageManager(), packageName);
+        return context.getSystemService(UserManager.class).isManagedProfile(userId)
+                ? context.getString(R.string.accessibility_work_profile_app_description, appLabel)
+                : appLabel.toString();
+    }
+}
diff --git a/packages/SettingsLib/res/drawable/ic_headphone.xml b/packages/SettingsLib/res/drawable/ic_headphone.xml
new file mode 100644
index 0000000..3b44f8f
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_headphone.xml
@@ -0,0 +1,29 @@
+<!--
+  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"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="#000000"
+        android:pathData="M19,15v3c0,0.55 -0.45,1 -1,1h-1v-4h2M7,15v4H6c-0.55,
+        0 -1,-0.45 -1,-1v-3h2m5,-13c-4.97,0 -9,4.03 -9,9v7c0,1.66 1.34,3 3,3h3v-8H5v-2c0,
+        -3.87 3.13,-7 7,-7s7,3.13 7,7v2h-4v8h3c1.66,0 3,-1.34 3,-3v-7c0,-4.97 -4.03,
+        -9 -9,-9z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/drawable/ic_media_device.xml b/packages/SettingsLib/res/drawable/ic_media_device.xml
deleted file mode 100644
index 5a6aeb4..0000000
--- a/packages/SettingsLib/res/drawable/ic_media_device.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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:viewportWidth="24"
-        android:viewportHeight="24"
-        android:width="24dp"
-        android:height="24dp"
-        android:tint="?android:attr/colorControlNormal">
-    <path
-        android:fillColor="#00000000"
-        android:fillAlpha=".1"
-        android:pathData="M0 0h24v24H0z" />
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M0 0h24v24H0z" />
-    <path
-        android:fillColor="#000000"
-        android:pathData="M21 3H3c-1.1 0-2 0.9-2 2v3h2V5h18v14h-7v2h7c1.1 0 2 -0.9 2-2V5c0-1.1 -0.9-2-2-2zM1 18v3h3c0-1.66-1.34-3-3-3zm0-4v2c2.76 0 5 2.24 5 5h2c0-3.87-3.13-7-7-7zm0-4v2c4.97 0 9 4.03 9 9h2c0-6.08-4.93-11-11-11z" />
-</vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/drawable/ic_media_display_device.xml b/packages/SettingsLib/res/drawable/ic_media_display_device.xml
new file mode 100644
index 0000000..78b4e2a
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_media_display_device.xml
@@ -0,0 +1,30 @@
+<?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="14dp"
+        android:height="11dp"
+        android:viewportWidth="14"
+        android:viewportHeight="11"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:pathData="M10,10v1H4v-1H1.5A1.5,1.5 0,0 1,0 8.5v-7A1.5,1.5 0,
+        0 1,1.5 0h11A1.5,1.5 0,0 1,14 1.5v7a1.5,1.5 0,0 1,-1.5 1.5H10zM1.5,
+        1a0.5,0.5 0,0 0,-0.5 0.5v7a0.5,0.5 0,0 0,0.5 0.5h11a0.5,0.5 0,0 0,
+        0.5 -0.5v-7a0.5,0.5 0,0 0,-0.5 -0.5h-11z"
+        android:fillColor="#000000"
+        android:fillType="evenOdd"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/drawable/ic_media_group_device.xml b/packages/SettingsLib/res/drawable/ic_media_group_device.xml
index ba5e651..478a860 100644
--- a/packages/SettingsLib/res/drawable/ic_media_group_device.xml
+++ b/packages/SettingsLib/res/drawable/ic_media_group_device.xml
@@ -21,12 +21,16 @@
         android:viewportHeight="24"
         android:tint="?android:attr/colorControlNormal">
     <path
-        android:pathData="M18.2,1L9.8,1C8.81,1 8,1.81 8,2.8v14.4c0,0.99 0.81,1.79 1.8,1.79l8.4,0.01c0.99,0 1.8,-0.81 1.8,-1.8L20,2.8c0,-0.99 -0.81,-1.8 -1.8,-1.8zM14,3c1.1,0 2,0.89 2,2s-0.9,2 -2,2 -2,-0.89 -2,-2 0.9,-2 2,-2zM14,16.5c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4z"
-        android:fillColor="#000000"/>
+        android:fillColor="#000000"
+        android:pathData="M19,4v14l-10,-0.01V4h10m0,-2H9c-1.1,0 -2,0.9 -2,2v13.99c0,1.1 0.89,
+        2 2,2L19,20c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2z"/>
     <path
-        android:pathData="M14,12.5m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"
-        android:fillColor="#000000"/>
+        android:fillColor="#000000"
+        android:pathData="M14,7m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
     <path
-        android:pathData="M6,5H4v16c0,1.1 0.89,2 2,2h10v-2H6V5z"
-        android:fillColor="#000000"/>
+        android:fillColor="#000000"
+        android:pathData="M14,17c1.93,0 3.5,-1.57 3.5,-3.5S15.93,10 14,10s-3.5,
+        1.57 -3.5,3.5S12.07,17 14,17zM14,12c0.83,0 1.5,0.67 1.5,1.5S14.83,15 14,
+        15s-1.5,-0.67 -1.5,-1.5 0.67,-1.5 1.5,-1.5zM6,5L4,5v16c0,1.1 0.89,2 2,
+        2h10v-2L6,21L6,5z"/>
 </vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/drawable/ic_media_speaker_device.xml b/packages/SettingsLib/res/drawable/ic_media_speaker_device.xml
new file mode 100644
index 0000000..32fe7d1
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_media_speaker_device.xml
@@ -0,0 +1,30 @@
+<!--
+  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"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="#000000"
+        android:pathData="M17,2L7,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,1.99 2,1.99L17,
+        22c1.1,0 2,-0.9 2,-2L19,4c0,-1.1 -0.9,-2 -2,-2zM7,20L7,4h10v16L7,20zM12,9c1.1,0 2,
+        -0.9 2,-2s-0.9,-2 -2,-2c-1.11,0 -2,0.9 -2,2s0.89,2 2,2zM12,11c-2.21,0 -4,1.79 -4,
+        4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,
+        0.9 2,2 -0.9,2 -2,2z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/drawable/ic_smartphone.xml b/packages/SettingsLib/res/drawable/ic_smartphone.xml
index 84a96da..09811bb 100644
--- a/packages/SettingsLib/res/drawable/ic_smartphone.xml
+++ b/packages/SettingsLib/res/drawable/ic_smartphone.xml
@@ -21,9 +21,8 @@
         android:height="24dp"
         android:tint="?android:attr/colorControlNormal">
     <path
-        android:fillColor="#00000000"
-        android:pathData="M0 0h24v24H0z" />
-    <path
         android:fillColor="#000000"
-        android:pathData="M17 1.01L7 1c-1.1 0-2 0.9-2 2v18c0 1.1 0.9 2 2 2h10c1.1 0 2 -0.9 2-2V3c0-1.1 -0.9-1.99-2-1.99zM17 19H7V5h10v14z" />
+        android:pathData="M17,1.01L7,1c-1.1,0 -2,0.9 -2,2v18c0,1.1 0.9,
+        2 2,2h10c1.1,0 2,-0.9 2,-2L19,3c0,-1.1 -0.9,-1.99 -2,-1.99zM17,
+        21L7,21v-1h10v1zM17,18L7,18L7,6h10v12zM7,4L7,3h10v1L7,4z"/>
 </vector>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 66787c2..35e2295 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Bedraade oorfoon"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index ead0ebf..25cea4d 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ባለገመድ ጆሮ ማዳመጫ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index c1f4fd9..bd94c40 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -558,6 +558,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"سمّاعة رأس سلكية"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index b5d642a..5572994 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"তাঁৰযুক্ত হেডফ\'ন"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index aecaf70..39ab078 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Simli qulaqlıq"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 092bd42..78fd0bf 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -555,6 +555,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Žičane slušalice"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index d610973..30a9e0e 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -556,6 +556,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Правадныя навушнікі"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 5c3fe75..c8dd82f 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Слушалки с кабел"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 27d3707..02ca679 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"তার যুক্ত হেডফোন"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index a9d9e70..785460f 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -555,6 +555,5 @@
     <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">"Poslovna aplikacija <xliff:g id="APP_NAME">%s</xliff:g>"</string>
-    <!-- no translation found for media_transfer_wired_usb_device_name (7699141088423210903) -->
-    <skip />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Žičane slušalice"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 5ed0f1b..50c0374 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Auriculars amb cable"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index d4d3735..9fb63ea 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -556,6 +556,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Kabelová sluchátka"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 89dbf25..dc4f873 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Høretelefoner med ledning"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index c2030b1..bee2d79 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Kabelgebundene Kopfhörer"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index bfc183e..b1d07ac 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Ενσύρματα ακουστικά"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 9d869ba..e51456a 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphone"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 9d869ba..e51456a 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphone"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 9d869ba..e51456a 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphone"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 9d869ba..e51456a 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphone"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 7765824..34ff568 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎‏‎‎‎‏‏‎‏‏‏‏‏‎‎‏‎‏‏‏‎Wired headphone‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 6a76beb..fb5e9d7 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -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 se establecieron configuraciones predeterminadas"</string>
+    <string name="launch_defaults_none" msgid="8049374306261262709">"Sin 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>
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Auriculares con cable"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 010b85b..a6a89dd 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Auriculares con cable"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index ad2a561..65f1043 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Juhtmega kõrvaklapid"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 1ceb738..6864db1 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Entzungailu kableduna"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index d3f1c56..5e13c1b 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"هدفون سیمی"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 5ab01c4b..1ec71c7 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Langalliset kuulokkeet"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 26e5042..0a32ca5 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Écouteurs filaires"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index b8fc50d..bb069b5 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Casque filaire"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 8dc58ef..a27f2c4 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Auriculares con cable"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 9f69a2c..cf1e5ee 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"વાયરવાળો હૅડફોન"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index dc8e28b..89b7f67 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"वायर वाला हेडफ़ोन"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index f887839..f57a302 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -555,6 +555,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Žičane slušalice"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index d7d2694..e8699dc 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Vezetékes fejhallgató"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index a5ef6b5..3f2b414 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Լարով ականջակալ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 04ca2f6..dd1f999 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Headphone berkabel"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index ce60eb5..5dad63d 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Heyrnartól með snúru"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index bef644b..02b8533 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Cuffie con cavo"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index ed79632..af6a870 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -556,6 +556,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"אוזניות עם חוט"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 3f08a6a..080c1a9 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有線ヘッドフォン"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 2ebc3ee..23de5b2 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"სადენიანი ყურსასმენი"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 91e5488..821c566 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Сымды құлақаспап"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 143f5f9..f93ab25 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"កាស​មានខ្សែ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 1df141c..e418779 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ವೈಯರ್ ಹೊಂದಿರುವ ಹೆಡ್‌ಫೋನ್"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 86e1650..6b273a3 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"유선 헤드폰"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 925f4a7..d035362 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Зымдуу гарнитура"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 3bf1996..e188f3d 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ຫູຟັງແບບມີສາຍ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 153c995..075032c 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -556,6 +556,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Laidinės ausinės"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index f6e7f35..c37811f 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -555,6 +555,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Vadu austiņas"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index d55f1af..1f5908c 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Жичени слушалки"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index c5267d6..6ee9777 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"വയർ മുഖേന ബന്ധിപ്പിച്ച ഹെഡ്ഫോൺ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 0a01f84..29647df 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Утастай чихэвч"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 075c748..99bf1e8 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"वायर असलेला हेडफोन"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index cdf32a7..bdecf64 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Fon kepala berwayar"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 2bd3b45..1519380 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ကြိုးတပ်နားကြပ်"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index de5bed6..a2f862e 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Hodetelefoner med kabel"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index bfe295a..159050e 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"तारसहितको हेडफोन"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index a822719..7e3005b 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Bedrade hoofdtelefoon"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index ab9fbc3..19e250b 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ତାରଯୁକ୍ତ ହେଡଫୋନ୍"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 35d8cba..184f4cd 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ਤਾਰ ਵਾਲੇ ਹੈੱਡਫ਼ੋਨ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 54ed131..eebea5f 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -556,6 +556,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Słuchawki przewodowe"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index c6dc1d3..142ef47 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Fones de ouvido com fio"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 999e684..0c6f488 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Auscultadores com fios"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index c6dc1d3..142ef47 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Fones de ouvido com fio"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index ba2f36f..036cf83 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -555,6 +555,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Căști cu fir"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 8ec3875..6b39754 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -556,6 +556,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Проводные наушники"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 01c3634..9074c63 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"රැහැන්ගත කළ හෙඩ්ෆෝන්"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index b5cbf43..cd3109f 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -556,6 +556,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Slúchadlá s káblom"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 86cccb8..0e492c7 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -556,6 +556,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Žične slušalke"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index bd3353c..4a80bcd 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Kufje me tela"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 29f23b4..321645e 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -555,6 +555,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Жичане слушалице"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index a40100e..cd28c86b 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Hörlurar med sladd"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index fedf1c8..2bc038e 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Vipokea sauti vyenye waya vinavyobanwa kichwani"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 345f0a7..a28fdce 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"வயருள்ள ஹெட்ஃபோன்"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index c4fda01..b7bb6e8 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"వైర్ ఉన్న హెడ్‌ఫోన్"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index a9032eb..2f9ac46 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"หูฟังแบบมีสาย"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 712c06b..5064c1e 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired na headphone"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 8818498..454ca3b 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Kablolu kulaklık"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index f6568e3..7e969f7 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -556,6 +556,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Дротові навушники"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index f13f8fb..e3b28c7 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"وائرڈ ہیڈ فون"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 7b8f627..04707c5 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Simli quloqlik"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 35cecc1..e7fbf46 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Tai nghe có dây"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index c69ea2d..bda7d8b 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有线耳机"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index b0324d9..841de63 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有線耳機"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 0574c7e..a6c1647 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -554,6 +554,5 @@
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有線耳機"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index b60553a..c437580 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -554,6 +554,5 @@
     <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>
     <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 />
+    <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Ama-headphone anentambo"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 9c7bdbd..8e8368f 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1374,9 +1374,6 @@
     <!-- Developer setting dialog prompting the user to reboot after changing the app freezer setting [CHAR LIMIT=NONE]-->
     <string name="cached_apps_freezer_reboot_dialog_text">Your device must be rebooted for this change to apply. Reboot now or cancel.</string>
 
-    <!-- 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=50] -->
     <string name="media_transfer_wired_usb_device_name">Wired headphone</string>
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java b/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java
index b1f2a39..a6202956 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java
@@ -26,7 +26,6 @@
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.util.Log;
 
 import com.android.settingslib.R;
@@ -112,17 +111,8 @@
     /** Returns the label for a given package. */
     public static CharSequence getApplicationLabel(
             PackageManager packageManager, String packageName) {
-        try {
-            final ApplicationInfo appInfo =
-                    packageManager.getApplicationInfo(
-                            packageName,
-                            PackageManager.MATCH_DISABLED_COMPONENTS
-                                    | PackageManager.MATCH_ANY_USER);
-            return appInfo.loadLabel(packageManager);
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.w(TAG, "Unable to find info for package: " + packageName);
-        }
-        return null;
+        return com.android.settingslib.utils.applications.AppUtils
+                .getApplicationLabel(packageManager, packageName);
     }
 
     /**
@@ -160,9 +150,7 @@
      */
     public static String getAppContentDescription(Context context, String packageName,
             int userId) {
-        final CharSequence appLabel = getApplicationLabel(context.getPackageManager(), packageName);
-        return UserManager.get(context).isManagedProfile(userId)
-                ? context.getString(R.string.accessibility_work_profile_app_description, appLabel)
-                : appLabel.toString();
+        return com.android.settingslib.utils.applications.AppUtils.getAppContentDescription(context,
+                packageName, userId);
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index af72888..1d4cfdc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -500,6 +500,20 @@
         }
     }
 
+    /**
+     * To generate and cache the label description.
+     *
+     * @param entry contain the entries of an app
+     */
+    public void ensureLabelDescription(AppEntry entry) {
+        if (entry.labelDescription != null) {
+            return;
+        }
+        synchronized (entry) {
+            entry.ensureLabelDescriptionLocked(mContext);
+        }
+    }
+
     public void requestSize(String packageName, int userId) {
         if (DEBUG_LOCKING) Log.v(TAG, "requestSize about to acquire lock...");
         synchronized (mEntriesMap) {
@@ -1524,6 +1538,7 @@
         public long size;
         public long internalSize;
         public long externalSize;
+        public String labelDescription;
 
         public boolean mounted;
 
@@ -1616,6 +1631,24 @@
                 return "";
             }
         }
+
+        /**
+         * Get the label description which distinguishes a personal app from a work app for
+         * accessibility purpose. If the app is in a work profile, then add a "work" prefix to the
+         * app label.
+         *
+         * @param context The application context
+         */
+        public void ensureLabelDescriptionLocked(Context context) {
+            final int userId = UserHandle.getUserId(this.info.uid);
+            if (UserManager.get(context).isManagedProfile(userId)) {
+                this.labelDescription = context.getString(
+                        com.android.settingslib.R.string.accessibility_work_profile_app_description,
+                        this.label);
+            } else {
+                this.labelDescription = this.label;
+            }
+        }
     }
 
     private static boolean hasFlag(int flags, int flag) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
index a2f77e2..40d8048 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
@@ -59,12 +59,18 @@
     public Drawable getIcon() {
         final Pair<Drawable, String> pair = BluetoothUtils
                 .getBtRainbowDrawableWithDescription(mContext, mCachedDevice);
-        return pair.first;
+        return isFastPairDevice()
+                ? pair.first
+                : BluetoothUtils.buildBtRainbowDrawable(mContext,
+                        mContext.getDrawable(R.drawable.ic_headphone),
+                        mCachedDevice.getAddress().hashCode());
     }
 
     @Override
     public Drawable getIconWithoutBackground() {
-        return BluetoothUtils.getBtDrawableWithDescription(mContext, mCachedDevice).first;
+        return isFastPairDevice()
+                ? BluetoothUtils.getBtDrawableWithDescription(mContext, mCachedDevice).first
+                : mContext.getDrawable(R.drawable.ic_headphone);
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
index 22dc906..8d6bc5c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
@@ -73,9 +73,11 @@
                 resId = R.drawable.ic_media_group_device;
                 break;
             case TYPE_REMOTE_TV:
+                resId = R.drawable.ic_media_display_device;
+                break;
             case TYPE_REMOTE_SPEAKER:
             default:
-                resId = R.drawable.ic_media_device;
+                resId = R.drawable.ic_media_speaker_device;
                 break;
         }
         return resId;
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index 959c42fe..b83a9c4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -219,6 +219,33 @@
     }
 
     /**
+     * Get the MediaDevice list that can be removed from current media session.
+     *
+     * @return list of MediaDevice
+     */
+    List<MediaDevice> getDeselectableMediaDevice() {
+        final List<MediaDevice> deviceList = new ArrayList<>();
+        if (TextUtils.isEmpty(mPackageName)) {
+            Log.d(TAG, "getDeselectableMediaDevice() package name is null or empty!");
+            return deviceList;
+        }
+
+        final RoutingSessionInfo info = getRoutingSessionInfo();
+        if (info != null) {
+            for (MediaRoute2Info route : mRouterManager.getDeselectableRoutes(info)) {
+                deviceList.add(new InfoMediaDevice(mContext, mRouterManager,
+                        route, mPackageName));
+                Log.d(TAG, route.getName() + " is deselectable for " + mPackageName);
+            }
+            return deviceList;
+        }
+        Log.d(TAG, "getDeselectableMediaDevice() cannot found deselectable MediaDevice from : "
+                + mPackageName);
+
+        return deviceList;
+    }
+
+    /**
      * Get the MediaDevice list that has been selected to current media.
      *
      * @return list of MediaDevice
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index f34903c..e89f628 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -308,6 +308,15 @@
     }
 
     /**
+     * Get the MediaDevice list that can be removed from current media session.
+     *
+     * @return list of MediaDevice
+     */
+    public List<MediaDevice> getDeselectableMediaDevice() {
+        return mInfoMediaManager.getDeselectableMediaDevice();
+    }
+
+    /**
      * Release session to stop playing media on MediaDevice.
      */
     public boolean releaseSession() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/ConversationIconFactory.java b/packages/SettingsLib/src/com/android/settingslib/notification/ConversationIconFactory.java
index 9dc454f..d5f1ece 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/ConversationIconFactory.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/ConversationIconFactory.java
@@ -22,6 +22,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ShortcutInfo;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.ColorFilter;
 import android.graphics.Paint;
 import android.graphics.Rect;
@@ -40,18 +41,31 @@
  * also includes shadows, which are only appropriate on top of wallpaper, not embedded in UI.
  */
 public class ConversationIconFactory extends BaseIconFactory {
-    // Geometry of the various parts of the design. All values are 1dp on a 48x48dp icon grid.
+    // Geometry of the various parts of the design. All values are 1dp on a 56x56dp icon grid.
     // Space is left around the "head" (main avatar) for
     // ........
     // .HHHHHH.
     // .HHHrrrr
     // .HHHrBBr
     // ....rrrr
+    // This is trying to recreate the view layout in notification_template_material_conversation.xml
 
-    private static final float BASE_ICON_SIZE = 48f;
-    private static final float RING_STROKE_WIDTH = 2f;
-    private static final float HEAD_SIZE = BASE_ICON_SIZE - RING_STROKE_WIDTH * 2 - 2; // 40
-    private static final float BADGE_SIZE = HEAD_SIZE * 0.4f; // 16
+    private static final float HEAD_SIZE = 52f;
+    private static final float BADGE_SIZE = 12f;
+    private static final float BADGE_CENTER = 46f;
+    private static final float CIRCLE_MARGIN = 36f;
+    private static final float BADGE_ORIGIN = HEAD_SIZE - BADGE_SIZE; // 40f
+    private static final float BASE_ICON_SIZE = 56f;
+
+    private static final float OUT_CIRCLE_DIA = (BASE_ICON_SIZE - CIRCLE_MARGIN); // 20f
+    private static final float INN_CIRCLE_DIA = (float) Math.sqrt(2 * BADGE_SIZE * BADGE_SIZE) ;
+    private static final float OUT_CIRCLE_RAD = OUT_CIRCLE_DIA / 2;
+    private static final float INN_CIRCLE_RAD = INN_CIRCLE_DIA / 2;
+    // Android draws strokes centered on the radius, so our actual radius is an avg of the outside
+    // and inside of the ring stroke
+    private static final float CIRCLE_RADIUS =
+            INN_CIRCLE_RAD + ((OUT_CIRCLE_RAD - INN_CIRCLE_RAD) / 2);
+    private static final float RING_STROKE_WIDTH = (OUT_CIRCLE_DIA - INN_CIRCLE_DIA) / 2;
 
     final LauncherApps mLauncherApps;
     final PackageManager mPackageManager;
@@ -125,6 +139,7 @@
         private int mIconSize;
         private Paint mRingPaint;
         private boolean mShowRing;
+        private Paint mPaddingPaint;
 
         public ConversationIconDrawable(Drawable baseIcon,
                 Drawable badgeIcon,
@@ -138,6 +153,9 @@
             mRingPaint = new Paint();
             mRingPaint.setStyle(Paint.Style.STROKE);
             mRingPaint.setColor(ringColor);
+            mPaddingPaint = new Paint();
+            mPaddingPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+            mPaddingPaint.setColor(Color.WHITE);
         }
 
         /**
@@ -165,40 +183,38 @@
         public void draw(Canvas canvas) {
             final Rect bounds = getBounds();
 
-            // scale to our internal 48x48 grid
+            // scale to our internal grid
             final float scale = bounds.width() / BASE_ICON_SIZE;
-            final int centerX = bounds.centerX();
-            final int centerY = bounds.centerX();
             final int ringStrokeWidth = (int) (RING_STROKE_WIDTH * scale);
             final int headSize = (int) (HEAD_SIZE * scale);
-            final int badgeSize = (int) (BADGE_SIZE * scale);
+            final int badgePadding = (int) (BADGE_ORIGIN * scale);
+            final int badgeCenter = (int) (BADGE_CENTER * scale);
 
+            mPaddingPaint.setStrokeWidth(ringStrokeWidth);
+            final float radius = (int) (CIRCLE_RADIUS * scale); // stroke outside
             if (mBaseIcon != null) {
-                mBaseIcon.setBounds(
-                        centerX - headSize / 2,
-                        centerY - headSize / 2,
-                        centerX + headSize / 2,
-                        centerY + headSize / 2);
+                mBaseIcon.setBounds(0,
+                        0,
+                        headSize ,
+                        headSize);
                 mBaseIcon.draw(canvas);
             } else {
                 Log.w("ConversationIconFactory", "ConversationIconDrawable has null base icon");
             }
             if (mBadgeIcon != null) {
+                canvas.drawCircle(badgeCenter, badgeCenter, radius, mPaddingPaint);
                 mBadgeIcon.setBounds(
-                        bounds.right - badgeSize - ringStrokeWidth,
-                        bounds.bottom - badgeSize - ringStrokeWidth,
-                        bounds.right - ringStrokeWidth,
-                        bounds.bottom - ringStrokeWidth);
+                        badgePadding,
+                        badgePadding,
+                        headSize,
+                        headSize);
                 mBadgeIcon.draw(canvas);
             } else {
                 Log.w("ConversationIconFactory", "ConversationIconDrawable has null badge icon");
             }
             if (mShowRing) {
                 mRingPaint.setStrokeWidth(ringStrokeWidth);
-                final float radius = badgeSize * 0.5f + ringStrokeWidth * 0.5f; // stroke outside
-                final float cx = bounds.right - badgeSize * 0.5f - ringStrokeWidth;
-                final float cy = bounds.bottom - badgeSize * 0.5f - ringStrokeWidth;
-                canvas.drawCircle(cx, cy, radius, mRingPaint);
+                canvas.drawCircle(badgeCenter, badgeCenter, radius, mRingPaint);
             }
         }
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java
index 685c834..49b236a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java
@@ -95,11 +95,13 @@
     public void getDrawableResId_returnCorrectResId() {
         when(mRouteInfo.getType()).thenReturn(TYPE_REMOTE_TV);
 
-        assertThat(mInfoMediaDevice.getDrawableResId()).isEqualTo(R.drawable.ic_media_device);
+        assertThat(mInfoMediaDevice.getDrawableResId()).isEqualTo(
+                R.drawable.ic_media_display_device);
 
         when(mRouteInfo.getType()).thenReturn(TYPE_REMOTE_SPEAKER);
 
-        assertThat(mInfoMediaDevice.getDrawableResId()).isEqualTo(R.drawable.ic_media_device);
+        assertThat(mInfoMediaDevice.getDrawableResId()).isEqualTo(
+                R.drawable.ic_media_speaker_device);
 
         when(mRouteInfo.getType()).thenReturn(TYPE_GROUP);
 
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 c514671..248eb5b 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
@@ -416,6 +416,31 @@
     }
 
     @Test
+    public void getDeselectableMediaDevice_packageNameIsNull_returnFalse() {
+        mInfoMediaManager.mPackageName = null;
+
+        assertThat(mInfoMediaManager.getDeselectableMediaDevice()).isEmpty();
+    }
+
+    @Test
+    public void getDeselectableMediaDevice_checkList() {
+        final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+        final RoutingSessionInfo info = mock(RoutingSessionInfo.class);
+        routingSessionInfos.add(info);
+        final List<MediaRoute2Info> mediaRoute2Infos = new ArrayList<>();
+        final MediaRoute2Info mediaRoute2Info = mock(MediaRoute2Info.class);
+        mediaRoute2Infos.add(mediaRoute2Info);
+        mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+        mShadowRouter2Manager.setDeselectableRoutes(mediaRoute2Infos);
+        when(mediaRoute2Info.getName()).thenReturn(TEST_NAME);
+
+        final List<MediaDevice> mediaDevices = mInfoMediaManager.getDeselectableMediaDevice();
+
+        assertThat(mediaDevices.size()).isEqualTo(1);
+        assertThat(mediaDevices.get(0).getName()).isEqualTo(TEST_NAME);
+    }
+
+    @Test
     public void adjustSessionVolume_routingSessionInfoIsNull_noCrash() {
         mInfoMediaManager.adjustSessionVolume(null, 10);
     }
diff --git a/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowRouter2Manager.java b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowRouter2Manager.java
index db0cb06..5bb5500 100644
--- a/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowRouter2Manager.java
+++ b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowRouter2Manager.java
@@ -15,6 +15,7 @@
  */
 package com.android.settingslib.testutils.shadow;
 
+import android.annotation.NonNull;
 import android.media.MediaRoute2Info;
 import android.media.MediaRouter2Manager;
 import android.media.RoutingSessionInfo;
@@ -31,6 +32,7 @@
 
     private List<MediaRoute2Info> mAvailableRoutes;
     private List<MediaRoute2Info> mAllRoutes;
+    private List<MediaRoute2Info> mDeselectableRoutes;
     private List<RoutingSessionInfo> mActiveSessions;
     private List<RoutingSessionInfo> mRoutingSessions;
 
@@ -70,6 +72,15 @@
         mRoutingSessions = infos;
     }
 
+    @Implementation
+    public List<MediaRoute2Info> getDeselectableRoutes(@NonNull RoutingSessionInfo sessionInfo) {
+        return mDeselectableRoutes;
+    }
+
+    public void setDeselectableRoutes(List<MediaRoute2Info> routes) {
+        mDeselectableRoutes = routes;
+    }
+
     public static ShadowRouter2Manager getShadow() {
         return (ShadowRouter2Manager) Shadow.extract(
                 MediaRouter2Manager.getInstance(RuntimeEnvironment.application));
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 3d7559b..aae72e5 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1131,6 +1131,10 @@
                 Settings.Global.NSD_ON,
                 GlobalSettingsProto.NSD_ON);
 
+        dumpSetting(s, p,
+                Settings.Global.NR_NSA_TRACKING_SCREEN_OFF_MODE,
+                GlobalSettingsProto.NR_NSA_TRACKING_SCREEN_OFF_MODE);
+
         final long ntpToken = p.start(GlobalSettingsProto.NTP);
         dumpSetting(s, p,
                 Settings.Global.NTP_SERVER,
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index e537b76..fa87b62 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -391,6 +391,7 @@
                     Settings.Global.NITZ_UPDATE_DIFF,
                     Settings.Global.NITZ_UPDATE_SPACING,
                     Settings.Global.NOTIFICATION_SNOOZE_OPTIONS,
+                    Settings.Global.NR_NSA_TRACKING_SCREEN_OFF_MODE,
                     Settings.Global.NSD_ON,
                     Settings.Global.NTP_SERVER,
                     Settings.Global.NTP_TIMEOUT,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index b85c771..a0130f8 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -300,6 +300,9 @@
     <!-- Permissions needed to test shared libraries -->
     <uses-permission android:name="android.permission.ACCESS_SHARED_LIBRARIES" />
 
+    <!-- Permissions required for CTS test - TVInputManagerTest -->
+    <uses-permission android:name="android.permission.TV_INPUT_HARDWARE" />
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 055b2be..985269b 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -607,7 +607,7 @@
                   android:excludeFromRecents="true"
                   android:stateNotNeeded="true"
                   android:resumeWhilePausing="true"
-                  android:theme="@android:style/Theme.Black.NoTitleBar">
+                  android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen">
             <intent-filter>
                 <action android:name="android.app.action.CONFIRM_DEVICE_CREDENTIAL_WITH_USER" />
                 <category android:name="android.intent.category.DEFAULT" />
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index c8cf7f50..28491d6 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -41,6 +41,7 @@
 tsuji@google.com
 twickham@google.com
 winsonc@google.com
+zakcohen@google.com
 
 #Android Auto
 stenning@google.com
diff --git a/packages/SystemUI/res-product/values/strings.xml b/packages/SystemUI/res-product/values/strings.xml
index 54e5d41..f1c539e 100644
--- a/packages/SystemUI/res-product/values/strings.xml
+++ b/packages/SystemUI/res-product/values/strings.xml
@@ -122,4 +122,12 @@
        Try again in <xliff:g id="number">%3$d</xliff:g> seconds.
     </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>
+
 </resources>
diff --git a/packages/SystemUI/res/drawable/stat_sys_media.xml b/packages/SystemUI/res/drawable/stat_sys_media.xml
deleted file mode 100644
index d48db7b..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_media.xml
+++ /dev/null
@@ -1,31 +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.
-  -->
-
-<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/controls_more_item.xml b/packages/SystemUI/res/layout/controls_more_item.xml
index f24850e..df03787 100644
--- a/packages/SystemUI/res/layout/controls_more_item.xml
+++ b/packages/SystemUI/res/layout/controls_more_item.xml
@@ -18,5 +18,7 @@
     style="@style/Control.MenuItem"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_gravity="start" />
+    android:layout_gravity="start"
+    android:paddingStart="@dimen/control_menu_horizontal_padding"
+    android:paddingEnd="@dimen/control_menu_horizontal_padding"/>
 
diff --git a/packages/SystemUI/res/layout/keyguard_media_header.xml b/packages/SystemUI/res/layout/keyguard_media_header.xml
index a520719..63a878f 100644
--- a/packages/SystemUI/res/layout/keyguard_media_header.xml
+++ b/packages/SystemUI/res/layout/keyguard_media_header.xml
@@ -24,25 +24,4 @@
     android:paddingEnd="0dp"
     android:focusable="true"
     android:clickable="true"
->
-
-    <!-- Background views required by ActivatableNotificationView. -->
-    <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
-        android:id="@+id/backgroundNormal"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-    />
-
-    <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
-        android:id="@+id/backgroundDimmed"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-    />
-
-    <com.android.systemui.statusbar.notification.FakeShadowView
-        android:id="@+id/fake_shadow"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-    />
-
-</com.android.systemui.statusbar.notification.stack.MediaHeaderView>
+/>
diff --git a/packages/SystemUI/res/layout/qs_media_panel.xml b/packages/SystemUI/res/layout/media_view.xml
similarity index 85%
rename from packages/SystemUI/res/layout/qs_media_panel.xml
rename to packages/SystemUI/res/layout/media_view.xml
index bf06242..1a1fddb 100644
--- a/packages/SystemUI/res/layout/qs_media_panel.xml
+++ b/packages/SystemUI/res/layout/media_view.xml
@@ -16,7 +16,7 @@
   -->
 
 <!-- Layout for media controls inside QSPanel carousel -->
-<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.systemui.util.animation.TransitionLayout 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"
@@ -24,18 +24,7 @@
     android:clipChildren="false"
     android:clipToPadding="false"
     android:gravity="center_horizontal|fill_vertical"
-    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"
-        />
+    android:background="@drawable/qs_media_background">
 
     <FrameLayout
         android:id="@+id/notification_media_progress_time"
@@ -185,15 +174,5 @@
     <!-- Buttons to remove this view when no longer needed -->
     <include
         layout="@layout/qs_media_panel_options"
-        android:visibility="gone"
-        app:layout_constraintEnd_toEndOf="@id/view_width"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <androidx.constraintlayout.widget.Guideline
-        android:id="@+id/view_width"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        app:layout_constraintGuide_begin="300dp" />
-</androidx.constraintlayout.motion.widget.MotionLayout>
+        android:visibility="gone" />
+</com.android.systemui.util.animation.TransitionLayout>
diff --git a/packages/SystemUI/res/layout/notification_conversation_info.xml b/packages/SystemUI/res/layout/notification_conversation_info.xml
index 9f0a9bf..3bd7e04 100644
--- a/packages/SystemUI/res/layout/notification_conversation_info.xml
+++ b/packages/SystemUI/res/layout/notification_conversation_info.xml
@@ -21,33 +21,33 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:focusable="true"
-    android:clipChildren="false"
+    android:clipChildren="true"
     android:clipToPadding="true"
     android:orientation="vertical"
     android:background="@color/notification_material_background_color"
-    android:paddingStart="@*android:dimen/notification_content_margin_start">
+    android:paddingStart="12dp">
 
     <!-- Package Info -->
     <LinearLayout
         android:id="@+id/header"
         android:layout_width="match_parent"
-        android:layout_height="@dimen/notification_guts_conversation_header_height"
+        android:layout_height="wrap_content"
         android:gravity="center_vertical"
         android:clipChildren="false"
-        android:clipToPadding="false">
+        android:paddingTop="8dp"
+        android:clipToPadding="true">
         <ImageView
             android:id="@+id/conversation_icon"
             android:layout_width="@dimen/notification_guts_conversation_icon_size"
             android:layout_height="@dimen/notification_guts_conversation_icon_size"
-            android:layout_centerVertical="true"
+            android:layout_centerVertical="false"
             android:layout_alignParentStart="true"
-            android:layout_marginEnd="15dp" />
+            android:layout_marginEnd="12dp" />
         <LinearLayout
             android:id="@+id/names"
             android:layout_weight="1"
             android:layout_width="0dp"
             android:orientation="vertical"
-
             android:layout_height="wrap_content"
             android:minHeight="@dimen/notification_guts_conversation_icon_size"
             android:layout_centerVertical="true"
@@ -63,6 +63,8 @@
                     android:id="@+id/parent_channel_name"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
+                    android:ellipsize="end"
+                    android:textDirection="locale"
                     android:layout_weight="1"
                     style="@style/TextAppearance.NotificationImportanceChannel"/>
                 <TextView
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index e8e0133..af5a8f4 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -46,7 +46,6 @@
             android:layout_weight="1"
             android:layout_width="0dp"
             android:orientation="vertical"
-
             android:layout_height="wrap_content"
             android:minHeight="@dimen/notification_guts_conversation_icon_size"
             android:layout_centerVertical="true"
@@ -57,6 +56,7 @@
                 android:id="@+id/channel_name"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:textDirection="locale"
                 style="@style/TextAppearance.NotificationImportanceChannel"/>
             <LinearLayout
                 android:layout_width="match_parent"
@@ -84,6 +84,7 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
+                    android:textDirection="locale"
                     style="@style/TextAppearance.NotificationImportanceChannelGroup"/>
             </LinearLayout>
             <TextView
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 17469cd..9e6b80b 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoem om skerm te vul"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Strek om skerm te vul"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skermkiekie"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Ontsluit jou foon vir meer opsies"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Ontsluit jou tablet vir meer opsies"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Ontsluit jou toestel vir meer opsies"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"het \'n prent gestuur"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Stoor tans skermkiekie..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Stoor tans skermkiekie..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Ligging deur GPS gestel"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Liggingversoeke aktief"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensors Af is aktief"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Media is aktief"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Verwyder alle kennisgewings."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Bestuur"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Geskiedenis"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Inkomend"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Stil"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Kennisgewings"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Gesprekke"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Vee alle stil kennisgewings uit"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Kennisgewings onderbreek deur Moenie Steur Nie"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Skakel kennisgewings af"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Hou aan om kennisgewings van hierdie program af te wys?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Stil"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Verstek"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Borrel"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Geen klank of vibrasie nie"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Geen klank of vibrasie nie en verskyn laer in gespreksafdeling"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Kan lui of vibreer op grond van fooninstellings"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan lui of vibreer op grond van fooninstellings. Gesprekke van <xliff:g id="APP_NAME">%1$s</xliff:g> af verskyn by verstek in \'n borrel."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Hou jou aandag met \'n swewende kortpad na hierdie inhoud toe."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Wys boaan die gespreksafdeling, verskyn as \'n swewende borrel, wys profielfoto op sluitskerm"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Instellings"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioriteit"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> steun nie gesprekspesifieke-instellings nie"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index b40a617..2271946 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ማያ እንዲሞላ አጉላ"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ማያ ለመሙለት ሳብ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ቅጽበታዊ ገጽ እይታ"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"ለተጨማሪ አማራጮች የእርስዎን ስልክ ይክፈቱ"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"ለተጨማሪ አማራጮች የእርስዎን ጡባዊ ይክፈቱ"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"ለተጨማሪ አማራጮች የእርስዎን መሣሪያ ይክፈቱ"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ምስል ተልኳል"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ቅጽበታዊ ገጽ እይታ በማስቀመጥ ላይ..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ቅጽበታዊ ገጽ እይታ በማስቀመጥ ላይ..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"በ GPS የተዘጋጀ ሥፍራ"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"የአካባቢ ጥያቄዎች ነቅተዋል"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"ዳሳሾች ጠፍተዋል ገቢር"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"ሚዲያ ገቢር ነው"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"ሁሉንም ማሳወቂያዎች አጽዳ"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"ያቀናብሩ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ታሪክ"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"ገቢ"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"ጸጥ ያለ"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"ማሳወቂያዎች"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"ማሳወቂያዎችን አጥፋ"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"ከዚህ መተግበሪያ ማሳወቂያዎችን ማሳየት ይቀጥል?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"ፀጥ ያለ"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"ነባሪ"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"አረፋ"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"ምንም ድምጽ ወይም ንዝረት የለም"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"ምንም ድምጽ ወይም ንዝረት የለም እና በውይይት ክፍል ላይ አይታይም"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"በእርስዎ የስልክ ቅንብሮች የሚወሰን ሆኖ ሊደውል ወይም ሊነዝር ይችላል"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"በእርስዎ የስልክ ቅንብሮች የሚወሰን ሆኖ ሊደውል ወይም ሊነዝር ይችላል። የ<xliff:g id="APP_NAME">%1$s</xliff:g> አረፋ ውይይቶች በነባሪነት።"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ለዚህ ይዞታ ከተንሳፋፊ አቋራጭ ጋር የእርስዎን ትኩረት ያቆያል።"</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"በውይይት ክፍል አናት ላይ ያሳያል፣ እንደ ተንሳፋፊ አረፋ ብቅ ይላል፣ በቆልፍ ማያ ገጽ ላይ የመገለጫ ሥዕልን ያሳያል"</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>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index f33847c..f871c10 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"স্ক্ৰীণ পূর্ণ কৰিবলৈ জুম কৰক"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"স্ক্ৰীণ পূর্ণ কৰিবলৈ প্ৰসাৰিত কৰক"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"স্ক্ৰীনশ্বট"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"অধিক বিকল্পৰ বাবে আপোনাৰ ফ’নটো আনলক কৰক"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"অধিক বিকল্পৰ বাবে আপোনাৰ টেবলেটটো আনলক কৰক"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"অধিক বিকল্পৰ বাবে আপোনাৰ ডিভাইচটো আনলক কৰক"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"এখন প্ৰতিচ্ছবি পঠিয়াইছে"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"স্ক্ৰীণশ্বট ছেভ কৰি থকা হৈছে…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"স্ক্ৰীণশ্বট ছেভ কৰি থকা হৈছে…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"জিপিএছএ অৱস্থান ছেট কৰিছে"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"অৱস্থানৰ অনুৰোধ সক্ৰিয় হৈ আছে"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"ছেন্সৰ অফ সক্ৰিয় কৰা আছে"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"মিডিয়া সক্ৰিয় হৈ আছে"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"সকলো জাননী মচক৷"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"পৰিচালনা"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ইতিহাস"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"অন্তৰ্গামী"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"নীৰৱ"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"জাননীসমূহ"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"জাননী অফ কৰক"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"এই এপটোৰ জাননী দেখুওৱাই থাকিব লাগিবনে?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"নীৰৱ"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"ডিফ’ল্ট"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"বাবল"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"কোনো ধ্বনি অথবা কম্পন নাই"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"কোনো ধ্বনি অথবা কম্পন নাই আৰু বাৰ্তালাপ শাখাটোৰ তলৰ অংশত দেখা পোৱা যায়"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"ফ’নৰ ছেটিঙৰ ওপৰত নিৰ্ভৰ কৰি ৰিং কৰিব অথবা কম্পন হ’ব পাৰে"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ফ’নৰ ছেটিঙৰ ওপৰত নিৰ্ভৰ কৰি ৰিং কৰিব অথবা কম্পন হ’ব পাৰে। <xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাৰ্তালাপ ডিফ’ল্ট হিচাপে বাবল হয়।"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"উপঙি থকা এটা শ্বৰ্টকাটৰ জৰিয়তে এই সমলখিনিৰ প্ৰতি আপোনাক মনোযোগী কৰি ৰাখে।"</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"বাৰ্তালাপ শাখাটোৰ শীৰ্ষত দেখুৱায়, ওপঙা বাবল হিচাপে দেখা পোৱা যায়, লক স্ক্ৰীনত প্ৰ’ফাইলৰ চিত্ৰ প্ৰদৰ্শন কৰে"</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>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 443d2f2..b7777cd 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Ekranı doldurmaq üçün yaxınlaşdır"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ekranı doldurmaq üçün uzat"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skrinşot"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Daha çox seçim üçün telefonu kiliddən çıxarın"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Daha çox seçim üçün planşeti kiliddən çıxarın"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Daha çox seçim üçün cihazı kiliddən çıxarın"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"şəkil göndərdi"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Skrinşot yadda saxlanılır..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Skrinşot yadda saxlanır..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Yer GPS tərəfindən müəyyən edildi"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Məkan sorğuları arxivi"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"\"Deaktiv sensorlar\" aktivdir"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Media aktivdir"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Bütün bildirişləri sil."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"İdarə edin"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Tarixçə"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Gələn"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Səssiz"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Bildirişlər"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Söhbətlər"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Səssiz bildirişlərin hamısını silin"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Bildirişlər \"Narahat Etməyin\" rejimi tərəfindən dayandırıldı"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Bildirişləri deaktiv edin"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Bu tətbiqin bildirişləri göstərilməyə davam edilsin?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Səssiz"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Defolt"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Qabarcıq"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Səs və ya vibrasiya yoxdur"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Səs və ya vibrasiya yoxdur və söhbət bölməsinin aşağısında görünür"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Telefon ayarlarına əsasən zəng çala və ya vibrasiya edə bilər"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Telefon ayarlarına əsasən zəng çala və ya vibrasiya edə bilər. <xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqindən söhbətlərdə defolt olaraq qabarcıq çıxır."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Bu məzmuna üzən qısayol ilə diqqətinizi cəlb edir."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Söhbət bölməsinin yuxarısında göstərilir, üzən qabarcıq kimi görünür, kilid ekranında profil şəkli göstərir"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ayarlar"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> söhbətə aid ayarları dəstəkləmir"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 0f14ff1..e8f5dbb 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zumiraj na celom ekranu"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Razvuci na ceo ekran"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snimak ekrana"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Otključajte telefon za još opcija"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Otključajte tablet za još opcija"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Otključajte uređaj za još opcija"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"je poslao/la sliku"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Čuvanje snimka ekrana..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Čuvanje snimka ekrana..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Lokaciju je podesio GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Ima aktivnih zahteva za lokaciju"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Senzori su isključeni"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Medijum je aktivan"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Obriši sva obaveštenja."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"i još <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -522,10 +518,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Upravljajte"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Istorija"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Dolazno"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Nečujno"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Obaveštenja"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Konverzacije"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Obrišite sva nečujna obaveštenja"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Obaveštenja su pauzirana režimom Ne uznemiravaj"</string>
@@ -720,20 +714,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Isključi obaveštenja"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Želite li da se obaveštenja iz ove aplikacije i dalje prikazuju?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Nečujno"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Podrazumevano"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Oblačić"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Bez zvuka i vibriranja"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Bez zvuka i vibriranja i prikazuje se u nastavku odeljka za konverzacije"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Može da zvoni ili vibrira u zavisnosti od podešavanja telefona"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Može da zvoni ili vibrira u zavisnosti od podešavanja telefona. Konverzacije iz aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g> se podrazumevano prikazuju u oblačićima."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Privlači vam pažnju pomoću plutajuće prečice do ovog sadržaja."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Prikazuje se u vrhu odeljka za konverzacije kao plutajući oblačić, prikazuje sliku profila na zaključanom ekranu"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Podešavanja"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> ne podržava podešavanja za konverzacije"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 610c186..d508ab3 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Павял. на ўвесь экран"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Расцягн. на ўвесь экран"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Здымак экрана"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Каб адкрыць іншыя параметры, разблакіруйце тэлефон"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Каб адкрыць іншыя параметры, разблакіруйце планшэт"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Каб адкрыць іншыя параметры, разблакіруйце прыладу"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"адпраўлены відарыс"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Захаванне скрыншота..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Захаванне скрыншота..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Месца задана праз GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Ёсць актыўныя запыты пра месцазнаходжанне"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Датчыкі выключаны"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Мультымедыя ўключана"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Выдалiць усе апавяшчэннi."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -525,10 +521,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Кіраваць"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Гісторыя"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Уваходныя"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Без гуку"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Апавяшчэнні"</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>
@@ -723,20 +717,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Выключыць апавяшчэнні"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Працягваць паказваць апавяшчэнні гэтай праграмы?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Бязгучны рэжым"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Стандартна"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Усплывальнае апавяшчэнне"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Без гуку ці вібрацыі"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Паказваецца без гуку ці вібрацыі ў раздзеле размоў"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"У залежнасці ад налад тэлефона магчымы званок або вібрацыя"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"У залежнасці ад налад тэлефона магчымы званок або вібрацыя. Размовы ў праграме \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" стандартна паяўляюцца ў выглядзе ўсплывальных апавяшчэнняў."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Прыцягвае ўвагу да гэтага змесціва ўсплывальнай кнопкай."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Паказваецца ўверсе раздзела размоў у выглядзе ўсплывальнага апавяшчэння, а на экране блакіроўкі – у выглядзе відарыса профілю"</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>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 26790c5..a224bd6 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Мащаб – запълва екрана"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Разпъване – запълва екрана"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Екранна снимка"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Отключете телефона си за още опции"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Отключете таблета си за още опции"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Отключете устройството си за още опции"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"изпратено изображение"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Екранната снимка се запазва..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Екранната снимка се запазва..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Местоположението е зададено от GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Активни заявки за местоположение"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Сензорите са изключени"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Мултимедията е активна"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Изчистване на всички известия."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Управление"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"История"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Входящи"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Беззвучни"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Известия"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Изключване на известията"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Да продължат ли да се показват известията от това приложение?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Тих режим"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Стандартно"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Балонче"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Без звук или вибриране"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Без звук или вибриране и се показва по-долу в секцията с разговори"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Може да звъни или да вибрира въз основа на настройките за телефона"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Може да звъни или да вибрира въз основа на настройките за телефона. Разговорите от <xliff:g id="APP_NAME">%1$s</xliff:g> се показват като балончета по подразбиране."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Задържа вниманието ви посредством плаващ пряк път към това съдържание."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Показва се като плаващо балонче в горната част на секцията с разговори и показва снимката на потребителския профил на заключения екран"</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>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 46dd9b9..43a3f4e 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"স্ক্রীণ পূরণ করতে জুম করুন"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ফুল স্ক্রিন করুন"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"স্ক্রিনশট"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"আরও বিকল্প দেখতে আপনার ফোন আনলক করুন"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"আরও বিকল্প দেখতে আপনার ট্যাবলেট আনলক করুন"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"আরও বিকল্প দেখতে আপনার ডিভাইস আনলক করুন"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"একটি ছবি পাঠানো হয়েছে"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPS এর দ্বারা সেট করা লোকেশন"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"লোকেশন অনুরোধ সক্রিয় রয়েছে"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"সেন্সর অফ অ্যাক্টিভ"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"মিডিয়া চালু আছে"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"সমস্ত বিজ্ঞপ্তি সাফ করুন৷"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>টি"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"পরিচালনা করুন"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ইতিহাস"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"ইনকামিং"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"আওয়াজ করবে না"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"বিজ্ঞপ্তি"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"বিজ্ঞপ্তি বন্ধ করুন"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"এই অ্যাপের বিজ্ঞপ্তি পরেও দেখে যেতে চান?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"সাইলেন্ট"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"ডিফল্ট"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"বাবল"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"আওয়াজ করবে না বা ভাইব্রেট হবে না"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"আওয়াজ করবে না বা ভাইব্রেট হবে না এবং কথোপকথন বিভাগের নিচের দিকে দেখা যাবে"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"ফোনের সেটিংস অনুযায়ী ফোন রিং বা ভাইব্রেট হতে পারে"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ফোনের সেটিংস অনুযায়ী ফোন রিং বা ভাইব্রেট হতে পারে। <xliff:g id="APP_NAME">%1$s</xliff:g>-এর কথোপকথন সাধারণত বাবলের মতো দেখাবে।"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ফ্লোটিং শর্টকাট ব্যবহার করে এই কন্টেন্টে আপনার দৃষ্টি আকর্ষণ করে রাখে।"</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"কথোপকথন বিভাগের উপরে ভাসমান বাবলের মতো দেখা যাবে, লক স্ক্রিনে প্রোফাইল ছবি দেখাবে"</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>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 89ecc72..abb0167 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Uvećaj prikaz na ekran"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Razvuci prikaz na ekran"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snimak ekrana"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Otključajte telefon za više opcija"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Otključajte tablet za više opcija"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Otključajte uređaj za više opcija"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"je poslao/la sliku"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Spašavanje snimka ekrana..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Spašavanje snimka ekrana..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Lokacija utvrđena GPS signalom"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Aktiviran je zahtjev za lokaciju"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Senzori su isključeni"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Medij je aktivan"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Uklanjanje svih obavještenja."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -522,10 +518,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Upravljajte"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historija"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Dolazno"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Nečujno"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Obavještenja"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Razgovori"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Obriši sva nečujna obavještenja"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Obavještenja su pauzirana načinom rada Ne ometaj"</string>
@@ -722,20 +716,14 @@
     <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>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Zadano"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Oblačić"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Bez zvuka ili vibracije"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Bez zvuka ili vibracije i pojavljuje se pri dnu odjeljka za razgovor"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Može zvoniti ili vibrirati na osnovu postavki vašeg telefona"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Može zvoniti ili vibrirati na osnovu postavki vašeg telefona. 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>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Prikazuje se na vrhu odjeljka za razgovor, pojavljuje se kao plutajući oblačić, prikazuje sliku profila na zaključanom ekranu"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Postavke"</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>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index e478654..62f5d95 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom per omplir pantalla"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Estira per omplir pant."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Desbloqueja el teu telèfon per veure més opcions"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Desbloqueja la teva tauleta per veure més opcions"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Desbloqueja el teu dispositiu per veure més opcions"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ha enviat una imatge"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"S\'està desant captura de pantalla..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"S\'està desant la captura de pantalla..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"S\'ha establert la ubicació per GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Sol·licituds d\'ubicació actives"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensors desactivats"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Hi ha fitxers multimèdia actius"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Esborra totes les notificacions."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gestiona"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Entrants"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Silenci"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notificacions"</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>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificacions pausades pel mode No molestis"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desactiva les notificacions"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Vols continuar rebent notificacions d\'aquesta aplicació?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Silenci"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Predeterminada"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bombolla"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Sense so ni vibració"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Sense so ni vibració i es mostra més avall a la secció de converses"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Pot sonar o vibrar en funció de la configuració del telèfon"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pot sonar o vibrar en funció de la configuració del telèfon. Les converses de l\'aplicació <xliff:g id="APP_NAME">%1$s</xliff:g> es mostren com a bombolles de manera predeterminada."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Atrau la teva atenció amb una drecera flotant a aquest contingut."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Es mostra com a bombolla flotant a la part superior de la secció de converses i mostra la foto de perfil a la pantalla de bloqueig"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configuració"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritat"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> no admet opcions de configuració específiques de converses"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index a717c50..12b3d24 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Přiblížit na celou obrazovku"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Na celou obrazovku"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snímek obrazovky"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Chcete-li zobrazit další možnosti, odemkněte telefon"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Chcete-li zobrazit další možnosti, odemkněte tablet"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Chcete-li zobrazit další možnosti, odemkněte zařízení"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"odesílá obrázek"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Ukládání snímku obrazovky..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Ukládání snímku obrazovky..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Poloha nastavena pomocí systému GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Aktivní žádosti o polohu"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Vypnutí senzorů je aktivní"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Média jsou aktivní"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Vymazat všechna oznámení."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"a ještě <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -525,10 +521,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Spravovat"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historie"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Příchozí"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Tiché"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Oznámení"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Konverzace"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Vymazat všechna tichá oznámení"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Oznámení jsou pozastavena režimem Nerušit"</string>
@@ -723,20 +717,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Vypnout oznámení"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Mají se oznámení z této aplikace nadále zobrazovat?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Ticho"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Výchozí"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bublina"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Žádný zvuk ani vibrace"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Žádný zvuk ani vibrace a zobrazovat níže v sekci konverzací"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Může vyzvánět nebo vibrovat v závislosti na nastavení telefonu"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Může vyzvánět nebo vibrovat v závislosti na nastavení telefonu. Konverzace z aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> ve výchozím nastavení bublají."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Přitahuje pozornost pomocí plovoucí zkratky k tomuto obsahu."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Zobrazuje se v horní části sekce konverzace a má podobu plovoucí bubliny, zobrazuje profilovou fotku na obrazovce uzamčení"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nastavení"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorita"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> nepodporuje nastavení specifická pro konverzaci"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index a17311f..ede673d 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom til fuld skærm"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stræk til fuld skærm"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Lås din telefon op for at se flere valgmuligheder"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Lås din tablet op for at se flere valgmuligheder"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Lås din enhed op for at se flere valgmuligheder"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sendte et billede"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Gemmer screenshot..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Gemmer screenshot..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Placeringen er angivet ved hjælp af GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Aktive placeringsanmodninger"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensorer er slået fra"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Der er aktive mediefiler"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Ryd alle notifikationer."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"<xliff:g id="NUMBER">%s</xliff:g> mere"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Administrer"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historik"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Indgående"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Lydløs"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notifikationer"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Samtaler"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Ryd alle lydløse notifikationer"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifikationer er sat på pause af Forstyr ikke"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Deaktiver notifikationer"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Vil du fortsætte med at se notifikationer fra denne app?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Lydløs"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Standard"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Boble"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Ingen lyd eller vibration"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Ingen lyd eller vibration, og den vises længere nede i samtalesektionen"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Kan ringe eller vibrere baseret på telefonens indstillinger"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan ringe eller vibrere baseret på telefonens indstillinger. Samtaler fra <xliff:g id="APP_NAME">%1$s</xliff:g> vises som standard i bobler."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Fastholder din opmærksomhed med en svævende genvej til indholdet."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Vises øverst i samtalesektionen, som en svævende boble og med profilbillede på låseskærmen"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Indstillinger"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> understøtter ikke samtalespecifikke indstillinger"</string>
@@ -792,7 +780,7 @@
     <string name="keyboard_key_dpad_left" msgid="8329738048908755640">"Venstre"</string>
     <string name="keyboard_key_dpad_right" msgid="6282105433822321767">"Højre"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Midtertast"</string>
-    <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab-tast"</string>
+    <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Mellemrumstast"</string>
     <string name="keyboard_key_enter" msgid="8633362970109751646">"Enter"</string>
     <string name="keyboard_key_backspace" msgid="4095278312039628074">"Tilbagetast"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index a42c512..c0751c8 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Ζουμ σε πλήρη οθόνη"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Προβoλή σε πλήρη οθ."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Στιγμιότυπο οθόνης"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Ξεκλειδώστε το τηλέφωνό σας για περισσότερες επιλογές."</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Ξεκλειδώστε το tablet για περισσότερες επιλογές."</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Ξεκλειδώστε τη συσκευή σας για περισσότερες επιλογές."</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"έστειλε μια εικόνα"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Αποθήκ. στιγμιότυπου οθόνης..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Αποθήκευση στιγμιότυπου οθόνης..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Ρύθμιση τοποθεσίας με GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Τα αιτήματα τοποθεσίας έχουν ενεργοποιηθεί"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Απενεργοποίηση αισθητήρων ενεργή"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Το πολυμέσο είναι ενεργό."</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Διαγραφή όλων των ειδοποιήσεων."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Διαχείριση"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Ιστορικό"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Εισερχόμενες"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Σίγαση"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Ειδοποιήσεις"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Απενεργοποίηση ειδοποιήσεων"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Να συνεχίσουν να εμφανίζονται ειδοποιήσεις από αυτήν την εφαρμογή;"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Σίγαση"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Προεπιλογή"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Φούσκα"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Χωρίς ήχο ή δόνηση"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Χωρίς ήχο ή δόνηση και εμφανίζεται χαμηλά στην ενότητα συζητήσεων"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Ενδέχεται να κουδουνίζει ή να δονείται βάσει των ρυθμίσεων του τηλεφώνου"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Ενδέχεται να κουδουνίζει ή να δονείται βάσει των ρυθμίσεων του τηλεφώνου. Οι συζητήσεις από την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> εμφανίζονται σε συννεφάκι από προεπιλογή."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Κρατάει την προσοχή σας με μια κινούμενη συντόμευση προς αυτό το περιεχόμενο."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Εμφανίζεται στο επάνω μέρος της ενότητας συζητήσεων, προβάλλεται ως κινούμενο συννεφάκι, εμφανίζει τη φωτογραφία προφίλ στην οθόνη κλειδώματος"</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>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 7ca02dd..6f86e50 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Unlock your phone for more options"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Unlock your tablet for more options"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Unlock your device for more options"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sent an image"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Location set by GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Location requests active"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensors off active"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Media is active"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Clear all notifications."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+<xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Manage"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"History"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Incoming"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Silent"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notifications"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversations"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Clear all silent notifications"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifications paused by Do Not Disturb"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Turn off notifications"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Keep showing notifications from this app?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Silent"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Default"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bubble"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"No sound or vibration"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"No sound or vibration and appears lower in conversation section"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"May ring or vibrate based on phone settings"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"May ring or vibrate based on phone settings. Conversations from <xliff:g id="APP_NAME">%1$s</xliff:g> bubble by default."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Keeps your attention with a floating shortcut to this content."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Settings"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> does not support conversation-specific settings"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 2e09b65..711e645 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Unlock your phone for more options"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Unlock your tablet for more options"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Unlock your device for more options"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sent an image"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Location set by GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Location requests active"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensors off active"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Media is active"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Clear all notifications."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+<xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Manage"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"History"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Incoming"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Silent"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notifications"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversations"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Clear all silent notifications"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifications paused by Do Not Disturb"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Turn off notifications"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Keep showing notifications from this app?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Silent"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Default"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bubble"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"No sound or vibration"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"No sound or vibration and appears lower in conversation section"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"May ring or vibrate based on phone settings"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"May ring or vibrate based on phone settings. Conversations from <xliff:g id="APP_NAME">%1$s</xliff:g> bubble by default."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Keeps your attention with a floating shortcut to this content."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Settings"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> does not support conversation-specific settings"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 7ca02dd..6f86e50 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Unlock your phone for more options"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Unlock your tablet for more options"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Unlock your device for more options"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sent an image"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Location set by GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Location requests active"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensors off active"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Media is active"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Clear all notifications."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+<xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Manage"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"History"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Incoming"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Silent"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notifications"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversations"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Clear all silent notifications"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifications paused by Do Not Disturb"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Turn off notifications"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Keep showing notifications from this app?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Silent"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Default"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bubble"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"No sound or vibration"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"No sound or vibration and appears lower in conversation section"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"May ring or vibrate based on phone settings"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"May ring or vibrate based on phone settings. Conversations from <xliff:g id="APP_NAME">%1$s</xliff:g> bubble by default."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Keeps your attention with a floating shortcut to this content."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Settings"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> does not support conversation-specific settings"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 7ca02dd..6f86e50 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Unlock your phone for more options"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Unlock your tablet for more options"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Unlock your device for more options"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sent an image"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Location set by GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Location requests active"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensors off active"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Media is active"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Clear all notifications."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+<xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Manage"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"History"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Incoming"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Silent"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notifications"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversations"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Clear all silent notifications"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifications paused by Do Not Disturb"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Turn off notifications"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Keep showing notifications from this app?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Silent"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Default"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bubble"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"No sound or vibration"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"No sound or vibration and appears lower in conversation section"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"May ring or vibrate based on phone settings"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"May ring or vibrate based on phone settings. Conversations from <xliff:g id="APP_NAME">%1$s</xliff:g> bubble by default."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Keeps your attention with a floating shortcut to this content."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Settings"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> does not support conversation-specific settings"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 9b8d5d7..ee0e232 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -77,9 +77,6 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‎‎‎‏‏‏‎‏‏‏‎‏‎‎‎Zoom to fill screen‎‏‎‎‏‎"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‎‎‎‎‎‎‎‎‏‎‎‏‎‏‏‎‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‏‎Stretch to fill screen‎‏‎‎‏‎"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‎‎‏‏‎‎Screenshot‎‏‎‎‏‎"</string>
-    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎Unlock your phone for more options‎‏‎‎‏‎"</string>
-    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‏‎‏‎‏‏‏‎‏‎‎Unlock your tablet for more options‎‏‎‎‏‎"</string>
-    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‎‏‎‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎Unlock your device for more options‎‏‎‎‏‎"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‎‏‎‎‎‏‏‎‎‎‎‎‎‏‏‎‏‎‎‏‎‏‎‎‎‏‏‎sent an image‎‏‎‎‏‎"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎Saving screenshot…‎‏‎‎‏‎"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎Saving screenshot…‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 90ff857..a0328677 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom para ocupar la pantalla"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Estirar p/ ocupar la pantalla"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Desbloquea el teléfono para ver más opciones"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Desbloquea la tablet para ver más opciones"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Desbloquea el dispositivo para ver más opciones"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"envió una imagen"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Guardando captura de pantalla"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Guardando la captura de pantalla..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"La ubicación se estableció por GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Solicitudes de ubicación activas"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensores desactivados sí"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Se está reproduciendo contenido multimedia"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Eliminar todas las notificaciones"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"<xliff:g id="NUMBER">%s</xliff:g> más"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Administrar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Entrante"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Silenciadas"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notificaciones"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversaciones"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Borrar todas las notificaciones silenciosas"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificaciones pausadas por el modo \"No interrumpir\""</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desactivar notificaciones"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"¿Quieres seguir viendo las notificaciones de esta app?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Silencio"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Predeterminada"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Cuadro"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Sin sonido ni vibración"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"No suena ni vibra, y aparece en una parte inferior de la sección de conversaciones"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Puede sonar o vibrar en función de la configuración del teléfono"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Puede sonar o vibrar en función de la configuración del teléfono. Conversaciones de la burbuja de <xliff:g id="APP_NAME">%1$s</xliff:g> de forma predeterminada."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Retiene tu atención con un acceso directo flotante a este contenido."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparece en la parte superior de la sección de conversaciones, en forma de burbuja flotante, y muestra la foto de perfil en la pantalla de bloqueo"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configuración"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioridad"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> no admite opciones de configuración específicas de conversaciones"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 5a691fce..4fb2bc4 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom para ajustar"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Expandir para ajustar"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Desbloquea el teléfono para ver más opciones"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Desbloquea el tablet para ver más opciones"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Desbloquea el dispositivo para ver más opciones"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ha enviado una imagen"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Guardando captura..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Guardando captura..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Ubicación definida por GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Solicitudes de ubicación activas"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensores desactivados"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Hay archivos multimedia activos"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Borrar todas las notificaciones"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"<xliff:g id="NUMBER">%s</xliff:g> más"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gestionar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Entrantes"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Silenciadas"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notificaciones"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversaciones"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Borrar todas las notificaciones silenciadas"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificaciones pausadas por el modo No molestar"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desactivar notificaciones"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"¿Quieres seguir viendo las notificaciones de esta aplicación?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Silencio"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Predeterminada"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Burbuja"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Sin sonido ni vibración"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Sin sonido ni vibración y se muestra más abajo en la sección de conversaciones"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Según los ajustes definidos en el teléfono, es posible que suene o vibre"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Según los ajustes definidos en el teléfono, es posible que suene o vibre. Las conversaciones de <xliff:g id="APP_NAME">%1$s</xliff:g> aparecen como burbujas de forma predeterminada."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Llama tu atención con un acceso directo flotante a este contenido."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Se muestra en la parte superior de la sección de conversaciones en forma de burbuja flotante, y la imagen de perfil aparece en la pantalla de bloqueo"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ajustes"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioridad"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> no es compatible con ajustes específicos de conversaciones"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index ef32e10..8124dd4 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Suumi ekraani täitmiseks"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Venita ekraani täitmiseks"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekraanipilt"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Lisavalikute nägemiseks avage oma telefon"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Lisavalikute nägemiseks avage oma tahvelarvuti"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Lisavalikute nägemiseks avage oma seade"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"saatis kujutise"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Kuvatõmmise salvestamine ..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Kuvatõmmise salvestamine ..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPS-i määratud asukoht"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Asukoha taotlused on aktiivsed"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Valik Andurid on väljas on aktiivne"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Meedia on aktiivne"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Kustuta kõik teatised."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Haldamine"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Ajalugu"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Sissetulevad"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Hääletu"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Märguanded"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Vestlused"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Kustuta kõik hääletud märguanded"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Režiim Mitte segada peatas märguanded"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Lülita märguanded välja"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Kas jätkata selle rakenduse märguannete kuvamist?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Hääletu"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Vaikeseade"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Mull"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Ilma heli ja vibreerimiseta"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Ilma heli ja vibreerimiseta, kuvatakse vestluste jaotises allpool"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Võib telefoni seadete põhjal heliseda või vibreerida"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Võib telefoni seadete põhjal heliseda või vibreerida. Rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> vestlused kuvatakse vaikimisi mullis."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Hoiab teie tähelepanu hõljuva otseteega selle sisu juurde."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Kuvatakse vestluste jaotise ülaosas hõljuva mullina ja lukustuskuval kuvatakse profiilipilt"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Seaded"</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>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index b83323e..d4c80a3 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Handiagotu pantaila betetzeko"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Luzatu pantaila betetzeko"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Pantaila-argazkia"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Desblokeatu telefonoa aukera gehiago ikusteko"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Desblokeatu tableta aukera gehiago ikusteko"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Desblokeatu gailua aukera gehiago ikusteko"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"erabiltzaileak irudi bat bidali du"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Pantaila-argazkia gordetzen…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Pantaila-argazkia gordetzen…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Kokapena GPS bidez ezarri da"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Aplikazioen kokapen-eskaerak aktibo daude"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Aktibo dago sentsore guztiak desaktibatzen dituen aukera"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Multimedia-edukia aktibo dago"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Garbitu jakinarazpen guztiak."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Kudeatu"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historia"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Jasotako azkenak"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Isila"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Jakinarazpenak"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desaktibatu jakinarazpenak"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Aplikazio honen jakinarazpenak erakusten jarraitzea nahi duzu?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Isila"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Balio lehenetsia"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Burbuila"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Ez du jotzen tonua edo egiten dar-dar"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Ez du jotzen tonua edo egiten dar-dar, eta elkarrizketaren atalaren behealdean agertzen da"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Tonua jo edo dar-dar egin dezake, telefonoaren ezarpenen arabera"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Tonua jo edo dar-dar egin dezake, telefonoaren ezarpenen arabera. Modu lehenetsian, <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioko elkarrizketak burbuila gisa agertzen dira."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Eduki honetarako lasterbide gainerakor bat eskaintzen dizu, arretarik gal ez dezazun."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Burbuila gisa agertzen da elkarrizketen atalaren goialdean, eta profileko argazkia bistaratzen du pantaila blokeatuta dagoenean"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ezarpenak"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Lehentasuna"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak ez du onartzen elkarrizketen berariazko ezarpenik"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 42c4e2f..7c37f66 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"بزرگ‌نمایی برای پر کردن صفحه"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"گسترده کردن برای پر کردن صفحه"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"نماگرفت"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"برای گزینه‌های بیشتر، قفل تلفن را باز کنید"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"برای گزینه‌های بیشتر، قفل رایانه لوحی را باز کنید"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"برای گزینه‌های بیشتر، قفل دستگاه را باز کنید"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"تصویری ارسال کرد"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"در حال ذخیره نماگرفت..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"درحال ذخیره نماگرفت…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"‏مکان تنظیم شده توسط GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"درخواست‌های موقعیت مکانی فعال است"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"«حسگرها خاموش» فعال است"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"رسانه فعال است"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"پاک کردن تمام اعلان‌ها"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"مدیریت"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"سابقه"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"ورودی"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"بی‌صدا"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"اعلان‌ها"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"خاموش کردن اعلان‌ها"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"نمایش اعلان از این برنامه ادامه یابد؟"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"بی‌صدا"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"پیش‌فرض"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"حباب"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"بدون صدا یا لرزش"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"بدون صدا و لرزش در پایین بخش مکالمه نشان داده می‌شود"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"بسته به تنظیمات ممکن است تلفن زنگ بزند یا لرزش داشته باشد"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"بسته به تنظیمات ممکن است تلفن زنگ بزند یا لرزش داشته باشد. مکالمه‌های <xliff:g id="APP_NAME">%1$s</xliff:g> به‌طور پیش‌فرض در حبابک نشان داده می‌شوند."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"با میان‌بری شناور به این محتوا، توجه‌تان را جلب می‌کند."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"در بالای بخش مکالمه به‌صورت حبابک شناور نشان داده می‌شود و تصویر نمایه را در صفحه قفل نمایش می‌دهد"</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>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index c2a70f9..6333fc5 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoomaa koko näyttöön"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Venytä koko näyttöön"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Kuvakaappaus"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Avaa puhelimen lukitus, niin näet enemmän vaihtoehtoja"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Avaa tabletin lukitus, niin näet enemmän vaihtoehtoja"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Avaa laitteen lukitus, niin näet enemmän vaihtoehtoja"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"lähetti kuvan"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Tallennetaan kuvakaappausta..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Tallennetaan kuvakaappausta..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Sijainti määritetty GPS:n avulla"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Sijaintipyynnöt aktiiviset"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Anturit pois päältä aktiivinen"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Media on aktiivinen"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Tyhjennä kaikki ilmoitukset."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Muuta asetuksia"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historia"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Saapuvat"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Äänetön"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Ilmoitukset"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Keskustelut"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Tyhjennä kaikki hiljaiset ilmoitukset"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Älä häiritse ‑tila keskeytti ilmoitukset"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Poista ilmoitukset käytöstä"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Jatketaanko ilmoitusten näyttämistä tästä sovelluksesta?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Äänetön"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Oletus"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Kupla"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Ei ääntä tai värinää"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Ei ääntä tai värinää ja näkyy alempana keskusteluosiossa"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Voi soida tai väristä puhelimen asetuksista riippuen"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Voi soida tai väristä puhelimen asetuksista riippuen. 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>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Näkyy keskusteluosion yläosassa kelluvana kuplana, profiilikuva näkyy lukitusnäytöllä"</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>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 47a8450..c03a680 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoomer pour remplir l\'écran"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Étirer pour remplir l\'écran"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capture d\'écran"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Déverrouillez votre téléphone pour afficher davantage d\'options"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Déverrouillez votre tablette pour afficher davantage d\'options"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Déverrouillez votre appareil pour afficher davantage d\'options"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"a envoyé une image"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Enregistrement capture écran…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Enregistrement capture écran…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Position définie par GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Demandes de localisation actives"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Option « Capteurs désactivés » active"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"L\'élément multimédia est actif"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Supprimer toutes les notifications"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gérer"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historique"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Entrantes"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Mode silencieux"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notifications"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversations"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Effacer toutes les notifications silencieuses"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Les notifications sont suspendues par le mode Ne pas déranger"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Désactiver les notifications"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Continuer à afficher les notifications de cette application?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Mode silencieux"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Par défaut"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bulle"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Aucun son ni vibration"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Aucun son ni vibration, et s\'affiche plus bas dans la section des conversations"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Peut sonner ou vibrer, selon les paramètres du téléphone"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Peut sonner ou vibrer, selon les paramètres du téléphone. 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>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"S\'affiche en haut de la section des conversations sous forme de bulle flottante et affiche la photo du profil sur l\'écran de verrouillage"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Paramètres"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorité"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> ne prend pas en charge les paramètres propres aux conversations"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 577d2ea..33754c4 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoomer pour remplir l\'écran"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Étirer pour remplir l\'écran"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capture d\'écran"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Déverrouillez votre téléphone pour obtenir plus d\'options"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Déverrouillez votre tablette pour obtenir plus d\'options"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Déverrouillez votre appareil pour obtenir plus d\'options"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"a envoyé une image"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Enregistrement capture écran…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Enregistrement de la capture d\'écran…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Position définie par GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Demandes de localisation actives"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Option \"Capteurs désactivés\" active"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Des contenus multimédias sont actifs"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Supprimer toutes les notifications"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"<xliff:g id="NUMBER">%s</xliff:g> autres"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gérer"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historique"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Notifications entrantes"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Silencieuses"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notifications"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversations"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Effacer toutes les notifications silencieuses"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifications suspendues par le mode Ne pas déranger"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Désactiver les notifications"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Continuer d\'afficher les notifications de cette application ?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Silencieux"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Par défaut"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bulle"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Aucun son ni vibration"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Aucun son ni vibration, s\'affiche plus bas dans la section des conversations"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Peut sonner ou vibrer en fonction des paramètres du téléphone"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Peut sonner ou vibrer en fonction des paramètres du téléphone. Les conversations provenant de <xliff:g id="APP_NAME">%1$s</xliff:g> s\'affichent sous forme de bulles par défaut."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Attire votre attention à l\'aide d\'un raccourci flottant vers ce contenu."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"S\'affiche en haut de la section des conversations, apparaît sous forme de bulle flottante, affiche la photo de profil sur l\'écran de verrouillage"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Paramètres"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritaire"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas compatible avec les paramètres de conversation"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 15740b3..c808125 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -77,12 +77,9 @@
     <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">"Facer captura"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Desbloquea o teléfono para ver máis opcións"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Desbloquea a tableta para ver máis opcións"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Desbloquea o dispositivo para ver máis opcións"</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>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Localización establecida polo GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Solicitudes de localización activas"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"A opción Desactivar sensores está activada"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"A reprodución multimedia está activa"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Eliminar todas as notificacións."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"<xliff:g id="NUMBER">%s</xliff:g> máis"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Xestionar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Entrantes"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Silencio"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notificacións"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversas"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Borra todas as notificacións silenciadas"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"O modo Non molestar puxo en pausa as notificacións"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desactivar notificacións"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Queres seguir mostrando as notificacións desta aplicación?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Silenciosas"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Configuración predeterminada"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Burbulla"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Sen son nin vibración"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Non soa nin vibra, e aparece máis abaixo na sección de conversas"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Podería soar ou vibrar en función da configuración do teléfono"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Podería soar ou vibrar en función da configuración do teléfono. Conversas desde a burbulla da aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> de forma predeterminada."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantén a túa atención cun atallo flotante a este contido."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Móstrase na parte superior da sección de conversas en forma de burbulla flotante e aparece a imaxe do perfil na pantalla de bloqueo"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configuración"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> non admite opcións de configuración específicas para conversas"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 28088ff..915547c 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"स्‍क्रीन भरने के लिए ज़ूम करें"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"स्‍क्रीन भरने के लिए खींचें"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रीनशॉट"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"ज़्यादा विकल्प देखने के लिए, अपना फ़ोन अनलॉक करें"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"ज़्यादा विकल्प देखने के लिए, अपना टैबलेट अनलॉक करें"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"ज़्यादा विकल्प देखने के लिए, अपना डिवाइस अनलॉक करें"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"एक इमेज भेजी गई"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
@@ -331,8 +328,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"जीपीएस ने यह जगह सेट की है"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"जगह का अनुरोध किया जा रहा है"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"सेंसर बंद हैं"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"मीडिया चल रहा है"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"सभी सूचनाएं साफ़ करें."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -521,10 +517,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"प्रबंधित करें"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"इतिहास"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"हाल ही में मिली सूचनाएं"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"बिना आवाज़ किए मिलने वाली सूचनाएं"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"वाइब्रेशन या आवाज़ के साथ मिलने वाली सूचनाएं"</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>
@@ -719,20 +713,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"सूचनाएं बंद करें"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"इस ऐप्लिकेशन से जुड़ी सूचनाएं दिखाना जारी रखें?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"आवाज़ के बिना सूचनाएं दिखाएं"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"डिफ़ॉल्ट"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"बबल"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"किसी तरह की आवाज़ या वाइब्रेशन न हो"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"इससे किसी तरह की आवाज़ या वाइब्रेशन नहीं होता और बातचीत, सेक्शन में सबसे नीचे दिखती है"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"फ़ोन की सेटिंग के आधार पर, सूचना आने पर घंटी बज सकती है या वाइब्रेशन हो सकता है"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"फ़ोन की सेटिंग के आधार पर, सूचना आने पर घंटी बज सकती है या वाइब्रेशन हो सकता है. <xliff:g id="APP_NAME">%1$s</xliff:g> में होने वाली बातचीत, डिफ़ॉल्ट रूप से बबल के तौर पर दिखती हैं."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"फ़्लोट करने वाले शॉर्टकट की मदद से इस सामग्री पर आपका ध्यान बना रहता है."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"इससे बातचीत, सेक्शन में सबसे ऊपर और फ़्लोटिंग बबल के तौर पर दिखती है. साथ ही, लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो दिखती है"</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>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index a9d4b94..84be202 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zumiraj i ispuni zaslon"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Rastegni i ispuni zaslon"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snimka zaslona"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Za više opcija otključajte telefon"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Za više opcija otključajte tablet"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Za više opcija otključajte uređaj"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"šalje sliku"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Spremanje snimke zaslona..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Spremanje snimke zaslona..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Lokaciju utvrdio GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Zahtjevi za lokaciju aktivni su"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Senzori isključeni aktivno"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Mediji su aktivni"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Brisanje svih obavijesti."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"još <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -522,10 +518,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Upravljajte"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Povijest"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Dolazno"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Bešumno"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Obavijesti"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Razgovori"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Izbriši sve bešumne obavijesti"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Značajka Ne uznemiravaj pauzirala je Obavijesti"</string>
@@ -720,20 +714,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Isključi obavijesti"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Želite li da se obavijesti te aplikacije nastave prikazivati?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Bešumno"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Zadano"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Oblačić"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Bez zvuka ili vibracije"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Bez zvuka ili vibracije i prikazuje se pri dnu odjeljka razgovora"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Možda će zvoniti ili vibrirati, ovisno o postavkama telefona"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Možda će zvoniti ili vibrirati, ovisno o postavkama telefona. Razgovori iz aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g> prikazuju se u oblačiću prema zadanim postavkama."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Održava vam pozornost pomoću plutajućeg prečaca ovom sadržaju."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Prikazuje se pri vrhu odjeljka razgovora kao pomični oblačić i prikazuje profilnu sliku na zaključanom zaslonu"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Postavke"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> ne podržava postavke koje se odnose na razgovor"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index d0ae04b..07b1b1c 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Nagyítás a kitöltéshez"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Nyújtás kitöltéshez"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Képernyőkép"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"További lehetőségekért oldja fel a telefont"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"További lehetőségekért oldja fel a táblagépet"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"További lehetőségekért oldja fel az eszközt"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"képet küldött"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Képernyőkép mentése..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Képernyőkép mentése..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"A GPS beállította a helyet"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Aktív helylekérések"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Az Érzékelők kikapcsolva kártya aktív"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Médialejátszás folyamatban"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Minden értesítés törlése"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Kezelés"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Előzmények"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Bejövő"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Néma"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Értesítések"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Beszélgetések"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Az összes néma értesítés törlése"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Ne zavarjanak funkcióval szüneteltetett értesítések"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Az értesítések kikapcsolása"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Továbbra is megjelenjenek az alkalmazás értesítései?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Néma"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Alapértelmezett"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Buborék"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Nincs hang és rezgés"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Nincs hang és rezgés, továbbá lejjebb jelenik meg a beszélgetések szakaszában"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"A telefonbeállítások alapján csöröghet és rezeghet"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"A telefonbeállítások alapján csöröghet és rezeghet. A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazásban lévő beszélgetések alapértelmezés szerint buborékban jelennek meg."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"A tartalomra mutató lebegő parancsikon segítségével tartja fenn az Ön figyelmét."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"A beszélgetések szakaszának tetején, lebegő buborékként látható, megjeleníti a profilképet a lezárási képernyőn"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Beállítások"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritás"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás nem támogatja a beszélgetésspecifikus beállításokat"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index e42481a..bf1322a 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Խոշորացնել` էկրանը լցնելու համար"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ձգել` էկրանը լցնելու համար"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Սքրինշոթ"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Ապակողպեք ձեր հեռախոսը՝ լրացուցիչ կարգավորումները տեսնելու համար"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Ապակողպեք ձեր պլանշետը՝ լրացուցիչ կարգավորումները տեսնելու համար"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Ապակողպեք ձեր սարքը՝ լրացուցիչ կարգավորումները տեսնելու համար"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"պատկեր է ուղարկվել"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Սքրինշոթը պահվում է…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Սքրինշոթը պահվում է..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Տեղադրությունը կարգավորվել է GPS-ի կողմից"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Տեղադրության հարցումներն ակտիվ են"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Տվիչներն անջատված են"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Մեդիաֆայլը նվագարկվում է"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Մաքրել բոլոր ծանուցումները:"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Կառավարել"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Պատմություն"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Մուտքային"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Անձայն"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Ծանուցումներ"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Անջատել ծանուցումները"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Ցուցադրե՞լ ծանուցումներ այս հավելվածից։"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Անձայն"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Կանխադրված"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Պղպջակ"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Առանց ձայնի կամ թրթռոցի"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Հայտնվում է զրույցների ցանկի ներքևում, առանց ձայնի և թրթռոցի"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Կարող է զնգալ կամ թրթռալ (հեռախոսի կարգավորումներից կախված)"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Կարող է զնգալ կամ թրթռալ (հեռախոսի կարգավորումներից կախված)։ <xliff:g id="APP_NAME">%1$s</xliff:g>-ի զրույցներն ըստ կանխադրման հայտնվում են ամպիկների տեսքով։"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Լողացող դյուրանցման միջոցով ձեր ուշադրությունն է գրավում բովանդակության նկատմամբ"</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Ցուցադրվում է զրույցների ցանկի վերևում, հայտնվում է լողացող ամպիկի տեսքով, ցուցադրում է պրոֆիլի նկարը կողպէկրանին"</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>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index fdf7e3d..14dd521 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Perbesar utk mengisi layar"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Rentangkn utk mngisi layar"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Buka kunci ponsel untuk melihat opsi lainnya"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Buka kunci tablet untuk opsi lainnya"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Buka kunci perangkat untuk melihat opsi lainnya"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"mengirim gambar"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Menyimpan screenshot..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Menyimpan screenshot..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Lokasi yang disetel oleh GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Permintaan lokasi aktif"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensor nonaktif diaktifkan"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Media aktif"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Menghapus semua pemberitahuan."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Kelola"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Histori"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Masuk"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Senyap"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notifikasi"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Percakapan"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Hapus semua notifikasi senyap"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifikasi dijeda oleh mode Jangan Ganggu"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Nonaktifkan notifikasi"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Terus tampilkan notifikasi dari aplikasi ini?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Senyap"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Default"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Balon"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Tidak ada suara atau getaran"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Tidak ada suara atau getaran dan ditampilkan lebih rendah di bagian percakapan"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Dapat berdering atau bergetar berdasarkan setelan ponsel"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Dapat berdering atau bergetar berdasarkan setelan ponsel. Percakapan dari balon <xliff:g id="APP_NAME">%1$s</xliff:g> secara default."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Menjaga perhatian dengan pintasan floating ke konten ini."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Muncul di atas bagian percakapan, ditampilkan sebagai balon yang mengambang, menampilkan gambar profil di layar kunci"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Setelan"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritas"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak mendukung setelan khusus percakapan"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 7e4f1b7..a572634 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Fylla skjá með aðdrætti"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Teygja yfir allan skjáinn"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skjámynd"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Taktu símann úr lás til að fá fleiri valkosti"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Taktu spjaldtölvuna úr lás til að fá fleiri valkosti"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Taktu tækið úr lás til að fá fleiri valkosti"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sendi mynd"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Vistar skjámynd…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Vistar skjámynd…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Staðsetning valin með GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Staðsetningarbeiðnir virkar"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Slökkt á skynjurum valið"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Efni er virkt"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Hreinsa allar tilkynningar."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Stjórna"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Ferill"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Mótteknar"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Hljóðlaust"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Tilkynningar"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Samtöl"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Hreinsa allar þöglar tilkynningar"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Hlé gert á tilkynningum þar sem stillt er á „Ónáðið ekki“"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Slökkva á tilkynningum"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Sýna áfram tilkynningar frá þessu forriti?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Hljóðlaust"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Sjálfgefið"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Blaðra"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Ekkert hljóð eða titringur"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Ekkert hljóð eða titringur og birtist neðar í samtalshluta"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Gæti hringt eða titrað eftir stillingum símans"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Gæti hringt eða titrað eftir stillingum símans. Samtöl á <xliff:g id="APP_NAME">%1$s</xliff:g> birtast sjálfkrafa í blöðru."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Fangar athygli þína með fljótandi flýtileið á þetta efni."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Birtist efst í samtalshluta, birtist sem fljótandi blaðra, birtir prófílmynd á lásskjánum"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Áfram"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Forgangur"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> styður ekki stillingar fyrir einstök samtöl"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 167a2c9..3beed3a 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom per riempire schermo"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Estendi per riemp. schermo"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Sblocca il telefono per visualizzare altre opzioni"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Sblocca il tablet per visualizzare altre opzioni"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Sblocca il dispositivo per visualizzare altre opzioni"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"è stata inviata un\'immagine"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Salvataggio screenshot..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Salvataggio screenshot..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Posizione stabilita dal GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Richieste di accesso alla posizione attive"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Opzione Sensori disattivati attiva"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Contenuti multimediali attivi"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Cancella tutte le notifiche."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gestisci"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Cronologia"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"In arrivo"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Silenziose"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notifiche"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversazioni"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Cancella tutte le notifiche silenziose"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifiche messe in pausa in base alla modalità Non disturbare"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Disattiva notifiche"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Continuare a ricevere notifiche da questa app?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Modalità silenziosa"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Livello predefinito"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Fumetto"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Nessun suono o vibrazione"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Nessun suono o vibrazione e appare più in basso nella sezione delle conversazioni"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Potrebbero essere attivati lo squillo o la vibrazione in base alle impostazioni del telefono"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Potrebbero essere attivati lo squillo o la vibrazione in base alle impostazioni del telefono. 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>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Viene mostrata in cima alla sezione delle conversazioni, appare sotto forma di bolla mobile, mostra l\'immagine del profilo nella schermata di blocco"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Impostazioni"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorità"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> non supporta impostazioni specifiche per le conversazioni"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 4730334..705f776 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"הגדל תצוגה כדי למלא את המסך"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"מתח כדי למלא את המסך"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"צילום מסך"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"לאפשרויות נוספות, יש לבטל את נעילת הטלפון"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"לאפשרויות נוספות, יש לבטל את נעילת הטאבלט"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"לאפשרויות נוספות, יש לבטל את נעילת המכשיר"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"נשלחה תמונה"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"שומר צילום מסך..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"שומר צילום מסך..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"‏מיקום מוגדר על ידי GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"בקשות מיקום פעילות"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"ההגדרה \'חיישנים כבויים\' פעילה"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"המדיה פעילה"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"הסרת כל ההתראות."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -525,10 +521,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"ניהול"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"היסטוריה"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"התקבלו"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"שקט"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"התראות"</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>
@@ -723,20 +717,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"השבתת ההתראות"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"שנמשיך להציג לך התראות מהאפליקציה הזאת?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"שקט"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"ברירת מחדל"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"בועה"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"ללא צליל או רטט"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"ללא צליל או רטט ומופיעה למטה בקטע התראות השיחה"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"ייתכן שיופעל צלצול או רטט בהתאם להגדרות הטלפון"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ייתכן שיופעל צלצול או רטט בהתאם להגדרות הטלפון. שיחות מהאפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מופיעות בבועות כברירת מחדל."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"מעוררת תשומת לב באמצעות קיצור דרך צף לתוכן הזה."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"מוצגת בחלק העליון של קטע התראות השיחה, מופיעה בבועה צפה, תוצג תמונת פרופיל במסך הנעילה"</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>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 0631005..c1aaebe 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"画面サイズに合わせて拡大"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"画面サイズに合わせて拡大"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"スクリーンショット"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"スマートフォンのロックを解除してその他のオプションを表示する"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"タブレットのロックを解除してその他のオプションを表示する"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"デバイスのロックを解除してその他のオプションを表示する"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"画像を送信しました"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"スクリーンショットを保存中..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"スクリーンショットを保存しています..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPSにより現在地が設定されました"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"現在地リクエストがアクティブ"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"センサー OFF: 有効"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"メディアは有効です"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"通知をすべて消去。"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"他 <xliff:g id="NUMBER">%s</xliff:g> 件"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"履歴"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"新着"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"サイレント"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"通知"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"通知を OFF にする"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"このアプリからの通知を今後も表示しますか?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"サイレント"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"デフォルト"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"バブル"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"着信音もバイブレーションも無効です"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"着信音もバイブレーションも無効になり会話セクションの下に表示されます"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"スマートフォンの設定を基に着信音またはバイブレーションが有効になります"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"スマートフォンの設定を基に着信音またはバイブレーションが有効になります。デフォルトでは <xliff:g id="APP_NAME">%1$s</xliff:g> からの会話がふきだしで表示されます。"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"このコンテンツのフローティング ショートカットで通知をお知らせします。"</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"会話セクションの一番上にふきだしとして表示され、プロフィール写真がロック画面に表示されます"</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>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 8390853..e70642a 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"მასშტაბი შეცვალეთ ეკრანის შესავსებად."</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"გაწიეთ ეკრანის შესავსებად."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ეკრანის ანაბეჭდი"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"მეტი ვარიანტის სანახავად განბლოკეთ თქვენი ტელეფონი"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"მეტი ვარიანტის სანახავად განბლოკეთ თქვენი ტაბლეტი"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"მეტი ვარიანტის სანახავად განბლოკეთ თქვენი მოწყობილობა"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"გაიგზავნა სურათი"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"სკრინშოტის შენახვა…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ეკრანის სურათის შენახვა…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPS-ით დადგენილი მდებარეობა"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"მდებარეობის მოთხოვნები აქტიურია"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"სენსორების გამორთვა აქტიურია"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"მედია აქტიურია"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"ყველა შეტყობინების წაშლა"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"მართვა"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ისტორია"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"შემომავალი"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"ჩუმი"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"შეტყობინებები"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"შეტყობინებების გამორთვა"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"გაგრძელდეს შეტყობინებათა ჩვენება ამ აპიდან?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"ჩუმი"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"ნაგულისხმევი"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"ბუშტი"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"ხმისა და ვიბრაციის გარეშე"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"ხმისა და ვიბრაციის გარეშე, ჩნდება მიმოწერების სექციის ქვედა ნაწილში"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"დარეკვა ან ვიბრაცია ტელეფონის პარამეტრების მიხედვით"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"დარეკვა ან ვიბრაცია ტელეფონის პარამეტრების მიხედვით. მიმოწერები <xliff:g id="APP_NAME">%1$s</xliff:g>-ის ბუშტიდან, ნაგულისხმევად."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"იპყრობს თქვენს ყურადღებას ამ კონტენტის მოლივლივე მალსახმობით."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"გამოჩნდება მიმოწერების სექციის ზედა ნაწილში მოლივლივე ბუშტის სახით, აჩვენებს პროფილის სურათს ჩაკეტილ ეკრანზე"</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>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 7045c34..a2e19f8 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Экранды толтыру үшін ұлғайту"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Экранды толтыру үшін созу"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Басқа опцияларды көру үшін телефон құлпын ашыңыз."</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Басқа опцияларды көру үшін планшет құлпын ашыңыз."</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Басқа опцияларды көру үшін құрылғы құлпын ашыңыз."</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"сурет жіберілді"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Скриншотты сақтауда…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Скриншотты сақтауда…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Орын GPS арқылы орнатылған"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Орын өтініштері қосылған"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Датчиктер өшірулі."</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Медиамазмұн ойнатылып жатыр."</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Барлық хабарларды жойыңыз."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Басқару"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Тарих"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Кіріс"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Үнсіз"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Хабарландырулар"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Хабарландыруларды өшіру"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Осы қолданбаның хабарландырулары көрсетілсін бе?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Дыбыссыз"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Әдепкі"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Көпіршік"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Дыбыс не діріл қолданылмайды"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Дыбыс не діріл қолданылмайды, төменде әңгімелер бөлімінде шығады"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Телефон параметрлеріне байланысты шылдырлауы не дірілдеуі мүмкін"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Телефон параметрлеріне байланысты шылдырлауы не дірілдеуі мүмкін. <xliff:g id="APP_NAME">%1$s</xliff:g> чаттары әдепкісінше қалқымалы етіп көрсетіледі."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Осы мазмұнға бекітілген қалқымалы таңбашамен назарыңызды өзіне тартады."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Әңгімелер бөлімінің жоғарғы жағында тұрады, қалқыма хабар түрінде шығады, құлыптаулы экранда профиль суретін көрсетеді"</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>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 82a9b33..e874df2 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ពង្រីក​​ដើម្បី​ឲ្យ​ពេញ​អេក្រង់"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ទាញ​ដើម្បី​ឲ្យ​ពេញ​អេក្រង់"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"រូបថតអេក្រង់"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"ដោះសោ​ទូរសព្ទរបស់អ្នក​សម្រាប់​ជម្រើសច្រើនទៀត"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"ដោះសោ​ថេប្លេតរបស់អ្នក​សម្រាប់​ជម្រើសច្រើនទៀត"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"ដោះសោ​ឧបករណ៍របស់អ្នក​សម្រាប់​ជម្រើសច្រើនទៀត"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"បាន​ផ្ញើរូបភាព"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"ទីតាំង​​​​​កំណត់​ដោយ GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"សំណើ​ទីតាំង​សកម្ម"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"ឧបករណ៍​ចាប់សញ្ញា​បានបិទ"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"មេឌៀ​កំពុងដំណើរការ"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"សម្អាត​ការ​ជូន​ដំណឹង​ទាំងអស់។"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"គ្រប់គ្រង"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ប្រវត្តិ"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"មក​ដល់"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"ស្ងាត់"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"ការជូនដំណឹង"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"បិទ​ការជូន​ដំណឹង"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"បន្ត​បង្ហាញ​ការជូនដំណឹង​ពីកម្មវិធីនេះ?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"ស្ងាត់"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"លំនាំដើម"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"ពពុះ"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"គ្មាន​សំឡេង ឬការញ័រទេ"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"គ្មានសំឡេង ឬការញ័រ និងការបង្ហាញ​កម្រិតទាបជាង​នេះនៅក្នុង​ផ្នែកសន្ទនាទេ"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"អាចរោទ៍ ឬញ័រ ដោយផ្អែកលើ​ការកំណត់​ទូរសព្ទ"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"អាចរោទ៍ ឬញ័រ ដោយផ្អែកលើ​ការកំណត់​ទូរសព្ទ។ ការសន្ទនា​ពី​ពពុះ <xliff:g id="APP_NAME">%1$s</xliff:g> តាម​លំនាំដើម​។"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ធ្វើឱ្យអ្នក​ចាប់អារម្មណ៍​ដោយប្រើ​ផ្លូវកាត់​អណ្ដែត​សម្រាប់ខ្លឹមសារនេះ។"</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"បង្ហាញនៅខាងលើ​ផ្នែកសន្ទនា បង្ហាញជា​ពពុះអណ្ដែត បង្ហាញ​រូបភាព​កម្រងព័ត៌មាន​នៅលើ​អេក្រង់ចាក់សោ"</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>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 3c0c091..750d161 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ಪರದೆ ತುಂಬಿಸಲು ಝೂಮ್ ಮಾಡು"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ಪರದೆ ತುಂಬಿಸಲು ವಿಸ್ತಾರಗೊಳಿಸು"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗಾಗಿ ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗಾಗಿ ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗಾಗಿ ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ಚಿತ್ರವನ್ನು ಕಳುಹಿಸಲಾಗಿದೆ"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"ಸ್ಥಾನವನ್ನು GPS ಮೂಲಕ ಹೊಂದಿಸಲಾಗಿದೆ"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"ಸ್ಥಳ ವಿನಂತಿಗಳು ಸಕ್ರಿಯವಾಗಿವೆ"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"ಸೆನ್ಸರ್‌ಗಳು ಆಫ್ ಆಗಿವೆ"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"ಮೀಡಿಯಾ ಸಕ್ರಿಯವಾಗಿದೆ"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೆರವುಗೊಳಿಸು."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"ನಿರ್ವಹಿಸಿ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ಇತಿಹಾಸ"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"ಒಳಬರುವ"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"ನಿಶ್ಶಬ್ದ"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"ಅಧಿಸೂಚನೆಗಳು"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"ಅಧಿಸೂಚನೆಗಳನ್ನು ಆಫ್ ಮಾಡಿ"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"ಈ ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೋರಿಸುತ್ತಲೇ ಇರಬೇಕೆ?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"ನಿಶ್ಶಬ್ದ"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"ಡೀಫಾಲ್ಟ್"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"ಬಬಲ್"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"ಯಾವುದೇ ಧ್ವನಿ ಅಥವಾ ವೈಬ್ರೇಷನ್‌ ಆಗುವುದಿಲ್ಲ"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"ಯಾವುದೇ ಧ್ವನಿ ಅಥವಾ ವೈಬ್ರೇಷನ್‌ ಆಗುವುದಿಲ್ಲ, ಸಂಭಾಷಣೆ ವಿಭಾಗದ ಕೆಳಭಾಗದಲ್ಲಿ ಗೋಚರಿಸುತ್ತದೆ"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಆಧರಿಸಿ ಫೋನ್ ರಿಂಗ್ ಅಥವಾ ವೈಬ್ರೇಟ್ ಆಗುತ್ತದೆ"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಆಧರಿಸಿ ಫೋನ್ ರಿಂಗ್ ಅಥವಾ ವೈಬ್ರೇಟ್ ಆಗುತ್ತದೆ. ಡಿಫಾಲ್ಟ್ ಆಗಿ, <xliff:g id="APP_NAME">%1$s</xliff:g> ನ ಬಬಲ್ ಸಂಭಾಷಣೆಗಳು."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ಈ ವಿಷಯಕ್ಕೆ ಲಿಂಕ್ ಮಾಡಿ ಕೊಂಡೊಯ್ಯುವ ಶಾರ್ಟ್‌ಕಟ್‌ ಕಡೆಗೆ ಗಮನ ಇರಿಸಿ."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"ಸಂಭಾಷಣೆ ವಿಭಾಗದ ಮೇಲ್ಭಾಗದಲ್ಲಿ ತೇಲುವ ಬಬಲ್‌ ಆಗಿ ಗೋಚರಿಸುತ್ತದೆ ಮತ್ತು ಪ್ರೊಫೈಲ್ ಚಿತ್ರವನ್ನು ಲಾಕ್‌ಸ್ಕ್ರೀನ್‌ ಮೇಲೆ‌ ಗೋಚರಿಸುತ್ತದೆ"</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>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 6ee038c..6fa6e9e 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"전체화면 모드로 확대"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"전체화면 모드로 확대"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"스크린샷"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"더 많은 옵션을 확인하려면 휴대전화를 잠금 해제하세요."</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"더 많은 옵션을 확인하려면 태블릿을 잠금 해제하세요."</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"더 많은 옵션을 확인하려면 기기를 잠금 해제하세요."</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"이미지 보냄"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"캡쳐화면 저장 중..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"캡쳐화면 저장 중..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPS에서 위치 설정"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"위치 요청 있음"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"센서 끄기 활성화"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"미디어가 활성화되어 있음"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"모든 알림 지우기"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"<xliff:g id="NUMBER">%s</xliff:g>개 더보기"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"관리"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"기록"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"최근 알림"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"무음"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"알림"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"알림 사용 중지"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"이 앱의 알림을 계속 표시하시겠습니까?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"무음"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"기본값"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"버블"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"소리 또는 진동 없음"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"소리나 진동이 울리지 않으며 대화 섹션 하단에 표시됨"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"휴대전화 설정에 따라 벨소리나 진동이 울릴 수 있음"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"휴대전화 설정에 따라 벨소리나 진동이 울릴 수 있습니다. 기본적으로 <xliff:g id="APP_NAME">%1$s</xliff:g>의 대화는 대화창으로 표시됩니다."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"이 콘텐츠로 연결되는 플로팅 바로가기로 사용자의 주의를 끕니다."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"대화 섹션 상단의 플로팅 대화창 또는 잠금 화면의 프로필 사진으로 표시됩니다."</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>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 69d4c68..49f7c00 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Экрнд тлтр ү. чен өлч өзг"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Экранды толтуруу ү-н чоюу"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Дагы башка параметрлерди көрүү үчүн телефонуңуздун кулпусун ачыңыз"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Дагы башка параметрлерди көрүү үчүн планшетиңиздин кулпусун ачыңыз"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Дагы башка параметрлерди көрүү үчүн түзмөгүңүздүн кулпусун ачыңыз"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"сүрөт жөнөттү"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Скриншот сакталууда…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Скриншот сакталууда..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPS боюнча аныкталган жайгашуу"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Жайгаштыруу талаптары иштелүүдө"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"\"Сенсорлорду өчүрүүнү\" активдештирүү"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Медиа ойнотулууда"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Бардык билдирмелерди өчүрүү."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Башкаруу"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Таржымал"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Кирүүчү"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Үнсүз"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Билдирмелер"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Билдирмелерди өчүрүү"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Бул колдонмонун билдирмелери көрсөтүлө берсинби?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Үнсүз"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Демейки"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Көбүк"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Үнү чыкпайт жана дирилдебейт"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Үнү чыгып же дирилдебейт жана жазышуу бөлүмүнүн ылдый жагында көрүнөт"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Телефондун жөндөөлөрүнө жараша шыңгырап же дирилдеши мүмкүн"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Телефондун жөндөөлөрүнө жараша шыңгырап же дирилдеши мүмкүн. <xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосундагы жазышуулар демейки жөндөө боюнча калкып чыкма билдирмелер болуп көрүнөт."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Калкыма ыкчам баскыч менен көңүлүңүздү бул мазмунга буруп турат."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Жазышуу бөлүмүнүн жогорку жагында калкып чыкма билдирме түрүндө көрүнүп, профиль сүрөтү кулпуланган экрандан чагылдырылат"</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>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 17f9184..6841a86 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ຊູມໃຫ້ເຕັມໜ້າຈໍ"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ປັບໃຫ້ເຕັມໜ້າຈໍ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ພາບໜ້າຈໍ"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"ປົດລັອກໂທລະສັບຂອງທ່ານເພື່ອໃຊ້ຕົວເລືອກເພີ່ມເຕີມ"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"ປົດລັອກແທັບເລັດຂອງທ່ານເພື່ອໃຊ້ຕົວເລືອກເພີ່ມເຕີມ"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"ປົດລັອກອຸປະກອນຂອງທ່ານເພື່ອໃຊ້ຕົວເລືອກເພີ່ມເຕີມ"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ສົ່ງຮູບແລ້ວ"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ກຳລັງບັນທຶກຮູບໜ້າຈໍ"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ກຳລັງບັນທຶກພາບໜ້າຈໍ..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"ສະຖານທີ່ກຳນົດໂດຍ GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"ການຮ້ອງຂໍສະຖານທີ່ທີ່ເຮັດວຽກຢູ່"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"ປິດການເຮັດວຽກຂອງເຊັນເຊີແລ້ວ"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"ເປີດໃຊ້ມີເດຍຢູ່"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"ລຶບການແຈ້ງເຕືອນທັງໝົດ."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"ຈັດການ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ປະຫວັດ"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"ຂາເຂົ້າ"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"ປິດສຽງ"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"ການແຈ້ງເຕືອນ"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"ປິດການແຈ້ງເຕືອນ"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"ສະແດງການແຈ້ງເຕືອນຈາກແອັບນີ້ຕໍ່ໄປບໍ?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"ປິດສຽງ"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"ຄ່າເລີ່ມຕົ້ນ"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"ຟອງ"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"ບໍ່ມີສຽງ ຫຼື ການສັ່ນເຕືອນ"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"ບໍ່ມີສຽງ ຫຼື ການສັ່ນເຕືອນ ແລະ ປາກົດຢູ່ທາງລຸ່ມຂອງພາກສ່ວນການສົນທະນາ"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"ອາດສົ່ງສຽງ ຫຼື ສັ່ນເຕືອນໂດຍອ້າງອີງຈາກການຕັ້ງຄ່າໂທລະສັບ"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ອາດສົ່ງສຽງ ຫຼື ສັ່ນເຕືອນໂດຍອ້າງອີງຈາກການຕັ້ງຄ່າໂທລະສັບ. ການສົນທະນາຈາກ <xliff:g id="APP_NAME">%1$s</xliff:g> ຈະເປັນ bubble ຕາມຄ່າເລີ່ມຕົ້ນ."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ເອົາໃຈໃສ່ທາງລັດແບບລອຍໄປຫາເນື້ອຫານີ້."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"ສະແດງຢູ່ເທິງສຸດຂອງພາກສ່ວນການສົນທະນາ, ປາກົດເປັນ bubble ແບບລອຍ, ສະແດງຮູບໂປຣໄຟລ໌ຢູ່ໜ້າຈໍລັອກ"</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>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 5684b63..29a6ffd 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Keisti mast., kad atit. ekr."</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ištempti, kad atit. ekr."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekrano kopija"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Atrakinkite telefoną, kad galėtumėte naudoti daugiau parinkčių"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Atrakinkite planšetinį kompiuterį, kad galėtumėte naudoti daugiau parinkčių"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Atrakinkite įrenginį, kad galėtumėte naudoti daugiau parinkčių"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"išsiuntė vaizdą"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Išsaugoma ekrano kopija..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Išsaugoma ekrano kopija..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPS nustatyta vieta"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Vietovės užklausos aktyvios"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Parinktis „Jutikliai išjungti“ aktyvi"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Medija aktyvi"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Išvalyti visus pranešimus."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"Dar <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -525,10 +521,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Tvarkyti"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Istorija"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Gaunami"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Tylūs"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Pranešimai"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Pokalbiai"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Išvalyti visus tylius pranešimus"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Pranešimai pristabdyti naudojant netrukdymo režimą"</string>
@@ -723,20 +717,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Išjungti pranešimus"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Toliau rodyti iš šios programos gautus pranešimus?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Tylūs"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Numatytasis"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Debesėlis"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Neskamba ir nevibruoja"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Neskamba, nevibruoja ir rodoma apatinėje pokalbių skilties dalyje"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Gali skambėti arba vibruoti, atsižvelgiant į telefono nustatymus"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Gali skambėti arba vibruoti, atsižvelgiant į telefono nustatymus. Pokalbiai iš „<xliff:g id="APP_NAME">%1$s</xliff:g>“ debesėlio pagal numatytuosius nustatymus."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Naudojant slankųjį spartųjį klavišą lengviau sutelkti dėmesį į šį turinį."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Rodoma pokalbių skilties viršuje, rodoma kaip slankusis burbulas, pateikiama profilio nuotrauka užrakinimo ekrane"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nustatymai"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritetas"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ nepalaiko konkrečių pokalbių nustatymų"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 873216e..2804b6f 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Tālumm., lai aizp. ekr."</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stiepiet, lai aizp. ekr."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekrānuzņēmums"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Atbloķējiet tālruni, lai skatītu citas opcijas."</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Atbloķējiet planšetdatoru, lai skatītu citas opcijas."</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Atbloķējiet ierīci, lai skatītu citas opcijas."</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"nosūtīts attēls"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saglabā ekrānuzņēmumu…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Notiek ekrānuzņēmuma saglabāšana..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPS iestatītā atrašanās vieta"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Aktīvi atrašanās vietu pieprasījumi"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Aktivizēts iestatījums “Sensori izslēgti”"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Tiek atskaņots multivides saturs"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Notīrīt visus paziņojumus"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"vēl <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -522,10 +518,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Pārvaldīt"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Vēsture"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Ienākošie"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Klusums"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Paziņojumi"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Sarunas"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Notīrīt visus klusos paziņojumus"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Paziņojumi pārtraukti, izmantojot iestatījumu “Netraucēt”"</string>
@@ -720,20 +714,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Izslēgt paziņojumus"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Vai turpināt rādīt paziņojumus no šīs lietotnes?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Klusums"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Noklusējums"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Burbulis"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Nav skaņas signāla vai vibrācijas"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Nav skaņas signāla vai vibrācijas, kā arī atrodas zemāk sarunu sadaļā"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Atkarībā no tālruņa iestatījumiem var zvanīt vai vibrēt"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Atkarībā no tālruņa iestatījumiem var zvanīt vai vibrēt. Sarunas no lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> pēc noklusējuma tiek parādītas burbulī."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Piesaista jūsu uzmanību, rādot peldošu saīsni uz šo saturu."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Parādās sarunu sadaļas augšdaļā un kā peldošs burbulis, kā arī bloķēšanas ekrānā tiek rādīts profila attēls"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Iestatījumi"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritārs"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"Lietotnē <xliff:g id="APP_NAME">%1$s</xliff:g> netiek atbalstīti atsevišķu sarunu iestatījumi."</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index d7a8d1b..071b3d8 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"സ്‌ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ സൂം ചെയ്യുക"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"സ്‌ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ വലിച്ചുനീട്ടുക"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"സ്ക്രീൻഷോട്ട്"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"കൂടുതൽ ഓപ്ഷനുകൾക്ക് നിങ്ങളുടെ ഫോൺ അൺലോക്ക് ചെയ്യുക"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"കൂടുതൽ ഓപ്ഷനുകൾക്ക് നിങ്ങളുടെ ടാബ്‌ലെറ്റ് അൺലോക്ക് ചെയ്യുക"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"കൂടുതൽ ഓപ്ഷനുകൾക്ക് നിങ്ങളുടെ ഉപകരണം അൺലോക്ക് ചെയ്യുക"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ചിത്രം അയച്ചു"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"ലൊക്കേഷൻ സജ്ജീകരിച്ചത് GPS ആണ്"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"ലൊക്കേഷൻ അഭ്യർത്ഥനകൾ സജീവമാണ്"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"സെൻസറുകൾ ഓഫ് സജീവമാണ്"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"മീഡിയ സജീവമാണ്"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"എല്ലാ വിവരങ്ങളും മായ്‌ക്കുക."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"മാനേജ് ചെയ്യുക"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ചരിത്രം"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"ഇൻകമിംഗ്"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"നിശബ്‌ദം"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"അറിയിപ്പുകൾ"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"അറിയിപ്പുകൾ ഓഫാക്കുക"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"ഈ ആപ്പിൽ നിന്നുള്ള അറിയിപ്പുകൾ തുടർന്നും കാണിക്കണോ?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"നിശബ്‌ദം"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"ഡിഫോൾട്ട്"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"ബബ്ൾ"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"ശബ്ദമോ വൈബ്രേഷനോ ഇല്ല"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"ശബ്‌ദമോ വൈബ്രേഷനോ ഇല്ല, കൂടാതെ സംഭാഷണ വിഭാഗത്തിന് താഴെയായി ദൃശ്യമാകും"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"ഫോൺ ക്രമീകരണം അടിസ്ഥാനമാക്കി റിംഗ് ചെയ്‌തേക്കാം അല്ലെങ്കിൽ വൈബ്രേറ്റ് ചെയ്‌തേക്കാം"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ഫോൺ ക്രമീകരണം അടിസ്ഥാനമാക്കി റിംഗ് ചെയ്‌തേക്കാം അല്ലെങ്കിൽ വൈബ്രേറ്റ് ചെയ്‌തേക്കാം. <xliff:g id="APP_NAME">%1$s</xliff:g>-ൽ നിന്നുള്ള സംഭാഷണങ്ങൾ ഡിഫോൾട്ടായി ബബ്ൾ ആവുന്നു."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ഈ ഉള്ളടക്കത്തിലേക്ക് ഒരു ഫ്ലോട്ടിംഗ് കുറുക്കുവഴി ഉപയോഗിച്ച് നിങ്ങളുടെ ശ്രദ്ധ നിലനിർത്തുന്നു."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"സംഭാഷണ വിഭാഗത്തിന് മുകളിലായി കാണിക്കുന്നു, ഫ്ലോട്ടിംഗ് ബബിളായി ദൃശ്യമാകുന്നു, ലോക്ക് സ്ക്രീനിൽ പ്രൊഫൈൽ ചിത്രം പ്രദർശിപ്പിക്കുന്നു"</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>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 9f4be26..fbb3b69 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Дэлгэц дүүргэх бол өсгөнө үү"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Дэлгэц дүүргэх бол татна уу"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Дэлгэцийн зураг дарах"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Бусад сонголтыг харахын тулд утасныхаа түгжээг тайлна уу"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Бусад сонголтыг харахын тулд таблетынхаа түгжээг тайлна уу"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Бусад сонголтыг харахын тулд төхөөрөмжийнхөө түгжээг тайлна уу"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"зураг илгээсэн"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Дэлгэцийн агшинг хадгалж байна…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Дэлгэцийн агшинг хадгалж байна…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPS байршил"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Байршлын хүсэлтүүд идэвхтэй"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Мэдрэгчийг унтраах идэвхтэй байна"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Медиа идэвхтэй байна"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Бүх мэдэгдлийг цэвэрлэх."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Удирдах"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Түүх"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Ирж буй"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Чимээгүй"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Мэдэгдлүүд"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Мэдэгдлийг унтраах"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Энэ аппаас мэдэгдэл харуулсан хэвээр байх уу?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Чимээгүй"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Өгөгдмөл"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Бөмбөлөг"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Дуу эсвэл чичиргээ байхгүй"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Дуу эсвэл чичиргээ байхгүй бөгөөд харицан ярианы хэсгийн доод талд харагдана"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Утасны тохиргоонд тулгуурлан хонх дуугаргах буюу эсхүл чичирхийлж болзошгүй"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Утасны тохиргоонд тулгуурлан хонх дуугаргах буюу эсхүл чичирхийлж болзошгүй. <xliff:g id="APP_NAME">%1$s</xliff:g>-н харилцан яриаг өгөгдмөл тохиргооны дагуу бөмбөлөг болгоно."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Энэ контентын хөвөн гарч ирэх товчлолтойгоор таны анхаарлыг татдаг."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Харилцан ярианы хэсгийн дээд талд хөвж буй бөмбөлөг хэлбэрээр харагдах бөгөөд профайлын зургийг түгжигдсэн дэлгэцэд үзүүлнэ"</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>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 76a15a8..1ee0c53 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"स्क्रीन भरण्यासाठी झूम करा"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"स्क्रीन भरण्यासाठी ताणा"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रीनशॉट"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"आणखी पर्यायांसाठी तुमचा फोन अनलॉक करा"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"आणखी पर्यायांसाठी तुमचा टॅबलेट अनलॉक करा"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"आणखी पर्यायांसाठी तुमचे डिव्हाइस अनलॉक करा"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"इमेज पाठवली आहे"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"स्क्रीनशॉट सेव्ह करत आहे…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रीनशॉट सेव्ह करत आहे…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPS द्वारे स्थान सेट केले"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"स्थान विनंत्या सक्रिय"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"सेन्सर बंद आहेत"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"मीडिया अ‍ॅक्टिव्ह आहे"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"सर्व सूचना साफ करा."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"व्यवस्थापित करा"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"इतिहास"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"आलेल्या"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"सायलंट"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"सूचना"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"सूचना बंद करा"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"या अ‍ॅपकडील सूचना दाखवणे सुरू ठेवायचे?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"सायलंट"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"डीफॉल्ट"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"बबल"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"आवाज किंवा व्हायब्रेशन नाही"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"आवाज किंवा व्हायब्रेशन नाही आणि संभाषण विभागात सर्वात तळाशी दिसते"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"फोन सेटिंग्जच्या आधारावर रिंग किंवा व्हायब्रेट होऊ शकतो"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"फोन सेटिंग्जच्या आधारावर रिंग किंवा व्हायब्रेट होऊ शकतो. <xliff:g id="APP_NAME">%1$s</xliff:g> मधील संभाषणे बाय डीफॉल्ट बबल होतात."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"या आशयाच्या फ्लोटिंग शॉर्टकटसह तुमचे लक्ष केंद्रित करते."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"संभाषण विभागात सर्वात वरती फ्लोटिंग बबल म्हणून दिसते, लॉक स्क्रीनवर प्रोफाइल पिक्चर दाखवते"</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>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 660fe7a..48c73df 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zum untuk memenuhi skrin"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Regang utk memenuhi skrin"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Tangkapan skrin"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Buka kunci telefon anda untuk mendapatkan lagi pilihan"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Buka kunci tablet anda untuk mendapatkan lagi pilihan"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Buka kunci peranti anda untuk mendapatkan lagi pilihan"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"menghantar imej"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Menyimpan tangkapan skrin..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Menyimpan tangkapan skrin..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Lokasi ditetapkan oleh GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Permintaan lokasi aktif"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Penderia dimatikan aktif"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Media aktif"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Padamkan semua pemberitahuan."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Urus"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Sejarah"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Masuk"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Senyap"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Pemberitahuan"</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>
@@ -717,20 +711,14 @@
     <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>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Lalai"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Gelembung"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Tiada bunyi atau getaran"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Tiada bunyi atau getaran dan muncul di sebelah bawah dalam bahagian perbualan"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Mungkin berbunyi atau bergetar berdasarkan tetapan telefon"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Mungkin berbunyi atau bergetar berdasarkan tetapan telefon. Perbualan daripada gelembung <xliff:g id="APP_NAME">%1$s</xliff:g> secara lalai."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Memastikan anda memberikan perhatian dengan pintasan terapung ke kandungan ini."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Ditunjukkan di sebelah atas bahagian perbualan, muncul sebagai gelembung terapung, memaparkan gambar profil pada skrin kunci"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Tetapan"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Keutamaan"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak menyokong tetapan khusus perbualan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index f5b3f6e..cf8f811 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ဇူးမ်အပြည့်ဆွဲခြင်း"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ဖန်သားပြင်အပြည့်ဆန့်ခြင်း"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"နောက်ထပ် ထိန်းချုပ်မှုများအတွက် သင့်ဖုန်းကို လော့ခ်ဖွင့်ပါ"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"နောက်ထပ် ထိန်းချုပ်မှုများအတွက် သင့်တက်ဘလက်ကို လော့ခ်ဖွင့်ပါ"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"နောက်ထပ် ထိန်းချုပ်မှုများအတွက် သင့်စက်ကို လော့ခ်ဖွင့်ပါ"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ပုံပို့ထားသည်"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ဖန်သားပြင်ဓါတ်ပုံသိမ်းစဉ်.."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား သိမ်းဆည်းပါမည်"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPSမှတည်နေရာကိုအတည်ပြုသည်"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"တည်နေရာပြ တောင်းဆိုချက်များ အသက်ဝင်ရန်"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"အာရုံခံစနစ်များ ပိတ်ထားသည်"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"မီဒီယာ ဖွင့်ထားသည်"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"သတိပေးချက်အားလုံးအား ဖယ်ရှားခြင်း။"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"စီမံရန်"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"မှတ်တမ်း"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"အဝင်"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"အသံတိတ်ခြင်း"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"အကြောင်းကြားချက်များ"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"အကြောင်းကြားချက်များ ပိတ်ရန်"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"ဤအက်ပ်ထံမှ အကြောင်းကြားချက်များကို ဆက်ပြလိုပါသလား။"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"အသံတိတ်ရန်"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"မူလ"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"ပူဖောင်းဖောက်သံ"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"အသံ သို့မဟုတ် တုန်ခါမှုမရှိပါ"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"အသံ သို့မဟုတ် တုန်ခါမှုမရှိပါ၊ စကားဝိုင်းကဏ္ဍ၏ အောက်ပိုင်းတွင် မြင်ရသည်"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"ဖုန်းဆက်တင်များပေါ် အခြေခံပြီး အသံမြည်နိုင်သည် သို့မဟုတ် တုန်ခါနိုင်သည်"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ဖုန်းဆက်တင်များပေါ် အခြေခံပြီး အသံမြည်နိုင်သည် သို့မဟုတ် တုန်ခါနိုင်သည်။ မူရင်းသတ်မှတ်ချက်အဖြစ် <xliff:g id="APP_NAME">%1$s</xliff:g> မှ စကားဝိုင်းများကို ပူဖောင်းကွက်ဖြင့် ပြသည်။"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"အကြောင်းအရာကို floating shortcut ကိုသုံး၍ အာရုံစိုက်လာအောင်လုပ်ပါ။"</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"စကားဝိုင်းကဏ္ဍ၏ ထိပ်ပိုင်းတွင် ပြပြီး ပူဖောင်းကွက်အဖြစ် မြင်ရသည်၊ လော့ခ်ချထားချိန် မျက်နှာပြင်တွင် ပရိုဖိုင်ပုံကို ပြသည်"</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>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index a38fb4c..4bedaab 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom for å fylle skjermen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Strekk for å fylle skjerm"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skjermdump"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Lås opp telefonen din for å få flere alternativer"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Lås opp nettbrettet ditt for å få flere alternativer"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Lås opp enheten din for å få flere alternativer"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"har sendt et bilde"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Lagrer skjermdumpen …"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Lagrer skjermdumpen …"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Posisjon angitt av GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Aktive stedsforespørsler"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"«Sensorene er av» er aktiv"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Medier er aktive"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Fjern alle varslinger."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Administrer"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Logg"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Innkommende"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Lydløs"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Varsler"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Samtaler"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Fjern alle lydløse varsler"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Varsler er satt på pause av «Ikke forstyrr»"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Slå av varsler"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Vil du fortsette å vise varsler fra denne appen?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Lydløs"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Standard"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Boble"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Ingen lyd eller vibrering"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Ingen lyd eller vibrering, og vises lavere i samtaledelen"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Kan ringe eller vibrere basert på telefoninnstillingene"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan ringe eller vibrere basert på telefoninnstillingene. Samtaler fra <xliff:g id="APP_NAME">%1$s</xliff:g> lager bobler som standard."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Holder deg oppmerksom med en svevende snarvei til dette innholdet."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Vises øverst i samtaledelen, vises som en flytende boble, viser profilbildet på låseskjermen"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Innstillinger"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> støtter ikke samtalespesifikke innstillinger"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 4483c5e..05839b3 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"स्क्रिन भर्न जुम गर्नुहोस्"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"स्क्रिन भर्न तन्काउनुहोस्"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रिनसट"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"थप विकल्पहरू हेर्न आफ्नो फोन अनलक गर्नुहोस्"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"थप विकल्पहरू हेर्न आफ्नो ट्याब्लेट अनलक गर्नुहोस्"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"थप विकल्पहरू हेर्न आफ्नो यन्त्र अनलक गर्नुहोस्"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"कुनै छवि पठाइयो"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"स्क्रिनसट बचत गर्दै…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रिनसट बचत गर्दै…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPS द्वारा स्थान सेट गरिएको"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"स्थान अनुरोधहरू सक्रिय"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"सेन्सर निष्क्रिय नामक सुविधा सक्रिय छ"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"मिडिया प्ले भइरहेको छ"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"सबै सूचनाहरू हटाउनुहोस्।"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"व्यवस्थित गर्नुहोस्"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"इतिहास"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"हालसालै प्राप्त भएका सूचनाहरू"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"मौन"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"सूचनाहरू"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"सूचनाहरू निष्क्रिय पार्नुहोस्"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"यो अनुप्रयोगका सूचनाहरू देखाउने क्रम जारी राख्ने हो?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"मौन"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"पूर्वनिर्धारित"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"बबल"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"न घन्टी बज्छ न त कम्पन नै हुन्छ"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"न घन्टी बज्छ न त कम्पन नै हुन्छ र वार्तालाप खण्डको तलतिर देखा पर्छ"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"फोनको सेटिङका आधारमा घन्टी बज्न वा कम्पन हुन सक्छ"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"फोनको सेटिङका आधारमा घन्टी बज्न वा कम्पन हुन सक्छ। <xliff:g id="APP_NAME">%1$s</xliff:g> का वार्तालापहरू पूर्वनिर्धारित रूपमा बबलमा देखाइन्छन्।"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"फ्लोटिङ सर्टकटमार्फत यो सामग्रीतर्फ तपाईंको ध्यान आकर्षित गर्दछ।"</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"वार्तालाप खण्डको सिरानमा देखा पर्छ, तैरने बबलका रूपमा देखा पर्छ, लक स्क्रिनमा प्रोफाइल तस्बिर देखाइन्छ"</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>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index deea505..8116345 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom om scherm te vullen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Rek uit v. schermvulling"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Ontgrendel je telefoon voor meer opties"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Ontgrendel je tablet voor meer opties"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Ontgrendel je apparaat voor meer opties"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"heeft een afbeelding gestuurd"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Screenshot opslaan..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Screenshot opslaan..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Locatie bepaald met gps"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Locatieverzoeken actief"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"\'Sensoren uit\' actief"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Media is actief"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Alle meldingen wissen."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Beheren"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Geschiedenis"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Inkomend"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Stil"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Meldingen"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Gesprekken"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Alle stille meldingen wissen"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Meldingen onderbroken door \'Niet storen\'"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Meldingen uitschakelen"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Meldingen van deze app blijven weergeven?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Stil"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Standaard"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bubbel"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Geen geluid of trilling"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Geen geluid of trilling en wordt op een lagere positie in het gedeelte met gesprekken weergegeven"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Kan overgaan of trillen op basis van de telefooninstellingen"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan overgaan of trillen op basis van de telefooninstellingen. Gesprekken uit <xliff:g id="APP_NAME">%1$s</xliff:g> worden standaard als bubbels weergegeven."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Trekt de aandacht met een zwevende snelkoppeling naar deze content."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Wordt bovenaan het gedeelte met gesprekken weergegeven, verschijnt als zwevende bubbel, geeft de profielfoto weer op het vergrendelingsscherm"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Instellingen"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioriteit"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> ondersteunt geen gespreksspecifieke instellingen"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 6961613..5622788b 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਜ਼ੂਮ ਕਰੋ"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਸਟ੍ਰੈਚ ਕਰੋ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਕਰੋ"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਆਪਣਾ ਟੈਬਲੈੱਟ ਅਣਲਾਕ ਕਰੋ"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਆਪਣਾ ਡੀਵਾਈਸ ਅਣਲਾਕ ਕਰੋ"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ਚਿੱਤਰ ਭੇਜਿਆ ਗਿਆ"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPS ਵੱਲੋਂ ਸੈੱਟ ਕੀਤਾ ਗਿਆ ਟਿਕਾਣਾ"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਸੇਵਾ ਬੇਨਤੀਆਂ ਸਕਿਰਿਆ"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"\'ਸੈਂਸਰ ਬੰਦ ਕਰੋ\' ਨੂੰ ਕਿਰਿਆਸ਼ੀਲ ਕਰੋ"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"ਮੀਡੀਆ ਕਿਰਿਆਸ਼ੀਲ ਹੈ"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਹਟਾਓ।"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ਇਤਿਹਾਸ"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"ਇਨਕਮਿੰਗ"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"ਸ਼ਾਂਤ"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"ਸੂਚਨਾਵਾਂ"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"ਸੂਚਨਾਵਾਂ ਬੰਦ ਕਰੋ"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"ਕੀ ਇਸ ਐਪ ਤੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਦਿਖਾਉਣਾ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"ਸ਼ਾਂਤ"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"ਪੂਰਵ-ਨਿਰਧਾਰਤ"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"ਬੁਲਬੁਲਾ"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"ਕੋਈ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਹੀਂ"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"ਕੋਈ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਹੀਂ ਅਤੇ ਸੂਚਨਾਵਾਂ ਗੱਲਬਾਤ ਸੈਕਸ਼ਨ ਵਿੱਚ ਹੇਠਲੇ ਪਾਸੇ ਦਿਸਦੀਆਂ ਹਨ"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"ਫ਼ੋਨ ਸੈਟਿੰਗਾਂ ਦੇ ਆਧਾਰ \'ਤੇ ਘੰਟੀ ਵੱਜ ਸਕਦੀ ਹੈ ਜਾਂ ਥਰਥਰਾਹਟ ਹੋ ਸਕਦੀ ਹੈ"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ਫ਼ੋਨ ਸੈਟਿੰਗਾਂ ਦੇ ਆਧਾਰ \'ਤੇ ਘੰਟੀ ਵੱਜ ਸਕਦੀ ਹੈ ਜਾਂ ਥਰਥਰਾਹਟ ਹੋ ਸਕਦੀ ਹੈ। ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੌਰ \'ਤੇ <xliff:g id="APP_NAME">%1$s</xliff:g> ਬਬਲ ਤੋਂ ਗੱਲਾਂਬਾਤਾਂ।"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ਇਸ ਸਮੱਗਰੀ ਦੇ ਅਸਥਿਰ ਸ਼ਾਰਟਕੱਟ ਨਾਲ ਆਪਣਾ ਧਿਆਨ ਕੇਂਦਰਿਤ ਰੱਖੋ।"</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"ਗੱਲਬਾਤ ਸੈਕਸ਼ਨ ਦੇ ਸਿਖਰ \'ਤੇ ਦਿਖਾਈਆਂ ਜਾਂਦੀਆਂ ਹਨ, ਬਬਲ ਵਜੋਂ ਦਿਸਦੀਆਂ ਹਨ, ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ ਦਿਖਾਈ ਜਾਂਦੀ ਹੈ"</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>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index cd6facc7..abb4cfc 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Powiększ, aby wypełnić ekran"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Rozciągnij, aby wypełnić ekran"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Zrzut ekranu"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Odblokuj telefon, by wyświetlić więcej opcji"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Odblokuj tablet, by wyświetlić więcej opcji"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Odblokuj urządzenie, by wyświetlić więcej opcji"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"wysłano obraz"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Zapisywanie zrzutu ekranu..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Zapisywanie zrzutu ekranu..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Lokalizacja z GPSa"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Prośby o lokalizację są aktywne"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Wyłączenie czujników aktywne"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Multimedia są aktywne"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Usuń wszystkie powiadomienia."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -525,10 +521,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Zarządzaj"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historia"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Przychodzące"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Ciche"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Powiadomienia"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Rozmowy"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Usuń wszystkie ciche powiadomienia"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Powiadomienia wstrzymane przez tryb Nie przeszkadzać"</string>
@@ -723,20 +717,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Wyłącz powiadomienia"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Nadal pokazywać powiadomienia z tej aplikacji?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Bez dźwięku"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Domyślne"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Dymek"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Brak dźwięku i wibracji"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Brak dźwięku i wibracji, wyświetla się niżej w sekcji rozmów"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Może włączyć dzwonek lub wibracje w zależności od ustawień telefonu"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Może włączyć dzwonek lub wibracje w zależności od ustawień telefonu. Rozmowy z aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g> są domyślnie wyświetlane jako dymki."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Przyciąga uwagę dzięki pływającym skrótom do treści."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Wyświetla się jako pływający dymek u góry sekcji rozmów, pokazuje zdjęcie profilowe na ekranie blokady"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ustawienia"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorytet"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> nie obsługuje ustawień rozmowy"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index c106584..e581176 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom p/ preencher a tela"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ampliar p/ preencher tela"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capturar tela"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Desbloqueie seu smartphone para ver mais opções"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Desbloqueie seu tablet para ver mais opções"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Desbloqueie seu dispositivo para ver mais opções"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"enviou uma imagem"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Salvando captura de tela..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Salvando captura de tela..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Local definido por GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Solicitações de localização ativas"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"A opção \"Sensores desativados\" está ativa"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"A mídia está ativa"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Limpar todas as notificações."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"Mais <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gerenciar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Histórico"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Recebidas"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Silenciosas"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notificações"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversas"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Apagar todas as notificações silenciosas"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificações pausadas pelo modo \"Não perturbe\""</string>
@@ -717,20 +711,14 @@
     <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">"Silencioso"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Padrão"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bolha"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Som e vibração desativados"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"O som e a vibração estão desativados, e o balão aparece na parte inferior da seção de conversa"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Pode vibrar ou tocar com base nas configurações do smartphone"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pode vibrar ou tocar com base nas configurações do smartphone. As conversas do app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem em balões por padrão."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantém sua atenção com um atalho flutuante para esse conteúdo."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparece na parte superior de uma seção de conversa, em forma de balão, mostrando a foto do perfil na tela de bloqueio"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configurações"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> não é compatível com configurações específicas de conversa"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index fefff49..8102e6b 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom para preencher o ecrã"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Esticar p. caber em ec. int."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de ecrã"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Desbloqueie o telemóvel para obter mais opções."</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Desbloqueie o tablet para obter mais opções."</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Desbloqueie o dispositivo para obter mais opções."</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"enviou uma imagem"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"A guardar captura de ecrã..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"A guardar captura de ecrã..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Localização definida por GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Pedidos de localização ativos"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensores desativados ativo"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"O conteúdo multimédia está ativo."</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Limpar todas as notificações."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gerir"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Histórico"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"A receber"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Silencioso"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notificações"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversas"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Limpar todas as notificações silenciosas"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificações colocadas em pausa pelo modo Não incomodar."</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desativar notificações"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Pretende continuar a ver notificações desta app?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Silencioso"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Predefinição"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Balão"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Sem som ou vibração"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Sem som ou vibração e aparece na parte inferior na secção de conversas."</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Pode tocar ou vibrar com base nas definições do telemóvel."</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pode tocar ou vibrar com base nas definições do telemóvel. 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>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparece na parte superior da secção de conversas, surge como um balão flutuante e apresenta a imagem do perfil no ecrã de bloqueio."</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>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index c106584..e581176 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom p/ preencher a tela"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ampliar p/ preencher tela"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capturar tela"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Desbloqueie seu smartphone para ver mais opções"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Desbloqueie seu tablet para ver mais opções"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Desbloqueie seu dispositivo para ver mais opções"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"enviou uma imagem"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Salvando captura de tela..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Salvando captura de tela..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Local definido por GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Solicitações de localização ativas"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"A opção \"Sensores desativados\" está ativa"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"A mídia está ativa"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Limpar todas as notificações."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"Mais <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gerenciar"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Histórico"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Recebidas"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Silenciosas"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notificações"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversas"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Apagar todas as notificações silenciosas"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificações pausadas pelo modo \"Não perturbe\""</string>
@@ -717,20 +711,14 @@
     <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">"Silencioso"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Padrão"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bolha"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Som e vibração desativados"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"O som e a vibração estão desativados, e o balão aparece na parte inferior da seção de conversa"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Pode vibrar ou tocar com base nas configurações do smartphone"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pode vibrar ou tocar com base nas configurações do smartphone. As conversas do app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem em balões por padrão."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantém sua atenção com um atalho flutuante para esse conteúdo."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparece na parte superior de uma seção de conversa, em forma de balão, mostrando a foto do perfil na tela de bloqueio"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configurações"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> não é compatível com configurações específicas de conversa"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index b5534fd..d5a774d 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom pt. a umple ecranul"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Înt. pt. a umple ecranul"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captură de ecran"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Deblocați telefonul pentru mai multe opțiuni"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Deblocați tableta pentru mai multe opțiuni"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Deblocați dispozitivul pentru mai multe opțiuni"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"a trimis o imagine"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Se salv. captura de ecran..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Se salvează captura de ecran..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Locație setată prin GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Solicitări locație active"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Dezactivarea senzorilor este activă"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Serviciile media sunt active"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Ștergeți toate notificările."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -522,10 +518,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Gestionați"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Istoric"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Primite"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Silențioase"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Notificări"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversații"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Ștergeți toate notificările silențioase"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificări întrerupte prin „Nu deranja”"</string>
@@ -720,20 +714,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Dezactivați notificările"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Doriți să continuați afișarea notificărilor de la această aplicație?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Silențios"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Prestabilite"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Balon"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Fără sunet sau vibrații"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Fără sunet sau vibrații și apare în partea de jos a secțiunii de conversație"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Poate să sune sau să vibreze, în funcție de setările telefonului"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Poate să sune sau să vibreze, în funcție de setările telefonului. Conversațiile din balonul <xliff:g id="APP_NAME">%1$s</xliff:g> în mod prestabilit."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Vă atrage atenția printr-o comandă rapidă flotantă la acest conținut."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Se afișează în partea de sus a secțiunii de conversație, apare ca un balon flotant, afișează fotografia de profil pe ecranul de blocare"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Setări"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritate"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> nu acceptă setările pentru conversații"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index fd4ed6e..da367e7 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Подогнать по размерам экрана"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Растянуть на весь экран"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Чтобы посмотреть дополнительные параметры, разблокируйте телефон."</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Чтобы посмотреть дополнительные параметры, разблокируйте планшет."</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Чтобы посмотреть дополнительные параметры, разблокируйте устройство."</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"отправлено изображение"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Сохранение..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Сохранение..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Координаты по GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Есть активные запросы на определение местоположения"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Датчики отключены"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Идет воспроизведение мультимедиа"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Удалить все уведомления"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -525,10 +521,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Настроить"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"История"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Входящие"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Без звука"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Уведомления"</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>
@@ -723,20 +717,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Выключить уведомления"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Показывать уведомления от этого приложения?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Без звука"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"По умолчанию"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Всплывающая подсказка"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Без звука или вибрации"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Без звука или вибрации, появляется в нижней части списка разговоров"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Звонок или вибрация в зависимости от настроек телефона"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Звонок или вибрация в зависимости от настроек телефона. Разговоры из приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" по умолчанию появляются в виде всплывающего чата."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Привлекает ваше внимание к контенту с помощью плавающего ярлыка"</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Появляется в верхней части списка разговоров и как всплывающий чат, а также показывает фото профиля на заблокированном экране"</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>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 1cabf2a..a75d5ee 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"තිරය පිරවීමට විශාලනය කරන්න"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"තිරය පිරවීමට අදින්න"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"තිර රුව"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"තව විකල්ප සඳහා ඔබේ දුරකථනය අගුලු හරින්න"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"තව විකල්ප සඳහා ඔබේ ටැබ්ලට් පරිගණකය අගුලු හරින්න"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"තව විකල්ප සඳහා ඔබේ උපාංගය අගුලු හරින්න"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"රූපයක් එවන ලදී"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"තිර රුව සුරකිමින්…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"තිර රුව සුරැකෙමින් පවතී…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPS මඟින් ස්ථානය සකසා ඇත"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"පිහිටීම් ඉල්ලීම් සක්‍රියයි"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"සංවේදක ක්‍රියාවිරහිතය සක්‍රියයි"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"මාධ්‍ය සක්‍රියයි"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"සියලු දැනුම්දීම් හිස් කරන්න."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"කළමනාකරණය කරන්න"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ඉතිහාසය"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"එන"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"නිහඬ"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"දැනුම් දීම්"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"දැනුම්දීම් අක්‍රිය කරන්න"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"මෙම යෙදුම වෙතින් දැනුම්දීම් පෙන්වමින් තබන්නද?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"නිහඬ"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"පෙරනිමි"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"බුබුළු"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"හඬක් හෝ කම්පනයක් නැත"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"හඬක් හෝ කම්පනයක් නැති අතර සංවාද කොටසේ පහළම දිස් වේ"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"දුරකථන සැකසීම් මත පදනම්ව නාද කිරීමට හෝ කම්පනය කිරීමට හැකිය"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"දුරකථන සැකසීම් මත පදනම්ව නාද කිරීමට හෝ කම්පනය කිරීමට හැකිය. <xliff:g id="APP_NAME">%1$s</xliff:g> වෙතින් සංවාද පෙරනිමියෙන් බුබුළු දමයි"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"පාවෙන කෙටිමගක් සමග ඔබේ අවධානය මෙම අන්තර්ගතය වෙත තබා ගන්න."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"සංවාද කොටසේ ඉහළම පෙන්වයි, බුබුළක් ලෙස දිස් වේ, අගුලු තිරයේ පැතිකඩ පින්තූරය සංදර්ශනය වේ"</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>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index e71c3ee..7add73f 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Priblížiť na celú obrazovku"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Na celú obrazovku"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snímka obrazovky"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Odomknite svoj telefón pre ďalšie možnosti"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Odomknite svoj tablet pre ďalšie možnosti"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Odomknite svoje zariadenie pre ďalšie možnosti"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"odoslal(a) obrázok"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Prebieha ukladanie snímky obrazovky..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Prebieha ukladanie snímky obrazovky..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Poloha nastavená pomocou GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Žiadosti o polohu sú aktívne"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Funkcia Senzory sú vypnuté je aktívna"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Médium je aktívne"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Vymazať všetky upozornenia."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -525,10 +521,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Spravovať"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"História"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Prichádzajúce"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Ticho"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Upozornenia"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Konverzácie"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Vymazať všetky tiché upozornenia"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Upozornenia sú pozastavené režimom bez vyrušení"</string>
@@ -723,20 +717,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Vypnúť upozornenia"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Majú sa upozornenia z tejto aplikácie naďalej zobrazovať?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Tiché"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Predvolené"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bublina"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Žiadny zvuk ani vibrácie"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Žiadny zvuk ani vibrácie a zobrazuje sa v dolnej sekcii konverzácie"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Môže zvoniť alebo vibrovať podľa nastavení telefónu"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Môže zvoniť alebo vibrovať podľa nastavení telefónu. Predvolene sa zobrazia konverzácie z bubliny <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Upúta vás plávajúcim odkazom na tento obsah."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Nájdete ju v hornej sekcii konverzácie ako plávajúcu bublinu a zobrazuje profilovú fotku na uzamknutej obrazovke"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nastavenia"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorita"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> nepodporuje nastavenia konkrétnych konverzácií"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 5615c3a..024188f 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Povečava čez cel zaslon"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Raztegnitev čez zaslon"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Posnetek zaslona"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Za več možnosti odklenite telefon"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Za več možnosti odklenite tablični računalnik"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Za več možnosti odklenite napravo"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"je poslal(-a) sliko"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Shranjev. posnetka zaslona ..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Shranjevanje posnetka zaslona ..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Lokacija nastavljena z GPS-om"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Aktivne zahteve za lokacijo"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Izklop za tipala je aktiven"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Predstavnost je aktivna"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Izbriši vsa obvestila."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"in <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -525,10 +521,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Upravljanje"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Zgodovina"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Dohodno"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Tiho"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Obvestila"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Pogovori"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Brisanje vseh tihih obvestil"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Prikazovanje obvestil je začasno zaustavljeno z načinom »ne moti«"</string>
@@ -723,20 +717,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Izklopi obvestila"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Želite, da so obvestila te aplikacije še naprej prikazana?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Tiho"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Privzeto"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Mehurček"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Brez zvočnega opozarjanja ali vibriranja"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Brez zvočnega opozarjanja ali vibriranja, prikaz nižje v razdelku s pogovorom"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Zvonjenje ali vibriranje je omogočeno na podlagi nastavitev telefona"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Zvonjenje ali vibriranje je omogočeno na podlagi nastavitev telefona. Pogovori v aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> so privzeto prikazani v oblačkih."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Zadrži vašo pozornost z lebdečo bližnjico do te vsebine."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Prikaz na vrhu razdelka s pogovorom in v plavajočem oblačku, prikaz profilne slike na zaklenjenem zaslonu"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nastavitve"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prednost"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> ne podpira posebnih nastavitev za pogovore"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 5d10a71..1402646 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zmadho për të mbushur ekranin"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Shtrije për të mbushur ekranin"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Pamja e ekranit"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Shkyçe telefonin për më shumë opsione"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Shkyçe tabletin për më shumë opsione"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Shkyçe pajisjen për më shumë opsione"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"dërgoi një imazh"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Po ruan pamjen e ekranit..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Po ruan pamjen e ekranit…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Vendndodhja është caktuar nga GPS-ja"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Kërkesat për vendodhje janë aktive"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Çaktivizimi i sensorëve aktiv"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Media është aktive"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Pastro të gjitha njoftimet."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Menaxho"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historiku"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Hyrëse"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Në heshtje"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Njoftimet"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Bisedat"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Pastro të gjitha njoftimet në heshtje"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Njoftimet janë vendosur në pauzë nga modaliteti \"Mos shqetëso\""</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Çaktivizo njoftimet"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Do të vazhdosh t\'i shfaqësh njoftimet nga ky aplikacion?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Në heshtje"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"E parazgjedhur"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Flluskë"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Asnjë tingull ose dridhje"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Asnjë tingull ose dridhje dhe shfaqet më poshtë në seksionin e bisedave"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Mund të bjerë zilja ose të dridhet në bazë të cilësimeve të telefonit"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Mund të bjerë zilja ose të dridhet në bazë të cilësimeve të telefonit. Bisedat nga flluska e <xliff:g id="APP_NAME">%1$s</xliff:g> si parazgjedhje."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mban vëmendjen tënde me një shkurtore pluskuese te kjo përmbajtje."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shfaqet në krye të seksionit të bisedës dhe shfaqet si flluskë pluskuese, shfaq fotografinë e profilit në ekranin e kyçjes"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Cilësimet"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Përparësia"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk i mbështet cilësimet specifike të bisedës"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index f24c5d4..4b6de24 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Зумирај на целом екрану"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Развуци на цео екран"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Снимак екрана"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Откључајте телефон за још опција"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Откључајте таблет за још опција"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Откључајте уређај за још опција"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"је послао/ла слику"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Чување снимка екрана..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Чување снимка екрана..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Локацију је подесио GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Има активних захтева за локацију"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Сензори су искључени"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Медијум је активан"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Обриши сва обавештења."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"и још <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -522,10 +518,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Управљајте"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Историја"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Долазно"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Нечујно"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Обавештења"</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>
@@ -720,20 +714,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Искључи обавештења"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Желите ли да се обавештења из ове апликације и даље приказују?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Нечујно"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Подразумевано"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Облачић"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Без звука и вибрирања"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Без звука и вибрирања и приказује се у наставку одељка за конверзације"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Може да звони или вибрира у зависности од подешавања телефона"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Може да звони или вибрира у зависности од подешавања телефона. Конверзације из апликације <xliff:g id="APP_NAME">%1$s</xliff:g> се подразумевано приказују у облачићима."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Привлачи вам пажњу помоћу плутајуће пречице до овог садржаја."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Приказује се у врху одељка за конверзације као плутајући облачић, приказује слику профила на закључаном екрану"</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>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index e289a16..7c4962e 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zooma för att fylla skärm"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Dra för att fylla skärmen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skärmdump"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Lås upp telefonen för fler alternativ"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Lås upp surfplattan för fler alternativ"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Lås upp enheten för fler alternativ"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"har skickat en bild"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Skärmdumpen sparas ..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Skärmdumpen sparas ..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Platsen har identifierats av GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Det finns aktiva platsbegäranden"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensorer har inaktiverats"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Media har aktiverats"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Ta bort alla meddelanden."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"<xliff:g id="NUMBER">%s</xliff:g> till"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Hantera"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historik"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Inkommande"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Ljudlöst"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Aviseringar"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Inaktivera aviseringar"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Vill du fortsätta visa aviseringar för den här appen?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Tyst"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Standard"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bubbla"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Inga ljud eller vibrationer"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Inga ljud eller vibrationer och visas längre ned bland konversationerna"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Kan ringa eller vibrera beroende på inställningarna på telefonen"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan ringa eller vibrera beroende på inställningarna på telefonen. Konversationer från <xliff:g id="APP_NAME">%1$s</xliff:g> visas i bubblor som standard."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Behåller din uppmärksamhet med en flytande genväg till innehållet."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Visas högst upp bland konversationerna som en flytande bubbla, visar profilbilden på låsskärmen"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Inställningar"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> har inte stöd för konversationsspecifika inställningar"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 49e7a8e..fd3194a 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Kuza ili kujaza skrini"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Tanua ili kujaza skrini"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Picha ya skrini"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Fungua simu yako ili upate chaguo zaidi"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Fungua kompyuta yako kibao ili upate chaguo zaidi"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Fungua kifaa chako ili upate chaguo zaidi"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"imetuma picha"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Inahifadhi picha ya skrini..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Inahifadhi picha ya skrini..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Mahali pamewekwa na GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Maombi ya eneo yanatumika"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Kipengele cha kuzima vitambuzi kimewashwa"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Maudhui yanachezwa"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Futa arifa zote."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Dhibiti"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Historia"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Simu inayoingia"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Kimya"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Arifa"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Zima arifa"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Ungependa kuendelea kuonyesha arifa kutoka programu hii?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Kimya"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Chaguomsingi"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Kiputo"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Hakuna sauti wala mtetemo"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Hakuna sauti wala mtetemo na huonekana upande wa chini katika sehemu ya mazungumzo"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Huenda ikalia au kutetema kulingana na mipangilio ya simu"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Huenda ikalia au kutetema kulingana na mipangilio ya simu. 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>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Huonyeshwa kwenye sehemu ya juu ya mazungumzo, huonekana kama kiputo, huonyesha picha ya wasifu kwenye skrini iliyofungwa"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Mipangilio"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Kipaumbele"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g> haitumii mipangilio mahususi ya mazungumzo"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 4c01182..8e9370a 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"திரையை நிரப்ப அளவை மாற்று"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"திரையை நிரப்ப இழு"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ஸ்கிரீன்ஷாட்"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"மேலும் விருப்பங்களுக்கு மொபைலை அன்லாக் செய்யவும்"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"மேலும் விருப்பங்களுக்கு டேப்லெட்டை அன்லாக் செய்யவும்"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"மேலும் விருப்பங்களுக்குச் சாதனத்தை அன்லாக் செய்யவும்"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"படம் அனுப்பப்பட்டது"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPS அமைத்த இருப்பிடம்"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"இருப்பிடக் கோரிக்கைகள் இயக்கப்பட்டன"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"’சென்சார்கள் ஆஃப்’ செயலில் உள்ளது"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"மீடியா பிளே ஆகிறது"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"எல்லா அறிவிப்புகளையும் அழி."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"அறிவிப்புகளை நிர்வகி"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"வரலாறு"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"உள்வருவது"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"நிசப்தம்"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"அறிவிப்புகள்"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"அறிவிப்புகளை முடக்கு"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"இந்த ஆப்ஸின் அறிவிப்புகளைத் தொடர்ந்து காட்டவா?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"நிசப்தம்"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"இயல்புநிலை"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"பபிள்"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"ஒலி / அதிர்வு இல்லை"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"ஒலி / அதிர்வு இல்லாமல் உரையாடல் பிரிவின் கீழ்ப் பகுதியில் தோன்றும்"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"மொபைல் அமைப்புகளின் அடிப்படையில் ஒலிக்கவோ அதிரவோ செய்யும்"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"மொபைல் அமைப்புகளின் அடிப்படையில் ஒலிக்கவோ அதிரவோ செய்யும். <xliff:g id="APP_NAME">%1$s</xliff:g> இலிருந்து வரும் உரையாடல்கள் இயல்பாகவே குமிழாகத் தோன்றும்."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"இந்த உள்ளடக்கத்திற்கான மிதக்கும் ஷார்ட்கட் மூலம் உங்கள் கவனத்தைப் பெற்றிருக்கும்."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"உரையாடல் பிரிவின் மேற்பகுதியில் மிதக்கும் குமிழாகத் தோன்றும். பூட்டுத் திரையின் மேல் சுயவிவரப் படத்தைக் காட்டும்"</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>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index ea991a3..2fe2bd8 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"స్క్రీన్‌కు నింపేలా జూమ్ చేయండి"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"స్క్రీన్‌కు నింపేలా విస్తరించండి"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"స్క్రీన్‌షాట్"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"మరిన్ని ఆప్షన్‌ల కోసం మీ ఫోన్‌ను అన్‌లాక్ చేయండి"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"మరిన్ని ఆప్షన్‌ల కోసం మీ టాబ్లెట్‌ను అన్‌లాక్ చేయండి"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"మరిన్ని ఆప్షన్‌ల కోసం మీ పరికరాన్ని అన్‌లాక్ చేయండి"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ఇమేజ్‌ను పంపారు"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"స్క్రీన్‌షాట్‌ను సేవ్ చేస్తోంది…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"స్క్రీన్‌షాట్‌ను సేవ్ చేస్తోంది…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"స్థానం GPS ద్వారా సెట్ చేయబడింది"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"స్థాన అభ్యర్థనలు సక్రియంగా ఉన్నాయి"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"సెన్సార్‌లు ఆఫ్ యాక్టివ్‌లో ఉంది"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"మీడియా యాక్టివ్‌గా ఉంది"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"అన్ని నోటిఫికేషన్‌లను క్లియర్ చేయండి."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"నిర్వహించండి"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"చరిత్ర"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"ఇన్‌కమింగ్"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"నిశ్శబ్దం"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"నోటిఫికేషన్‌లు"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"నోటిఫికేషన్‌లను ఆఫ్ చేయి"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"ఈ యాప్ నుండి నోటిఫికేషన్‌లను చూపిస్తూ ఉండాలా?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"నిశ్శబ్దం"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"ఆటోమేటిక్ సెట్టింగ్"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"బబుల్"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"శబ్దం లేదా వైబ్రేషన్‌లు ఏవీ లేవు"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"శబ్దం లేదా వైబ్రేషన్ లేదు, సంభాషణ విభాగం దిగువన కనిపిస్తుంది"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"ఫోన్ సెట్టింగ్‌ల ఆధారంగా రింగ్ లేదా వైబ్రేట్ కావచ్చు"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ఫోన్ సెట్టింగ్‌ల ఆధారంగా రింగ్ లేదా వైబ్రేట్ కావచ్చు. <xliff:g id="APP_NAME">%1$s</xliff:g> నుండి సంభాషణలు ఆటోమేటిక్‌గా బబుల్‌గా కనిపిస్తాయి."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ఫ్లోటింగ్ షార్ట్‌కట్‌తో మీ దృష్టిని ఈ కంటెంట్‌పై నిలిపి ఉంచుతుంది."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"సంభాషణ విభాగం ఎగువన ఉంటుంది, తేలుతున్న బబుల్‌లాగా కనిపిస్తుంది, లాక్ స్క్రీన్‌పై ప్రొఫైల్ ఫోటోను ప్రదర్శిస్తుంది"</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>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 6f71dd5..d4aaafb 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ขยายจนเต็มหน้าจอ"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ยืดจนเต็มหน้าจอ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ภาพหน้าจอ"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"ปลดล็อกโทรศัพท์เพื่อดูตัวเลือกเพิ่มเติม"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"ปลดล็อกแท็บเล็ตเพื่อดูตัวเลือกเพิ่มเติม"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"ปลดล็อกอุปกรณ์เพื่อดูตัวเลือกเพิ่มเติม"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ส่งรูปภาพ"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"กำลังบันทึกภาพหน้าจอ..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"กำลังบันทึกภาพหน้าจอ..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"ตำแหน่งที่กำหนดโดย GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"คำขอตำแหน่งที่มีการใช้งาน"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"\"ปิดเซ็นเซอร์\" เปิดใช้งานอยู่"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"กำลังเล่นสื่ออยู่"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"ล้างการแจ้งเตือนทั้งหมด"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"จัดการ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ประวัติ"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"เข้ามาใหม่"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"เงียบ"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"การแจ้งเตือน"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"ปิดการแจ้งเตือน"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"แสดงการแจ้งเตือนจากแอปนี้ต่อไปไหม"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"เงียบ"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"ค่าเริ่มต้น"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"บับเบิล"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"ไม่มีเสียงหรือการสั่น"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"ไม่มีเสียงหรือการสั่น และปรากฏต่ำลงมาในส่วนการสนทนา"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"อาจส่งเสียงหรือสั่นโดยขึ้นอยู่กับการตั้งค่าโทรศัพท์"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"อาจส่งเสียงหรือสั่นโดยขึ้นอยู่กับการตั้งค่าโทรศัพท์ การสนทนาจาก <xliff:g id="APP_NAME">%1$s</xliff:g> จะแสดงเป็นบับเบิลโดยค่าเริ่มต้น"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ดึงดูดความสนใจของคุณไว้เสมอด้วยทางลัดแบบลอยที่มายังเนื้อหานี้"</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"แสดงที่ด้านบนของส่วนการสนทนา ปรากฏเป็นบับเบิลแบบลอย แสดงรูปโปรไฟล์บนหน้าจอล็อก"</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>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 2b19d1c..417ec5c 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"I-zoom upang punan screen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"I-stretch upang mapuno screen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"I-unlock ang iyong telepono para sa higit pang opsyon"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"I-unlock ang iyong tablet para sa higit pang opsyon"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"I-unlock ang iyong device para sa higit pang opsyon"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"nagpadala ng larawan"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Sine-save ang screenshot…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Sine-save ang screenshot…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Lokasyong itinatakda ng GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Aktibo ang mga kahilingan ng lokasyon"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Aktibo ang i-off ang mga sensor"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Aktibo ang media"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"I-clear ang lahat ng notification."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Pamahalaan"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"History"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Papasok"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Naka-silent"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Mga Notification"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Mga Pag-uusap"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"I-clear ang lahat ng silent na notification"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Mga notification na na-pause ng Huwag Istorbohin"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"I-off ang mga notification"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Patuloy na ipakita ang mga notification mula sa app na ito?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Naka-silent"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Default"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bubble"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Walang tunog o pag-vibrate"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Walang tunog o pag-vibrate at lumalabas nang mas mababa sa seksyon ng pag-uusap"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Puwedeng mag-ring o mag-vibrate batay sa mga setting ng telepono"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Puwedeng mag-ring o mag-vibrate batay sa mga setting ng telepono. 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>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Makikita sa itaas ng seksyon ng pag-uusap, lumalabas bilang floating bubble, ipinapakita sa lock screen ang larawan sa profile"</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>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index be32390..3a5cc3a 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Yakınlaştır (ekranı kaplasın)"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Genişlet (ekran kapansın)"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekran görüntüsü"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Diğer seçenekler için telefonunuzun kilidini açın"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Diğer seçenekler için tabletinizin kilidini açın"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Diğer seçenekler için cihazınızın kilidini açın"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"bir resim gönderildi"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Ekran görüntüsü kaydediliyor..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Ekran görüntüsü kaydediliyor..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Konum GPS ile belirlendi"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Konum bilgisi istekleri etkin"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensörler kapalı ayarı etkin"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Medya etkin durumda"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Tüm bildirimleri temizle"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Yönet"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Geçmiş"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Gelen"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Sessiz"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Bildirimler"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Görüşmeler"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Sessiz bildirimlerin tümünü temizle"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Bildirimler, Rahatsız Etmeyin özelliği tarafından duraklatıldı"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Bildirimleri kapat"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Bu uygulamadan gelen bildirimler gösterilmeye devam edilsin mi?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Sessiz"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Varsayılan"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Baloncuk"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Sessiz veya titreşim yok"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Sessizdir veya titreşim yoktur ve görüşme bölümünün altında görünür"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Telefon ayarlarına bağlı olarak zili çalabilir veya titreyebilir"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Telefon ayarlarına bağlı olarak zili çalabilir veya titreyebilir <xliff:g id="APP_NAME">%1$s</xliff:g> adlı uygulamadan görüşmeler varsayılan olarak baloncukla gösterilir."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Kayan kısayolla dikkatinizi bu içerik üzerinde tutar."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Görüşme bölümünün üstünde gösterilir, kayan baloncuk olarak görünür, kilit ekranında profil resmini görüntüler"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ayarlar"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Öncelik"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"<xliff:g id="APP_NAME">%1$s</xliff:g>, görüşmeye özgü ayarları desteklemiyor"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 2764540..d194405 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Масштабув. на весь екран"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Розтягнути на весь екран"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Знімок екрана"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Розблокуйте телефон, щоб переглянути інші параметри"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Розблокуйте планшет, щоб переглянути інші параметри"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Розблокуйте пристрій, щоб переглянути інші параметри"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"надіслане зображення"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Збереження знімка екрана..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Збереження знімка екрана..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Місцезнаходження встановлено за допомогою GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Запити про місцезнаходження активні"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Активовано вимкнення датчиків"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Відтворюються медіафайли"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Очистити всі сповіщення."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -525,10 +521,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Керувати"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Історія"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Нові"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Без звуку"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Сповіщення"</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>
@@ -723,20 +717,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Вимкнути сповіщення"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Чи показувати сповіщення з цього додатка надалі?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Без звуку"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"За умовчанням"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Спливаюче сповіщення"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Без звуку чи вібрації"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Без звуку чи вібрації, з\'являється нижче в розділі розмов"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Може дзвонити або вібрувати залежно від налаштувань телефона"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Може дзвонити або вібрувати залежно від налаштувань телефона. Показує спливаючі розмови з додатка <xliff:g id="APP_NAME">%1$s</xliff:g> за умовчанням."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Привертає увагу до контенту плаваючим ярликом."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"З\'являється вгорі розділу розмов у спливаючому сповіщенні та показує зображення профілю на заблокованому екрані"</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>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index c2e8ea9..0da2928 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"پوری سکرین پر زوم کریں"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"پوری سکرین پر پھیلائیں"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"اسکرین شاٹ"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"مزید اختیارات کے لیے اپنا فون غیر مقفل کریں"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"مزید اختیارات کے لیے اپنا ٹیبلیٹ غیر مقفل کریں"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"مزید اختیارات کے لیے اپنا آلہ غیر مقفل کریں"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ایک تصویر بھیجی"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"‏مقام متعین کیا گیا بذریعہ GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"مقام کی درخواستیں فعال ہیں"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"سینسرز آف فعال ہے"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"میڈیا سرگرم ہے"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"سبھی اطلاعات صاف کریں۔"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"<xliff:g id="NUMBER">%s</xliff:g> +"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"نظم کریں"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"سرگزشت"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"اِن کمنگ"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"خاموش"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"اطلاعات"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"اطلاعات کو آف کریں"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"اس ایپ کی طرف سے اطلاعات دکھانا جاری رکھیں؟"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"خاموش"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"ڈیفالٹ"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"بلبلہ"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"کوئی آواز یا وائبریشن نہیں"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"کوئی آواز یا وائبریشن نہیں اور گفتگو کے سیکشن میں نیچے ظاہر ہوتا ہے"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"آپ کے آلہ کی ترتیبات کے مطابق وائبریٹ یا گھنٹی بج سکتی ہے"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"فون کی ترتیبات کے مطابق وائبریٹ یا گھنٹی بج سکتی ہے۔ بذریعہ ڈیفالٹ <xliff:g id="APP_NAME">%1$s</xliff:g> بلبلہ سے گفتگوئیں۔"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"اس مواد کے فلوٹنگ شارٹ کٹ کے ساتھ آپ کی توجہ دیتی ہے۔"</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"گفتگو کے سیکشن کے اوپری حصے پر دکھاتا ہے، تیرتے بلبلے کی طرح ظاہر ہوتا ہے، لاک اسکرین پر پروفائل تصویر دکھاتا ہے"</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>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index a32fdb2..ed3001e 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -77,9 +77,6 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Ekranga moslashtirish"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ekran hajmida cho‘zish"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skrinshot"</string>
-    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Boshqa parametrlar uchun telefoningiz qulfini oching"</string>
-    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Boshqa parametrlar uchun planshetingiz qulfini oching"</string>
-    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Boshqa parametrlar uchun qurilmangiz qulfini oching"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"rasm yuborildi"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Skrinshot saqlanmoqda…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Skrinshot saqlanmoqda…"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 800b731..6c3e17c 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"T.phóng để lấp đầy m.hình"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Giãn ra để lấp đầy m.hình"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Chụp ảnh màn hình"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Mở khóa điện thoại của bạn để xem thêm tùy chọn"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Mở khóa máy tính bảng của bạn để xem thêm tùy chọn"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Mở khóa thiết bị của bạn để xem thêm tùy chọn"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"đã gửi hình ảnh"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Đang lưu ảnh chụp màn hình..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Đang lưu ảnh chụp màn hình..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Vị trí đặt bởi GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Yêu cầu về thông tin vị trí đang hoạt động"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Tùy chọn tắt cảm biến đang hoạt động"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Nội dung nghe nhìn đang hoạt động"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Xóa tất cả thông báo."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Quản lý"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Lịch sử"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Hiển thị gần đây"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Im lặng"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Thông báo"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Cuộc trò chuyện"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Xóa tất cả thông báo im lặng"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Chế độ Không làm phiền đã tạm dừng thông báo"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Tắt thông báo"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Tiếp tục hiển thị các thông báo từ ứng dụng này?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Im lặng"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Mặc định"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Bong bóng"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Không phát âm thanh hoặc rung"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Không phát âm thanh hoặc rung và xuất hiện phía dưới trong phần cuộc trò chuyện"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Có thể đổ chuông hoặc rung tùy theo phần cài đặt trên điện thoại"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Có thể đổ chuông hoặc rung tùy theo phần cài đặt trên điện thoại. Theo mặc định, các cuộc trò chuyện từ <xliff:g id="APP_NAME">%1$s</xliff:g> được phép hiển thị dưới dạng bong bóng."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Luôn chú ý vào nội dung này bằng phím tắt nổi."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Hiển thị cuộc trò chuyện ở đầu phần cuộc trò chuyện và dưới dạng bong bóng nổi, hiển thị ảnh hồ sơ trên màn hình khóa"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Cài đặt"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Mức độ ưu tiên"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"Ứng dụng <xliff:g id="APP_NAME">%1$s</xliff:g> không hỗ trợ tùy chọn cài đặt dành riêng cho cuộc trò chuyện"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 97be514..cfa8e85 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"缩放以填满屏幕"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"拉伸以填满屏幕"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"屏幕截图"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"解锁手机即可查看更多选项"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"解锁平板电脑即可查看更多选项"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"解锁设备即可查看更多选项"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"发送了一张图片"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在保存屏幕截图..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"正在保存屏幕截图..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"已通过GPS确定位置"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"应用发出了有效位置信息请求"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"传感器已关闭"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"正在播放媒体内容"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"清除所有通知。"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"历史记录"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"收到的通知"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"静音"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"通知"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"关闭通知"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"要继续显示来自此应用的通知吗?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"静音"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"默认"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"气泡"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"不发出提示音也不振动"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"不发出提示音也不振动,显示在对话部分的靠下位置"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"可能会响铃或振动(取决于手机设置)"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"可能会响铃或振动(取决于手机设置)。默认情况下,来自<xliff:g id="APP_NAME">%1$s</xliff:g>的对话会以对话泡的形式显示。"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"通过可链接到这项内容的浮动快捷方式吸引您的注意。"</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"以悬浮对话泡形式显示在对话部分顶部,如果设备处于锁定状态,在锁定屏幕上显示个人资料照片"</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>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index a8c6c52..e3e7d37 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"放大為全螢幕"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"放大為全螢幕"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"螢幕截圖"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"解鎖手機以存取更多選項"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"解鎖平板電腦以存取更多選項"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"解鎖裝置以存取更多選項"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"已傳送圖片"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在儲存螢幕擷取畫面..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"正在儲存螢幕擷取畫面..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPS 已定位"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"位置要求啟動中"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"已啟用「感應器關閉」"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"播緊媒體"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"清除所有通知。"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"記錄"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"收到的通知"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"靜音"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"通知"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"關閉通知"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"要繼續顯示此應用程式的通知嗎?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"靜音"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"預設"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"氣泡"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"無音效或震動"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"無音效或震動,並在對話部分的較低位置顯示"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"可能會根據手機設定發出鈴聲或震動"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"可能會根據手機設定發出鈴聲或震動。「<xliff:g id="APP_NAME">%1$s</xliff:g>」的對話會預設以對話氣泡顯示。"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"為此內容建立浮動捷徑以保持注意力。"</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"在對話部分的頂部以浮動對話氣泡顯示,並在上鎖畫面顯示個人檔案相片"</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>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 0e8e133..382ce68 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"放大為全螢幕"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"放大為全螢幕"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"擷取螢幕畫面"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"解鎖手機可查看更多選項"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"解鎖平板電腦可查看更多選項"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"解鎖裝置可查看更多選項"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"傳送了一張圖片"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在儲存螢幕截圖…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"正在儲存螢幕截圖…"</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"GPS 已定位"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"有位置資訊要求"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"感應器已關閉"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"正在播放媒體"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"清除所有通知。"</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"管理"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"記錄"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"收到的通知"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"靜音"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"通知"</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>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"關閉通知"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"要繼續顯示這個應用程式的通知嗎?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"靜音"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"預設"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"泡泡"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"不震動或發出聲音"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"不震動或發出聲音,並顯示在對話部分的下方"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"可能會根據手機的設定響鈴或震動"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"可能會根據手機的設定響鈴或震動。根據預設,來自「<xliff:g id="APP_NAME">%1$s</xliff:g>」的對話會以對話框形式顯示。"</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"利用浮動式捷徑快速存取這項內容。"</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"以浮動對話框的形式顯示在對話部分的頂端。如果裝置處於鎖定狀態,則在螢幕鎖定畫面上顯示個人資料相片"</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>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 5a19f62..01a057e 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -77,12 +77,9 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Sondeza ukugcwalisa isikrini"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Nweba ukugcwalisa isikrini"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Isithombe-skrini"</string>
-    <!-- no translation found for global_action_lock_message (4466026255205186456) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (7621167597240332986) -->
-    <skip />
-    <!-- no translation found for global_action_lock_message (538790401275363781) -->
-    <skip />
+    <string name="global_action_lock_message" product="default" msgid="4466026255205186456">"Vula ifoni yakho ukuthola izinketho ezengeziwe"</string>
+    <string name="global_action_lock_message" product="tablet" msgid="7621167597240332986">"Vula ithebulethi yakho ukuthola izinketho ezengeziwe"</string>
+    <string name="global_action_lock_message" product="device" msgid="538790401275363781">"Vula idivayisi yakho ukuthola izinketho ezengeziwe"</string>
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"uthumele isithombe"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Ilondoloz umfanekiso weskrini..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Ilondoloz umfanekiso weskrini..."</string>
@@ -329,8 +326,7 @@
     <string name="gps_notification_found_text" msgid="3145873880174658526">"Indawo ihlelwe i-GPS"</string>
     <string name="accessibility_location_active" msgid="2845747916764660369">"Izicelo zendawo ziyasebenza"</string>
     <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Izinzwa zivalwe kokusebenzayo"</string>
-    <!-- no translation found for accessibility_media_active (4942087422908239969) -->
-    <skip />
+    <string name="accessibility_media_active" msgid="4942087422908239969">"Imidiya iyasebenza"</string>
     <string name="accessibility_clear_all" msgid="970525598287244592">"Susa zonke izaziso."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
@@ -519,10 +515,8 @@
     <string name="manage_notifications_text" msgid="6885645344647733116">"Phatha"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"Umlando"</string>
     <string name="notification_section_header_incoming" msgid="5295312809341711367">"Okungenayo"</string>
-    <!-- no translation found for notification_section_header_gentle (6804099527336337197) -->
-    <skip />
-    <!-- no translation found for notification_section_header_alerting (5581175033680477651) -->
-    <skip />
+    <string name="notification_section_header_gentle" msgid="6804099527336337197">"Kuthulile"</string>
+    <string name="notification_section_header_alerting" msgid="5581175033680477651">"Izaziso"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Izingxoxo"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Sula zonke izaziso ezithulile"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Izaziso zimiswe okwesikhashana ukungaphazamisi"</string>
@@ -717,20 +711,14 @@
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Vala izaziso"</string>
     <string name="inline_keep_showing_app" msgid="4393429060390649757">"Qhubeka nokubonisa izaziso kusuka kulolu hlelo lokusebenza?"</string>
     <string name="notification_silence_title" msgid="8608090968400832335">"Kuthulile"</string>
-    <!-- no translation found for notification_alert_title (3656229781017543655) -->
-    <skip />
+    <string name="notification_alert_title" msgid="3656229781017543655">"Okuzenzekelayo"</string>
     <string name="notification_bubble_title" msgid="8330481035191903164">"Ibhamuza"</string>
-    <!-- no translation found for notification_channel_summary_low (4860617986908931158) -->
-    <skip />
-    <!-- no translation found for notification_conversation_summary_low (1734433426085468009) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default (3282930979307248890) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (1782419896613644568) -->
-    <skip />
+    <string name="notification_channel_summary_low" msgid="4860617986908931158">"Awukho umsindo noma ukudlidliza"</string>
+    <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Awukho umsindo noma ukudlidliza futhi ivela ngezansi esigabeni sengxoxo"</string>
+    <string name="notification_channel_summary_default" msgid="3282930979307248890">"Ingase ikhale noma idlidlize kuya ngamasethingi wefoni yakho"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Ingase ikhale noma idlidlize kuya ngamasethingi wefoni yakho. Izingxoxo ezivela ku-<xliff:g id="APP_NAME">%1$s</xliff:g> ziba yibhamuza ngokuzenzakalela."</string>
     <string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Igcina ukunaka kwakho ngesinqamuleli esintantayo kulokhu okuqukethwe."</string>
-    <!-- no translation found for notification_channel_summary_priority (7952654515769021553) -->
-    <skip />
+    <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Iboniswa ngenhla kwesigaba sengxoxo, ivela njengebhamuza elintantayo, ibonisa isithombe sephrofayela kukukhiya isikrini"</string>
     <string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Izilungiselelo"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Okubalulekile"</string>
     <string name="no_shortcut" msgid="7176375126961212514">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayisekeli amasethingi athile engxoxo"</string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 07de701..7f1763d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -221,7 +221,7 @@
     <dimen name="notification_guts_button_horizontal_spacing">8dp</dimen>
 
     <dimen name="notification_guts_conversation_header_height">84dp</dimen>
-    <dimen name="notification_guts_conversation_icon_size">52dp</dimen>
+    <dimen name="notification_guts_conversation_icon_size">56dp</dimen>
     <dimen name="notification_guts_conversation_action_height">56dp</dimen>
     <dimen name="notification_guts_conversation_action_text_padding_start">32dp</dimen>
 
@@ -907,6 +907,8 @@
     <dimen name="screen_pinning_nav_highlight_size">56dp</dimen>
     <!-- Screen pinning inner nav bar outer circle size -->
     <dimen name="screen_pinning_nav_highlight_outer_size">84dp</dimen>
+    <!-- Screen pinning description bullet gap width -->
+    <dimen name="screen_pinning_description_bullet_gap_width">6sp</dimen>
 
     <!-- Padding to be used on the bottom of the fingerprint icon on Keyguard so it better aligns
          with the other icons. -->
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 09918e7..d47ad7f 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -90,6 +90,8 @@
     <item type="id" name="view_width_animator_end_tag"/>
     <item type="id" name="view_width_current_value"/>
 
+    <item type="id" name="requires_remeasuring"/>
+
     <!-- Whether the icon is from a notification for which targetSdk < L -->
     <item type="id" name="icon_is_pre_L"/>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index f7f1ef6..e567b51 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -212,13 +212,6 @@
     <!-- 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>
@@ -797,9 +790,6 @@
     <!-- 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>
 
@@ -1522,7 +1512,7 @@
     <string name="accessibility_output_chooser">Switch output device</string>
 
     <!-- Screen pinning dialog title. -->
-    <string name="screen_pinning_title">Screen is pinned</string>
+    <string name="screen_pinning_title">App is pinned</string>
     <!-- Screen pinning dialog description. -->
     <string name="screen_pinning_description">This keeps it in view until you unpin. Touch &amp; hold Back and Overview to unpin.</string>
     <string name="screen_pinning_description_recents_invisible">This keeps it in view until you unpin. Touch &amp; hold Back and Home to unpin.</string>
@@ -1530,20 +1520,24 @@
     <!-- Screen pinning dialog description. -->
     <string name="screen_pinning_description_accessible">This keeps it in view until you unpin. Touch &amp; hold Overview to unpin.</string>
     <string name="screen_pinning_description_recents_invisible_accessible">This keeps it in view until you unpin. Touch &amp; hold Home to unpin.</string>
+    <!-- Screen pinning security warning: personal data, email, contacts may be exposed while screen is pinned. [CHAR LIMIT=NONE] -->
+    <string name="screen_pinning_exposes_personal_data">Personal data may be accessible (such as contacts and email content).</string>
+    <!-- Screen pinning security warning: a pinned app can still launch other apps. [CHAR LIMIT=NONE] -->
+    <string name="screen_pinning_can_open_other_apps">Pinned app may open other apps.</string>
     <!-- Notify use that they are in Lock-to-app -->
-    <string name="screen_pinning_toast">To unpin this screen, touch &amp; hold Back and Overview
+    <string name="screen_pinning_toast">To unpin this app, touch &amp; hold Back and Overview
         buttons</string>
-    <string name="screen_pinning_toast_recents_invisible">To unpin this screen, touch &amp; hold Back
+    <string name="screen_pinning_toast_recents_invisible">To unpin this app, touch &amp; hold Back
         and Home buttons</string>
     <!-- Notify (in toast) user how to unpin screen in gesture navigation mode [CHAR LIMIT=NONE] -->
-    <string name="screen_pinning_toast_gesture_nav">To unpin this screen, swipe up &amp; hold</string>
+    <string name="screen_pinning_toast_gesture_nav">To unpin this app, swipe up &amp; hold</string>
     <!-- Screen pinning positive response. -->
     <string name="screen_pinning_positive">Got it</string>
     <!-- Screen pinning negative response. -->
     <string name="screen_pinning_negative">No thanks</string>
     <!-- Enter/Exiting screen pinning indication. -->
-    <string name="screen_pinning_start">Screen pinned</string>
-    <string name="screen_pinning_exit">Screen unpinned</string>
+    <string name="screen_pinning_start">App pinned</string>
+    <string name="screen_pinning_exit">App unpinned</string>
 
 
     <!-- Hide quick settings tile confirmation title -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 52ace2b..07ba5eb 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -396,6 +396,7 @@
     <style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
 
     <style name="Theme.SystemUI.Dialog.GlobalActions" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen">
+        <item name="android:colorError">@*android:color/error_color_material_dark</item>
         <item name="android:windowIsFloating">true</item>
     </style>
 
@@ -573,6 +574,7 @@
         <item name="android:textColor">?attr/wallpaperTextColor</item>
         <item name="android:textAllCaps">false</item>
         <item name="android:textSize">14sp</item>
+        <item name="android:minWidth">0dp</item>
     </style>
 
     <style name="TextAppearance.HeadsUpStatusBarText"
diff --git a/packages/SystemUI/res/xml/media_collapsed.xml b/packages/SystemUI/res/xml/media_collapsed.xml
new file mode 100644
index 0000000..57e6f36
--- /dev/null
+++ b/packages/SystemUI/res/xml/media_collapsed.xml
@@ -0,0 +1,184 @@
+<?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
+  -->
+<ConstraintSet
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+    <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="parent"
+        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="parent"
+        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="parent"
+        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="parent"
+        >
+    </Constraint>
+</ConstraintSet>
diff --git a/packages/SystemUI/res/xml/media_expanded.xml b/packages/SystemUI/res/xml/media_expanded.xml
new file mode 100644
index 0000000..78973f3
--- /dev/null
+++ b/packages/SystemUI/res/xml/media_expanded.xml
@@ -0,0 +1,178 @@
+<?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
+  -->
+<ConstraintSet
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+    <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="parent"
+        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="parent"
+        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="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:layout_marginTop="3dp"
+        app:layout_constraintTop_toBottomOf="@id/header_artist"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        />
+
+    <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="parent"
+        />
+
+    <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="parent"
+        app:layout_constraintTop_toTopOf="@id/action0"
+        app:layout_constraintBottom_toBottomOf="parent">
+    </Constraint>
+</ConstraintSet>
diff --git a/packages/SystemUI/res/xml/media_scene.xml b/packages/SystemUI/res/xml/media_scene.xml
deleted file mode 100644
index f61b2b0..0000000
--- a/packages/SystemUI/res/xml/media_scene.xml
+++ /dev/null
@@ -1,447 +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
-  -->
-<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/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index f1b401e..15eda06 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -15,7 +15,7 @@
  */
 package com.android.systemui.bubbles;
 
-
+import static android.app.Notification.FLAG_BUBBLE;
 import static android.os.AsyncTask.Status.FINISHED;
 import static android.view.Display.INVALID_DISPLAY;
 
@@ -27,6 +27,7 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
 import android.content.pm.ShortcutInfo;
@@ -55,9 +56,13 @@
 class Bubble implements BubbleViewProvider {
     private static final String TAG = "Bubble";
 
+    /**
+     * NotificationEntry associated with the bubble. A null value implies this bubble is loaded
+     * from disk.
+     */
+    @Nullable
     private NotificationEntry mEntry;
     private final String mKey;
-    private final String mGroupId;
 
     private long mLastUpdated;
     private long mLastAccessed;
@@ -69,6 +74,8 @@
 
     /** Whether flyout text should be suppressed, regardless of any other flags or state. */
     private boolean mSuppressFlyout;
+    /** Whether this bubble should auto expand regardless of the normal flag, used for overflow. */
+    private boolean mShouldAutoExpand;
 
     // Items that are typically loaded later
     private String mAppName;
@@ -95,18 +102,18 @@
     private Bitmap mBadgedImage;
     private int mDotColor;
     private Path mDotPath;
+    private int mFlags;
 
-
-    public static String groupId(NotificationEntry entry) {
-        UserHandle user = entry.getSbn().getUser();
-        return user.getIdentifier() + "|" + entry.getSbn().getPackageName();
-    }
-
-    // TODO: Decouple Bubble from NotificationEntry and transform ShortcutInfo into Bubble
-    Bubble(ShortcutInfo shortcutInfo) {
+    /**
+     * Create a bubble with limited information based on given {@link ShortcutInfo}.
+     * Note: Currently this is only being used when the bubble is persisted to disk.
+     */
+    Bubble(@NonNull final String key, @NonNull final ShortcutInfo shortcutInfo) {
+        Objects.requireNonNull(key);
+        Objects.requireNonNull(shortcutInfo);
         mShortcutInfo = shortcutInfo;
-        mKey = shortcutInfo.getId();
-        mGroupId = shortcutInfo.getId();
+        mKey = key;
+        mFlags = 0;
     }
 
     /** Used in tests when no UI is required. */
@@ -116,8 +123,8 @@
         mEntry = e;
         mKey = e.getKey();
         mLastUpdated = e.getSbn().getPostTime();
-        mGroupId = groupId(e);
         mSuppressionListener = listener;
+        mFlags = e.getSbn().getNotification().flags;
     }
 
     @Override
@@ -125,16 +132,22 @@
         return mKey;
     }
 
+    @Nullable
     public NotificationEntry getEntry() {
         return mEntry;
     }
 
-    public String getGroupId() {
-        return mGroupId;
+    @Nullable
+    public UserHandle getUser() {
+        if (mEntry != null) return mEntry.getSbn().getUser();
+        if (mShortcutInfo != null) return mShortcutInfo.getUserHandle();
+        return null;
     }
 
     public String getPackageName() {
-        return mEntry.getSbn().getPackageName();
+        return mEntry == null
+                ? mShortcutInfo == null ? null : mShortcutInfo.getPackage()
+                : mEntry.getSbn().getPackageName();
     }
 
     @Override
@@ -178,6 +191,18 @@
         return mExpandedView;
     }
 
+    @Nullable
+    public String getTitle() {
+        final CharSequence titleCharSeq;
+        if (mEntry == null) {
+            titleCharSeq = null;
+        } else {
+            titleCharSeq = mEntry.getSbn().getNotification().extras.getCharSequence(
+                    Notification.EXTRA_TITLE);
+        }
+        return titleCharSeq != null ? titleCharSeq.toString() : null;
+    }
+
     /**
      * Call when the views should be removed, ensure this is called to clean up ActivityView
      * content.
@@ -218,7 +243,8 @@
     void inflate(BubbleViewInfoTask.Callback callback,
             Context context,
             BubbleStackView stackView,
-            BubbleIconFactory iconFactory) {
+            BubbleIconFactory iconFactory,
+            boolean skipInflation) {
         if (isBubbleLoading()) {
             mInflationTask.cancel(true /* mayInterruptIfRunning */);
         }
@@ -226,6 +252,7 @@
                 context,
                 stackView,
                 iconFactory,
+                skipInflation,
                 callback);
         if (mInflateSynchronously) {
             mInflationTask.onPostExecute(mInflationTask.doInBackground());
@@ -297,20 +324,13 @@
     }
 
     /**
-     * @return the newer of {@link #getLastUpdateTime()} and {@link #getLastAccessTime()}
+     * @return the last time this bubble was updated or accessed, whichever is most recent.
      */
     long getLastActivity() {
         return Math.max(mLastUpdated, mLastAccessed);
     }
 
     /**
-     * @return the timestamp in milliseconds of the most recent notification entry for this bubble
-     */
-    long getLastUpdateTime() {
-        return mLastUpdated;
-    }
-
-    /**
      * @return if the bubble was ever expanded
      */
     boolean getWasAccessed() {
@@ -345,6 +365,7 @@
      * Whether this notification should be shown in the shade.
      */
     boolean showInShade() {
+        if (mEntry == null) return false;
         return !shouldSuppressNotification() || !mEntry.isClearable();
     }
 
@@ -352,8 +373,8 @@
      * Sets whether this notification should be suppressed in the shade.
      */
     void setSuppressNotification(boolean suppressNotification) {
+        if (mEntry == null) return;
         boolean prevShowInShade = showInShade();
-
         Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
         int flags = data.getFlags();
         if (suppressNotification) {
@@ -384,6 +405,7 @@
      */
     @Override
     public boolean showDot() {
+        if (mEntry == null) return false;
         return mShowBubbleUpdateDot
                 && !mEntry.shouldSuppressNotificationDot()
                 && !shouldSuppressNotification();
@@ -393,6 +415,7 @@
      * Whether the flyout for the bubble should be shown.
      */
     boolean showFlyout() {
+        if (mEntry == null) return false;
         return !mSuppressFlyout && !mEntry.shouldSuppressPeek()
                 && !shouldSuppressNotification()
                 && !mEntry.shouldSuppressNotificationList();
@@ -411,16 +434,8 @@
         return mFlyoutMessage;
     }
 
-    /**
-     * Returns whether the notification for this bubble is a foreground service. It shows that this
-     * is an ongoing bubble.
-     */
-    boolean isOngoing() {
-        int flags = mEntry.getSbn().getNotification().flags;
-        return (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
-    }
-
     float getDesiredHeight(Context context) {
+        if (mEntry == null) return 0;
         Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
         boolean useRes = data.getDesiredHeightResId() != 0;
         if (useRes) {
@@ -434,6 +449,7 @@
     }
 
     String getDesiredHeightString() {
+        if (mEntry == null) return String.valueOf(0);
         Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
         boolean useRes = data.getDesiredHeightResId() != 0;
         if (useRes) {
@@ -450,11 +466,13 @@
      * To populate the icon use {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)}.
      */
     boolean usingShortcutInfo() {
-        return mEntry.getBubbleMetadata().getShortcutId() != null;
+        return mEntry != null && mEntry.getBubbleMetadata().getShortcutId() != null
+                || mShortcutInfo != null;
     }
 
     @Nullable
     PendingIntent getBubbleIntent() {
+        if (mEntry == null) return null;
         Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
         if (data != null) {
             return data.getIntent();
@@ -462,16 +480,32 @@
         return null;
     }
 
-    Intent getSettingsIntent() {
+    Intent getSettingsIntent(final Context context) {
         final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS);
         intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
-        intent.putExtra(Settings.EXTRA_APP_UID, mEntry.getSbn().getUid());
+        final int uid = getUid(context);
+        if (uid != -1) {
+            intent.putExtra(Settings.EXTRA_APP_UID, uid);
+        }
         intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
         return intent;
     }
 
+    private int getUid(final Context context) {
+        if (mEntry != null) return mEntry.getSbn().getUid();
+        final PackageManager pm = context.getPackageManager();
+        if (pm == null) return -1;
+        try {
+            final ApplicationInfo info = pm.getApplicationInfo(mShortcutInfo.getPackage(), 0);
+            return info.uid;
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(TAG, "cannot find uid", e);
+        }
+        return -1;
+    }
+
     private int getDimenForPackageUser(Context context, int resId, String pkg, int userId) {
         PackageManager pm = context.getPackageManager();
         Resources r;
@@ -493,13 +527,32 @@
     }
 
     private boolean shouldSuppressNotification() {
+        if (mEntry == null) return false;
         return mEntry.getBubbleMetadata() != null
                 && mEntry.getBubbleMetadata().isNotificationSuppressed();
     }
 
     boolean shouldAutoExpand() {
+        if (mEntry == null) return false;
         Notification.BubbleMetadata metadata = mEntry.getBubbleMetadata();
-        return metadata != null && metadata.getAutoExpandBubble();
+        return (metadata != null && metadata.getAutoExpandBubble()) ||  mShouldAutoExpand;
+    }
+
+    void setShouldAutoExpand(boolean shouldAutoExpand) {
+        mShouldAutoExpand = shouldAutoExpand;
+    }
+
+    public boolean isBubble() {
+        if (mEntry == null) return (mFlags & FLAG_BUBBLE) != 0;
+        return (mEntry.getSbn().getNotification().flags & FLAG_BUBBLE) != 0;
+    }
+
+    public void enable(int option) {
+        mFlags |= option;
+    }
+
+    public void disable(int option) {
+        mFlags &= ~option;
     }
 
     @Override
@@ -562,7 +615,7 @@
                     normalX,
                     normalY,
                     this.showInShade(),
-                    this.isOngoing(),
+                    false /* isOngoing (unused) */,
                     false /* isAppForeground (unused) */);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 2587369..f05d547 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -42,6 +42,7 @@
 import static java.lang.annotation.ElementType.PARAMETER;
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
+import android.annotation.NonNull;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.INotificationManager;
@@ -113,6 +114,7 @@
 import java.lang.annotation.Target;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Bubbles are a special type of content that can "float" on top of other apps or System UI.
@@ -243,13 +245,13 @@
          * This can happen when an app cancels a bubbled notification or when the user dismisses a
          * bubble.
          */
-        void removeNotification(NotificationEntry entry, int reason);
+        void removeNotification(@NonNull NotificationEntry entry, int reason);
 
         /**
          * Called when a bubbled notification has changed whether it should be
          * filtered from the shade.
          */
-        void invalidateNotifications(String reason);
+        void invalidateNotifications(@NonNull String reason);
 
         /**
          * Called on a bubbled entry that has been removed when there are no longer
@@ -259,7 +261,7 @@
          * removes all remnants of the group's summary from the notification pipeline.
          * TODO: (b/145659174) Only old pipeline needs this - delete post-migration.
          */
-        void maybeCancelSummary(NotificationEntry entry);
+        void maybeCancelSummary(@NonNull NotificationEntry entry);
     }
 
     /**
@@ -655,7 +657,13 @@
 
         try {
             mAddedToWindowManager = false;
-            mWindowManager.removeView(mStackView);
+            if (mStackView != null) {
+                mWindowManager.removeView(mStackView);
+                mStackView.removeView(mBubbleScrim);
+                mStackView = null;
+            } else {
+                Log.w(TAG, "StackView added to WindowManager, but was null when removing!");
+            }
         } 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.
@@ -729,8 +737,9 @@
                 mNotificationEntryManager.getActiveNotificationsForCurrentUser()) {
             if (savedBubbleKeys.contains(e.getKey())
                     && mNotificationInterruptStateProvider.shouldBubbleUp(e)
+                    && e.isBubble()
                     && canLaunchInActivityView(mContext, e)) {
-                updateBubble(e, /* suppressFlyout= */ true);
+                updateBubble(e, true /* suppressFlyout */, false /* showInShade */);
             }
         }
         // Finally, remove the entries for this user now that bubbles are restored.
@@ -754,10 +763,12 @@
         mBubbleIconFactory = new BubbleIconFactory(mContext);
         // Reload each bubble
         for (Bubble b: mBubbleData.getBubbles()) {
-            b.inflate(null /* callback */, mContext, mStackView, mBubbleIconFactory);
+            b.inflate(null /* callback */, mContext, mStackView, mBubbleIconFactory,
+                    false /* skipInflation */);
         }
         for (Bubble b: mBubbleData.getOverflowBubbles()) {
-            b.inflate(null /* callback */, mContext, mStackView, mBubbleIconFactory);
+            b.inflate(null /* callback */, mContext, mStackView, mBubbleIconFactory,
+                    false /* skipInflation */);
         }
     }
 
@@ -776,6 +787,10 @@
         }
     }
 
+    boolean inLandscape() {
+        return mOrientation == Configuration.ORIENTATION_LANDSCAPE;
+    }
+
     /**
      * Set a listener to be notified of bubble expand events.
      */
@@ -846,19 +861,28 @@
 
     /**
      * Request the stack expand if needed, then select the specified Bubble as current.
+     * If no bubble exists for this entry, one is created.
      *
-     * @param notificationKey the notification key for the bubble to be selected
+     * @param entry the notification for the bubble to be selected
      */
-    public void expandStackAndSelectBubble(String notificationKey) {
-        Bubble bubble = mBubbleData.getBubbleInStackWithKey(notificationKey);
-        if (bubble == null) {
-            bubble = mBubbleData.getOverflowBubbleWithKey(notificationKey);
-            if (bubble != null) {
-                mBubbleData.promoteBubbleFromOverflow(bubble, mStackView, mBubbleIconFactory);
-            }
-        } else if (bubble.getEntry().isBubble()){
+    public void expandStackAndSelectBubble(NotificationEntry entry) {
+        String key = entry.getKey();
+        Bubble bubble = mBubbleData.getBubbleInStackWithKey(key);
+        if (bubble != null) {
             mBubbleData.setSelectedBubble(bubble);
+        } else {
+            bubble = mBubbleData.getOverflowBubbleWithKey(key);
+            if (bubble != null) {
+                bubble.setShouldAutoExpand(true);
+                promoteBubbleFromOverflow(bubble);
+            } else if (entry.canBubble()) {
+                // It can bubble but it's not -- it got aged out of the overflow before it
+                // was dismissed or opened, make it a bubble again.
+                setIsBubble(entry, true);
+                updateBubble(entry, true /* suppressFlyout */, false /* showInShade */);
+            }
         }
+
         mBubbleData.setExpanded(true);
     }
 
@@ -878,17 +902,33 @@
      * @param notif the notification associated with this bubble.
      */
     void updateBubble(NotificationEntry notif) {
-        updateBubble(notif, false /* suppressFlyout */);
+        updateBubble(notif, false /* suppressFlyout */, true /* showInShade */);
     }
 
-    void updateBubble(NotificationEntry notif, boolean suppressFlyout) {
-        updateBubble(notif, suppressFlyout, true /* showInShade */);
+    /**
+     * Fills the overflow bubbles by loading them from disk.
+     */
+    void loadOverflowBubblesFromDisk() {
+        if (!mBubbleData.getOverflowBubbles().isEmpty()) {
+            // we don't need to load overflow bubbles from disk if it is already in memory
+            return;
+        }
+        mDataRepository.loadBubbles((bubbles) -> {
+            bubbles.forEach(bubble -> {
+                if (mBubbleData.getBubbles().contains(bubble)) {
+                    // if the bubble is already active, there's no need to push it to overflow
+                    return;
+                }
+                bubble.inflate((b) -> mBubbleData.overflowBubble(DISMISS_AGED, bubble),
+                        mContext, mStackView, mBubbleIconFactory, true /* skipInflation */);
+            });
+            return null;
+        });
     }
 
     void updateBubble(NotificationEntry notif, boolean suppressFlyout, boolean showInShade) {
         // 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();
@@ -897,7 +937,8 @@
         bubble.setInflateSynchronously(mInflateSynchronously);
         bubble.inflate(
                 b -> {
-                    mBubbleData.notificationEntryUpdated(b, suppressFlyout, showInShade);
+                    mBubbleData.notificationEntryUpdated(b, suppressFlyout,
+                            showInShade);
                     if (bubble.getBubbleIntent() == null) {
                         return;
                     }
@@ -907,11 +948,11 @@
                             return;
                         }
                         mHandler.post(
-                                () -> removeBubble(bubble.getEntry(),
+                                () -> removeBubble(bubble.getKey(),
                                         BubbleController.DISMISS_INVALID_INTENT));
                     });
                 },
-                mContext, mStackView, mBubbleIconFactory);
+                mContext, mStackView, mBubbleIconFactory, false /* skipInflation */);
     }
 
     /**
@@ -923,7 +964,10 @@
      * @param entry the notification to change bubble state for.
      * @param shouldBubble whether the notification should show as a bubble or not.
      */
-    public void onUserChangedBubble(NotificationEntry entry, boolean shouldBubble) {
+    public void onUserChangedBubble(@Nullable final NotificationEntry entry, boolean shouldBubble) {
+        if (entry == null) {
+            return;
+        }
         NotificationChannel channel = entry.getChannel();
         final String appPkg = entry.getSbn().getPackageName();
         final int appUid = entry.getSbn().getUid();
@@ -962,31 +1006,33 @@
     }
 
     /**
-     * Removes the bubble with the given NotificationEntry.
+     * Removes the bubble with the given key.
      * <p>
      * Must be called from the main thread.
      */
     @MainThread
-    void removeBubble(NotificationEntry entry, int reason) {
-        if (mBubbleData.hasAnyBubbleWithKey(entry.getKey())) {
-            mBubbleData.notificationEntryRemoved(entry, reason);
+    void removeBubble(String key, int reason) {
+        if (mBubbleData.hasAnyBubbleWithKey(key)) {
+            mBubbleData.notificationEntryRemoved(key, reason);
         }
     }
 
     private void onEntryAdded(NotificationEntry entry) {
         if (mNotificationInterruptStateProvider.shouldBubbleUp(entry)
+                && entry.isBubble()
                 && canLaunchInActivityView(mContext, entry)) {
             updateBubble(entry);
         }
     }
 
     private void onEntryUpdated(NotificationEntry entry) {
+        // shouldBubbleUp checks canBubble & for bubble metadata
         boolean shouldBubble = mNotificationInterruptStateProvider.shouldBubbleUp(entry)
                 && canLaunchInActivityView(mContext, entry);
         if (!shouldBubble && mBubbleData.hasAnyBubbleWithKey(entry.getKey())) {
             // It was previously a bubble but no longer a bubble -- lets remove it
-            removeBubble(entry, DISMISS_NO_LONGER_BUBBLE);
-        } else if (shouldBubble) {
+            removeBubble(entry.getKey(), DISMISS_NO_LONGER_BUBBLE);
+        } else if (shouldBubble && entry.isBubble()) {
             updateBubble(entry);
         }
     }
@@ -999,10 +1045,10 @@
             // Remove any associated bubble children with the summary
             final List<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(groupKey);
             for (int i = 0; i < bubbleChildren.size(); i++) {
-                removeBubble(bubbleChildren.get(i).getEntry(), DISMISS_GROUP_CANCELLED);
+                removeBubble(bubbleChildren.get(i).getKey(), DISMISS_GROUP_CANCELLED);
             }
         } else {
-            removeBubble(entry, DISMISS_NOTIF_CANCEL);
+            removeBubble(entry.getKey(), DISMISS_NOTIF_CANCEL);
         }
     }
 
@@ -1024,7 +1070,8 @@
             rankingMap.getRanking(key, mTmpRanking);
             boolean isActiveBubble = mBubbleData.hasAnyBubbleWithKey(key);
             if (isActiveBubble && !mTmpRanking.canBubble()) {
-                mBubbleData.notificationEntryRemoved(entry, BubbleController.DISMISS_BLOCKED);
+                mBubbleData.notificationEntryRemoved(entry.getKey(),
+                        BubbleController.DISMISS_BLOCKED);
             } else if (entry != null && mTmpRanking.isBubble() && !isActiveBubble) {
                 entry.setFlagBubble(true);
                 onEntryUpdated(entry);
@@ -1032,24 +1079,45 @@
         }
     }
 
-    private void setIsBubble(Bubble b, boolean isBubble) {
+    private void setIsBubble(@NonNull final NotificationEntry entry, final boolean isBubble) {
+        Objects.requireNonNull(entry);
         if (isBubble) {
-            b.getEntry().getSbn().getNotification().flags |= FLAG_BUBBLE;
+            entry.getSbn().getNotification().flags |= FLAG_BUBBLE;
         } else {
-            b.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
+            entry.getSbn().getNotification().flags &= ~FLAG_BUBBLE;
         }
         try {
-            mBarService.onNotificationBubbleChanged(b.getKey(), isBubble, 0);
+            mBarService.onNotificationBubbleChanged(entry.getKey(), isBubble, 0);
         } catch (RemoteException e) {
             // Bad things have happened
         }
     }
 
+    private void setIsBubble(@NonNull final Bubble b, final boolean isBubble) {
+        Objects.requireNonNull(b);
+        if (isBubble) {
+            b.enable(FLAG_BUBBLE);
+        } else {
+            b.disable(FLAG_BUBBLE);
+        }
+        if (b.getEntry() != null) {
+            setIsBubble(b.getEntry(), isBubble);
+        } else {
+            try {
+                mBarService.onNotificationBubbleChanged(b.getKey(), isBubble, 0);
+            } catch (RemoteException e) {
+                // Bad things have happened
+            }
+        }
+    }
+
     @SuppressWarnings("FieldCanBeLocal")
     private final BubbleData.Listener mBubbleDataListener = new BubbleData.Listener() {
 
         @Override
         public void applyUpdate(BubbleData.Update update) {
+            // Lazy load overflow bubbles from disk
+            loadOverflowBubblesFromDisk();
             // Update bubbles in overflow.
             if (mOverflowCallback != null) {
                 mOverflowCallback.run();
@@ -1084,23 +1152,27 @@
                         // The bubble is now gone & the notification is hidden from the shade, so
                         // time to actually remove it
                         for (NotifCallback cb : mCallbacks) {
-                            cb.removeNotification(bubble.getEntry(), REASON_CANCEL);
+                            if (bubble.getEntry() != null) {
+                                cb.removeNotification(bubble.getEntry(), REASON_CANCEL);
+                            }
                         }
                     } else {
-                        if (bubble.getEntry().isBubble() && bubble.showInShade()) {
-                            setIsBubble(bubble, /* isBubble */ false);
+                        if (bubble.isBubble() && bubble.showInShade()) {
+                            setIsBubble(bubble, false /* isBubble */);
                         }
-                        if (bubble.getEntry().getRow() != null) {
+                        if (bubble.getEntry() != null && bubble.getEntry().getRow() != null) {
                             bubble.getEntry().getRow().updateBubbleButton();
                         }
                     }
 
                 }
-                final String groupKey = bubble.getEntry().getSbn().getGroupKey();
-                if (mBubbleData.getBubblesInGroup(groupKey).isEmpty()) {
-                    // Time to potentially remove the summary
-                    for (NotifCallback cb : mCallbacks) {
-                        cb.maybeCancelSummary(bubble.getEntry());
+                if (bubble.getEntry() != null) {
+                    final String groupKey = bubble.getEntry().getSbn().getGroupKey();
+                    if (mBubbleData.getBubblesInGroup(groupKey).isEmpty()) {
+                        // Time to potentially remove the summary
+                        for (NotifCallback cb : mCallbacks) {
+                            cb.maybeCancelSummary(bubble.getEntry());
+                        }
                     }
                 }
             }
@@ -1125,7 +1197,7 @@
 
             if (update.selectionChanged) {
                 mStackView.setSelectedBubble(update.selectedBubble);
-                if (update.selectedBubble != null) {
+                if (update.selectedBubble != null && update.selectedBubble.getEntry() != null) {
                     mNotificationGroupManager.updateSuppression(
                             update.selectedBubble.getEntry());
                 }
@@ -1323,7 +1395,8 @@
                 boolean clearedTask, boolean wasVisible) {
             for (Bubble b : mBubbleData.getBubbles()) {
                 if (b.getDisplayId() == task.displayId) {
-                    expandStackAndSelectBubble(b.getKey());
+                    mBubbleData.setSelectedBubble(b);
+                    mBubbleData.setExpanded(true);
                     return;
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index 65d5beb..857f1dd 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -21,12 +21,10 @@
 import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
 import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
 
-import static java.util.stream.Collectors.toList;
-
+import android.annotation.NonNull;
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.content.Context;
-import android.service.notification.NotificationListenerService;
 import android.util.Log;
 import android.util.Pair;
 import android.view.View;
@@ -45,7 +43,6 @@
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 
 import javax.inject.Inject;
@@ -62,9 +59,6 @@
     private static final Comparator<Bubble> BUBBLES_BY_SORT_KEY_DESCENDING =
             Comparator.comparing(BubbleData::sortKey).reversed();
 
-    private static final Comparator<Map.Entry<String, Long>> GROUPS_BY_MAX_SORT_KEY_DESCENDING =
-            Comparator.<Map.Entry<String, Long>, Long>comparing(Map.Entry::getValue).reversed();
-
     /** Contains information about changes that have been made to the state of bubbles. */
     static final class Update {
         boolean expandedChanged;
@@ -129,8 +123,6 @@
     // State tracked during an operation -- keeps track of what listener events to dispatch.
     private Update mStateChange;
 
-    private NotificationListenerService.Ranking mTmpRanking;
-
     private TimeSource mTimeSource = System::currentTimeMillis;
 
     @Nullable
@@ -216,15 +208,14 @@
         }
         moveOverflowBubbleToPending(bubble);
         // Preserve new order for next repack, which sorts by last updated time.
-        bubble.markUpdatedAt(mTimeSource.currentTimeMillis());
         bubble.inflate(
                 b -> {
-                    notificationEntryUpdated(bubble, /* suppressFlyout */
-                            false, /* showInShade */ true);
-                    setSelectedBubble(bubble);
+                    b.setShouldAutoExpand(true);
+                    b.markUpdatedAt(mTimeSource.currentTimeMillis());
+                    notificationEntryUpdated(bubble, false /* suppressFlyout */,
+                            true /* showInShade */);
                 },
-                mContext, stack, factory);
-        dispatchPendingChanges();
+                mContext, stack, factory, false /* skipInflation */);
     }
 
     void setShowingOverflow(boolean showingOverflow) {
@@ -278,7 +269,8 @@
         }
         mPendingBubbles.remove(bubble); // No longer pending once we're here
         Bubble prevBubble = getBubbleInStackWithKey(bubble.getKey());
-        suppressFlyout |= !bubble.getEntry().getRanking().visuallyInterruptive();
+        suppressFlyout |= bubble.getEntry() == null
+                || !bubble.getEntry().getRanking().visuallyInterruptive();
 
         if (prevBubble == null) {
             // Create a new bubble
@@ -290,13 +282,13 @@
             bubble.setSuppressFlyout(suppressFlyout);
             doUpdate(bubble);
         }
+
         if (bubble.shouldAutoExpand()) {
+            bubble.setShouldAutoExpand(false);
             setSelectedBubbleInternal(bubble);
             if (!mExpanded) {
                 setExpandedInternal(true);
             }
-        } else if (mSelectedBubble == null) {
-            setSelectedBubbleInternal(bubble);
         }
 
         boolean isBubbleExpandedAndSelected = mExpanded && mSelectedBubble == bubble;
@@ -307,11 +299,14 @@
         dispatchPendingChanges();
     }
 
-    public void notificationEntryRemoved(NotificationEntry entry, @DismissReason int reason) {
+    /**
+     * Called when a notification associated with a bubble is removed.
+     */
+    public void notificationEntryRemoved(String key, @DismissReason int reason) {
         if (DEBUG_BUBBLE_DATA) {
-            Log.d(TAG, "notificationEntryRemoved: entry=" + entry + " reason=" + reason);
+            Log.d(TAG, "notificationEntryRemoved: key=" + key + " reason=" + reason);
         }
-        doRemove(entry.getKey(), reason);
+        doRemove(key, reason);
         dispatchPendingChanges();
     }
 
@@ -359,7 +354,7 @@
             return bubbleChildren;
         }
         for (Bubble b : mBubbles) {
-            if (groupKey.equals(b.getEntry().getSbn().getGroupKey())) {
+            if (b.getEntry() != null && groupKey.equals(b.getEntry().getSbn().getGroupKey())) {
                 bubbleChildren.add(b);
             }
         }
@@ -370,20 +365,11 @@
         if (DEBUG_BUBBLE_DATA) {
             Log.d(TAG, "doAdd: " + bubble);
         }
-        int minInsertPoint = 0;
-        boolean newGroup = !hasBubbleWithGroupId(bubble.getGroupId());
-        if (isExpanded()) {
-            // first bubble of a group goes to the beginning, otherwise within the existing group
-            minInsertPoint = newGroup ? 0 : findFirstIndexForGroup(bubble.getGroupId());
-        }
-        if (insertBubble(minInsertPoint, bubble) < mBubbles.size() - 1) {
-            mStateChange.orderChanged = true;
-        }
+        mBubbles.add(0, bubble);
         mStateChange.addedBubble = bubble;
-
+        // Adding the first bubble doesn't change the order
+        mStateChange.orderChanged = mBubbles.size() > 1;
         if (!isExpanded()) {
-            mStateChange.orderChanged |= packGroup(findFirstIndexForGroup(bubble.getGroupId()));
-            // Top bubble becomes selected.
             setSelectedBubbleInternal(mBubbles.get(0));
         }
     }
@@ -406,14 +392,10 @@
         }
         mStateChange.updatedBubble = bubble;
         if (!isExpanded()) {
-            // while collapsed, update causes re-pack
             int prevPos = mBubbles.indexOf(bubble);
             mBubbles.remove(bubble);
-            int newPos = insertBubble(0, bubble);
-            if (prevPos != newPos) {
-                packGroup(newPos);
-                mStateChange.orderChanged = true;
-            }
+            mBubbles.add(0, bubble);
+            mStateChange.orderChanged = prevPos != 0;
             setSelectedBubbleInternal(mBubbles.get(0));
         }
     }
@@ -470,7 +452,9 @@
             Bubble newSelected = mBubbles.get(newIndex);
             setSelectedBubbleInternal(newSelected);
         }
-        maybeSendDeleteIntent(reason, bubbleToRemove.getEntry());
+        if (bubbleToRemove.getEntry() != null) {
+            maybeSendDeleteIntent(reason, bubbleToRemove.getEntry());
+        }
     }
 
     void overflowBubble(@DismissReason int reason, Bubble bubble) {
@@ -581,7 +565,6 @@
                 Log.e(TAG, "Attempt to expand stack without selected bubble!");
                 return;
             }
-            mSelectedBubble.markUpdatedAt(mTimeSource.currentTimeMillis());
             mSelectedBubble.markAsAccessedAt(mTimeSource.currentTimeMillis());
             mStateChange.orderChanged |= repackAll();
         } else if (!mBubbles.isEmpty()) {
@@ -596,17 +579,11 @@
             }
             if (mBubbles.indexOf(mSelectedBubble) > 0) {
                 // Move the selected bubble to the top while collapsed.
-                if (!mSelectedBubble.isOngoing() && mBubbles.get(0).isOngoing()) {
-                    // The selected bubble cannot be raised to the first position because
-                    // there is an ongoing bubble there. Instead, force the top ongoing bubble
-                    // to become selected.
-                    setSelectedBubbleInternal(mBubbles.get(0));
-                } else {
-                    // Raise the selected bubble (and it's group) up to the front so the selected
-                    // bubble remains on top.
+                int index = mBubbles.indexOf(mSelectedBubble);
+                if (index != 0) {
                     mBubbles.remove(mSelectedBubble);
                     mBubbles.add(0, mSelectedBubble);
-                    mStateChange.orderChanged |= packGroup(0);
+                    mStateChange.orderChanged = true;
                 }
             }
         }
@@ -616,91 +593,12 @@
     }
 
     private static long sortKey(Bubble bubble) {
-        long key = bubble.getLastUpdateTime();
-        if (bubble.isOngoing()) {
-            // Set 2nd highest bit (signed long int), to partition between ongoing and regular
-            key |= 0x4000000000000000L;
-        }
-        return key;
+        return bubble.getLastActivity();
     }
 
     /**
-     * Locates and inserts the bubble into a sorted position. The is inserted
-     * based on sort key, groupId is not considered. A call to {@link #packGroup(int)} may be
-     * required to keep grouping intact.
-     *
-     * @param minPosition the first insert point to consider
-     * @param newBubble   the bubble to insert
-     * @return the position where the bubble was inserted
-     */
-    private int insertBubble(int minPosition, Bubble newBubble) {
-        long newBubbleSortKey = sortKey(newBubble);
-        String previousGroupId = null;
-
-        for (int pos = minPosition; pos < mBubbles.size(); pos++) {
-            Bubble bubbleAtPos = mBubbles.get(pos);
-            String groupIdAtPos = bubbleAtPos.getGroupId();
-            boolean atStartOfGroup = !groupIdAtPos.equals(previousGroupId);
-
-            if (atStartOfGroup && newBubbleSortKey > sortKey(bubbleAtPos)) {
-                // Insert before the start of first group which has older bubbles.
-                mBubbles.add(pos, newBubble);
-                return pos;
-            }
-            previousGroupId = groupIdAtPos;
-        }
-        mBubbles.add(newBubble);
-        return mBubbles.size() - 1;
-    }
-
-    private boolean hasBubbleWithGroupId(String groupId) {
-        return mBubbles.stream().anyMatch(b -> b.getGroupId().equals(groupId));
-    }
-
-    private int findFirstIndexForGroup(String appId) {
-        for (int i = 0; i < mBubbles.size(); i++) {
-            Bubble bubbleAtPos = mBubbles.get(i);
-            if (bubbleAtPos.getGroupId().equals(appId)) {
-                return i;
-            }
-        }
-        return 0;
-    }
-
-    /**
-     * Starting at the given position, moves all bubbles with the same group id to follow. Bubbles
-     * at positions lower than {@code position} are unchanged. Relative order within the group
-     * unchanged. Relative order of any other bubbles are also unchanged.
-     *
-     * @param position the position of the first bubble for the group
-     * @return true if the position of any bubbles has changed as a result
-     */
-    private boolean packGroup(int position) {
-        if (DEBUG_BUBBLE_DATA) {
-            Log.d(TAG, "packGroup: position=" + position);
-        }
-        Bubble groupStart = mBubbles.get(position);
-        final String groupAppId = groupStart.getGroupId();
-        List<Bubble> moving = new ArrayList<>();
-
-        // Walk backward, collect bubbles within the group
-        for (int i = mBubbles.size() - 1; i > position; i--) {
-            if (mBubbles.get(i).getGroupId().equals(groupAppId)) {
-                moving.add(0, mBubbles.get(i));
-            }
-        }
-        if (moving.isEmpty()) {
-            return false;
-        }
-        mBubbles.removeAll(moving);
-        mBubbles.addAll(position + 1, moving);
-        return true;
-    }
-
-    /**
-     * This applies a full sort and group pass to all existing bubbles. The bubbles are grouped
-     * by groupId. Each group is then sorted by the max(lastUpdated) time of its bubbles. Bubbles
-     * within each group are then sorted by lastUpdated descending.
+     * This applies a full sort and group pass to all existing bubbles.
+     * Bubbles are sorted by lastUpdated descending.
      *
      * @return true if the position of any bubbles changed as a result
      */
@@ -711,31 +609,11 @@
         if (mBubbles.isEmpty()) {
             return false;
         }
-        Map<String, Long> groupLastActivity = new HashMap<>();
-        for (Bubble bubble : mBubbles) {
-            long maxSortKeyForGroup = groupLastActivity.getOrDefault(bubble.getGroupId(), 0L);
-            long sortKeyForBubble = sortKey(bubble);
-            if (sortKeyForBubble > maxSortKeyForGroup) {
-                groupLastActivity.put(bubble.getGroupId(), sortKeyForBubble);
-            }
-        }
-
-        // Sort groups by their most recently active bubble
-        List<String> groupsByMostRecentActivity =
-                groupLastActivity.entrySet().stream()
-                        .sorted(GROUPS_BY_MAX_SORT_KEY_DESCENDING)
-                        .map(Map.Entry::getKey)
-                        .collect(toList());
-
         List<Bubble> repacked = new ArrayList<>(mBubbles.size());
-
-        // For each group, add bubbles, freshest to oldest
-        for (String appId : groupsByMostRecentActivity) {
-            mBubbles.stream()
-                    .filter((b) -> b.getGroupId().equals(appId))
-                    .sorted(BUBBLES_BY_SORT_KEY_DESCENDING)
-                    .forEachOrdered(repacked::add);
-        }
+        // Add bubbles, freshest to oldest
+        mBubbles.stream()
+                .sorted(BUBBLES_BY_SORT_KEY_DESCENDING)
+                .forEachOrdered(repacked::add);
         if (repacked.equals(mBubbles)) {
             return false;
         }
@@ -744,7 +622,8 @@
         return true;
     }
 
-    private void maybeSendDeleteIntent(@DismissReason int reason, NotificationEntry entry) {
+    private void maybeSendDeleteIntent(@DismissReason int reason,
+            @NonNull final NotificationEntry entry) {
         if (reason == BubbleController.DISMISS_USER_GESTURE) {
             Notification.BubbleMetadata bubbleMetadata = entry.getBubbleMetadata();
             PendingIntent deleteIntent = bubbleMetadata != null
@@ -778,11 +657,12 @@
     public List<Bubble> getBubbles() {
         return Collections.unmodifiableList(mBubbles);
     }
+
     /**
      * The set of bubbles in overflow.
      */
     @VisibleForTesting(visibility = PRIVATE)
-    public List<Bubble> getOverflowBubbles() {
+    List<Bubble> getOverflowBubbles() {
         return Collections.unmodifiableList(mOverflowBubbles);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
index ba93f41..1c5e98b 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt
@@ -74,8 +74,10 @@
 
     private fun transform(userId: Int, bubbles: List<Bubble>): List<BubbleEntity> {
         return bubbles.mapNotNull { b ->
-            val shortcutId = b.shortcutInfo?.id ?: return@mapNotNull null
-            BubbleEntity(userId, b.packageName, shortcutId)
+            var shortcutId = b.shortcutInfo?.id
+            if (shortcutId == null) shortcutId = b.entry?.bubbleMetadata?.shortcutId
+            if (shortcutId == null) return@mapNotNull null
+            BubbleEntity(userId, b.packageName, shortcutId, b.key)
         }
     }
 
@@ -108,7 +110,6 @@
     /**
      * Load bubbles from disk.
      */
-    // TODO: call this method from BubbleController and update UI
     @SuppressLint("WrongConstant")
     fun loadBubbles(cb: (List<Bubble>) -> Unit) = ioScope.launch {
         /**
@@ -132,17 +133,17 @@
         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.
+         * from the userId/packageName pair to a list of associated ShortcutInfo.
          * e.g.
          * {
-         *     BubbleEntity(0, "com.example.messenger", "id-0") ->
+         *     ShortcutKey(0, "com.example.messenger") -> [
          *         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=0, pkg="com.example.messenger", id="id-2")
+         *     ]
+         *     ShortcutKey(10, "com.example.chat") -> [
          *         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 ->
@@ -150,11 +151,15 @@
                     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()
+                    ?: emptyList()
+        }.groupBy { ShortcutKey(it.userId, it.`package`) }
         // 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) } }
+        val bubbles = entities.mapNotNull { entity ->
+            shortcutMap[ShortcutKey(entity.userId, entity.packageName)]
+                    ?.first { shortcutInfo -> entity.shortcutId == shortcutInfo.id }
+                    ?.let { shortcutInfo -> Bubble(entity.key, shortcutInfo) }
+        }
         uiScope.launch { cb(bubbles) }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDebugConfig.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDebugConfig.java
index 19733a5..d98fee3 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDebugConfig.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDebugConfig.java
@@ -69,10 +69,10 @@
                         && selected.getKey() != BubbleOverflow.KEY
                         && bubble == selected);
                 String arrow = isSelected ? "=>" : "  ";
-                sb.append(String.format("%s Bubble{act=%12d, ongoing=%d, key=%s}\n",
+                sb.append(String.format("%s Bubble{act=%12d, showInShade=%d, key=%s}\n",
                         arrow,
                         bubble.getLastActivity(),
-                        (bubble.isOngoing() ? 1 : 0),
+                        (bubble.showInShade() ? 1 : 0),
                         bubble.getKey()));
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 7697400..64dc2cc 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -65,7 +65,6 @@
 import com.android.systemui.R;
 import com.android.systemui.recents.TriangleShape;
 import com.android.systemui.statusbar.AlphaOptimizedButton;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 
 /**
  * Container for the expanded bubble view, handles rendering the caret and settings icon.
@@ -161,7 +160,7 @@
                             // the bubble again so we'll just remove it.
                             Log.w(TAG, "Exception while displaying bubble: " + getBubbleKey()
                                     + ", " + e.getMessage() + "; removing bubble");
-                            mBubbleController.removeBubble(getBubbleEntry(),
+                            mBubbleController.removeBubble(getBubbleKey(),
                                     BubbleController.DISMISS_INVALID_INTENT);
                         }
                     });
@@ -205,7 +204,7 @@
             }
             if (mBubble != null) {
                 // Must post because this is called from a binder thread.
-                post(() -> mBubbleController.removeBubble(mBubble.getEntry(),
+                post(() -> mBubbleController.removeBubble(mBubble.getKey(),
                         BubbleController.DISMISS_TASK_FINISHED));
             }
         }
@@ -226,8 +225,12 @@
     public BubbleExpandedView(Context context, AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        updateDimensions();
+    }
+
+    void updateDimensions() {
         mDisplaySize = new Point();
-        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
         // Get the real size -- this includes screen decorations (notches, statusbar, navbar).
         mWindowManager.getDefaultDisplay().getRealSize(mDisplaySize);
         Resources res = getResources();
@@ -293,10 +296,6 @@
         return mBubble != null ? mBubble.getKey() : "null";
     }
 
-    private NotificationEntry getBubbleEntry() {
-        return mBubble != null ? mBubble.getEntry() : null;
-    }
-
     void setManageClickListener(OnClickListener manageClickListener) {
         findViewById(R.id.settings_button).setOnClickListener(manageClickListener);
     }
@@ -307,7 +306,9 @@
      * if a view has been added or removed from on top of the ActivityView, such as the manage menu.
      */
     void updateObscuredTouchableRegion() {
-        mActivityView.onLocationChanged();
+        if (mActivityView != null) {
+            mActivityView.onLocationChanged();
+        }
     }
 
     void applyThemeAttrs() {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java
index f4eb580..b77e226 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java
@@ -61,9 +61,7 @@
     }
 
     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);
+        updateDimensions();
 
         mExpandedView = (BubbleExpandedView) mInflater.inflate(
                 R.layout.bubble_expanded_view, parentViewGroup /* root */,
@@ -74,6 +72,15 @@
         updateIcon(mContext, parentViewGroup);
     }
 
+    void updateDimensions() {
+        mBitmapSize = mContext.getResources().getDimensionPixelSize(R.dimen.bubble_bitmap_size);
+        mIconBitmapSize = mContext.getResources().getDimensionPixelSize(
+                R.dimen.bubble_overflow_icon_bitmap_size);
+        if (mExpandedView != null) {
+            mExpandedView.updateDimensions();
+        }
+    }
+
     void updateIcon(Context context, ViewGroup parentViewGroup) {
         mContext = context;
         mInflater = LayoutInflater.from(context);
@@ -122,7 +129,7 @@
         return mOverflowBtn;
     }
 
-    void setBtnVisible(int visible) {
+    void setVisible(int visible) {
         mOverflowBtn.setVisibility(visible);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
index 08ec789..2109a7b 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
@@ -21,7 +21,6 @@
 import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
 
 import android.app.Activity;
-import android.app.Notification;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -70,6 +69,9 @@
         }
         @Override
         public boolean canScrollVertically() {
+            if (mBubbleController.inLandscape()) {
+                return super.canScrollVertically();
+            }
             return false;
         }
     }
@@ -89,6 +91,14 @@
         mRecyclerView = findViewById(R.id.bubble_overflow_recycler);
         mEmptyStateImage = findViewById(R.id.bubble_overflow_empty_state_image);
 
+        updateDimensions();
+        onDataChanged(mBubbleController.getOverflowBubbles());
+        mBubbleController.setOverflowCallback(() -> {
+            onDataChanged(mBubbleController.getOverflowBubbles());
+        });
+    }
+
+    void updateDimensions() {
         Resources res = getResources();
         final int columns = res.getInteger(R.integer.bubbles_overflow_columns);
         mRecyclerView.setLayoutManager(
@@ -96,8 +106,9 @@
 
         DisplayMetrics displayMetrics = new DisplayMetrics();
         getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
-        final int recyclerViewWidth = (displayMetrics.widthPixels
-                - res.getDimensionPixelSize(R.dimen.bubble_overflow_padding));
+
+        final int overflowPadding = res.getDimensionPixelSize(R.dimen.bubble_overflow_padding);
+        final int recyclerViewWidth = displayMetrics.widthPixels - (overflowPadding * 2);
         final int viewWidth = recyclerViewWidth / columns;
 
         final int maxOverflowBubbles = res.getInteger(R.integer.bubbles_max_overflow);
@@ -109,17 +120,12 @@
         mAdapter = new BubbleOverflowAdapter(getApplicationContext(), mOverflowBubbles,
                 mBubbleController::promoteBubbleFromOverflow, viewWidth, viewHeight);
         mRecyclerView.setAdapter(mAdapter);
-        onDataChanged(mBubbleController.getOverflowBubbles());
-        mBubbleController.setOverflowCallback(() -> {
-            onDataChanged(mBubbleController.getOverflowBubbles());
-        });
-        onThemeChanged();
     }
 
     /**
      * Handle theme changes.
      */
-    void onThemeChanged() {
+    void updateTheme() {
         final int mode =
                 getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
         switch (mode) {
@@ -178,7 +184,8 @@
     @Override
     public void onResume() {
         super.onResume();
-        onThemeChanged();
+        updateDimensions();
+        updateTheme();
     }
 
     @Override
@@ -252,12 +259,9 @@
             mPromoteBubbleFromOverflow.accept(b);
         });
 
-        final CharSequence titleCharSeq =
-                b.getEntry().getSbn().getNotification().extras.getCharSequence(
-                        Notification.EXTRA_TITLE);
-        String titleStr = mContext.getResources().getString(R.string.notification_bubble_title);
-        if (titleCharSeq != null) {
-            titleStr = titleCharSeq.toString();
+        String titleStr = b.getTitle();
+        if (titleStr == null) {
+            titleStr = mContext.getResources().getString(R.string.notification_bubble_title);
         }
         vh.iconView.setContentDescription(mContext.getResources().getString(
                 R.string.bubble_content_description_single, titleStr, b.getAppName()));
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index c9f362b8..239132e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -31,7 +31,6 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.annotation.SuppressLint;
-import android.app.Notification;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -49,9 +48,7 @@
 import android.graphics.RectF;
 import android.graphics.Region;
 import android.os.Bundle;
-import android.os.Vibrator;
 import android.provider.Settings;
-import android.service.notification.StatusBarNotification;
 import android.util.Log;
 import android.view.Choreographer;
 import android.view.DisplayCutout;
@@ -188,7 +185,6 @@
     private final SpringAnimation mExpandedViewYAnim;
     private final BubbleData mBubbleData;
 
-    private final Vibrator mVibrator;
     private final ValueAnimator mDesaturateAndDarkenAnimator;
     private final Paint mDesaturateAndDarkenPaint = new Paint();
 
@@ -701,8 +697,6 @@
         // We use the real size & subtract screen decorations / window insets ourselves when needed
         wm.getDefaultDisplay().getRealSize(mDisplaySize);
 
-        mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
-
         mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
         int elevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
 
@@ -945,10 +939,10 @@
                     showManageMenu(false /* show */);
                     final Bubble bubble = mBubbleData.getSelectedBubble();
                     if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) {
-                        final Intent intent = bubble.getSettingsIntent();
+                        final Intent intent = bubble.getSettingsIntent(mContext);
                         collapseStack(() -> {
-                            mContext.startActivityAsUser(
-                                    intent, bubble.getEntry().getSbn().getUser());
+
+                            mContext.startActivityAsUser(intent, bubble.getUser());
                             logBubbleClickEvent(
                                     bubble,
                                     SysUiStatsLog.BUBBLE_UICHANGED__ACTION__HEADER_GO_TO_SETTINGS);
@@ -1033,6 +1027,7 @@
             mBubbleOverflow.setUpOverflow(mBubbleContainer, this);
         } else {
             mBubbleContainer.removeView(mBubbleOverflow.getBtn());
+            mBubbleOverflow.updateDimensions();
             mBubbleOverflow.updateIcon(mContext,this);
             overflowBtnIndex = mBubbleContainer.getChildCount();
         }
@@ -1122,6 +1117,9 @@
         super.onDetachedFromWindow();
         getViewTreeObserver().removeOnPreDrawListener(mViewUpdater);
         getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
+        if (mBubbleOverflow != null && mBubbleOverflow.getExpandedView() != null) {
+            mBubbleOverflow.getExpandedView().cleanUpExpandedState();
+        }
     }
 
     @Override
@@ -1205,13 +1203,10 @@
         for (int i = 0; i < mBubbleData.getBubbles().size(); i++) {
             final Bubble bubble = mBubbleData.getBubbles().get(i);
             final String appName = bubble.getAppName();
-            final Notification notification = bubble.getEntry().getSbn().getNotification();
-            final CharSequence titleCharSeq =
-                    notification.extras.getCharSequence(Notification.EXTRA_TITLE);
 
-            String titleStr = getResources().getString(R.string.notification_bubble_title);
-            if (titleCharSeq != null) {
-                titleStr = titleCharSeq.toString();
+            String titleStr = bubble.getTitle();
+            if (titleStr == null) {
+                titleStr = getResources().getString(R.string.notification_bubble_title);
             }
 
             if (bubble.getIconView() != null) {
@@ -1342,21 +1337,12 @@
         Log.d(TAG, "was asked to remove Bubble, but didn't find the view! " + bubble);
     }
 
-    private void updateOverflowBtnVisibility() {
-        if (!BubbleExperimentConfig.allowBubbleOverflow(mContext)) {
+    private void updateOverflowVisibility() {
+        if (!BubbleExperimentConfig.allowBubbleOverflow(mContext)
+                || mBubbleOverflow == null) {
             return;
         }
-        if (mIsExpanded) {
-            if (DEBUG_BUBBLE_STACK_VIEW) {
-                Log.d(TAG, "Show overflow button.");
-            }
-            mBubbleOverflow.setBtnVisible(VISIBLE);
-        } else {
-            if (DEBUG_BUBBLE_STACK_VIEW) {
-                Log.d(TAG, "Collapsed. Hide overflow button.");
-            }
-            mBubbleOverflow.setBtnVisible(GONE);
-        }
+        mBubbleOverflow.setVisible(mIsExpanded ? VISIBLE : GONE);
     }
 
     // via BubbleData.Listener
@@ -1610,7 +1596,7 @@
             Log.d(TAG, BubbleDebugConfig.formatBubblesString(getBubblesOnScreen(),
                     mExpandedBubble));
         }
-        updateOverflowBtnVisibility();
+        updateOverflowVisibility();
         mBubbleContainer.cancelAllAnimations();
         mExpandedAnimationController.collapseBackToStack(
                 mStackAnimationController.getStackPositionAlongNearestHorizontalEdge()
@@ -1634,7 +1620,7 @@
         beforeExpandedViewAnimation();
 
         mBubbleContainer.setActiveController(mExpandedAnimationController);
-        updateOverflowBtnVisibility();
+        updateOverflowVisibility();
         mExpandedAnimationController.expandFromStack(() -> {
             updatePointerPosition();
             afterExpandedViewAnimation();
@@ -1824,7 +1810,7 @@
     private void dismissBubbleIfExists(@Nullable Bubble bubble) {
         if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) {
             mBubbleData.notificationEntryRemoved(
-                    bubble.getEntry(), BubbleController.DISMISS_USER_GESTURE);
+                    bubble.getKey(), BubbleController.DISMISS_USER_GESTURE);
         }
     }
 
@@ -2322,18 +2308,12 @@
      * @param action the user interaction enum.
      */
     private void logBubbleClickEvent(Bubble bubble, int action) {
-        StatusBarNotification notification = bubble.getEntry().getSbn();
-        SysUiStatsLog.write(SysUiStatsLog.BUBBLE_UI_CHANGED,
-                notification.getPackageName(),
-                notification.getNotification().getChannelId(),
-                notification.getId(),
-                getBubbleIndex(getExpandedBubble()),
+        bubble.logUIEvent(
                 getBubbleCount(),
                 action,
                 getNormalizedXPosition(),
                 getNormalizedYPosition(),
-                bubble.showInShade(),
-                bubble.isOngoing(),
-                false /* isAppForeground (unused) */);
+                getBubbleIndex(getExpandedBubble())
+        );
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java
index 8a57a73..525d5b5 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java
@@ -37,6 +37,7 @@
 import android.graphics.drawable.Icon;
 import android.os.AsyncTask;
 import android.os.Parcelable;
+import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.util.Log;
@@ -74,6 +75,7 @@
     private WeakReference<Context> mContext;
     private WeakReference<BubbleStackView> mStackView;
     private BubbleIconFactory mIconFactory;
+    private boolean mSkipInflation;
     private Callback mCallback;
 
     /**
@@ -84,17 +86,20 @@
             Context context,
             BubbleStackView stackView,
             BubbleIconFactory factory,
+            boolean skipInflation,
             Callback c) {
         mBubble = b;
         mContext = new WeakReference<>(context);
         mStackView = new WeakReference<>(stackView);
         mIconFactory = factory;
+        mSkipInflation = skipInflation;
         mCallback = c;
     }
 
     @Override
     protected BubbleViewInfo doInBackground(Void... voids) {
-        return BubbleViewInfo.populate(mContext.get(), mStackView.get(), mIconFactory, mBubble);
+        return BubbleViewInfo.populate(mContext.get(), mStackView.get(), mIconFactory, mBubble,
+                mSkipInflation);
     }
 
     @Override
@@ -123,11 +128,36 @@
 
         @Nullable
         static BubbleViewInfo populate(Context c, BubbleStackView stackView,
-                BubbleIconFactory iconFactory, Bubble b) {
+                BubbleIconFactory iconFactory, Bubble b, boolean skipInflation) {
+            final NotificationEntry entry = b.getEntry();
+            if (entry == null) {
+                // populate from ShortcutInfo when NotificationEntry is not available
+                final ShortcutInfo s = b.getShortcutInfo();
+                return populate(c, stackView, iconFactory, skipInflation || b.isInflated(),
+                        s.getPackage(), s.getUserHandle(), s, null);
+            }
+            final StatusBarNotification sbn = entry.getSbn();
+            final String bubbleShortcutId =  entry.getBubbleMetadata().getShortcutId();
+            final ShortcutInfo si = bubbleShortcutId == null
+                    ? null : entry.getRanking().getShortcutInfo();
+            return populate(
+                    c, stackView, iconFactory, skipInflation || b.isInflated(),
+                    sbn.getPackageName(), sbn.getUser(), si, entry);
+        }
+
+        private static BubbleViewInfo populate(
+                @NonNull final Context c,
+                @NonNull final BubbleStackView stackView,
+                @NonNull final BubbleIconFactory iconFactory,
+                final boolean isInflated,
+                @NonNull final String packageName,
+                @NonNull final UserHandle user,
+                @Nullable final ShortcutInfo shortcutInfo,
+                @Nullable final NotificationEntry entry) {
             BubbleViewInfo info = new BubbleViewInfo();
 
             // View inflation: only should do this once per bubble
-            if (!b.isInflated()) {
+            if (!isInflated) {
                 LayoutInflater inflater = LayoutInflater.from(c);
                 info.imageView = (BadgedImageView) inflater.inflate(
                         R.layout.bubble_view, stackView, false /* attachToRoot */);
@@ -137,12 +167,8 @@
                 info.expandedView.setStackView(stackView);
             }
 
-            StatusBarNotification sbn = b.getEntry().getSbn();
-            String packageName = sbn.getPackageName();
-
-            String bubbleShortcutId =  b.getEntry().getBubbleMetadata().getShortcutId();
-            if (bubbleShortcutId != null) {
-                info.shortcutInfo = b.getEntry().getRanking().getShortcutInfo();
+            if (shortcutInfo != null) {
+                info.shortcutInfo = shortcutInfo;
             }
 
             // App name & app icon
@@ -161,7 +187,7 @@
                     info.appName = String.valueOf(pm.getApplicationLabel(appInfo));
                 }
                 appIcon = pm.getApplicationIcon(packageName);
-                badgedIcon = pm.getUserBadgedIcon(appIcon, sbn.getUser());
+                badgedIcon = pm.getUserBadgedIcon(appIcon, user);
             } catch (PackageManager.NameNotFoundException exception) {
                 // If we can't find package... don't think we should show the bubble.
                 Log.w(TAG, "Unable to find package: " + packageName);
@@ -170,7 +196,7 @@
 
             // Badged bubble image
             Drawable bubbleDrawable = iconFactory.getBubbleDrawable(c, info.shortcutInfo,
-                    b.getEntry().getBubbleMetadata());
+                    entry == null ? null : entry.getBubbleMetadata());
             if (bubbleDrawable == null) {
                 // Default to app icon
                 bubbleDrawable = appIcon;
@@ -196,7 +222,9 @@
                     Color.WHITE, WHITE_SCRIM_ALPHA);
 
             // Flyout
-            info.flyoutMessage = extractFlyoutMessage(c, b.getEntry());
+            if (entry != null) {
+                info.flyoutMessage = extractFlyoutMessage(c, entry);
+            }
             return info;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleEntity.kt b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleEntity.kt
index 4690a8e..4348261 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleEntity.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleEntity.kt
@@ -20,5 +20,6 @@
 data class BubbleEntity(
     @UserIdInt val userId: Int,
     val packageName: String,
-    val shortcutId: String
+    val shortcutId: String,
+    val key: String
 )
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 821b64c..1df9f72 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/storage/BubbleXmlHelper.kt
@@ -30,6 +30,7 @@
 private const val ATTR_USER_ID = "uid"
 private const val ATTR_PACKAGE = "pkg"
 private const val ATTR_SHORTCUT_ID = "sid"
+private const val ATTR_KEY = "key"
 
 /**
  * Writes the bubbles in xml format into given output stream.
@@ -48,7 +49,7 @@
 /**
  * Creates a xml entry for given bubble in following format:
  * ```
- * <bb uid="0" pkg="com.example.messenger" sid="my-shortcut" />
+ * <bb uid="0" pkg="com.example.messenger" sid="my-shortcut" key="my-key" />
  * ```
  */
 private fun writeXmlEntry(serializer: XmlSerializer, bubble: BubbleEntity) {
@@ -57,6 +58,7 @@
         serializer.attribute(null, ATTR_USER_ID, bubble.userId.toString())
         serializer.attribute(null, ATTR_PACKAGE, bubble.packageName)
         serializer.attribute(null, ATTR_SHORTCUT_ID, bubble.shortcutId)
+        serializer.attribute(null, ATTR_KEY, bubble.key)
         serializer.endTag(null, TAG_BUBBLE)
     } catch (e: IOException) {
         throw RuntimeException(e)
@@ -83,7 +85,8 @@
     return BubbleEntity(
             parser.getAttributeWithName(ATTR_USER_ID)?.toInt() ?: return null,
             parser.getAttributeWithName(ATTR_PACKAGE) ?: return null,
-            parser.getAttributeWithName(ATTR_SHORTCUT_ID) ?: return null
+            parser.getAttributeWithName(ATTR_SHORTCUT_ID) ?: return null,
+            parser.getAttributeWithName(ATTR_KEY) ?: return null
     )
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
new file mode 100644
index 0000000..9a5b960
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
@@ -0,0 +1,55 @@
+/*
+ * 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.controls.dagger
+
+import com.android.systemui.controls.controller.ControlsController
+import com.android.systemui.controls.management.ControlsListingController
+import com.android.systemui.controls.ui.ControlsUiController
+import dagger.Lazy
+import java.util.Optional
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * Pseudo-component to inject into classes outside `com.android.systemui.controls`.
+ *
+ * If `featureEnabled` is false, all the optionals should be empty. The controllers will only be
+ * instantiated if `featureEnabled` is true.
+ */
+@Singleton
+class ControlsComponent @Inject constructor(
+    @ControlsFeatureEnabled private val featureEnabled: Boolean,
+    private val lazyControlsController: Lazy<ControlsController>,
+    private val lazyControlsUiController: Lazy<ControlsUiController>,
+    private val lazyControlsListingController: Lazy<ControlsListingController>
+) {
+    fun getControlsController(): Optional<ControlsController> {
+        return if (featureEnabled) Optional.of(lazyControlsController.get()) else Optional.empty()
+    }
+
+    fun getControlsUiController(): Optional<ControlsUiController> {
+        return if (featureEnabled) Optional.of(lazyControlsUiController.get()) else Optional.empty()
+    }
+
+    fun getControlsListingController(): Optional<ControlsListingController> {
+        return if (featureEnabled) {
+            Optional.of(lazyControlsListingController.get())
+        } else {
+            Optional.empty()
+        }
+    }
+}
\ No newline at end of file
diff --git a/apex/sdkextensions/derive_sdk/sdk.proto b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsFeatureEnabled.kt
similarity index 69%
rename from apex/sdkextensions/derive_sdk/sdk.proto
rename to packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsFeatureEnabled.kt
index d15b935..dd061c5 100644
--- a/apex/sdkextensions/derive_sdk/sdk.proto
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsFeatureEnabled.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-syntax = "proto3";
-package com.android.sdkext.proto;
+package com.android.systemui.controls.dagger
 
-option java_outer_classname = "SdkProto";
-option optimize_for = LITE_RUNTIME;
+import javax.inject.Qualifier
 
-message SdkVersion {
-  int32 version = 1;
-}
+@Qualifier
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+annotation class ControlsFeatureEnabled
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
index 5765be5..4760d29 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.controls.dagger
 
 import android.app.Activity
+import android.content.pm.PackageManager
 import com.android.systemui.controls.controller.ControlsBindingController
 import com.android.systemui.controls.controller.ControlsBindingControllerImpl
 import com.android.systemui.controls.controller.ControlsController
@@ -28,19 +29,39 @@
 import com.android.systemui.controls.management.ControlsListingControllerImpl
 import com.android.systemui.controls.management.ControlsProviderSelectorActivity
 import com.android.systemui.controls.management.ControlsRequestDialog
-import com.android.systemui.controls.ui.ControlsUiController
-import com.android.systemui.controls.ui.ControlsUiControllerImpl
 import com.android.systemui.controls.ui.ControlActionCoordinator
 import com.android.systemui.controls.ui.ControlActionCoordinatorImpl
+import com.android.systemui.controls.ui.ControlsUiController
+import com.android.systemui.controls.ui.ControlsUiControllerImpl
 import dagger.Binds
 import dagger.BindsOptionalOf
 import dagger.Module
+import dagger.Provides
 import dagger.multibindings.ClassKey
 import dagger.multibindings.IntoMap
+import javax.inject.Singleton
 
+/**
+ * Module for injecting classes in `com.android.systemui.controls`-
+ *
+ * Classes provided by this module should only be injected directly into other classes in this
+ * module. For injecting outside of this module (for example, [GlobalActionsDialog], inject
+ * [ControlsComponent] and obtain the corresponding optionals from it.
+ */
 @Module
 abstract class ControlsModule {
 
+    @Module
+    companion object {
+        @JvmStatic
+        @Provides
+        @Singleton
+        @ControlsFeatureEnabled
+        fun providesControlsFeatureEnabled(pm: PackageManager): Boolean {
+            return pm.hasSystemFeature(PackageManager.FEATURE_CONTROLS)
+        }
+    }
+
     @Binds
     abstract fun provideControlsListingController(
         controller: ControlsListingControllerImpl
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestReceiver.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestReceiver.kt
index 0d23557..bf84d77 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestReceiver.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestReceiver.kt
@@ -55,6 +55,9 @@
     }
 
     override fun onReceive(context: Context, intent: Intent) {
+        if (!context.packageManager.hasSystemFeature(PackageManager.FEATURE_CONTROLS)) {
+            return
+        }
 
         val packageName = intent.getParcelableExtra<ComponentName>(Intent.EXTRA_COMPONENT_NAME)
                 ?.packageName
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 ab33291..606e947 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -60,7 +60,6 @@
 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
 import java.text.Collator
@@ -80,7 +79,6 @@
     @Main val sharedPreferences: SharedPreferences,
     val controlActionCoordinator: ControlActionCoordinator,
     private val activityStarter: ActivityStarter,
-    private val keyguardStateController: KeyguardStateController,
     private val shadeController: ShadeController
 ) : ControlsUiController {
 
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 23bcb29..8368b2c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -96,12 +96,6 @@
         return new AmbientDisplayConfiguration(context);
     }
 
-    /** */
-    @Provides
-    public Handler provideHandler() {
-        return new Handler();
-    }
-
     @Singleton
     @Provides
     public DataSaverController provideDataSaverController(NetworkController networkController) {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
index 3a8212c..58aad86 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
@@ -28,6 +28,7 @@
 import android.app.NotificationManager;
 import android.app.WallpaperManager;
 import android.app.admin.DevicePolicyManager;
+import android.app.role.RoleManager;
 import android.app.trust.TrustManager;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -314,4 +315,9 @@
         return context.getSystemService(WindowManager.class);
     }
 
+    @Provides
+    @Singleton
+    static RoleManager provideRoleManager(Context context) {
+        return context.getSystemService(RoleManager.class);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 6572937..95a9006 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -28,6 +28,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.R;
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.FalsingManager;
@@ -69,7 +70,7 @@
             WakefulnessLifecycle wakefulnessLifecycle, KeyguardUpdateMonitor keyguardUpdateMonitor,
             DockManager dockManager, @Nullable IWallpaperManager wallpaperManager,
             ProximitySensor proximitySensor,
-            DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler,
+            DelayedWakeLock.Builder delayedWakeLockBuilder, @Main Handler handler,
             DelayableExecutor delayableExecutor,
             BiometricUnlockController biometricUnlockController,
             BroadcastDispatcher broadcastDispatcher, DozeHost dozeHost) {
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index ac289cb..0f3a94b 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -120,8 +120,8 @@
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.controls.ControlsServiceInfo;
 import com.android.systemui.controls.controller.ControlsController;
+import com.android.systemui.controls.dagger.ControlsComponent;
 import com.android.systemui.controls.management.ControlsAnimations;
-import com.android.systemui.controls.management.ControlsListingController;
 import com.android.systemui.controls.ui.ControlsUiController;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -129,6 +129,7 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
 import com.android.systemui.plugins.GlobalActionsPanelPlugin;
+import com.android.systemui.settings.CurrentUserContextTracker;
 import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -139,6 +140,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
@@ -233,15 +235,16 @@
     private final IStatusBarService mStatusBarService;
     private final NotificationShadeWindowController mNotificationShadeWindowController;
     private GlobalActionsPanelPlugin mWalletPlugin;
-    private ControlsUiController mControlsUiController;
+    private Optional<ControlsUiController> mControlsUiControllerOptional;
     private final IWindowManager mIWindowManager;
     private final Executor mBackgroundExecutor;
     private List<ControlsServiceInfo> mControlsServiceInfos = new ArrayList<>();
-    private ControlsController mControlsController;
+    private Optional<ControlsController> mControlsControllerOptional;
     private SharedPreferences mControlsPreferences;
     private final RingerModeTracker mRingerModeTracker;
     private int mDialogPressDelay = DIALOG_PRESS_DELAY; // ms
     private Handler mMainHandler;
+    private CurrentUserContextTracker mCurrentUserContextTracker;
     @VisibleForTesting
     boolean mShowLockScreenCardsAndControls = false;
 
@@ -297,12 +300,13 @@
             NotificationShadeDepthController depthController, SysuiColorExtractor colorExtractor,
             IStatusBarService statusBarService,
             NotificationShadeWindowController notificationShadeWindowController,
-            ControlsUiController controlsUiController, IWindowManager iWindowManager,
+            IWindowManager iWindowManager,
             @Background Executor backgroundExecutor,
-            ControlsListingController controlsListingController,
-            ControlsController controlsController, UiEventLogger uiEventLogger,
-            RingerModeTracker ringerModeTracker, SysUiState sysUiState, @Main Handler handler) {
-        mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme);
+            UiEventLogger uiEventLogger,
+            RingerModeTracker ringerModeTracker, SysUiState sysUiState, @Main Handler handler,
+            ControlsComponent controlsComponent,
+            CurrentUserContextTracker currentUserContextTracker) {
+        mContext = context;
         mWindowManagerFuncs = windowManagerFuncs;
         mAudioManager = audioManager;
         mDreamManager = iDreamManager;
@@ -323,13 +327,14 @@
         mSysuiColorExtractor = colorExtractor;
         mStatusBarService = statusBarService;
         mNotificationShadeWindowController = notificationShadeWindowController;
-        mControlsUiController = controlsUiController;
+        mControlsUiControllerOptional = controlsComponent.getControlsUiController();
         mIWindowManager = iWindowManager;
         mBackgroundExecutor = backgroundExecutor;
         mRingerModeTracker = ringerModeTracker;
-        mControlsController = controlsController;
+        mControlsControllerOptional = controlsComponent.getControlsController();
         mSysUiState = sysUiState;
         mMainHandler = handler;
+        mCurrentUserContextTracker = currentUserContextTracker;
 
         // receive broadcasts
         IntentFilter filter = new IntentFilter();
@@ -371,7 +376,7 @@
                         mDialog.mWalletViewController.onDeviceLockStateChanged(!unlocked);
                     }
                     if (!mDialog.isShowingControls() && shouldShowControls()) {
-                        mDialog.showControls(mControlsUiController);
+                        mDialog.showControls(mControlsUiControllerOptional.get());
                     }
                     if (unlocked) {
                         mDialog.hideLockMessage();
@@ -380,7 +385,10 @@
             }
         });
 
-        controlsListingController.addCallback(list -> mControlsServiceInfos = list);
+        if (controlsComponent.getControlsListingController().isPresent()) {
+            controlsComponent.getControlsListingController().get()
+                    .addCallback(list -> mControlsServiceInfos = list);
+        }
 
         // Need to be user-specific with the context to make sure we read the correct prefs
         Context userContext = context.createContextAsUser(
@@ -402,9 +410,16 @@
     }
 
     private void seedFavorites() {
+        if (!mControlsControllerOptional.isPresent()) return;
         if (mControlsServiceInfos.isEmpty()
-                || mControlsController.getFavorites().size() > 0
-                || mControlsPreferences.getBoolean(PREFS_CONTROLS_SEEDING_COMPLETED, false)) {
+                || mControlsControllerOptional.get().getFavorites().size() > 0) {
+            return;
+        }
+
+        // Need to be user-specific with the context to make sure we read the correct prefs
+        SharedPreferences prefs = mCurrentUserContextTracker.getCurrentUserContext()
+                .getSharedPreferences(PREFS_CONTROLS_FILE, Context.MODE_PRIVATE);
+        if (prefs.getBoolean(PREFS_CONTROLS_SEEDING_COMPLETED, false)) {
             return;
         }
 
@@ -426,16 +441,15 @@
 
         if (preferredComponent == null) {
             Log.i(TAG, "Controls seeding: No preferred component has been set, will not seed");
-            mControlsPreferences.edit().putBoolean(PREFS_CONTROLS_SEEDING_COMPLETED, true).apply();
+            prefs.edit().putBoolean(PREFS_CONTROLS_SEEDING_COMPLETED, true).apply();
             return;
         }
 
-        mControlsController.seedFavoritesForComponent(
+        mControlsControllerOptional.get().seedFavoritesForComponent(
                 preferredComponent,
                 (accepted) -> {
                     Log.i(TAG, "Controls seeded: " + accepted);
-                    mControlsPreferences.edit().putBoolean(PREFS_CONTROLS_SEEDING_COMPLETED,
-                        accepted).apply();
+                    prefs.edit().putBoolean(PREFS_CONTROLS_SEEDING_COMPLETED, accepted).apply();
                 });
     }
 
@@ -550,8 +564,8 @@
 
         mItems.clear();
         mOverflowItems.clear();
-        String[] defaultActions = getDefaultActions();
 
+        String[] defaultActions = getDefaultActions();
         // make sure emergency affordance action is first, if needed
         if (mEmergencyAffordanceManager.needsEmergencyAffordance()) {
             addActionItem(new EmergencyAffordanceAction());
@@ -634,10 +648,14 @@
         mDepthController.setShowingHomeControls(true);
         GlobalActionsPanelPlugin.PanelViewController walletViewController =
                 getWalletViewController();
+        ControlsUiController uiController = null;
+        if (mControlsUiControllerOptional.isPresent() && shouldShowControls()) {
+            uiController = mControlsUiControllerOptional.get();
+        }
         ActionsDialog dialog = new ActionsDialog(mContext, mAdapter, mOverflowAdapter,
                 walletViewController, mDepthController, mSysuiColorExtractor,
                 mStatusBarService, mNotificationShadeWindowController,
-                controlsAvailable(), shouldShowControls() ? mControlsUiController : null,
+                controlsAvailable(), uiController,
                 mSysUiState, this::onRotate, mKeyguardShowing);
         boolean walletViewAvailable = walletViewController != null
                 && walletViewController.getPanelContent() != null;
@@ -1323,18 +1341,11 @@
             View view = convertView != null ? convertView
                     : LayoutInflater.from(mContext).inflate(viewLayoutResource, parent, false);
             TextView textView = (TextView) view;
-            textView.setOnClickListener(v -> onClickItem(position));
             if (action.getMessageResId() != 0) {
                 textView.setText(action.getMessageResId());
             } else {
                 textView.setText(action.getMessage());
             }
-
-            if (action instanceof LongPressAction) {
-                textView.setOnLongClickListener(v -> onLongClickItem(position));
-            } else {
-                textView.setOnLongClickListener(null);
-            }
             return textView;
         }
 
@@ -2046,11 +2057,15 @@
         }
 
         private ListPopupWindow createPowerOverflowPopup() {
-            ListPopupWindow popup = new GlobalActionsPopupMenu(
+            GlobalActionsPopupMenu popup = new GlobalActionsPopupMenu(
                     new ContextThemeWrapper(
-                        mContext,
-                        com.android.systemui.R.style.Control_ListPopupWindow
+                            mContext,
+                            com.android.systemui.R.style.Control_ListPopupWindow
                     ), false /* isDropDownMode */);
+            popup.setOnItemClickListener(
+                    (parent, view, position, id) -> mOverflowAdapter.onClickItem(position));
+            popup.setOnItemLongClickListener(
+                    (parent, view, position, id) -> mOverflowAdapter.onLongClickItem(position));
             View overflowButton =
                     findViewById(com.android.systemui.R.id.global_actions_overflow_button);
             popup.setAnchorView(overflowButton);
@@ -2401,7 +2416,8 @@
 
     private boolean controlsAvailable() {
         return mDeviceProvisioned
-                && mControlsUiController.getAvailable()
+                && mControlsUiControllerOptional.isPresent()
+                && mControlsUiControllerOptional.get().getAvailable()
                 && !mControlsServiceInfos.isEmpty();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPopupMenu.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPopupMenu.java
index a5ced7b..6b71f1e 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPopupMenu.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPopupMenu.java
@@ -22,6 +22,7 @@
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.WindowManager;
+import android.widget.AdapterView;
 import android.widget.ListAdapter;
 import android.widget.ListPopupWindow;
 import android.widget.ListView;
@@ -37,10 +38,10 @@
 public class GlobalActionsPopupMenu extends ListPopupWindow {
     private Context mContext;
     private boolean mIsDropDownMode;
-    private int mMenuHorizontalPadding = 0;
     private int mMenuVerticalPadding = 0;
     private int mGlobalActionsSidePadding = 0;
     private ListAdapter mAdapter;
+    private AdapterView.OnItemLongClickListener mOnItemLongClickListener;
 
     public GlobalActionsPopupMenu(@NonNull Context context, boolean isDropDownMode) {
         super(context);
@@ -57,8 +58,6 @@
         mGlobalActionsSidePadding = res.getDimensionPixelSize(R.dimen.global_actions_side_margin);
         if (!isDropDownMode) {
             mMenuVerticalPadding = res.getDimensionPixelSize(R.dimen.control_menu_vertical_padding);
-            mMenuHorizontalPadding =
-                res.getDimensionPixelSize(R.dimen.control_menu_horizontal_padding);
         }
     }
 
@@ -76,6 +75,9 @@
     public void show() {
         // need to call show() first in order to construct the listView
         super.show();
+        if (mOnItemLongClickListener != null) {
+            getListView().setOnItemLongClickListener(mOnItemLongClickListener);
+        }
 
         ListView listView = getListView();
         Resources res = mContext.getResources();
@@ -92,7 +94,7 @@
             // width should be between [.5, .9] of screen
             int parentWidth = res.getSystem().getDisplayMetrics().widthPixels;
             int widthSpec = MeasureSpec.makeMeasureSpec(
-                    (int) (parentWidth * 0.9) - 2 * mMenuHorizontalPadding, MeasureSpec.AT_MOST);
+                    (int) (parentWidth * 0.9), MeasureSpec.AT_MOST);
             int maxWidth = 0;
             for (int i = 0; i < mAdapter.getCount(); i++) {
                 View child = mAdapter.getView(i, null, listView);
@@ -100,10 +102,8 @@
                 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);
+            int width = Math.max(maxWidth, (int) (parentWidth * 0.5));
+            listView.setPadding(0, mMenuVerticalPadding, 0, mMenuVerticalPadding);
 
             setWidth(width);
             setHorizontalOffset(getAnchorView().getWidth() - mGlobalActionsSidePadding - width);
@@ -111,4 +111,8 @@
 
         super.show();
     }
+
+    public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) {
+        mOnItemLongClickListener = listener;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/GoneChildrenHideHelper.kt b/packages/SystemUI/src/com/android/systemui/media/GoneChildrenHideHelper.kt
deleted file mode 100644
index 2fe0d9f..0000000
--- a/packages/SystemUI/src/com/android/systemui/media/GoneChildrenHideHelper.kt
+++ /dev/null
@@ -1,52 +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.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/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
index 85e1c6b..5f43e43 100644
--- a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
@@ -45,6 +45,7 @@
             }
         })
     }
+
     private var view: MediaHeaderView? = null
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/media/LayoutAnimationHelper.kt b/packages/SystemUI/src/com/android/systemui/media/LayoutAnimationHelper.kt
deleted file mode 100644
index a366725..0000000
--- a/packages/SystemUI/src/com/android/systemui/media/LayoutAnimationHelper.kt
+++ /dev/null
@@ -1,115 +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.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/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index c7b9326..8e1e1b2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -43,12 +43,9 @@
 import android.widget.SeekBar;
 import android.widget.TextView;
 
+import androidx.annotation.NonNull;
 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;
@@ -59,11 +56,11 @@
 import com.android.systemui.R;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.qs.QSMediaBrowser;
+import com.android.systemui.util.animation.TransitionLayout;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 
 import org.jetbrains.annotations.NotNull;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Executor;
 
@@ -87,16 +84,15 @@
     private final Executor mForegroundExecutor;
     protected final Executor mBackgroundExecutor;
     private final ActivityStarter mActivityStarter;
-    private LayoutAnimationHelper mLayoutAnimationHelper;
 
     private Context mContext;
     private PlayerViewHolder mViewHolder;
+    private MediaViewController mMediaViewController;
     private MediaSession.Token mToken;
     private MediaController mController;
     private int mBackgroundColor;
     protected ComponentName mServiceComponent;
     private boolean mIsRegistered = false;
-    private List<KeyFrames> mKeyFrames;
     private String mKey;
     private int mAlbumArtSize;
     private int mAlbumArtRadius;
@@ -133,12 +129,14 @@
      * @param activityStarter activity starter
      */
     public MediaControlPanel(Context context, Executor foregroundExecutor,
-            DelayableExecutor backgroundExecutor, ActivityStarter activityStarter) {
+            DelayableExecutor backgroundExecutor, ActivityStarter activityStarter,
+            MediaHostStatesManager mediaHostStatesManager) {
         mContext = context;
         mForegroundExecutor = foregroundExecutor;
         mBackgroundExecutor = backgroundExecutor;
         mActivityStarter = activityStarter;
         mSeekBarViewModel = new SeekBarViewModel(backgroundExecutor);
+        mMediaViewController = new MediaViewController(context, mediaHostStatesManager);
         loadDimens();
     }
 
@@ -147,6 +145,7 @@
             mSeekBarViewModel.getProgress().removeObserver(mSeekBarObserver);
         }
         mSeekBarViewModel.onDestroy();
+        mMediaViewController.onDestroy();
     }
 
     private void loadDimens() {
@@ -165,6 +164,15 @@
     }
 
     /**
+     * Get the view controller used to display media controls
+     * @return the media view controller
+     */
+    @NonNull
+    public MediaViewController getMediaViewController() {
+        return mMediaViewController;
+    }
+
+    /**
      * 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
@@ -187,15 +195,13 @@
     /** 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();
+        TransitionLayout player = vh.getPlayer();
         mSeekBarObserver = new SeekBarObserver(vh);
         mSeekBarViewModel.getProgress().observeForever(mSeekBarObserver);
         SeekBar bar = vh.getSeekBar();
         bar.setOnSeekBarChangeListener(mSeekBarViewModel.getSeekBarListener());
         bar.setOnTouchListener(mSeekBarViewModel.getSeekBarTouchListener());
+        mMediaViewController.attach(player);
     }
 
     /**
@@ -220,8 +226,8 @@
 
         mController = new MediaController(mContext, mToken);
 
-        ConstraintSet expandedSet = mViewHolder.getPlayer().getConstraintSet(R.id.expanded);
-        ConstraintSet collapsedSet = mViewHolder.getPlayer().getConstraintSet(R.id.collapsed);
+        ConstraintSet expandedSet = mMediaViewController.getExpandedLayout();
+        ConstraintSet collapsedSet = mMediaViewController.getCollapsedLayout();
 
         // Try to find a browser service component for this app
         // TODO also check for a media button receiver intended for restarting (b/154127084)
@@ -247,7 +253,7 @@
 
         mController.registerCallback(mSessionCallback);
 
-        mViewHolder.getBackground().setBackgroundTintList(
+        mViewHolder.getPlayer().setBackgroundTintList(
                 ColorStateList.valueOf(mBackgroundColor));
 
         // Click action
@@ -356,7 +362,6 @@
                 }
             });
             boolean visibleInCompat = actionsWhenCollapsed.contains(i);
-            updateKeyFrameVisibility(actionId, visibleInCompat);
             setVisibleAndAlpha(collapsedSet, actionId, visibleInCompat);
             setVisibleAndAlpha(expandedSet, actionId, true /*visible */);
         }
@@ -374,9 +379,9 @@
         // 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);
+        // TODO: We don't need to refresh this state constantly, only if the state actually changed
+        // to something which might impact the measurement
+        mMediaViewController.refreshState();
     }
 
     @UiThread
@@ -412,30 +417,6 @@
     }
 
     /**
-     * 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);
-                }
-            }
-        }
-    }
-
-    /**
      * Return the token for the current media session
      * @return the token
      */
@@ -528,8 +509,8 @@
         }
         // Hide all the old buttons
 
-        ConstraintSet expandedSet = mViewHolder.getPlayer().getConstraintSet(R.id.expanded);
-        ConstraintSet collapsedSet = mViewHolder.getPlayer().getConstraintSet(R.id.collapsed);
+        ConstraintSet expandedSet = mMediaViewController.getExpandedLayout();
+        ConstraintSet collapsedSet = mMediaViewController.getCollapsedLayout();
         for (int i = 1; i < ACTION_IDS.length; i++) {
             setVisibleAndAlpha(expandedSet, ACTION_IDS[i], false /*visible */);
             setVisibleAndAlpha(collapsedSet, ACTION_IDS[i], false /*visible */);
@@ -571,6 +552,7 @@
             options.setVisibility(View.VISIBLE);
             return true; // consumed click
         });
+        mMediaViewController.refreshState();
     }
 
     private void setVisibleAndAlpha(ConstraintSet set, int actionId, boolean visible) {
@@ -649,33 +631,4 @@
      * 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/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 009f549..cf7fbfa 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -36,6 +36,7 @@
 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.Assert
 import com.android.systemui.util.Utils
 import java.io.IOException
 import java.util.concurrent.Executor
@@ -85,6 +86,7 @@
 
     fun onNotificationAdded(key: String, sbn: StatusBarNotification) {
         if (Utils.useQsMediaPlayer(context) && isMediaNotification(sbn)) {
+            Assert.isMainThread()
             if (!mediaEntries.containsKey(key)) {
                 mediaEntries.put(key, LOADING)
             }
@@ -269,19 +271,23 @@
     }
 
     fun onMediaDataLoaded(key: String, data: MediaData) {
+        Assert.isMainThread()
         if (mediaEntries.containsKey(key)) {
             // Otherwise this was removed already
             mediaEntries.put(key, data)
-            listeners.forEach {
+            val listenersCopy = listeners.toSet()
+            listenersCopy.forEach {
                 it.onMediaDataLoaded(key, data)
             }
         }
     }
 
     fun onNotificationRemoved(key: String) {
+        Assert.isMainThread()
         val removed = mediaEntries.remove(key)
         if (removed != null) {
-            listeners.forEach {
+            val listenersCopy = listeners.toSet()
+            listenersCopy.forEach {
                 it.onMediaDataRemoved(key)
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
index 0b04fd0..552fea6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
@@ -81,7 +81,7 @@
 
     private fun processDevice(key: String, device: MediaDevice?) {
         val enabled = device != null
-        val data = MediaDeviceData(enabled, device?.icon, device?.name)
+        val data = MediaDeviceData(enabled, device?.iconWithoutBackground, device?.name)
         listeners.forEach {
             it.onMediaDeviceChanged(key, data)
         }
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
index cce1d3e..775a1649 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
@@ -21,10 +21,13 @@
 import android.animation.ValueAnimator
 import android.annotation.IntDef
 import android.content.Context
+import android.graphics.Rect
+import android.util.MathUtils
 import android.view.View
 import android.view.ViewGroup
 import android.view.ViewGroupOverlay
 import com.android.systemui.Interpolators
+import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.statusbar.NotificationLockscreenUserManager
 import com.android.systemui.statusbar.StatusBarState
@@ -47,8 +50,8 @@
     private val keyguardStateController: KeyguardStateController,
     private val bypassController: KeyguardBypassController,
     private val mediaViewManager: MediaViewManager,
-    private val mediaMeasurementProvider: MediaMeasurementManager,
-    private val notifLockscreenUserManager: NotificationLockscreenUserManager
+    private val notifLockscreenUserManager: NotificationLockscreenUserManager,
+    wakefulnessLifecycle: WakefulnessLifecycle
 ) {
     /**
      * The root overlay of the hierarchy. This is where the media notification is attached to
@@ -56,23 +59,31 @@
      * 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
+
+    private var rootView: View? = null
+    private var currentBounds = Rect()
+    private var animationStartBounds: Rect = Rect()
+    private var targetBounds: Rect = Rect()
+    private val mediaFrame
         get() = mediaViewManager.mediaFrame
-    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))
+            interpolateBounds(animationStartBounds, targetBounds, animatedFraction,
+                    result = currentBounds)
+            applyState(currentBounds)
         }
         addListener(object : AnimatorListenerAdapter() {
             private var cancelled: Boolean = false
 
             override fun onAnimationCancel(animation: Animator?) {
                 cancelled = true
+                animationPending = false
+                rootView?.removeCallbacks(startAnimation)
             }
+
             override fun onAnimationEnd(animation: Animator?) {
                 if (!cancelled) {
                     applyTargetStateIfNotAnimating()
@@ -81,30 +92,41 @@
 
             override fun onAnimationStart(animation: Animator?) {
                 cancelled = false
+                animationPending = false
             }
         })
     }
-    private var targetState: MediaState? = null
-    private val mediaHosts = arrayOfNulls<MediaHost>(LOCATION_LOCKSCREEN + 1)
 
+    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
-
+    @MediaLocation
+    private var previousLocation = -1
     /**
      * The desired location where the view will be at the end of the transition.
      */
-    @MediaLocation private var desiredLocation = -1
+    @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
+    @MediaLocation
+    private var currentAttachmentLocation = -1
 
+    /**
+     * Are we currently waiting on an animation to start?
+     */
+    private var animationPending: Boolean = false
+    private val startAnimation: Runnable = Runnable { animator.start() }
+
+    /**
+     * The expansion of quick settings
+     */
     var qsExpansion: Float = 0.0f
         set(value) {
             if (field != value) {
@@ -117,6 +139,40 @@
             }
         }
 
+    /**
+     * Are location changes currently blocked?
+     */
+    private val blockLocationChanges: Boolean
+        get() {
+            return goingToSleep || dozeAnimationRunning
+        }
+
+    /**
+     * Are we currently going to sleep
+     */
+    private var goingToSleep: Boolean = false
+        set(value) {
+            if (field != value) {
+                field = value
+                if (!value) {
+                    updateDesiredLocation()
+                }
+            }
+        }
+
+    /**
+     * Is the doze animation currently Running
+     */
+    private var dozeAnimationRunning: Boolean = false
+        private set(value) {
+            if (field != value) {
+                field = value
+                if (!value) {
+                    updateDesiredLocation()
+                }
+            }
+        }
+
     init {
         statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
             override fun onStatePreChange(oldState: Int, newState: Int) {
@@ -129,6 +185,34 @@
             override fun onStateChanged(newState: Int) {
                 updateTargetState()
             }
+
+            override fun onDozeAmountChanged(linear: Float, eased: Float) {
+                dozeAnimationRunning = linear != 0.0f && linear != 1.0f
+            }
+
+            override fun onDozingChanged(isDozing: Boolean) {
+                if (!isDozing) {
+                    dozeAnimationRunning = false
+                }
+            }
+        })
+
+        wakefulnessLifecycle.addObserver(object : WakefulnessLifecycle.Observer {
+            override fun onFinishedGoingToSleep() {
+                goingToSleep = false
+            }
+
+            override fun onStartedGoingToSleep() {
+                goingToSleep = true
+            }
+
+            override fun onFinishedWakingUp() {
+                goingToSleep = false
+            }
+
+            override fun onStartedWakingUp() {
+                goingToSleep = false
+            }
         })
     }
 
@@ -138,8 +222,8 @@
      *
      * @return the hostView associated with this location
      */
-    fun register(mediaObject: MediaHost): ViewGroup {
-        val viewHost = createUniqueObjectHost(mediaObject)
+    fun register(mediaObject: MediaHost): UniqueObjectHostView {
+        val viewHost = createUniqueObjectHost()
         mediaObject.hostView = viewHost
         mediaHosts[mediaObject.location] = mediaObject
         if (mediaObject.location == desiredLocation) {
@@ -154,22 +238,13 @@
         return viewHost
     }
 
-    private fun createUniqueObjectHost(host: MediaHost): UniqueObjectHostView {
+    private fun createUniqueObjectHost(): 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)
+                    rootView = viewHost.viewRootImpl.view
+                    rootOverlay = (rootView!!.overlay as ViewGroupOverlay)
                 }
                 viewHost.removeOnAttachStateChangeListener(this)
             }
@@ -195,8 +270,9 @@
             // Let's perform a transition
             val animate = shouldAnimateTransition(desiredLocation, previousLocation)
             val (animDuration, delay) = getAnimationParams(previousLocation, desiredLocation)
-            mediaViewManager.onDesiredLocationChanged(getHost(desiredLocation)?.currentState,
-                    animate, animDuration, delay)
+            val host = getHost(desiredLocation)
+            mediaViewManager.onDesiredLocationChanged(desiredLocation, host, animate, animDuration,
+                    delay)
             performTransitionToNewLocation(isNewView, animate)
         }
     }
@@ -222,14 +298,18 @@
                 // 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()
+                animationStartBounds.set(currentBounds)
             } else {
                 // otherwise, let's take the freshest state, since the current one could
                 // be outdated
-                animationStartState = previousHost.currentState.copy()
+                animationStartBounds.set(previousHost.currentBounds)
             }
             adjustAnimatorForTransition(desiredLocation, previousLocation)
-            animator.start()
+            rootView?.let {
+                // Let's delay the animation start until we finished laying out
+                animationPending = true
+                it.postOnAnimation(startAnimation)
+            }
         } else {
             cancelAnimationAndApplyDesiredState()
         }
@@ -239,6 +319,9 @@
         @MediaLocation currentLocation: Int,
         @MediaLocation previousLocation: Int
     ): Boolean {
+        if (isCurrentlyInGuidedTransformation()) {
+            return false
+        }
         if (currentLocation == LOCATION_QQS &&
                 previousLocation == LOCATION_LOCKSCREEN &&
                 (statusBarStateController.leaveOpenOnKeyguardHide() ||
@@ -247,7 +330,7 @@
             // non-trivial reattaching logic happening that will make the view not-shown earlier
             return true
         }
-        return mediaCarousel.isShown || animator.isRunning
+        return mediaFrame.isShown || animator.isRunning || animationPending
     }
 
     private fun adjustAnimatorForTransition(desiredLocation: Int, previousLocation: Int) {
@@ -279,7 +362,7 @@
             // 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!!)
+            applyState(targetBounds)
         }
     }
 
@@ -291,14 +374,34 @@
             val progress = getTransformationProgress()
             val currentHost = getHost(desiredLocation)!!
             val previousHost = getHost(previousLocation)!!
-            val newState = currentHost.currentState
-            val previousState = previousHost.currentState
-            targetState = previousState.interpolate(newState, progress)
+            val newBounds = currentHost.currentBounds
+            val previousBounds = previousHost.currentBounds
+            targetBounds = interpolateBounds(previousBounds, newBounds, progress)
         } else {
-            targetState = getHost(desiredLocation)?.currentState
+            val bounds = getHost(desiredLocation)?.currentBounds ?: return
+            targetBounds.set(bounds)
         }
     }
 
+    private fun interpolateBounds(
+        startBounds: Rect,
+        endBounds: Rect,
+        progress: Float,
+        result: Rect? = null
+    ): Rect {
+        val left = MathUtils.lerp(startBounds.left.toFloat(),
+                endBounds.left.toFloat(), progress).toInt()
+        val top = MathUtils.lerp(startBounds.top.toFloat(),
+                endBounds.top.toFloat(), progress).toInt()
+        val right = MathUtils.lerp(startBounds.right.toFloat(),
+                endBounds.right.toFloat(), progress).toInt()
+        val bottom = MathUtils.lerp(startBounds.bottom.toFloat(),
+                endBounds.bottom.toFloat(), progress).toInt()
+        val resultBounds = result ?: Rect()
+        resultBounds.set(left, top, right, bottom)
+        return resultBounds
+    }
+
     /**
      * @return true if this transformation is guided by an external progress like a finger
      */
@@ -339,21 +442,27 @@
     private fun cancelAnimationAndApplyDesiredState() {
         animator.cancel()
         getHost(desiredLocation)?.let {
-            applyState(it.currentState)
+            applyState(it.currentBounds, immediately = true)
         }
     }
 
-    private fun applyState(state: MediaState) {
-        currentState = state.copy()
-        mediaViewManager.setCurrentState(currentState)
+    /**
+     * Apply the current state to the view, updating it's bounds and desired state
+     */
+    private fun applyState(bounds: Rect, immediately: Boolean = false) {
+        currentBounds.set(bounds)
+        val currentlyInGuidedTransformation = isCurrentlyInGuidedTransformation()
+        val startLocation = if (currentlyInGuidedTransformation) previousLocation else -1
+        val progress = if (currentlyInGuidedTransformation) getTransformationProgress() else 1.0f
+        val endLocation = desiredLocation
+        mediaViewManager.setCurrentState(startLocation, endLocation, progress, immediately)
         updateHostAttachment()
         if (currentAttachmentLocation == IN_OVERLAY) {
-            val boundsOnScreen = state.boundsOnScreen
-            mediaCarousel.setLeftTopRightBottom(
-                    boundsOnScreen.left,
-                    boundsOnScreen.top,
-                    boundsOnScreen.right,
-                    boundsOnScreen.bottom)
+            mediaFrame.setLeftTopRightBottom(
+                    currentBounds.left,
+                    currentBounds.top,
+                    currentBounds.right,
+                    currentBounds.bottom)
         }
     }
 
@@ -364,26 +473,29 @@
             currentAttachmentLocation = newLocation
 
             // Remove the carousel from the old host
-            (mediaCarousel.parent as ViewGroup?)?.removeView(mediaCarousel)
+            (mediaFrame.parent as ViewGroup?)?.removeView(mediaFrame)
 
             // Add it to the new one
             val targetHost = getHost(desiredLocation)!!.hostView
             if (inOverlay) {
-                rootOverlay!!.add(mediaCarousel)
+                rootOverlay!!.add(mediaFrame)
             } else {
-                targetHost.addView(mediaCarousel)
-                mediaViewManager.onViewReattached()
+                targetHost.addView(mediaFrame)
             }
         }
     }
 
     private fun isTransitionRunning(): Boolean {
         return isCurrentlyInGuidedTransformation() && getTransformationProgress() != 1.0f ||
-                animator.isRunning
+                animator.isRunning || animationPending
     }
 
     @MediaLocation
     private fun calculateLocation(): Int {
+        if (blockLocationChanges) {
+            // Keep the current location until we're allowed to again
+            return desiredLocation
+        }
         val onLockscreen = (!bypassController.bypassEnabled &&
                 (statusbarState == StatusBarState.KEYGUARD ||
                         statusbarState == StatusBarState.FULLSCREEN_USER_SWITCHER))
@@ -396,13 +508,6 @@
         }
     }
 
-    /**
-     * 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
@@ -425,3 +530,8 @@
         const val IN_OVERLAY = -1000
     }
 }
+
+@IntDef(prefix = ["LOCATION_"], value = [MediaHierarchyManager.LOCATION_QS,
+    MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN])
+@Retention(AnnotationRetention.SOURCE)
+annotation class MediaLocation
\ 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
index 240e44c..e904e93 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
@@ -1,20 +1,22 @@
 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 com.android.systemui.util.animation.MeasurementOutput
+import com.android.systemui.util.animation.UniqueObjectHostView
+import java.util.Objects
 import javax.inject.Inject
 
 class MediaHost @Inject constructor(
-    private val state: MediaHostState,
+    private val state: MediaHostStateHolder,
     private val mediaHierarchyManager: MediaHierarchyManager,
-    private val mediaDataManager: MediaDataManager
-) : MediaState by state {
-    lateinit var hostView: ViewGroup
+    private val mediaDataManager: MediaDataManager,
+    private val mediaDataManagerCombineLatest: MediaDataCombineLatest,
+    private val mediaHostStatesManager: MediaHostStatesManager
+) : MediaHostState by state {
+    lateinit var hostView: UniqueObjectHostView
     var location: Int = -1
         private set
     var visibleChangedListener: ((Boolean) -> Unit)? = null
@@ -24,9 +26,9 @@
     private val tmpLocationOnScreen: IntArray = intArrayOf(0, 0)
 
     /**
-     * Get the current Media state. This also updates the location on screen
+     * Get the current bounds on the screen. This makes sure the state is fresh and up to date
      */
-    val currentState: MediaState
+    val currentBounds: Rect = Rect()
         get() {
             hostView.getLocationOnScreen(tmpLocationOnScreen)
             var left = tmpLocationOnScreen[0] + hostView.paddingLeft
@@ -43,8 +45,8 @@
                 bottom = 0
                 top = 0
             }
-            state.boundsOnScreen.set(left, top, right, bottom)
-            return state
+            field.set(left, top, right, bottom)
+            return field
         }
 
     private val listener = object : MediaDataManager.Listener {
@@ -59,6 +61,8 @@
 
     /**
      * Initialize this MediaObject and create a host view.
+     * All state should already be set on this host before calling this method in order to avoid
+     * unnecessary state changes which lead to remeasurings later on.
      *
      * @param location the location this host name has. Used to identify the host during
      *                 transitions.
@@ -68,14 +72,39 @@
         hostView = mediaHierarchyManager.register(this)
         hostView.addOnAttachStateChangeListener(object : OnAttachStateChangeListener {
             override fun onViewAttachedToWindow(v: View?) {
-                mediaDataManager.addListener(listener)
+                // we should listen to the combined state change, since otherwise there might
+                // be a delay until the views and the controllers are initialized, leaving us
+                // with either a blank view or the controllers not yet initialized and the
+                // measuring wrong
+                mediaDataManagerCombineLatest.addListener(listener)
                 updateViewVisibility()
             }
 
             override fun onViewDetachedFromWindow(v: View?) {
-                mediaDataManager.removeListener(listener)
+                mediaDataManagerCombineLatest.removeListener(listener)
             }
         })
+
+        // Listen to measurement updates and update our state with it
+        hostView.measurementManager = object : UniqueObjectHostView.MeasurementManager {
+            override fun onMeasure(input: MeasurementInput): MeasurementOutput {
+                // Modify the measurement to exactly match the dimensions
+                if (View.MeasureSpec.getMode(input.widthMeasureSpec) == View.MeasureSpec.AT_MOST) {
+                    input.widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(
+                            View.MeasureSpec.getSize(input.widthMeasureSpec),
+                            View.MeasureSpec.EXACTLY)
+                }
+                // This will trigger a state change that ensures that we now have a state available
+                state.measurementInput = input
+                return mediaHostStatesManager.getPlayerDimensions(state)
+            }
+        }
+
+        // Whenever the state changes, let our state manager know
+        state.changedListener = {
+            mediaHostStatesManager.updateHostState(location, state)
+        }
+
         updateViewVisibility()
     }
 
@@ -89,71 +118,93 @@
         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()
+    class MediaHostStateHolder @Inject constructor() : MediaHostState {
 
-        override fun copy(): MediaState {
-            val mediaHostState = MediaHostState()
+        override var measurementInput: MeasurementInput? = null
+            set(value) {
+                if (value?.equals(field) != true) {
+                    field = value
+                    changedListener?.invoke()
+                }
+            }
+
+        override var expansion: Float = 0.0f
+            set(value) {
+                if (!value.equals(field)) {
+                    field = value
+                    changedListener?.invoke()
+                }
+            }
+
+        override var showsOnlyActiveMedia: Boolean = false
+            set(value) {
+                if (!value.equals(field)) {
+                    field = value
+                    changedListener?.invoke()
+                }
+            }
+
+        /**
+         * A listener for all changes. This won't be copied over when invoking [copy]
+         */
+        var changedListener: (() -> Unit)? = null
+
+        /**
+         * Get a copy of this state. This won't copy any listeners it may have set
+         */
+        override fun copy(): MediaHostState {
+            val mediaHostState = MediaHostStateHolder()
             mediaHostState.expansion = expansion
             mediaHostState.showsOnlyActiveMedia = showsOnlyActiveMedia
-            mediaHostState.boundsOnScreen.set(boundsOnScreen)
-            mediaHostState.measurementInput = measurementInput
+            mediaHostState.measurementInput = measurementInput?.copy()
             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
+        override fun equals(other: Any?): Boolean {
+            if (!(other is MediaHostState)) {
+                return false
             }
+            if (!Objects.equals(measurementInput, other.measurementInput)) {
+                return false
+            }
+            if (expansion != other.expansion) {
+                return false
+            }
+            if (showsOnlyActiveMedia != other.showsOnlyActiveMedia) {
+                return false
+            }
+            return true
+        }
+
+        override fun hashCode(): Int {
+            var result = measurementInput?.hashCode() ?: 0
+            result = 31 * result + expansion.hashCode()
+            result = 31 * result + showsOnlyActiveMedia.hashCode()
             return result
         }
-
-        override fun getMeasuringInput(input: MeasurementInput): MediaMeasurementInput {
-            measurementInput = MediaMeasurementInput(input, expansion)
-            return measurementInput as MediaMeasurementInput
-        }
     }
 }
 
-interface MediaState {
+interface MediaHostState {
+
+    /**
+     * The last measurement input that this state was measured with. Infers with and height of
+     * the players.
+     */
+    var measurementInput: MeasurementInput?
+
+    /**
+     * The expansion of the player, 0 for fully collapsed, 1 for fully expanded
+     */
     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
-    }
+    /**
+     * Is this host only showing active media or is it showing all of them including resumption?
+     */
+    var showsOnlyActiveMedia: Boolean
+
+    /**
+     * Get a copy of this view state, deepcopying all appropriate members
+     */
+    fun copy(): MediaHostState
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHostStatesManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHostStatesManager.kt
new file mode 100644
index 0000000..f90af2a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHostStatesManager.kt
@@ -0,0 +1,116 @@
+/*
+ * 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.MeasurementOutput
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * A class responsible for managing all media host states of the various host locations and
+ * coordinating the heights among different players. This class can be used to get the most up to
+ * date state for any location.
+ */
+@Singleton
+class MediaHostStatesManager @Inject constructor() {
+
+    private val callbacks: MutableSet<Callback> = mutableSetOf()
+    private val controllers: MutableSet<MediaViewController> = mutableSetOf()
+
+    /**
+     * A map with all media states of all locations.
+     */
+    val mediaHostStates: MutableMap<Int, MediaHostState> = mutableMapOf()
+
+    /**
+     * Notify that a media state for a given location has changed. Should only be called from
+     * Media hosts themselves.
+     */
+    fun updateHostState(@MediaLocation location: Int, hostState: MediaHostState) {
+        val currentState = mediaHostStates.get(location)
+        if (!hostState.equals(currentState)) {
+            val newState = hostState.copy()
+            mediaHostStates.put(location, newState)
+            // First update all the controllers to ensure they get the chance to measure
+            for (controller in controllers) {
+                controller.stateCallback.onHostStateChanged(location, newState)
+            }
+
+            // Then update all other callbacks which may depend on the controllers above
+            for (callback in callbacks) {
+                callback.onHostStateChanged(location, newState)
+            }
+        }
+    }
+
+    /**
+     * Get the dimensions of all players combined, which determines the overall height of the
+     * media carousel and the media hosts.
+     */
+    fun getPlayerDimensions(hostState: MediaHostState): MeasurementOutput {
+        val result = MeasurementOutput(0, 0)
+        for (controller in controllers) {
+            val measurement = controller.getMeasurementsForState(hostState)
+            measurement?.let {
+                if (it.measuredHeight > result.measuredHeight) {
+                    result.measuredHeight = it.measuredHeight
+                }
+                if (it.measuredWidth > result.measuredWidth) {
+                    result.measuredWidth = it.measuredWidth
+                }
+            }
+        }
+        return result
+    }
+
+    /**
+     * Add a callback to be called when a MediaState has updated
+     */
+    fun addCallback(callback: Callback) {
+        callbacks.add(callback)
+    }
+
+    /**
+     * Remove a callback that listens to media states
+     */
+    fun removeCallback(callback: Callback) {
+        callbacks.remove(callback)
+    }
+
+    /**
+     * Register a controller that listens to media states and is used to determine the size of
+     * the media carousel
+     */
+    fun addController(controller: MediaViewController) {
+        controllers.add(controller)
+    }
+
+    /**
+     * Notify the manager about the removal of a controller.
+     */
+    fun removeController(controller: MediaViewController) {
+        controllers.remove(controller)
+    }
+
+    interface Callback {
+        /**
+         * Notify the callbacks that a media state for a host has changed, and that the
+         * corresponding view states should be updated and applied
+         */
+        fun onHostStateChanged(@MediaLocation location: Int, mediaHostState: MediaHostState)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaMeasurementManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaMeasurementManager.kt
deleted file mode 100644
index 4bbf5eb..0000000
--- a/packages/SystemUI/src/com/android/systemui/media/MediaMeasurementManager.kt
+++ /dev/null
@@ -1,59 +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.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/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
new file mode 100644
index 0000000..e82bb40
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
@@ -0,0 +1,280 @@
+/*
+ * 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 androidx.constraintlayout.widget.ConstraintSet
+import com.android.systemui.R
+import com.android.systemui.util.animation.TransitionLayout
+import com.android.systemui.util.animation.TransitionLayoutController
+import com.android.systemui.util.animation.TransitionViewState
+import com.android.systemui.util.animation.MeasurementOutput
+
+/**
+ * A class responsible for controlling a single instance of a media player handling interactions
+ * with the view instance and keeping the media view states up to date.
+ */
+class MediaViewController(
+    context: Context,
+    val mediaHostStatesManager: MediaHostStatesManager
+) {
+
+    private var firstRefresh: Boolean = true
+    private var transitionLayout: TransitionLayout? = null
+    private val layoutController = TransitionLayoutController()
+    private var animationDelay: Long = 0
+    private var animationDuration: Long = 0
+    private var animateNextStateChange: Boolean = false
+    private val measurement = MeasurementOutput(0, 0)
+
+    /**
+     * A map containing all viewStates for all locations of this mediaState
+     */
+    private val mViewStates: MutableMap<MediaHostState, TransitionViewState?> = mutableMapOf()
+
+    /**
+     * The ending location of the view where it ends when all animations and transitions have
+     * finished
+     */
+    private var currentEndLocation: Int = -1
+
+    /**
+     * The ending location of the view where it ends when all animations and transitions have
+     * finished
+     */
+    private var currentStartLocation: Int = -1
+
+    /**
+     * The progress of the transition or 1.0 if there is no transition happening
+     */
+    private var currentTransitionProgress: Float = 1.0f
+
+    /**
+     * A temporary state used to store intermediate measurements.
+     */
+    private val tmpState = TransitionViewState()
+
+    /**
+     * A callback for media state changes
+     */
+    val stateCallback = object : MediaHostStatesManager.Callback {
+        override fun onHostStateChanged(location: Int, mediaHostState: MediaHostState) {
+            if (location == currentEndLocation || location == currentStartLocation) {
+                setCurrentState(currentStartLocation,
+                        currentEndLocation,
+                        currentTransitionProgress,
+                        applyImmediately = false)
+            }
+        }
+    }
+
+    /**
+     * The expanded constraint set used to render a expanded player. If it is modified, make sure
+     * to call [refreshState]
+     */
+    val collapsedLayout = ConstraintSet()
+
+    /**
+     * The expanded constraint set used to render a collapsed player. If it is modified, make sure
+     * to call [refreshState]
+     */
+    val expandedLayout = ConstraintSet()
+
+    init {
+        collapsedLayout.load(context, R.xml.media_collapsed)
+        expandedLayout.load(context, R.xml.media_expanded)
+        mediaHostStatesManager.addController(this)
+    }
+
+    /**
+     * Notify this controller that the view has been removed and all listeners should be destroyed
+     */
+    fun onDestroy() {
+        mediaHostStatesManager.removeController(this)
+    }
+
+    private fun ensureAllMeasurements() {
+        val mediaStates = mediaHostStatesManager.mediaHostStates
+        for (entry in mediaStates) {
+            obtainViewState(entry.value)
+        }
+    }
+
+    /**
+     * Get the constraintSet for a given expansion
+     */
+    private fun constraintSetForExpansion(expansion: Float): ConstraintSet =
+            if (expansion > 0) expandedLayout else collapsedLayout
+
+    /**
+     * Obtain a new viewState for a given media state. This usually returns a cached state, but if
+     * it's not available, it will recreate one by measuring, which may be expensive.
+     */
+    private fun obtainViewState(state: MediaHostState): TransitionViewState? {
+        val viewState = mViewStates[state]
+        if (viewState != null) {
+            // we already have cached this measurement, let's continue
+            return viewState
+        }
+
+        val result: TransitionViewState?
+        if (transitionLayout != null && state.measurementInput != null) {
+            // Let's create a new measurement
+            if (state.expansion == 0.0f || state.expansion == 1.0f) {
+                result = transitionLayout!!.calculateViewState(
+                        state.measurementInput!!,
+                        constraintSetForExpansion(state.expansion),
+                        TransitionViewState())
+
+                // We don't want to cache interpolated or null states as this could quickly fill up
+                // our cache. We only cache the start and the end states since the interpolation
+                // is cheap
+                mViewStates[state.copy()] = result
+            } else {
+                // This is an interpolated state
+                val startState = state.copy().also { it.expansion = 0.0f }
+
+                // Given that we have a measurement and a view, let's get (guaranteed) viewstates
+                // from the start and end state and interpolate them
+                val startViewState = obtainViewState(startState) as TransitionViewState
+                val endState = state.copy().also { it.expansion = 1.0f }
+                val endViewState = obtainViewState(endState) as TransitionViewState
+                result = TransitionViewState()
+                layoutController.getInterpolatedState(
+                        startViewState,
+                        endViewState,
+                        state.expansion,
+                        result)
+            }
+        } else {
+            result = null
+        }
+        return result
+    }
+
+    /**
+     * Attach a view to this controller. This may perform measurements if it's not available yet
+     * and should therefore be done carefully.
+     */
+    fun attach(transitionLayout: TransitionLayout) {
+        this.transitionLayout = transitionLayout
+        layoutController.attach(transitionLayout)
+        ensureAllMeasurements()
+        if (currentEndLocation == -1) {
+            return
+        }
+        // Set the previously set state immediately to the view, now that it's finally attached
+        setCurrentState(
+                startLocation = currentStartLocation,
+                endLocation = currentEndLocation,
+                transitionProgress = currentTransitionProgress,
+                applyImmediately = true)
+    }
+
+    /**
+     * Obtain a measurement for a given location. This makes sure that the state is up to date
+     * and all widgets know their location. Calling this method may create a measurement if we
+     * don't have a cached value available already.
+     */
+    fun getMeasurementsForState(hostState: MediaHostState): MeasurementOutput? {
+        val viewState = obtainViewState(hostState) ?: return null
+        measurement.measuredWidth = viewState.width
+        measurement.measuredHeight = viewState.height
+        return measurement
+    }
+
+    /**
+     * Set a new state for the controlled view which can be an interpolation between multiple
+     * locations.
+     */
+    fun setCurrentState(
+        @MediaLocation startLocation: Int,
+        @MediaLocation endLocation: Int,
+        transitionProgress: Float,
+        applyImmediately: Boolean
+    ) {
+        currentEndLocation = endLocation
+        currentStartLocation = startLocation
+        currentTransitionProgress = transitionProgress
+
+        val shouldAnimate = animateNextStateChange && !applyImmediately
+
+        // Obtain the view state that we'd want to be at the end
+        // The view might not be bound yet or has never been measured and in that case will be
+        // reset once the state is fully available
+        val endState = obtainViewStateForLocation(endLocation) ?: return
+        layoutController.setMeasureState(endState)
+
+        // If the view isn't bound, we can drop the animation, otherwise we'll executute it
+        animateNextStateChange = false
+        if (transitionLayout == null) {
+            return
+        }
+
+        val startState = obtainViewStateForLocation(startLocation)
+        val result: TransitionViewState?
+        if (transitionProgress == 1.0f || startState == null) {
+            result = endState
+        } else if (transitionProgress == 0.0f) {
+            result = startState
+        } else {
+            layoutController.getInterpolatedState(startState, endState, transitionProgress,
+                    tmpState)
+            result = tmpState
+        }
+        layoutController.setState(result, applyImmediately, shouldAnimate, animationDuration,
+                animationDelay)
+    }
+
+    private fun obtainViewStateForLocation(location: Int): TransitionViewState? {
+        val mediaState = mediaHostStatesManager.mediaHostStates[location] ?: return null
+        return obtainViewState(mediaState)
+    }
+
+    /**
+     * Notify that the location is changing right now and a [setCurrentState] change is imminent.
+     * This updates the width the view will me measured with.
+     */
+    fun onLocationPreChange(@MediaLocation newLocation: Int) {
+        val viewState = obtainViewStateForLocation(newLocation)
+        viewState?.let {
+            layoutController.setMeasureState(it)
+        }
+    }
+
+    /**
+     * Request that the next state change should be animated with the given parameters.
+     */
+    fun animatePendingStateChange(duration: Long, delay: Long) {
+        animateNextStateChange = true
+        animationDuration = duration
+        animationDelay = delay
+    }
+
+    /**
+     * Clear all existing measurements and refresh the state to match the view.
+     */
+    fun refreshState() {
+        if (!firstRefresh) {
+            // Let's clear all of our measurements and recreate them!
+            mViewStates.clear()
+            setCurrentState(currentStartLocation, currentEndLocation, currentTransitionProgress,
+                    applyImmediately = false)
+        }
+        firstRefresh = false
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt
index 16302d1..8ab30c7 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt
@@ -16,8 +16,8 @@
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.qs.PageIndicator
 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.animation.requiresRemeasuring
 import com.android.systemui.util.concurrency.DelayableExecutor
 import java.util.concurrent.Executor
 import javax.inject.Inject
@@ -36,16 +36,51 @@
     @Background private val backgroundExecutor: DelayableExecutor,
     private val visualStabilityManager: VisualStabilityManager,
     private val activityStarter: ActivityStarter,
+    private val mediaHostStatesManager: MediaHostStatesManager,
     mediaManager: MediaDataCombineLatest
 ) {
-    private var playerWidth: Int = 0
+
+    /**
+     * The desired location where we'll be at the end of the transformation. Usually this matches
+     * the end location, except when we're still waiting on a state update call.
+     */
+    @MediaLocation
+    private var desiredLocation: Int = -1
+
+    /**
+     * The ending location of the view where it ends when all animations and transitions have
+     * finished
+     */
+    @MediaLocation
+    private var currentEndLocation: Int = -1
+
+    /**
+     * The ending location of the view where it ends when all animations and transitions have
+     * finished
+     */
+    @MediaLocation
+    private var currentStartLocation: Int = -1
+
+    /**
+     * The progress of the transition or 1.0 if there is no transition happening
+     */
+    private var currentTransitionProgress: Float = 1.0f
+
+    /**
+     * The measured width of the carousel
+     */
+    private var carouselMeasureWidth: Int = 0
+
+    /**
+     * The measured height of the carousel
+     */
+    private var carouselMeasureHeight: Int = 0
     private var playerWidthPlusPadding: Int = 0
-    private var desiredState: MediaHost.MediaHostState? = null
-    private var currentState: MediaState? = null
+    private var desiredHostState: MediaHostState? = null
     private val mediaCarousel: HorizontalScrollView
     val mediaFrame: ViewGroup
+    val mediaPlayers: MutableMap<String, MediaControlPanel> = mutableMapOf()
     private val mediaContent: ViewGroup
-    private val mediaPlayers: MutableMap<String, MediaControlPanel> = mutableMapOf()
     private val pageIndicator: PageIndicator
     private val gestureDetector: GestureDetectorCompat
     private val visualStabilityCallback: VisualStabilityManager.Callback
@@ -115,6 +150,7 @@
             override fun onMediaDataLoaded(key: String, data: MediaData) {
                 updateView(key, data)
                 updatePlayerVisibilities()
+                mediaCarousel.requiresRemeasuring = true
             }
 
             override fun onMediaDataRemoved(key: String) {
@@ -137,6 +173,13 @@
                 }
             }
         })
+        mediaHostStatesManager.addCallback(object : MediaHostStatesManager.Callback {
+            override fun onHostStateChanged(location: Int, mediaHostState: MediaHostState) {
+                if (location == desiredLocation) {
+                    onDesiredLocationChanged(desiredLocation, mediaHostState, animate = false)
+                }
+            }
+        })
     }
 
     private fun inflateMediaCarousel(): ViewGroup {
@@ -220,7 +263,7 @@
         var existingPlayer = mediaPlayers[key]
         if (existingPlayer == null) {
             existingPlayer = MediaControlPanel(context, foregroundExecutor, backgroundExecutor,
-                    activityStarter)
+                    activityStarter, mediaHostStatesManager)
             existingPlayer.attach(PlayerViewHolder.create(LayoutInflater.from(context),
                     mediaContent))
             mediaPlayers[key] = existingPlayer
@@ -228,14 +271,14 @@
                     ViewGroup.LayoutParams.WRAP_CONTENT)
             existingPlayer.view?.player?.setLayoutParams(lp)
             existingPlayer.setListening(currentlyExpanded)
+            updatePlayerToState(existingPlayer, noAnimation = true)
             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) {
+                mediaContent.indexOfChild(existingPlayer.view?.player) != 0) {
             if (visualStabilityManager.isReorderingAllowed) {
                 mediaContent.removeView(existingPlayer.view?.player)
                 mediaContent.addView(existingPlayer.view?.player, 0)
@@ -244,20 +287,10 @@
             }
         }
         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()
         updatePageIndicator()
     }
 
-    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
@@ -281,117 +314,101 @@
     }
 
     /**
-     * Set the current state of a view. This is updated often during animations and we shouldn't
-     * do anything expensive.
+     * Set a new interpolated state for all players. This is a state that is usually controlled
+     * by a finger movement where the user drags from one state to the next.
      */
-    fun setCurrentState(state: MediaState) {
-        currentState = state
-        currentlyExpanded = state.expansion > 0
+    fun setCurrentState(
+        @MediaLocation startLocation: Int,
+        @MediaLocation endLocation: Int,
+        progress: Float,
+        immediately: Boolean
+    ) {
         // Hack: Since the indicator doesn't move with the player expansion, just make it disappear
         // and then reappear at the end.
-        pageIndicator.alpha = if (state.expansion == 1f || state.expansion == 0f) 1f else 0f
-        for (mediaPlayer in mediaPlayers.values) {
-            val view = mediaPlayer.view?.player
-            view?.progress = state.expansion
+        pageIndicator.alpha = if (progress == 1f || progress == 0f) 1f else 0f
+        if (startLocation != currentStartLocation ||
+                endLocation != currentEndLocation ||
+                progress != currentTransitionProgress ||
+                immediately
+        ) {
+            currentStartLocation = startLocation
+            currentEndLocation = endLocation
+            currentTransitionProgress = progress
+            for (mediaPlayer in mediaPlayers.values) {
+                updatePlayerToState(mediaPlayer, immediately)
+            }
         }
     }
 
+    private fun updatePlayerToState(mediaPlayer: MediaControlPanel, noAnimation: Boolean) {
+        mediaPlayer.mediaViewController.setCurrentState(
+                startLocation = currentStartLocation,
+                endLocation = currentEndLocation,
+                transitionProgress = currentTransitionProgress,
+                applyImmediately = noAnimation)
+    }
+
     /**
      * 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 desiredLocation the location we're going to
+     * @param desiredHostState the target state we're transitioning to
      * @param animate should this be animated
      */
     fun onDesiredLocationChanged(
-        desiredState: MediaState?,
+        desiredLocation: Int,
+        desiredHostState: MediaHostState?,
         animate: Boolean,
-        duration: Long,
-        startDelay: Long
+        duration: Long = 200,
+        startDelay: Long = 0
     ) {
-        if (desiredState is MediaHost.MediaHostState) {
+        desiredHostState?.let {
             // 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)
+            this.desiredLocation = desiredLocation
+            this.desiredHostState = it
+            currentlyExpanded = it.expansion > 0
             for (mediaPlayer in mediaPlayers.values) {
-                mediaPlayer.setPlayerWidth(width)
+                if (animate) {
+                    mediaPlayer.mediaViewController.animatePendingStateChange(
+                            duration = duration,
+                            delay = startDelay)
+                }
+                mediaPlayer.mediaViewController.onLocationPreChange(desiredLocation)
             }
-            // 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
+            updateCarouselSize()
         }
     }
 
     /**
-     * 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
+     * Update the size of the carousel, remeasuring it if necessary.
      */
-    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)
+    private fun updateCarouselSize() {
+        val width = desiredHostState?.measurementInput?.width ?: 0
+        val height = desiredHostState?.measurementInput?.height ?: 0
+        if (width != carouselMeasureWidth && width != 0 ||
+                height != carouselMeasureWidth && height != 0) {
+            carouselMeasureWidth = width
+            carouselMeasureHeight = height
+            playerWidthPlusPadding = carouselMeasureWidth + context.resources.getDimensionPixelSize(
+                    R.dimen.qs_media_padding)
+            // 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
             }
-        }
-        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)
-            }
+            mediaCarousel.scrollX = newScroll
+            // Let's remeasure the carousel
+            val widthSpec = desiredHostState?.measurementInput?.widthMeasureSpec ?: 0
+            val heightSpec = desiredHostState?.measurementInput?.heightMeasureSpec ?: 0
+            mediaCarousel.measure(widthSpec, heightSpec)
+            mediaCarousel.layout(0, 0, width, mediaCarousel.measuredHeight)
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
index 764dbe6..60c576b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
@@ -23,18 +23,15 @@
 import android.widget.ImageView
 import android.widget.SeekBar
 import android.widget.TextView
-
-import androidx.constraintlayout.motion.widget.MotionLayout
-
 import com.android.systemui.R
+import com.android.systemui.util.animation.TransitionLayout
 
 /**
  * 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)
+    val player = itemView as TransitionLayout
 
     // Player information
     val appIcon = itemView.requireViewById<ImageView>(R.id.icon)
@@ -61,7 +58,7 @@
     val action4 = itemView.requireViewById<ImageButton>(R.id.action4)
 
     init {
-        (background.background as IlluminationDrawable).let {
+        (player.background as IlluminationDrawable).let {
             it.setupTouch(seamless, player)
             it.setupTouch(action0, player)
             it.setupTouch(action1, player)
@@ -95,7 +92,7 @@
          * @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)
+            val v = inflater.inflate(R.layout.media_view, parent, false)
             return PlayerViewHolder(v)
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
index b9b8a25..a10972e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -36,10 +36,11 @@
 import android.util.TypedValue;
 import android.view.DisplayInfo;
 import android.view.Gravity;
-import android.view.IWindowManager;
-import android.view.WindowManagerGlobal;
 import android.window.WindowContainerTransaction;
 
+import com.android.systemui.wm.DisplayController;
+import com.android.systemui.wm.DisplayLayout;
+
 import java.io.PrintWriter;
 
 import javax.inject.Inject;
@@ -56,10 +57,10 @@
     private static final float INVALID_SNAP_FRACTION = -1f;
 
     private final Context mContext;
-    private final IWindowManager mWindowManager;
     private final PipSnapAlgorithm mSnapAlgorithm;
     private final DisplayInfo mDisplayInfo = new DisplayInfo();
-    private final Rect mTmpInsets = new Rect();
+    private final DisplayController mDisplayController;
+    private final DisplayLayout mDisplayLayout;
 
     private ComponentName mLastPipComponentName;
     private float mReentrySnapFraction = INVALID_SNAP_FRACTION;
@@ -80,11 +81,24 @@
     private boolean mIsShelfShowing;
     private int mShelfHeight;
 
+    private final DisplayController.OnDisplaysChangedListener mDisplaysChangedListener =
+            new DisplayController.OnDisplaysChangedListener() {
+        @Override
+        public void onDisplayAdded(int displayId) {
+            if (displayId == mContext.getDisplayId()) {
+                mDisplayLayout.set(mDisplayController.getDisplayLayout(displayId));
+            }
+        }
+    };
+
     @Inject
-    public PipBoundsHandler(Context context, PipSnapAlgorithm pipSnapAlgorithm) {
+    public PipBoundsHandler(Context context, PipSnapAlgorithm pipSnapAlgorithm,
+            DisplayController displayController) {
         mContext = context;
         mSnapAlgorithm = pipSnapAlgorithm;
-        mWindowManager = WindowManagerGlobal.getWindowManagerService();
+        mDisplayLayout = new DisplayLayout();
+        mDisplayController = displayController;
+        mDisplayController.addDisplayWindowListener(mDisplaysChangedListener);
         reloadResources();
         // Initialize the aspect ratio to the default aspect ratio.  Don't do this in reload
         // resources as it would clobber mAspectRatio when entering PiP from fullscreen which
@@ -272,8 +286,8 @@
      *
      * @return {@code true} if internal {@link DisplayInfo} is rotated, {@code false} otherwise.
      */
-    public boolean onDisplayRotationChanged(Rect outBounds, Rect oldBounds, int displayId,
-            int fromRotation, int toRotation, WindowContainerTransaction t) {
+    public boolean onDisplayRotationChanged(Rect outBounds, Rect oldBounds, Rect outInsetBounds,
+            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;
@@ -294,6 +308,9 @@
         final Rect postChangeStackBounds = new Rect(oldBounds);
         final float snapFraction = getSnapFraction(postChangeStackBounds);
 
+        // Update the display layout
+        mDisplayLayout.rotateTo(mContext.getResources(), toRotation);
+
         // Populate the new {@link #mDisplayInfo}.
         // The {@link DisplayInfo} queried from DisplayManager would be the one before rotation,
         // therefore, the width/height may require a swap first.
@@ -308,6 +325,7 @@
         mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
                 snapFraction);
 
+        getInsetBounds(outInsetBounds);
         outBounds.set(postChangeStackBounds);
         t.setBounds(pinnedStackInfo.stackToken, outBounds);
         return true;
@@ -425,15 +443,11 @@
      * Populates the bounds on the screen that the PIP can be visible in.
      */
     protected void getInsetBounds(Rect outRect) {
-        try {
-            mWindowManager.getStableInsets(mContext.getDisplayId(), mTmpInsets);
-            outRect.set(mTmpInsets.left + mScreenEdgeInsets.x,
-                    mTmpInsets.top + mScreenEdgeInsets.y,
-                    mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x,
-                    mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to get stable insets from WM", e);
-        }
+        Rect insets = mDisplayLayout.stableInsets();
+        outRect.set(insets.left + mScreenEdgeInsets.x,
+                insets.top + mScreenEdgeInsets.y,
+                mDisplayInfo.logicalWidth - insets.right - mScreenEdgeInsets.x,
+                mDisplayInfo.logicalHeight - insets.bottom - mScreenEdgeInsets.y);
     }
 
     /**
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 64df2ff..02bf745 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -95,8 +95,21 @@
     private final DisplayChangeController.OnDisplayChangingListener mRotationController = (
             int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> {
         final boolean changed = mPipBoundsHandler.onDisplayRotationChanged(mTmpNormalBounds,
-                mPipTaskOrganizer.getLastReportedBounds(), displayId, fromRotation, toRotation, t);
+                mPipTaskOrganizer.getLastReportedBounds(), mTmpInsetBounds, displayId, fromRotation,
+                toRotation, t);
         if (changed) {
+            // If the pip was in the offset zone earlier, adjust the new bounds to the bottom of the
+            // movement bounds
+            mTouchHandler.adjustBoundsForRotation(mTmpNormalBounds,
+                    mPipTaskOrganizer.getLastReportedBounds(), mTmpInsetBounds);
+
+            // The bounds are being applied to a specific snap fraction, so reset any known offsets
+            // for the previous orientation before updating the movement bounds
+            mPipBoundsHandler.setShelfHeight(false , 0);
+            mPipBoundsHandler.onImeVisibilityChanged(false, 0);
+            mTouchHandler.onShelfVisibilityChanged(false, 0);
+            mTouchHandler.onImeVisibilityChanged(false, 0);
+
             updateMovementBounds(mTmpNormalBounds, true /* fromRotation */,
                     false /* fromImeAdjustment */, false /* fromShelfAdjustment */);
         }
@@ -290,9 +303,10 @@
     @Override
     public void setShelfHeight(boolean visible, int height) {
         mHandler.post(() -> {
-            final boolean changed = mPipBoundsHandler.setShelfHeight(visible, height);
+            final int shelfHeight = visible ? height : 0;
+            final boolean changed = mPipBoundsHandler.setShelfHeight(visible, shelfHeight);
             if (changed) {
-                mTouchHandler.onShelfVisibilityChanged(visible, height);
+                mTouchHandler.onShelfVisibilityChanged(visible, shelfHeight);
                 updateMovementBounds(mPipTaskOrganizer.getLastReportedBounds(),
                         false /* fromRotation */, false /* fromImeAdjustment */,
                         true /* fromShelfAdjustment */);
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 3396f70..a3185a2 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -99,6 +99,7 @@
     public static final int MESSAGE_ANIMATION_ENDED = 6;
     public static final int MESSAGE_POINTER_EVENT = 7;
     public static final int MESSAGE_MENU_EXPANDED = 8;
+    public static final int MESSAGE_FADE_OUT_MENU = 9;
 
     private static final int INITIAL_DISMISS_DELAY = 3500;
     private static final int POST_INTERACTION_DISMISS_DELAY = 2000;
@@ -182,6 +183,10 @@
                     mMenuContainerAnimator.start();
                     break;
                 }
+                case MESSAGE_FADE_OUT_MENU: {
+                    fadeOutMenu();
+                    break;
+                }
             }
         }
     };
@@ -409,6 +414,18 @@
         }
     }
 
+    /**
+     * Different from {@link #hideMenu()}, this function does not try to finish this menu activity
+     * and instead, it fades out the controls by setting the alpha to 0 directly without menu
+     * visibility callbacks invoked.
+     */
+    private void fadeOutMenu() {
+        mMenuContainer.setAlpha(0f);
+        mSettingsButton.setAlpha(0f);
+        mDismissButton.setAlpha(0f);
+        mResizeHandle.setAlpha(0f);
+    }
+
     private void hideMenu() {
         hideMenu(null);
     }
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 bf2c3e9..8b4d932 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -262,6 +262,9 @@
      */
     public void showMenuWithDelay(int menuState, Rect stackBounds, boolean allowMenuTimeout,
             boolean willResizeMenu, boolean showResizeHandle) {
+        // hide all visible controls including close button and etc. first, this is to ensure
+        // menu is totally invisible during the transition to eliminate unpleasant artifacts
+        fadeOutMenu();
         showMenuInternal(menuState, stackBounds, allowMenuTimeout, willResizeMenu,
                 true /* withDelay */, showResizeHandle);
     }
@@ -347,6 +350,23 @@
         }
     }
 
+    private void fadeOutMenu() {
+        if (DEBUG) {
+            Log.d(TAG, "fadeOutMenu() state=" + mMenuState
+                    + " hasActivity=" + (mToActivityMessenger != null)
+                    + " callers=\n" + Debug.getCallers(5, "    "));
+        }
+        if (mToActivityMessenger != null) {
+            Message m = Message.obtain();
+            m.what = PipMenuActivity.MESSAGE_FADE_OUT_MENU;
+            try {
+                mToActivityMessenger.send(m);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Could not notify menu to fade out", e);
+            }
+        }
+    }
+
     /**
      * Hides the menu activity.
      */
@@ -513,7 +533,8 @@
     private void onMenuStateChanged(int menuState, boolean resize, Runnable callback) {
         if (DEBUG) {
             Log.d(TAG, "onMenuStateChanged() mMenuState=" + mMenuState
-                    + " menuState=" + menuState + " resize=" + resize);
+                    + " menuState=" + menuState + " resize=" + resize
+                    + " callers=\n" + Debug.getCallers(5, "    "));
         }
 
         if (menuState != mMenuState) {
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 cc3ab29d..4b23e67 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
@@ -37,6 +37,7 @@
 import android.view.InputEventReceiver;
 import android.view.InputMonitor;
 import android.view.MotionEvent;
+import android.view.ViewConfiguration;
 
 import com.android.internal.policy.TaskResizingAlgorithm;
 import com.android.systemui.R;
@@ -77,10 +78,12 @@
     private final Runnable mUpdateMovementBoundsRunnable;
 
     private int mDelta;
+    private float mTouchSlop;
     private boolean mAllowGesture;
     private boolean mIsAttached;
     private boolean mIsEnabled;
     private boolean mEnableUserResize;
+    private boolean mThresholdCrossed;
 
     private InputMonitor mInputMonitor;
     private InputEventReceiver mInputEventReceiver;
@@ -100,6 +103,7 @@
         mPipTaskOrganizer = pipTaskOrganizer;
         mMovementBoundsSupplier = movementBoundsSupplier;
         mUpdateMovementBoundsRunnable = updateMovementBoundsRunnable;
+
         context.getDisplay().getRealSize(mMaxSize);
         reloadResources();
 
@@ -126,6 +130,7 @@
     private void reloadResources() {
         final Resources res = mContext.getResources();
         mDelta = res.getDimensionPixelSize(R.dimen.pip_resize_edge_size);
+        mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
     }
 
     private void resetDragCorners() {
@@ -270,7 +275,12 @@
                     break;
                 case MotionEvent.ACTION_MOVE:
                     // Capture inputs
-                    mInputMonitor.pilferPointers();
+                    float dx = Math.abs(ev.getX() - mDownPoint.x);
+                    float dy = Math.abs(ev.getY() - mDownPoint.y);
+                    if (!mThresholdCrossed && dx > mTouchSlop && dy > mTouchSlop) {
+                        mThresholdCrossed = true;
+                        mInputMonitor.pilferPointers();
+                    }
                     final Rect currentPipBounds = mMotionHelper.getBounds();
                     mLastResizeBounds.set(TaskResizingAlgorithm.resizeDrag(ev.getX(), ev.getY(),
                             mDownPoint.x, mDownPoint.y, currentPipBounds, mCtrlType, mMinSize.x,
@@ -288,6 +298,7 @@
                             mUpdateMovementBoundsRunnable.run();
                             mCtrlType = CTRL_NONE;
                             mAllowGesture = false;
+                            mThresholdCrossed = 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 c408caa..c274ee9 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -397,6 +397,15 @@
         mShelfHeight = shelfHeight;
     }
 
+    public void adjustBoundsForRotation(Rect outBounds, Rect curBounds, Rect insetBounds) {
+        final Rect toMovementBounds = new Rect();
+        mSnapAlgorithm.getMovementBounds(outBounds, insetBounds, toMovementBounds, 0);
+        final int prevBottom = mMovementBounds.bottom - mMovementBoundsExtraOffsets;
+        if ((prevBottom - mBottomOffsetBufferPx) <= curBounds.top) {
+            outBounds.offsetTo(outBounds.left, toMovementBounds.bottom);
+        }
+    }
+
     public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect curBounds,
             boolean fromImeAdjustment, boolean fromShelfAdjustment, int displayRotation) {
         final int bottomOffset = mIsImeShowing ? mImeHeight : 0;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index b877e87..6af9e1e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -94,6 +94,8 @@
     private int mState;
     private QSContainerImplController mQSContainerImplController;
     private int[] mTmpLocation = new int[2];
+    private int mLastViewHeight;
+    private float mLastHeaderTranslation;
 
     @Inject
     public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
@@ -148,6 +150,13 @@
         setHost(mHost);
         mStatusBarStateController.addCallback(this);
         onStateChanged(mStatusBarStateController.getState());
+        view.addOnLayoutChangeListener(
+                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+                    boolean sizeChanged = (oldTop - oldBottom) != (top - bottom);
+                    if (sizeChanged) {
+                        setQsExpansion(mLastQSExpansion, mLastQSExpansion);
+                    }
+                });
     }
 
     @Override
@@ -374,11 +383,15 @@
                             ? translationScaleY * mHeader.getHeight()
                             : headerTranslation);
         }
-        if (expansion == mLastQSExpansion && mLastKeyguardAndExpanded == onKeyguardAndExpanded) {
+        int currentHeight = getView().getHeight();
+        mLastHeaderTranslation = headerTranslation;
+        if (expansion == mLastQSExpansion && mLastKeyguardAndExpanded == onKeyguardAndExpanded
+                && mLastViewHeight == currentHeight) {
             return;
         }
         mLastQSExpansion = expansion;
         mLastKeyguardAndExpanded = onKeyguardAndExpanded;
+        mLastViewHeight = currentHeight;
 
         boolean fullyExpanded = expansion == 1;
         int heightDiff = mQSPanel.getBottom() - mHeader.getBottom() + mHeader.getPaddingBottom();
@@ -427,7 +440,7 @@
                     (ViewGroup.MarginLayoutParams) hostView.getLayoutParams();
             float targetPosition = absoluteBottomPosition - params.bottomMargin
                     - hostView.getHeight();
-            float currentPosition = mediaHost.getCurrentState().getBoundsOnScreen().top
+            float currentPosition = mediaHost.getCurrentBounds().top
                     - hostView.getTranslationY();
             hostView.setTranslationY(targetPosition - currentPosition);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index cdde06b..4f0b56e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -187,9 +187,9 @@
     }
 
     protected void addMediaHostView() {
-        mMediaHost.init(MediaHierarchyManager.LOCATION_QS);
         mMediaHost.setExpansion(1.0f);
         mMediaHost.setShowsOnlyActiveMedia(false);
+        mMediaHost.init(MediaHierarchyManager.LOCATION_QS);
         ViewGroup hostView = mMediaHost.getHostView();
         addView(hostView);
         int sidePaddings = getResources().getDimensionPixelSize(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 2f06c4b..75507be 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -190,9 +190,9 @@
             switchTileLayout();
             return null;
         });
-        mMediaHost.init(MediaHierarchyManager.LOCATION_QQS);
         mMediaHost.setExpansion(0.0f);
         mMediaHost.setShowsOnlyActiveMedia(true);
+        mMediaHost.init(MediaHierarchyManager.LOCATION_QQS);
         reAttachMediaHost();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index fe84d818..3874903 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -31,6 +31,8 @@
 import android.graphics.drawable.ColorDrawable;
 import android.os.Binder;
 import android.os.RemoteException;
+import android.text.SpannableStringBuilder;
+import android.text.style.BulletSpan;
 import android.util.DisplayMetrics;
 import android.view.Gravity;
 import android.view.View;
@@ -293,8 +295,20 @@
                         .setImageDrawable(navigationBarView.getHomeDrawable());
             }
 
-            ((TextView) mLayout.findViewById(R.id.screen_pinning_description))
-                    .setText(descriptionStringResId);
+            // Create a bulleted list of the default description plus the two security notes.
+            int gapWidth = getResources().getDimensionPixelSize(
+                    R.dimen.screen_pinning_description_bullet_gap_width);
+            SpannableStringBuilder description = new SpannableStringBuilder();
+            description.append(getContext().getText(descriptionStringResId),
+                    new BulletSpan(gapWidth), /* flags */ 0);
+            description.append(System.lineSeparator());
+            description.append(getContext().getText(R.string.screen_pinning_exposes_personal_data),
+                    new BulletSpan(gapWidth), /* flags */ 0);
+            description.append(System.lineSeparator());
+            description.append(getContext().getText(R.string.screen_pinning_can_open_other_apps),
+                    new BulletSpan(gapWidth), /* flags */ 0);
+            ((TextView) mLayout.findViewById(R.id.screen_pinning_description)).setText(description);
+
             final int backBgVisibility = touchExplorationEnabled ? View.INVISIBLE : View.VISIBLE;
             mLayout.findViewById(R.id.screen_pinning_back_bg).setVisibility(backBgVisibility);
             mLayout.findViewById(R.id.screen_pinning_back_bg_light).setVisibility(backBgVisibility);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index f2d2eb3..33d692f 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -431,7 +431,13 @@
         data.createDeleteAction = false;
 
         if (mSaveInBgTask != null) {
-            mSaveInBgTask.ignoreResult();
+            // just log success/failure for the pre-existing screenshot
+            mSaveInBgTask.setActionsReadyListener(new ActionsReadyListener() {
+                @Override
+                void onActionsReady(SavedImageData imageData) {
+                    logSuccessOnActionsReady(imageData);
+                }
+            });
         }
 
         mSaveInBgTask = new SaveImageInBackgroundTask(mContext, data);
@@ -637,6 +643,52 @@
     }
 
     /**
+     * Sets up the action shade and its entrance animation, once we get the screenshot URI.
+     */
+    private void showUiOnActionsReady(SavedImageData imageData) {
+        logSuccessOnActionsReady(imageData);
+        if (imageData.uri != null) {
+            mScreenshotHandler.post(() -> {
+                if (mScreenshotAnimation != null && mScreenshotAnimation.isRunning()) {
+                    mScreenshotAnimation.addListener(new AnimatorListenerAdapter() {
+                        @Override
+                        public void onAnimationEnd(Animator animation) {
+                            super.onAnimationEnd(animation);
+                            createScreenshotActionsShadeAnimation(imageData).start();
+                        }
+                    });
+                } 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),
+                        timeoutMs);
+            });
+        }
+    }
+
+    /**
+     * Logs success/failure of the screenshot saving task, and shows an error if it failed.
+     */
+    private void logSuccessOnActionsReady(SavedImageData imageData) {
+        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);
+        }
+    }
+
+    /**
      * Starts the animation after taking the screenshot
      */
     private void startAnimation(final Consumer<Uri> finisher, int w, int h,
@@ -651,43 +703,11 @@
         mScreenshotAnimation = createScreenshotDropInAnimation(w, h, screenRect);
 
         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(() -> {
-                        if (mScreenshotAnimation != null && mScreenshotAnimation.isRunning()) {
-                            mScreenshotAnimation.addListener(
-                                    new AnimatorListenerAdapter() {
-                                        @Override
-                                        public void onAnimationEnd(Animator animation) {
-                                            super.onAnimationEnd(animation);
-                                            createScreenshotActionsShadeAnimation(imageData)
-                                                    .start();
-                                        }
-                                    });
-                        } 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),
-                                timeoutMs);
-                    });
-                }
-            }
-        });
+                    @Override
+                    void onActionsReady(SavedImageData imageData) {
+                        showUiOnActionsReady(imageData);
+                    }
+                });
         mScreenshotHandler.post(() -> {
             if (!mScreenshotLayout.isAttachedToWindow()) {
                 mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index e88ce5a..a5bab21 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -26,7 +26,6 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Icon;
@@ -146,7 +145,7 @@
             CompletableFuture<List<Notification.Action>> smartActionsFuture =
                     ScreenshotSmartActions.getSmartActionsFuture(
                             mScreenshotId, uri, image, mSmartActionsProvider,
-                            mSmartActionsEnabled, isManagedProfile(mContext));
+                            mSmartActionsEnabled, getUserHandle(mContext));
 
             try {
                 // First, write the actual data for our screenshot
@@ -215,6 +214,7 @@
             mImageData.deleteAction = createDeleteAction(mContext, mContext.getResources(), uri);
 
             mParams.mActionsReadyListener.onActionsReady(mImageData);
+            mParams.finisher.accept(mImageData.uri);
             mParams.image = null;
             mParams.errorMsgResId = 0;
         } catch (Exception e) {
@@ -225,22 +225,18 @@
             mParams.errorMsgResId = R.string.screenshot_failed_to_save_text;
             mImageData.reset();
             mParams.mActionsReadyListener.onActionsReady(mImageData);
+            mParams.finisher.accept(null);
         }
 
         return null;
     }
 
     /**
-     * If we get a new screenshot request while this one is saving, we want to continue saving in
-     * the background but not return anything.
+     * Update the listener run when the saving task completes. Used to avoid showing UI for the
+     * first screenshot when a second one is taken.
      */
-    void ignoreResult() {
-        mParams.mActionsReadyListener = new GlobalScreenshot.ActionsReadyListener() {
-            @Override
-            void onActionsReady(GlobalScreenshot.SavedImageData imageData) {
-                // do nothing
-            }
-        };
+    void setActionsReadyListener(GlobalScreenshot.ActionsReadyListener listener) {
+        mParams.mActionsReadyListener = listener;
     }
 
     @Override
@@ -382,10 +378,9 @@
         }
     }
 
-    private boolean isManagedProfile(Context context) {
+    private UserHandle getUserHandle(Context context) {
         UserManager manager = UserManager.get(context);
-        UserInfo info = manager.getUserInfo(getUserHandleOfForegroundApplication(context));
-        return info.isManagedProfile();
+        return manager.getUserInfo(getUserHandleOfForegroundApplication(context)).getUserHandle();
     }
 
     private List<Notification.Action> buildSmartActions(
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
index 3edb33d..63f323e 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
@@ -20,6 +20,7 @@
 import android.content.ComponentName;
 import android.graphics.Bitmap;
 import android.net.Uri;
+import android.os.UserHandle;
 import android.util.Log;
 
 import java.util.Collections;
@@ -64,14 +65,14 @@
      * @param componentName      Contains package and activity class names where the screenshot was
      *                           taken. This is used as an additional signal to generate and rank
      *                           more relevant actions.
-     * @param isManagedProfile   The screenshot was taken for a work profile app.
+     * @param userHandle         The user handle of the app where the screenshot was taken.
      */
     public CompletableFuture<List<Notification.Action>> getActions(
             String screenshotId,
             Uri screenshotUri,
             Bitmap bitmap,
             ComponentName componentName,
-            boolean isManagedProfile) {
+            UserHandle userHandle) {
         Log.d(TAG, "Returning empty smart action list.");
         return CompletableFuture.completedFuture(Collections.emptyList());
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java
index c228fe2..442b373 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java
@@ -26,6 +26,7 @@
 import android.net.Uri;
 import android.os.Handler;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -48,7 +49,7 @@
     static CompletableFuture<List<Notification.Action>> getSmartActionsFuture(
             String screenshotId, Uri screenshotUri, Bitmap image,
             ScreenshotNotificationSmartActionsProvider smartActionsProvider,
-            boolean smartActionsEnabled, boolean isManagedProfile) {
+            boolean smartActionsEnabled, UserHandle userHandle) {
         if (!smartActionsEnabled) {
             Slog.i(TAG, "Screenshot Intelligence not enabled, returning empty list.");
             return CompletableFuture.completedFuture(Collections.emptyList());
@@ -60,7 +61,7 @@
             return CompletableFuture.completedFuture(Collections.emptyList());
         }
 
-        Slog.d(TAG, "Screenshot from a managed profile: " + isManagedProfile);
+        Slog.d(TAG, "Screenshot from user profile: " + userHandle.getIdentifier());
         CompletableFuture<List<Notification.Action>> smartActionsFuture;
         long startTimeMs = SystemClock.uptimeMillis();
         try {
@@ -71,7 +72,7 @@
                             ? runningTask.topActivity
                             : new ComponentName("", "");
             smartActionsFuture = smartActionsProvider.getActions(
-                    screenshotId, screenshotUri, image, componentName, isManagedProfile);
+                    screenshotId, screenshotUri, image, componentName, userHandle);
         } catch (Throwable e) {
             long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
             smartActionsFuture = CompletableFuture.completedFuture(Collections.emptyList());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
index b57b22f..8e6398f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
@@ -133,7 +133,7 @@
     }
 
     public static void fadeIn(View view, float fadeInAmount) {
-        fadeIn(view, fadeInAmount, true /* remap */);
+        fadeIn(view, fadeInAmount, false /* remap */);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
index 2ed04eb..9dbec10 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
@@ -22,7 +22,9 @@
         entryManager.addCollectionListener(this)
     }
 
-    fun hasUserInteractedWith(key: String): Boolean = key in interactions
+    fun hasUserInteractedWith(key: String): Boolean {
+        return interactions[key] ?: false
+    }
 
     override fun onEntryAdded(entry: NotificationEntry) {
         interactions[entry.key] = false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 85560fe..6aef6b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -19,7 +19,6 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
-import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.graphics.Matrix;
 import android.graphics.Rect;
@@ -42,8 +41,6 @@
 import com.android.systemui.statusbar.phone.NotificationPanelViewController;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController;
 
-import java.util.concurrent.Executor;
-
 /**
  * A class that allows activities to be launched in a seamless way where the notification
  * transforms nicely into the starting window.
@@ -62,7 +59,6 @@
     private final float mWindowCornerRadius;
     private final NotificationShadeWindowViewController mNotificationShadeWindowViewController;
     private final NotificationShadeDepthController mDepthController;
-    private final Executor mMainExecutor;
     private Callback mCallback;
     private final Runnable mTimeoutRunnable = () -> {
         setAnimationPending(false);
@@ -77,14 +73,12 @@
             Callback callback,
             NotificationPanelViewController notificationPanel,
             NotificationShadeDepthController depthController,
-            NotificationListContainer container,
-            Executor mainExecutor) {
+            NotificationListContainer container) {
         mNotificationPanel = notificationPanel;
         mNotificationContainer = container;
         mDepthController = depthController;
         mNotificationShadeWindowViewController = notificationShadeWindowViewController;
         mCallback = callback;
-        mMainExecutor = mainExecutor;
         mWindowCornerRadius = ScreenDecorationsUtils
                 .getWindowCornerRadius(mNotificationShadeWindowViewController.getView()
                         .getResources());
@@ -97,7 +91,7 @@
             return null;
         }
         AnimationRunner animationRunner = new AnimationRunner(
-                (ExpandableNotificationRow) sourceView, mMainExecutor);
+                (ExpandableNotificationRow) sourceView);
         return new RemoteAnimationAdapter(animationRunner, ANIMATION_DURATION,
                 ANIMATION_DURATION - 150 /* statusBarTransitionDelay */);
     }
@@ -140,18 +134,17 @@
 
     class AnimationRunner extends IRemoteAnimationRunner.Stub {
 
-        private final ExpandAnimationParameters mParams = new ExpandAnimationParameters();
+        private final ExpandableNotificationRow mSourceNotification;
+        private final ExpandAnimationParameters mParams;
         private final Rect mWindowCrop = new Rect();
         private final float mNotificationCornerRadius;
-        private final Executor mMainExecutor;
-        @Nullable private ExpandableNotificationRow mSourceNotification;
-        @Nullable private SyncRtSurfaceTransactionApplier mSyncRtTransactionApplier;
         private float mCornerRadius;
         private boolean mIsFullScreenLaunch = true;
+        private final SyncRtSurfaceTransactionApplier mSyncRtTransactionApplier;
 
-        AnimationRunner(ExpandableNotificationRow sourceNotification, Executor mainExecutor) {
-            mMainExecutor = mainExecutor;
-            mSourceNotification = sourceNotification;
+        public AnimationRunner(ExpandableNotificationRow sourceNofitication) {
+            mSourceNotification = sourceNofitication;
+            mParams = new ExpandAnimationParameters();
             mSyncRtTransactionApplier = new SyncRtSurfaceTransactionApplier(mSourceNotification);
             mNotificationCornerRadius = Math.max(mSourceNotification.getCurrentTopRoundness(),
                     mSourceNotification.getCurrentBottomRoundness());
@@ -162,15 +155,13 @@
                 RemoteAnimationTarget[] remoteAnimationWallpaperTargets,
                 IRemoteAnimationFinishedCallback iRemoteAnimationFinishedCallback)
                     throws RemoteException {
-            mMainExecutor.execute(() -> {
+            mSourceNotification.post(() -> {
                 RemoteAnimationTarget primary = getPrimaryRemoteAnimationTarget(
                         remoteAnimationTargets);
-                if (primary == null || mSourceNotification == null) {
+                if (primary == null) {
                     setAnimationPending(false);
                     invokeCallback(iRemoteAnimationFinishedCallback);
                     mNotificationPanel.collapse(false /* delayed */, 1.0f /* speedUpFactor */);
-                    mSourceNotification = null;
-                    mSyncRtTransactionApplier = null;
                     return;
                 }
 
@@ -181,14 +172,28 @@
                 if (!mIsFullScreenLaunch) {
                     mNotificationPanel.collapseWithDuration(ANIMATION_DURATION);
                 }
-                mParams.initFrom(mSourceNotification);
-                final int targetWidth = primary.sourceContainerBounds.width();
-                final int notificationHeight;
-                final int notificationWidth;
-                notificationHeight = mSourceNotification.getActualHeight()
-                        - mSourceNotification.getClipBottomAmount();
-                notificationWidth = mSourceNotification.getWidth();
                 ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
+                mParams.startPosition = mSourceNotification.getLocationOnScreen();
+                mParams.startTranslationZ = mSourceNotification.getTranslationZ();
+                mParams.startClipTopAmount = mSourceNotification.getClipTopAmount();
+                if (mSourceNotification.isChildInGroup()) {
+                    int parentClip = mSourceNotification
+                            .getNotificationParent().getClipTopAmount();
+                    mParams.parentStartClipTopAmount = parentClip;
+                    // We need to calculate how much the child is clipped by the parent
+                    // because children always have 0 clipTopAmount
+                    if (parentClip != 0) {
+                        float childClip = parentClip
+                                - mSourceNotification.getTranslationY();
+                        if (childClip > 0.0f) {
+                            mParams.startClipTopAmount = (int) Math.ceil(childClip);
+                        }
+                    }
+                }
+                int targetWidth = primary.sourceContainerBounds.width();
+                int notificationHeight = mSourceNotification.getActualHeight()
+                        - mSourceNotification.getClipBottomAmount();
+                int notificationWidth = mSourceNotification.getWidth();
                 anim.setDuration(ANIMATION_DURATION);
                 anim.setInterpolator(Interpolators.LINEAR);
                 anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@@ -226,11 +231,6 @@
             });
         }
 
-        @Nullable
-        ExpandableNotificationRow getRow() {
-            return mSourceNotification;
-        }
-
         private void invokeCallback(IRemoteAnimationFinishedCallback callback) {
             try {
                 callback.onAnimationFinished();
@@ -253,9 +253,7 @@
 
         private void setExpandAnimationRunning(boolean running) {
             mNotificationPanel.setLaunchingNotification(running);
-            if (mSourceNotification != null) {
-                mSourceNotification.setExpandAnimationRunning(running);
-            }
+            mSourceNotification.setExpandAnimationRunning(running);
             mNotificationShadeWindowViewController.setExpandAnimationRunning(running);
             mNotificationContainer.setExpandingNotification(running ? mSourceNotification : null);
             mAnimationRunning = running;
@@ -263,8 +261,6 @@
                 mCallback.onExpandAnimationFinished(mIsFullScreenLaunch);
                 applyParamsToNotification(null);
                 applyParamsToNotificationShade(null);
-                mSourceNotification = null;
-                mSyncRtTransactionApplier = null;
             }
 
         }
@@ -276,9 +272,7 @@
         }
 
         private void applyParamsToNotification(ExpandAnimationParameters params) {
-            if (mSourceNotification != null) {
-                mSourceNotification.applyExpandAnimationParams(params);
-            }
+            mSourceNotification.applyExpandAnimationParams(params);
         }
 
         private void applyParamsToWindow(RemoteAnimationTarget app) {
@@ -293,18 +287,14 @@
                     .withCornerRadius(mCornerRadius)
                     .withVisibility(true)
                     .build();
-            if (mSyncRtTransactionApplier != null) {
-                mSyncRtTransactionApplier.scheduleApply(true /* earlyWakeup */, params);
-            }
+            mSyncRtTransactionApplier.scheduleApply(true /* earlyWakeup */, params);
         }
 
         @Override
         public void onAnimationCancelled() throws RemoteException {
-            mMainExecutor.execute(() -> {
+            mSourceNotification.post(() -> {
                 setAnimationPending(false);
                 mCallback.onLaunchAnimationCancelled();
-                mSourceNotification = null;
-                mSyncRtTransactionApplier = null;
             });
         }
     };
@@ -369,28 +359,6 @@
         public float getStartTranslationZ() {
             return startTranslationZ;
         }
-
-        /** Initialize with data pulled from the row. */
-        void initFrom(@Nullable ExpandableNotificationRow row) {
-            if (row == null) {
-                return;
-            }
-            startPosition = row.getLocationOnScreen();
-            startTranslationZ = row.getTranslationZ();
-            startClipTopAmount = row.getClipTopAmount();
-            if (row.isChildInGroup()) {
-                int parentClip = row.getNotificationParent().getClipTopAmount();
-                parentStartClipTopAmount = parentClip;
-                // We need to calculate how much the child is clipped by the parent
-                // because children always have 0 clipTopAmount
-                if (parentClip != 0) {
-                    float childClip = parentClip - row.getTranslationY();
-                    if (childClip > 0.0f) {
-                        startClipTopAmount = (int) Math.ceil(childClip);
-                    }
-                }
-            }
-        }
     }
 
     public interface Callback {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java
index dea1a07..cb7da4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java
@@ -66,7 +66,7 @@
             return false;
         }
         View view = ownState.getTransformedView();
-        CrossFadeHelper.fadeIn(view, transformationAmount);
+        CrossFadeHelper.fadeIn(view, transformationAmount, true /* remap */);
         ownState.transformViewFullyFrom(otherState, this, transformationAmount);
         otherState.recycle();
         return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 27109d2..9a8cff0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -95,7 +95,7 @@
         if (sameAs(otherState)) {
             ensureVisible();
         } else {
-            CrossFadeHelper.fadeIn(mTransformedView, transformationAmount);
+            CrossFadeHelper.fadeIn(mTransformedView, transformationAmount, true /* remap */);
         }
         transformViewFullyFrom(otherState, transformationAmount);
     }
@@ -424,7 +424,7 @@
         if (transformationAmount == 0.0f) {
             prepareFadeIn();
         }
-        CrossFadeHelper.fadeIn(mTransformedView, transformationAmount);
+        CrossFadeHelper.fadeIn(mTransformedView, transformationAmount, true /* remap */);
     }
 
     public void disappear(float transformationAmount, TransformableView otherView) {
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 1eadd9e..3377144 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
@@ -41,6 +41,7 @@
 import android.app.NotificationChannel;
 import android.app.NotificationManager.Policy;
 import android.app.Person;
+import android.app.RemoteInput;
 import android.app.RemoteInputHistoryItem;
 import android.content.Context;
 import android.content.pm.ShortcutInfo;
@@ -69,6 +70,7 @@
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController;
 import com.android.systemui.statusbar.notification.row.NotificationGuts;
 import com.android.systemui.statusbar.notification.stack.PriorityBucket;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -132,7 +134,7 @@
     private ShortcutInfo mShortcutInfo;
 
     /**
-     * If {@link android.app.RemoteInput#getEditChoicesBeforeSending} is enabled, and the user is
+     * If {@link RemoteInput#getEditChoicesBeforeSending} is enabled, and the user is
      * currently editing a choice (smart reply), then this field contains the information about the
      * suggestion being edited. Otherwise <code>null</code>.
      */
@@ -174,6 +176,8 @@
     private boolean mPulseSupressed;
     private boolean mAllowFgsDismissal;
     private int mBucket = BUCKET_ALERTING;
+    @Nullable private Long mPendingAnimationDuration;
+    private boolean mIsMarkedForUserTriggeredMovement;
 
     /**
      * @param sbn the StatusBarNotification from system server
@@ -193,7 +197,7 @@
             boolean allowFgsDismissal,
             long creationTime
     ) {
-        super(requireNonNull(Objects.requireNonNull(sbn).getKey()));
+        super(requireNonNull(requireNonNull(sbn).getKey()));
 
         requireNonNull(ranking);
 
@@ -441,7 +445,7 @@
      * Get the children that are actually attached to this notification's row.
      *
      * TODO: Seems like most callers here should probably be using
-     * {@link com.android.systemui.statusbar.phone.NotificationGroupManager#getChildren}
+     * {@link NotificationGroupManager#getChildren}
      */
     public @Nullable List<NotificationEntry> getAttachedNotifChildren() {
         if (row == null) {
@@ -809,7 +813,7 @@
         }
 
         if ((mSbn.getNotification().flags
-                & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
+                & FLAG_FOREGROUND_SERVICE) != 0) {
             return true;
         }
         if (mSbn.getNotification().isMediaNotification()) {
@@ -942,6 +946,19 @@
         mPulseSupressed = suppressed;
     }
 
+    /** Whether or not this entry has been marked for a user-triggered movement. */
+    public boolean isMarkedForUserTriggeredMovement() {
+        return mIsMarkedForUserTriggeredMovement;
+    }
+
+    /**
+     * Mark this entry for movement triggered by a user action (ex: changing the priorirty of a
+     * conversation). This can then be used for custom animations.
+     */
+    public void markForUserTriggeredMovement(boolean marked) {
+        mIsMarkedForUserTriggeredMovement = marked;
+    }
+
     /** Information about a suggestion that is being edited. */
     public static class EditedSuggestionInfo {
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index f55ce77..033a638 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -25,6 +25,7 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -105,6 +106,7 @@
             VisualStabilityManager visualStabilityManager,
             Lazy<StatusBar> statusBarLazy,
             @Main Handler mainHandler,
+            @Background Handler bgHandler,
             AccessibilityManager accessibilityManager,
             HighPriorityProvider highPriorityProvider,
             INotificationManager notificationManager,
@@ -118,6 +120,7 @@
                 visualStabilityManager,
                 statusBarLazy,
                 mainHandler,
+                bgHandler,
                 accessibilityManager,
                 highPriorityProvider,
                 notificationManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
index fefad53..71f6dac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
@@ -146,14 +146,6 @@
             return false;
         }
 
-        if (!entry.isBubble()) {
-            if (DEBUG) {
-                Log.d(TAG, "No bubble up: notification " + sbn.getKey()
-                        + " is bubble? " + entry.isBubble());
-            }
-            return false;
-        }
-
         if (entry.getBubbleMetadata() == null
                 || (entry.getBubbleMetadata().getShortcutId() == null
                     && entry.getBubbleMetadata().getIntent() == null)) {
@@ -206,6 +198,13 @@
             return false;
         }
 
+        if (isSnoozedPackage(sbn)) {
+            if (DEBUG_HEADS_UP) {
+                Log.d(TAG, "No alerting: snoozed package: " + sbn.getKey());
+            }
+            return false;
+        }
+
         boolean inShade = mStatusBarStateController.getState() == SHADE;
         if (entry.isBubble() && inShade) {
             if (DEBUG_HEADS_UP) {
@@ -365,14 +364,6 @@
                 return false;
             }
         }
-
-        if (isSnoozedPackage(sbn)) {
-            if (DEBUG_HEADS_UP) {
-                Log.d(TAG, "No alerting: snoozed package: " + sbn.getKey());
-            }
-            return false;
-        }
-
         return true;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index 92b597b..f1727ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -123,8 +123,6 @@
     private float mAppearAnimationFraction = -1.0f;
     private float mAppearAnimationTranslation;
     private int mNormalColor;
-    private boolean mLastInSection;
-    private boolean mFirstInSection;
     private boolean mIsBelowSpeedBump;
 
     private float mNormalBackgroundVisibilityAmount;
@@ -430,27 +428,21 @@
         mBackgroundDimmed.setDistanceToTopRoundness(distanceToTopRoundness);
     }
 
-    public boolean isLastInSection() {
-        return mLastInSection;
-    }
-
-    public boolean isFirstInSection() {
-        return mFirstInSection;
-    }
-
     /** Sets whether this view is the last notification in a section. */
+    @Override
     public void setLastInSection(boolean lastInSection) {
         if (lastInSection != mLastInSection) {
-            mLastInSection = lastInSection;
+            super.setLastInSection(lastInSection);
             mBackgroundNormal.setLastInSection(lastInSection);
             mBackgroundDimmed.setLastInSection(lastInSection);
         }
     }
 
     /** Sets whether this view is the first notification in a section. */
+    @Override
     public void setFirstInSection(boolean firstInSection) {
         if (firstInSection != mFirstInSection) {
-            mFirstInSection = firstInSection;
+            super.setFirstInSection(firstInSection);
             mBackgroundNormal.setFirstInSection(firstInSection);
             mBackgroundDimmed.setFirstInSection(firstInSection);
         }
@@ -963,6 +955,7 @@
         return false;
     }
 
+    @Override
     public int getHeadsUpHeightWithoutHeader() {
         return getHeight();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
index 049cafa..26ccd72 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
@@ -262,10 +262,7 @@
         setClipToOutline(mAlwaysRoundBothCorners);
     }
 
-    /**
-     * Set the topRoundness of this view.
-     * @return Whether the roundness was changed.
-     */
+    @Override
     public boolean setTopRoundness(float topRoundness, boolean animate) {
         if (mTopRoundness != topRoundness) {
             mTopRoundness = topRoundness;
@@ -302,10 +299,7 @@
         return mCurrentBottomRoundness * mOutlineRadius;
     }
 
-    /**
-     * Set the bottom roundness of this view.
-     * @return Whether the roundness was changed.
-     */
+    @Override
     public boolean setBottomRoundness(float bottomRoundness, boolean animate) {
         if (mBottomRoundness != bottomRoundness) {
             mBottomRoundness = bottomRoundness;
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 0831c0b..7ed8350 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
@@ -67,6 +67,8 @@
     protected int mContentShift;
     private final ExpandableViewState mViewState;
     private float mContentTranslation;
+    protected boolean mLastInSection;
+    protected boolean mFirstInSection;
 
     public ExpandableView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -771,6 +773,44 @@
         return true;
     }
 
+    /** Sets whether this view is the first notification in a section. */
+    public void setFirstInSection(boolean firstInSection) {
+        mFirstInSection = firstInSection;
+    }
+
+    /** Sets whether this view is the last notification in a section. */
+    public void setLastInSection(boolean lastInSection) {
+        mLastInSection = lastInSection;
+    }
+
+    public boolean isLastInSection() {
+        return mLastInSection;
+    }
+
+    public boolean isFirstInSection() {
+        return mFirstInSection;
+    }
+
+    /**
+     * Set the topRoundness of this view.
+     * @return Whether the roundness was changed.
+     */
+    public boolean setTopRoundness(float topRoundness, boolean animate) {
+        return false;
+    }
+
+    /**
+     * Set the bottom roundness of this view.
+     * @return Whether the roundness was changed.
+     */
+    public boolean setBottomRoundness(float bottomRoundness, boolean animate) {
+        return false;
+    }
+
+    public int getHeadsUpHeightWithoutHeader() {
+        return getHeight();
+    }
+
     /**
      * A listener notifying when {@link #getActualHeight} changes.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java
index 2071449..bc2adac3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java
@@ -92,7 +92,7 @@
                         // We want to transform from the same y location as the title
                         TransformState otherState = notification.getCurrentState(
                                 TRANSFORMING_VIEW_TITLE);
-                        CrossFadeHelper.fadeIn(mTextView, transformationAmount);
+                        CrossFadeHelper.fadeIn(mTextView, transformationAmount, true /* remap */);
                         if (otherState != null) {
                             ownState.transformViewVerticalFrom(otherState, transformationAmount);
                             otherState.recycle();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
index e0583be..9217756 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.notification.row;
 
-import static android.app.Notification.EXTRA_IS_GROUP_CONVERSATION;
 import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
 import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
 import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
@@ -43,9 +42,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
-import android.graphics.drawable.Icon;
 import android.os.Handler;
-import android.os.Parcelable;
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
@@ -65,15 +62,16 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.notification.ConversationIconFactory;
-import com.android.systemui.Dependency;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.statusbar.notification.NotificationChannelHelper;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 
 import java.lang.annotation.Retention;
-import java.util.List;
 
 import javax.inject.Provider;
 
@@ -86,10 +84,12 @@
 
 
     private INotificationManager mINotificationManager;
-    ShortcutManager mShortcutManager;
+    private ShortcutManager mShortcutManager;
     private PackageManager mPm;
     private ConversationIconFactory mIconFactory;
     private VisualStabilityManager mVisualStabilityManager;
+    private Handler mMainHandler;
+    private Handler mBgHandler;
 
     private String mPackageName;
     private String mAppName;
@@ -97,6 +97,7 @@
     private String mDelegatePkg;
     private NotificationChannel mNotificationChannel;
     private ShortcutInfo mShortcutInfo;
+    private NotificationEntry mEntry;
     private StatusBarNotification mSbn;
     @Nullable private Notification.BubbleMetadata mBubbleMetadata;
     private Context mUserContext;
@@ -213,11 +214,14 @@
             ConversationIconFactory conversationIconFactory,
             Context userContext,
             Provider<PriorityOnboardingDialogController.Builder> builderProvider,
-            boolean isDeviceProvisioned) {
+            boolean isDeviceProvisioned,
+            @Main Handler mainHandler,
+            @Background Handler bgHandler) {
         mSelectedAction = -1;
         mINotificationManager = iNotificationManager;
         mVisualStabilityManager = visualStabilityManager;
         mPackageName = pkg;
+        mEntry = entry;
         mSbn = entry.getSbn();
         mPm = pm;
         mAppName = mPackageName;
@@ -231,7 +235,8 @@
         mUserContext = userContext;
         mBubbleMetadata = bubbleMetadata;
         mBuilderProvider = builderProvider;
-
+        mMainHandler = mainHandler;
+        mBgHandler = bgHandler;
         mShortcutManager = shortcutManager;
         mShortcutInfo = entry.getRanking().getShortcutInfo();
         if (mShortcutInfo == null) {
@@ -494,11 +499,13 @@
     }
 
     private void updateChannel() {
-        Handler bgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
-        bgHandler.post(
+        mBgHandler.post(
                 new UpdateChannelRunnable(mINotificationManager, mPackageName,
                         mAppUid, mSelectedAction, mNotificationChannel));
-        mVisualStabilityManager.temporarilyAllowReordering();
+        mMainHandler.postDelayed(() -> {
+            mEntry.markForUserTriggeredMovement(true);
+            mVisualStabilityManager.temporarilyAllowReordering();
+        }, StackStateAnimator.ANIMATION_DURATION_STANDARD);
     }
 
     private boolean shouldShowPriorityOnboarding() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 3f7c7ca..1caf8f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -46,6 +46,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -111,6 +112,7 @@
 
     private final Lazy<StatusBar> mStatusBarLazy;
     private final Handler mMainHandler;
+    private final Handler mBgHandler;
     private Runnable mOpenRunnable;
     private final INotificationManager mNotificationManager;
     private final LauncherApps mLauncherApps;
@@ -122,7 +124,7 @@
      * Injected constructor. See {@link NotificationsModule}.
      */
     public NotificationGutsManager(Context context, VisualStabilityManager visualStabilityManager,
-            Lazy<StatusBar> statusBarLazy, @Main Handler mainHandler,
+            Lazy<StatusBar> statusBarLazy, @Main Handler mainHandler, @Background Handler bgHandler,
             AccessibilityManager accessibilityManager,
             HighPriorityProvider highPriorityProvider,
             INotificationManager notificationManager,
@@ -135,6 +137,7 @@
         mVisualStabilityManager = visualStabilityManager;
         mStatusBarLazy = statusBarLazy;
         mMainHandler = mainHandler;
+        mBgHandler = bgHandler;
         mAccessibilityManager = accessibilityManager;
         mHighPriorityProvider = highPriorityProvider;
         mNotificationManager = notificationManager;
@@ -463,7 +466,9 @@
                 iconFactoryLoader,
                 mContextTracker.getCurrentUserContext(),
                 mBuilderProvider,
-                mDeviceProvisionedController.isDeviceProvisioned());
+                mDeviceProvisionedController.isDeviceProvisioned(),
+                mMainHandler,
+                mBgHandler);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
index 2d99ab1..14aab9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
@@ -23,7 +23,6 @@
 import android.content.res.ColorStateList;
 import android.graphics.Color;
 import android.graphics.PorterDuffColorFilter;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.service.notification.StatusBarNotification;
 import android.util.ArraySet;
@@ -107,7 +106,7 @@
                         TransformState otherState = notification.getCurrentState(
                                 TRANSFORMING_VIEW_TITLE);
                         final View text = ownState.getTransformedView();
-                        CrossFadeHelper.fadeIn(text, transformationAmount);
+                        CrossFadeHelper.fadeIn(text, transformationAmount, true /* remap */);
                         if (otherState != null) {
                             ownState.transformViewVerticalFrom(otherState, this,
                                     transformationAmount);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index fa7f282..02e537d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -284,7 +284,7 @@
 
     @Override
     public void transformFrom(TransformableView notification, float transformationAmount) {
-        CrossFadeHelper.fadeIn(mView, transformationAmount);
+        CrossFadeHelper.fadeIn(mView, transformationAmount, true /* remap */);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index ecab188..b4220f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -64,7 +64,7 @@
     private int mZDistanceBetweenElements;
     private int mBaseZHeight;
     private int mMaxLayoutHeight;
-    private ActivatableNotificationView mLastVisibleBackgroundChild;
+    private ExpandableView mLastVisibleBackgroundChild;
     private float mCurrentScrollVelocity;
     private int mStatusBarState;
     private float mExpandingVelocity;
@@ -346,11 +346,11 @@
      * view in the shade, without the clear all button.
      */
     public void setLastVisibleBackgroundChild(
-            ActivatableNotificationView lastVisibleBackgroundChild) {
+            ExpandableView lastVisibleBackgroundChild) {
         mLastVisibleBackgroundChild = lastVisibleBackgroundChild;
     }
 
-    public ActivatableNotificationView getLastVisibleBackgroundChild() {
+    public ExpandableView getLastVisibleBackgroundChild() {
         return mLastVisibleBackgroundChild;
     }
 
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 3ac322f..383f2a2 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
@@ -16,45 +16,35 @@
 
 package com.android.systemui.statusbar.notification.stack;
 
+import android.animation.AnimatorListenerAdapter;
 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;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
 
 /**
  * Root view to insert Lock screen media controls into the notification stack.
  */
-public class MediaHeaderView extends ActivatableNotificationView {
-
-    private View mContentView;
+public class MediaHeaderView extends ExpandableView {
 
     public MediaHeaderView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
     @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
+    public long performRemoveAnimation(long duration, long delay, float translationDirection,
+            boolean isHeadsUpAnimation, float endLocation, Runnable onFinishedRunnable,
+            AnimatorListenerAdapter animationListener) {
+        return 0;
     }
 
     @Override
-    protected View getContentView() {
-        return mContentView;
-    }
-
-    /**
-     * Sets the background color, to be used when album art changes.
-     * @param color background
-     */
-    public void setBackgroundColor(int color) {
-        setTintColor(color);
+    public void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear) {
+        // No animation, it doesn't need it, this would be local
     }
 
     public void setContentView(ViewGroup contentView) {
-        mContentView = contentView;
         addView(contentView);
         ViewGroup.LayoutParams layoutParams = contentView.getLayoutParams();
         layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
index b4f7b59..2c3239a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
@@ -20,7 +20,6 @@
 
 import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-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.phone.KeyguardBypassController;
@@ -37,10 +36,10 @@
 @Singleton
 public class NotificationRoundnessManager implements OnHeadsUpChangedListener {
 
-    private final ActivatableNotificationView[] mFirstInSectionViews;
-    private final ActivatableNotificationView[] mLastInSectionViews;
-    private final ActivatableNotificationView[] mTmpFirstInSectionViews;
-    private final ActivatableNotificationView[] mTmpLastInSectionViews;
+    private final ExpandableView[] mFirstInSectionViews;
+    private final ExpandableView[] mLastInSectionViews;
+    private final ExpandableView[] mTmpFirstInSectionViews;
+    private final ExpandableView[] mTmpLastInSectionViews;
     private final KeyguardBypassController mBypassController;
     private boolean mExpanded;
     private HashSet<ExpandableView> mAnimatedChildren;
@@ -53,10 +52,10 @@
             KeyguardBypassController keyguardBypassController,
             NotificationSectionsFeatureManager sectionsFeatureManager) {
         int numberOfSections = sectionsFeatureManager.getNumberOfBuckets();
-        mFirstInSectionViews = new ActivatableNotificationView[numberOfSections];
-        mLastInSectionViews = new ActivatableNotificationView[numberOfSections];
-        mTmpFirstInSectionViews = new ActivatableNotificationView[numberOfSections];
-        mTmpLastInSectionViews = new ActivatableNotificationView[numberOfSections];
+        mFirstInSectionViews = new ExpandableView[numberOfSections];
+        mLastInSectionViews = new ExpandableView[numberOfSections];
+        mTmpFirstInSectionViews = new ExpandableView[numberOfSections];
+        mTmpLastInSectionViews = new ExpandableView[numberOfSections];
         mBypassController = keyguardBypassController;
     }
 
@@ -80,14 +79,14 @@
         updateView(entry.getRow(), false /* animate */);
     }
 
-    private void updateView(ActivatableNotificationView view, boolean animate) {
+    private void updateView(ExpandableView view, boolean animate) {
         boolean changed = updateViewWithoutCallback(view, animate);
         if (changed) {
             mRoundingChangedCallback.run();
         }
     }
 
-    private boolean updateViewWithoutCallback(ActivatableNotificationView view,
+    private boolean updateViewWithoutCallback(ExpandableView view,
             boolean animate) {
         float topRoundness = getRoundness(view, true /* top */);
         float bottomRoundness = getRoundness(view, false /* top */);
@@ -100,8 +99,7 @@
         return (firstInSection || lastInSection) && (topChanged || bottomChanged);
     }
 
-    private boolean isFirstInSection(ActivatableNotificationView view,
-            boolean includeFirstSection) {
+    private boolean isFirstInSection(ExpandableView view, boolean includeFirstSection) {
         int numNonEmptySections = 0;
         for (int i = 0; i < mFirstInSectionViews.length; i++) {
             if (view == mFirstInSectionViews[i]) {
@@ -114,7 +112,7 @@
         return false;
     }
 
-    private boolean isLastInSection(ActivatableNotificationView view, boolean includeLastSection) {
+    private boolean isLastInSection(ExpandableView view, boolean includeLastSection) {
         int numNonEmptySections = 0;
         for (int i = mLastInSectionViews.length - 1; i >= 0; i--) {
             if (view == mLastInSectionViews[i]) {
@@ -127,7 +125,7 @@
         return false;
     }
 
-    private float getRoundness(ActivatableNotificationView view, boolean top) {
+    private float getRoundness(ExpandableView view, boolean top) {
         if ((view.isPinned() || view.isHeadsUpAnimatingAway()) && !mExpanded) {
             return 1.0f;
         }
@@ -174,14 +172,14 @@
     }
 
     private boolean handleRemovedOldViews(NotificationSection[] sections,
-            ActivatableNotificationView[] oldViews, boolean first) {
+            ExpandableView[] oldViews, boolean first) {
         boolean anyChanged = false;
-        for (ActivatableNotificationView oldView : oldViews) {
+        for (ExpandableView oldView : oldViews) {
             if (oldView != null) {
                 boolean isStillPresent = false;
                 boolean adjacentSectionChanged = false;
                 for (NotificationSection section : sections) {
-                    ActivatableNotificationView newView =
+                    ExpandableView newView =
                             (first ? section.getFirstVisibleChild()
                                     : section.getLastVisibleChild());
                     if (newView == oldView) {
@@ -207,14 +205,14 @@
     }
 
     private boolean handleAddedNewViews(NotificationSection[] sections,
-            ActivatableNotificationView[] oldViews, boolean first) {
+            ExpandableView[] oldViews, boolean first) {
         boolean anyChanged = false;
         for (NotificationSection section : sections) {
-            ActivatableNotificationView newView =
+            ExpandableView newView =
                     (first ? section.getFirstVisibleChild() : section.getLastVisibleChild());
             if (newView != null) {
                 boolean wasAlreadyPresent = false;
-                for (ActivatableNotificationView oldView : oldViews) {
+                for (ExpandableView oldView : oldViews) {
                     if (oldView == newView) {
                         wasAlreadyPresent = true;
                         break;
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 bad36bf..1131a65 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
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.notification.stack;
 
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_MEDIA_CONTROLS;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
@@ -26,7 +28,7 @@
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.statusbar.notification.ShadeViewRefactor;
-import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
 
 /**
  * Represents the bounds of a section of the notification shade and handles animation when the
@@ -41,8 +43,8 @@
     private Rect mEndAnimationRect = new Rect();
     private ObjectAnimator mTopAnimator = null;
     private ObjectAnimator mBottomAnimator = null;
-    private ActivatableNotificationView mFirstVisibleChild;
-    private ActivatableNotificationView mLastVisibleChild;
+    private ExpandableView mFirstVisibleChild;
+    private ExpandableView mLastVisibleChild;
 
     NotificationSection(View owningView, @PriorityBucket int bucket) {
         mOwningView = owningView;
@@ -198,21 +200,21 @@
         mOwningView.invalidate();
     }
 
-    public ActivatableNotificationView getFirstVisibleChild() {
+    public ExpandableView getFirstVisibleChild() {
         return mFirstVisibleChild;
     }
 
-    public ActivatableNotificationView getLastVisibleChild() {
+    public ExpandableView getLastVisibleChild() {
         return mLastVisibleChild;
     }
 
-    public boolean setFirstVisibleChild(ActivatableNotificationView child) {
+    public boolean setFirstVisibleChild(ExpandableView child) {
         boolean changed = mFirstVisibleChild != child;
         mFirstVisibleChild = child;
         return changed;
     }
 
-    public boolean setLastVisibleChild(ActivatableNotificationView child) {
+    public boolean setLastVisibleChild(ExpandableView child) {
         boolean changed = mLastVisibleChild != child;
         mLastVisibleChild = child;
         return changed;
@@ -251,7 +253,7 @@
             boolean shiftBackgroundWithFirst) {
         int top = minTopPosition;
         int bottom = minTopPosition;
-        ActivatableNotificationView firstView = getFirstVisibleChild();
+        ExpandableView firstView = getFirstVisibleChild();
         if (firstView != null) {
             // Round Y up to avoid seeing the background during animation
             int finalTranslationY = (int) Math.ceil(ViewState.getFinalTranslationY(firstView));
@@ -276,7 +278,7 @@
             }
         }
         top = Math.max(minTopPosition, top);
-        ActivatableNotificationView lastView = getLastVisibleChild();
+        ExpandableView lastView = getLastVisibleChild();
         if (lastView != null) {
             float finalTranslationY = ViewState.getFinalTranslationY(lastView);
             int finalHeight = ExpandableViewState.getFinalActualHeight(lastView);
@@ -302,4 +304,8 @@
         mBounds.bottom = bottom;
         return bottom;
     }
+
+    public boolean needsBackground() {
+        return mFirstVisibleChild != null && mBucket != BUCKET_MEDIA_CONTROLS;
+    }
 }
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
index e39a4a0..ba7675f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
@@ -35,7 +35,6 @@
 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
@@ -456,14 +455,14 @@
     private sealed class SectionBounds {
 
         data class Many(
-            val first: ActivatableNotificationView,
-            val last: ActivatableNotificationView
+            val first: ExpandableView,
+            val last: ExpandableView
         ) : SectionBounds()
 
-        data class One(val lone: ActivatableNotificationView) : SectionBounds()
+        data class One(val lone: ExpandableView) : SectionBounds()
         object None : SectionBounds()
 
-        fun addNotif(notif: ActivatableNotificationView): SectionBounds = when (this) {
+        fun addNotif(notif: ExpandableView): SectionBounds = when (this) {
             is None -> One(notif)
             is One -> Many(lone, notif)
             is Many -> copy(last = notif)
@@ -476,8 +475,8 @@
         }
 
         private fun NotificationSection.setFirstAndLastVisibleChildren(
-            first: ActivatableNotificationView?,
-            last: ActivatableNotificationView?
+            first: ExpandableView?,
+            last: ExpandableView?
         ): Boolean {
             val firstChanged = setFirstVisibleChild(first)
             val lastChanged = setLastVisibleChild(last)
@@ -492,7 +491,7 @@
      */
     fun updateFirstAndLastViewsForAllSections(
         sections: Array<NotificationSection>,
-        children: List<ActivatableNotificationView>
+        children: List<ExpandableView>
     ): Boolean {
         // Create mapping of bucket to section
         val sectionBounds = children.asSequence()
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 e33cc60..a877bc1c 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
@@ -701,7 +701,7 @@
      * @return the height at which we will wake up when pulsing
      */
     public float getWakeUpHeight() {
-        ActivatableNotificationView firstChild = getFirstChildWithBackground();
+        ExpandableView firstChild = getFirstChildWithBackground();
         if (firstChild != null) {
             if (mKeyguardBypassController.getBypassEnabled()) {
                 return firstChild.getHeadsUpHeightWithoutHeader();
@@ -907,7 +907,7 @@
         // TODO(kprevas): this may not be necessary any more since we don't display the shelf in AOD
         boolean anySectionHasVisibleChild = false;
         for (NotificationSection section : mSections) {
-            if (section.getFirstVisibleChild() != null) {
+            if (section.needsBackground()) {
                 anySectionHasVisibleChild = true;
                 break;
             }
@@ -950,7 +950,7 @@
         int currentRight = right;
         boolean first = true;
         for (NotificationSection section : mSections) {
-            if (section.getFirstVisibleChild() == null) {
+            if (!section.needsBackground()) {
                 continue;
             }
             int sectionTop = section.getCurrentBounds().top + animationYOffset;
@@ -2685,40 +2685,40 @@
     }
 
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
-    private ActivatableNotificationView getLastChildWithBackground() {
+    private ExpandableView getLastChildWithBackground() {
         int childCount = getChildCount();
         for (int i = childCount - 1; i >= 0; i--) {
-            View child = getChildAt(i);
-            if (child.getVisibility() != View.GONE && child instanceof ActivatableNotificationView
+            ExpandableView child = (ExpandableView) getChildAt(i);
+            if (child.getVisibility() != View.GONE && !(child instanceof StackScrollerDecorView)
                     && child != mShelf) {
-                return (ActivatableNotificationView) child;
+                return child;
             }
         }
         return null;
     }
 
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
-    private ActivatableNotificationView getFirstChildWithBackground() {
+    private ExpandableView getFirstChildWithBackground() {
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child.getVisibility() != View.GONE && child instanceof ActivatableNotificationView
+            ExpandableView child = (ExpandableView) getChildAt(i);
+            if (child.getVisibility() != View.GONE && !(child instanceof StackScrollerDecorView)
                     && child != mShelf) {
-                return (ActivatableNotificationView) child;
+                return child;
             }
         }
         return null;
     }
 
     //TODO: We shouldn't have to generate this list every time
-    private List<ActivatableNotificationView> getChildrenWithBackground() {
-        ArrayList<ActivatableNotificationView> children = new ArrayList<>();
+    private List<ExpandableView> getChildrenWithBackground() {
+        ArrayList<ExpandableView> children = new ArrayList<>();
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child.getVisibility() != View.GONE && child instanceof ActivatableNotificationView
+            ExpandableView child = (ExpandableView) getChildAt(i);
+            if (child.getVisibility() != View.GONE && !(child instanceof StackScrollerDecorView)
                     && child != mShelf) {
-                children.add((ActivatableNotificationView) child);
+                children.add(child);
             }
         }
 
@@ -3283,13 +3283,13 @@
     private void updateFirstAndLastBackgroundViews() {
         NotificationSection firstSection = getFirstVisibleSection();
         NotificationSection lastSection = getLastVisibleSection();
-        ActivatableNotificationView previousFirstChild =
+        ExpandableView previousFirstChild =
                 firstSection == null ? null : firstSection.getFirstVisibleChild();
-        ActivatableNotificationView previousLastChild =
+        ExpandableView previousLastChild =
                 lastSection == null ? null : lastSection.getLastVisibleChild();
 
-        ActivatableNotificationView firstChild = getFirstChildWithBackground();
-        ActivatableNotificationView lastChild = getLastChildWithBackground();
+        ExpandableView firstChild = getFirstChildWithBackground();
+        ExpandableView lastChild = getLastChildWithBackground();
         boolean sectionViewsChanged = mSectionsManager.updateFirstAndLastViewsForAllSections(
                 mSections, getChildrenWithBackground());
 
@@ -3655,8 +3655,19 @@
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void generatePositionChangeEvents() {
         for (ExpandableView child : mChildrenChangingPositions) {
-            mAnimationEvents.add(new AnimationEvent(child,
-                    AnimationEvent.ANIMATION_TYPE_CHANGE_POSITION));
+            Integer duration = null;
+            if (child instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                if (row.getEntry().isMarkedForUserTriggeredMovement()) {
+                    duration = StackStateAnimator.ANIMATION_DURATION_PRIORITY_CHANGE;
+                    row.getEntry().markForUserTriggeredMovement(false);
+                }
+            }
+            AnimationEvent animEvent = duration == null
+                    ? new AnimationEvent(child, AnimationEvent.ANIMATION_TYPE_CHANGE_POSITION)
+                    : new AnimationEvent(
+                            child, AnimationEvent.ANIMATION_TYPE_CHANGE_POSITION, duration);
+            mAnimationEvents.add(animEvent);
         }
         mChildrenChangingPositions.clear();
         if (mGenerateChildOrderChangedEvent) {
@@ -4575,7 +4586,7 @@
                 ? (ExpandableNotificationRow) view
                 : null;
         NotificationSection firstSection = getFirstVisibleSection();
-        ActivatableNotificationView firstVisibleChild =
+        ExpandableView firstVisibleChild =
                 firstSection == null ? null : firstSection.getFirstVisibleChild();
         if (row != null) {
             if (row == firstVisibleChild
@@ -4611,7 +4622,7 @@
                 }
                 int layoutEnd = mMaxLayoutHeight + (int) mStackTranslation;
                 NotificationSection lastSection = getLastVisibleSection();
-                ActivatableNotificationView lastVisibleChild =
+                ExpandableView lastVisibleChild =
                         lastSection == null ? null : lastSection.getLastVisibleChild();
                 if (row != lastVisibleChild && mShelf.getVisibility() != GONE) {
                     layoutEnd -= mShelf.getIntrinsicHeight() + mPaddingBetweenElements;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index 6c0655e..d7d09e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -426,8 +426,8 @@
         final int height = (view instanceof ExpandableView)
                 ? ((ExpandableView) view).getActualHeight()
                 : view.getHeight();
-        final int rx = (int) ev.getRawX();
-        final int ry = (int) ev.getRawY();
+        final int rx = (int) ev.getX();
+        final int ry = (int) ev.getY();
         int[] temp = new int[2];
         view.getLocationOnScreen(temp);
         final int x = temp[0];
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index 7785082..d4add95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -56,6 +56,7 @@
     public static final int ANIMATION_DURATION_PULSE_APPEAR =
             KeyguardSliceView.DEFAULT_ANIM_DURATION;
     public static final int ANIMATION_DURATION_BLOCKING_HELPER_FADE = 240;
+    public static final int ANIMATION_DURATION_PRIORITY_CHANGE = 500;
     public static final int ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING = 80;
     public static final int ANIMATION_DELAY_PER_ELEMENT_MANUAL = 32;
     public static final int ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE = 48;
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 8bcdbfe..978394c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -624,6 +624,7 @@
         pw.println("  mIsBackGestureAllowed=" + mIsBackGestureAllowed);
         pw.println("  mAllowGesture=" + mAllowGesture);
         pw.println("  mDisabledForQuickstep=" + mDisabledForQuickstep);
+        pw.println("  mStartingQuickstepRotation=" + mStartingQuickstepRotation);
         pw.println("  mInRejectedExclusion" + mInRejectedExclusion);
         pw.println("  mExcludeRegion=" + mExcludeRegion);
         pw.println("  mUnrestrictedExcludeRegion=" + mUnrestrictedExcludeRegion);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index dcc3107..67b7e97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -18,10 +18,8 @@
 
 import static com.android.systemui.DejankUtils.whitelistIpcs;
 
-import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.os.UserManager;
-import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
@@ -97,33 +95,9 @@
     }
 
     public boolean isMultiUserEnabled() {
-        // Short-circuiting from UserManager. Needs to be extracted because of SystemUI boolean flag
-        // qs_show_user_switcher_for_single_user
-
         // TODO(b/138661450) Move IPC calls to background
-        return whitelistIpcs(() -> {
-            // The default in UserManager is to show the switcher. We want to not show it unless the
-            // user explicitly requests it in Settings
-            final boolean userSwitcherEnabled = Settings.Global.getInt(
-                    mContext.getContentResolver(),
-                    Settings.Global.USER_SWITCHER_ENABLED, 0) != 0;
-
-            if (!userSwitcherEnabled
-                    || !UserManager.supportsMultipleUsers()
-                    || UserManager.isDeviceInDemoMode(mContext)
-                    || mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)) {
-                return false;
-            }
-
-            final boolean guestEnabled = !mContext.getSystemService(DevicePolicyManager.class)
-                    .getGuestUserDisabled(null);
-            return mUserSwitcherController.getSwitchableUserCount() > 1
-                    // If we cannot add guests even if they are enabled, do not show
-                    || (guestEnabled && !mUserManager.hasUserRestriction(
-                    UserManager.DISALLOW_ADD_USER))
-                    || mContext.getResources().getBoolean(
-                    R.bool.qs_show_user_switcher_for_single_user);
-        });
+        return whitelistIpcs(() -> mUserManager.isUserSwitcherEnabled(
+                mContext.getResources().getBoolean(R.bool.qs_show_user_switcher_for_single_user)));
     }
 
     private void registerListener() {
@@ -175,7 +149,7 @@
     private void refreshContentDescription() {
         String currentUser = null;
         // TODO(b/138661450)
-        if (whitelistIpcs(mUserManager::isUserSwitcherEnabled)
+        if (whitelistIpcs(() -> mUserManager.isUserSwitcherEnabled())
                 && mUserSwitcherController != null) {
             currentUser = mUserSwitcherController.getCurrentUserName(mContext);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 662c744..46c873d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -93,7 +93,6 @@
 
     private boolean mIsVertical;
     private boolean mAlternativeOrder;
-    private boolean mUsingCustomLayout;
 
     private OverviewProxyService mOverviewProxyService;
     private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
@@ -145,7 +144,6 @@
     @Override
     public void onNavigationModeChanged(int mode) {
         mNavBarMode = mode;
-        onLikelyDefaultLayoutChange();
     }
 
     @Override
@@ -154,17 +152,7 @@
         super.onDetachedFromWindow();
     }
 
-    public void setNavigationBarLayout(String layoutValue) {
-        if (!Objects.equals(mCurrentLayout, layoutValue)) {
-            mUsingCustomLayout = layoutValue != null;
-            clearViews();
-            inflateLayout(layoutValue);
-        }
-    }
-
     public void onLikelyDefaultLayoutChange() {
-        // Don't override custom layouts
-        if (mUsingCustomLayout) return;
 
         // Reevaluate new layout
         final String newValue = getDefaultLayout();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
index 06b7d1a..daefef5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
@@ -16,19 +16,14 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static android.content.Intent.ACTION_OVERLAY_CHANGED;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
 
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.om.IOverlayManager;
 import android.content.om.OverlayInfo;
 import android.content.pm.PackageManager;
 import android.content.res.ApkAssets;
-import android.os.PatternMatcher;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -39,6 +34,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 
 import java.io.FileDescriptor;
@@ -69,16 +65,6 @@
 
     private ArrayList<ModeChangedListener> mListeners = new ArrayList<>();
 
-    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (DEBUG) {
-                Log.d(TAG, "ACTION_OVERLAY_CHANGED");
-            }
-            updateCurrentInteractionMode(true /* notify */);
-        }
-    };
-
     private final DeviceProvisionedController.DeviceProvisionedListener mDeviceProvisionedCallback =
             new DeviceProvisionedController.DeviceProvisionedListener() {
                 @Override
@@ -97,6 +83,7 @@
     @Inject
     public NavigationModeController(Context context,
             DeviceProvisionedController deviceProvisionedController,
+            ConfigurationController configurationController,
             @UiBackground Executor uiBgExecutor) {
         mContext = context;
         mCurrentUserContext = context;
@@ -105,10 +92,15 @@
         mUiBgExecutor = uiBgExecutor;
         deviceProvisionedController.addCallback(mDeviceProvisionedCallback);
 
-        IntentFilter overlayFilter = new IntentFilter(ACTION_OVERLAY_CHANGED);
-        overlayFilter.addDataScheme("package");
-        overlayFilter.addDataSchemeSpecificPart("android", PatternMatcher.PATTERN_LITERAL);
-        mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, overlayFilter, null, null);
+        configurationController.addCallback(new ConfigurationController.ConfigurationListener() {
+            @Override
+            public void onOverlayChanged() {
+                if (DEBUG) {
+                    Log.d(TAG, "onOverlayChanged");
+                }
+                updateCurrentInteractionMode(true /* notify */);
+            }
+        });
 
         updateCurrentInteractionMode(false /* notify */);
     }
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 2a4475b..a065b74 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -46,8 +46,6 @@
 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;
@@ -82,14 +80,14 @@
  */
 public class PhoneStatusBarPolicy
         implements BluetoothController.Callback,
-        CommandQueue.Callbacks,
-        RotationLockControllerCallback,
-        Listener,
-        ZenModeController.Callback,
-        DeviceProvisionedListener,
-        KeyguardStateController.Callback,
-        LocationController.LocationChangeCallback,
-        RecordingController.RecordingStateChangeCallback, MediaDataManager.Listener {
+                CommandQueue.Callbacks,
+                RotationLockControllerCallback,
+                Listener,
+                ZenModeController.Callback,
+                DeviceProvisionedListener,
+                KeyguardStateController.Callback,
+                LocationController.LocationChangeCallback,
+                RecordingController.RecordingStateChangeCallback {
     private static final String TAG = "PhoneStatusBarPolicy";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -110,7 +108,6 @@
     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;
@@ -138,7 +135,6 @@
     private final SensorPrivacyController mSensorPrivacyController;
     private final RecordingController mRecordingController;
     private final RingerModeTracker mRingerModeTracker;
-    private final MediaDataManager mMediaDataManager;
 
     private boolean mZenVisible;
     private boolean mVolumeVisible;
@@ -163,7 +159,6 @@
             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) {
@@ -190,7 +185,6 @@
         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);
@@ -208,7 +202,6 @@
         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;
@@ -287,11 +280,6 @@
         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);
@@ -308,7 +296,6 @@
         mSensorPrivacyController.addCallback(mSensorPrivacyListener);
         mLocationController.addCallback(this);
         mRecordingController.addCallback(this);
-        mMediaDataManager.addListener(this);
 
         mCommandQueue.addCallback(this);
     }
@@ -713,18 +700,4 @@
         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/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 19de191..e0e52001 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -143,7 +143,6 @@
 import com.android.systemui.charging.WirelessChargingAnimation;
 import com.android.systemui.classifier.FalsingLog;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.fragments.ExtensionFragmentListener;
 import com.android.systemui.fragments.FragmentHostManager;
@@ -511,7 +510,6 @@
     private final ScrimController mScrimController;
     protected DozeScrimController mDozeScrimController;
     private final Executor mUiBgExecutor;
-    private final Executor mMainExecutor;
 
     protected boolean mDozing;
 
@@ -670,7 +668,6 @@
             DisplayMetrics displayMetrics,
             MetricsLogger metricsLogger,
             @UiBackground Executor uiBgExecutor,
-            @Main Executor mainExecutor,
             NotificationMediaManager notificationMediaManager,
             NotificationLockscreenUserManager lockScreenUserManager,
             NotificationRemoteInputManager remoteInputManager,
@@ -751,7 +748,6 @@
         mDisplayMetrics = displayMetrics;
         mMetricsLogger = metricsLogger;
         mUiBgExecutor = uiBgExecutor;
-        mMainExecutor = mainExecutor;
         mMediaManager = notificationMediaManager;
         mLockscreenUserManager = lockScreenUserManager;
         mRemoteInputManager = remoteInputManager;
@@ -1279,8 +1275,7 @@
         mActivityLaunchAnimator = new ActivityLaunchAnimator(
                 mNotificationShadeWindowViewController, this, mNotificationPanelViewController,
                 mNotificationShadeDepthControllerLazy.get(),
-                (NotificationListContainer) mStackScroller,
-                mMainExecutor);
+                (NotificationListContainer) mStackScroller);
 
         // TODO: inject this.
         mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanelViewController,
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 64e5f0a..7bcfb46 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -350,7 +350,6 @@
         }
         Intent fillInIntent = null;
         NotificationEntry entry = row.getEntry();
-        final boolean isBubble = entry.isBubble();
         CharSequence remoteInputText = null;
         if (!TextUtils.isEmpty(entry.remoteInputText)) {
             remoteInputText = entry.remoteInputText;
@@ -359,14 +358,15 @@
             fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT,
                     remoteInputText.toString());
         }
-        if (isBubble) {
+        final boolean canBubble = entry.canBubble();
+        if (canBubble) {
             mLogger.logExpandingBubble(notificationKey);
-            expandBubbleStackOnMainThread(notificationKey);
+            expandBubbleStackOnMainThread(entry);
         } else {
             startNotificationIntent(
                     intent, fillInIntent, entry, row, wasOccluded, isActivityIntent);
         }
-        if (isActivityIntent || isBubble) {
+        if (isActivityIntent || canBubble) {
             mAssistManagerLazy.get().hideAssist();
         }
         if (shouldCollapse()) {
@@ -381,7 +381,7 @@
                 rank, count, true, location);
         mClickNotifier.onNotificationClick(notificationKey, nv);
 
-        if (!isBubble) {
+        if (!canBubble) {
             if (parentToCancelFinal != null) {
                 // TODO: (b/145659174) remove - this cancels the parent if the notification clicked
                 // on will auto-cancel and is the only child in the group. This won't be
@@ -398,12 +398,12 @@
         mIsCollapsingToShowActivityOverLockscreen = false;
     }
 
-    private void expandBubbleStackOnMainThread(String notificationKey) {
+    private void expandBubbleStackOnMainThread(NotificationEntry entry) {
         if (Looper.getMainLooper().isCurrentThread()) {
-            mBubbleController.expandStackAndSelectBubble(notificationKey);
+            mBubbleController.expandStackAndSelectBubble(entry);
         } else {
             mMainThreadHandler.post(
-                    () -> mBubbleController.expandStackAndSelectBubble(notificationKey));
+                    () -> mBubbleController.expandStackAndSelectBubble(entry));
         }
     }
 
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 669e6a4..72395e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -30,7 +30,6 @@
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.util.Log;
 import android.view.View;
 import android.view.ViewParent;
 
@@ -49,8 +48,6 @@
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
-import java.util.concurrent.atomic.AtomicReference;
-
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
@@ -58,8 +55,7 @@
  */
 @Singleton
 public class StatusBarRemoteInputCallback implements Callback, Callbacks,
-        StatusBarStateController.StateListener, KeyguardStateController.Callback {
-    private static final String TAG = StatusBarRemoteInputCallback.class.getSimpleName();
+        StatusBarStateController.StateListener {
 
     private final KeyguardStateController mKeyguardStateController;
     private final SysuiStatusBarStateController mStatusBarStateController;
@@ -78,7 +74,6 @@
     private int mDisabled2;
     protected BroadcastReceiver mChallengeReceiver = new ChallengeReceiver();
     private Handler mMainHandler = new Handler();
-    private final AtomicReference<Intent> mPendingConfirmCredentialIntent = new AtomicReference();
 
     /**
      */
@@ -107,9 +102,6 @@
         mActionClickLogger = clickLogger;
         mActivityIntentHelper = new ActivityIntentHelper(mContext);
         mGroupManager = groupManager;
-        // Listen to onKeyguardShowingChanged in case a managed profile needs to be unlocked
-        // once the primary profile's keyguard is no longer shown.
-        mKeyguardStateController.addCallback(this);
     }
 
     @Override
@@ -213,39 +205,12 @@
         // Clear pending remote view, as we do not want to trigger pending remote input view when
         // it's called by other code
         mPendingWorkRemoteInputView = null;
-
-        final Intent newIntent = createConfirmDeviceCredentialIntent(
-                userId, intendSender, notificationKey);
-        if (newIntent == null) {
-            Log.w(TAG, String.format("Cannot create intent to unlock user %d", userId));
-            return false;
-        }
-
-        mPendingConfirmCredentialIntent.set(newIntent);
-
-        // If the Keyguard is currently showing, starting the ConfirmDeviceCredentialActivity
-        // would cause it to pause, not letting the user actually unlock the managed profile.
-        // Instead, wait until we receive a callback indicating it is no longer showing and
-        // then start the pending intent.
-        if (mKeyguardStateController.isShowing()) {
-            // Do nothing, since the callback will get the pending intent and start it.
-            Log.w(TAG, String.format("Keyguard is showing, waiting until it's not"));
-        } else {
-            startPendingConfirmDeviceCredentialIntent();
-        }
-
-        return true;
-    }
-
-    private Intent createConfirmDeviceCredentialIntent(
-            int userId, IntentSender intendSender, String notificationKey) {
+        // Begin old BaseStatusBar.startWorkChallengeIfNecessary.
         final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
                 null, userId);
-
         if (newIntent == null) {
-            return null;
+            return false;
         }
-
         final Intent callBackIntent = new Intent(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
         callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender);
         callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey);
@@ -261,40 +226,14 @@
         newIntent.putExtra(
                 Intent.EXTRA_INTENT,
                 callBackPendingIntent.getIntentSender());
-
-        return newIntent;
-    }
-
-    private void startPendingConfirmDeviceCredentialIntent() {
-        final Intent pendingIntent = mPendingConfirmCredentialIntent.getAndSet(null);
-        if (pendingIntent == null) {
-            return;
-        }
-
         try {
-            if (mKeyguardStateController.isShowing()) {
-                Log.w(TAG, "Keyguard is showing while starting confirm device credential intent.");
-            }
-            ActivityManager.getService().startConfirmDeviceCredentialIntent(pendingIntent,
+            ActivityManager.getService().startConfirmDeviceCredentialIntent(newIntent,
                     null /*options*/);
         } catch (RemoteException ex) {
             // ignore
         }
-    }
-
-    @Override
-    public void onKeyguardShowingChanged() {
-        if (mKeyguardStateController.isShowing()) {
-            // In order to avoid jarring UX where/ the managed profile challenge is shown and
-            // immediately dismissed, do not attempt to start the confirm device credential
-            // activity if the keyguard is still showing.
-            if (mPendingConfirmCredentialIntent.get() != null) {
-                Log.w(TAG, "There's a pending unlock intent but keyguard is still showing, abort.");
-            }
-            return;
-        }
-
-        startPendingConfirmDeviceCredentialIntent();
+        return true;
+        // End old BaseStatusBar.startWorkChallengeIfNecessary.
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 62a3cf0..02e0312 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -33,7 +33,6 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -146,7 +145,6 @@
             DisplayMetrics displayMetrics,
             MetricsLogger metricsLogger,
             @UiBackground Executor uiBgExecutor,
-            @Main Executor mainExecutor,
             NotificationMediaManager notificationMediaManager,
             NotificationLockscreenUserManager lockScreenUserManager,
             NotificationRemoteInputManager remoteInputManager,
@@ -226,7 +224,6 @@
                 displayMetrics,
                 metricsLogger,
                 uiBgExecutor,
-                mainExecutor,
                 notificationMediaManager,
                 lockScreenUserManager,
                 remoteInputManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 412962c..db00770 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -409,18 +409,6 @@
         Log.e(TAG, "Couldn't switch to user, id=" + userId);
     }
 
-    public int getSwitchableUserCount() {
-        int count = 0;
-        final int N = mUsers.size();
-        for (int i = 0; i < N; ++i) {
-            UserRecord record = mUsers.get(i);
-            if (record.info != null && record.info.supportsSwitchToByUser()) {
-                count++;
-            }
-        }
-        return count;
-    }
-
     protected void switchToUserId(int id) {
         try {
             pauseRefreshUsers();
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/MeasurementCache.kt b/packages/SystemUI/src/com/android/systemui/util/animation/MeasurementCache.kt
deleted file mode 100644
index 2be698b..0000000
--- a/packages/SystemUI/src/com/android/systemui/util/animation/MeasurementCache.kt
+++ /dev/null
@@ -1,87 +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.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/MeasurementInput.kt b/packages/SystemUI/src/com/android/systemui/util/animation/MeasurementInput.kt
new file mode 100644
index 0000000..c7edd51
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/MeasurementInput.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.view.View
+
+/**
+ * The output of a view measurement
+ */
+data class MeasurementOutput(
+    var measuredWidth: Int,
+    var measuredHeight: Int
+)
+
+/**
+ * The data object holding a basic view measurement input
+ */
+data class MeasurementInput(
+    var widthMeasureSpec: Int,
+    var heightMeasureSpec: Int
+) {
+    val width: Int
+        get() {
+            return View.MeasureSpec.getSize(widthMeasureSpec)
+        }
+    val height: Int
+        get() {
+            return View.MeasureSpec.getSize(heightMeasureSpec)
+        }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt b/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt
new file mode 100644
index 0000000..701ff5e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt
@@ -0,0 +1,294 @@
+/*
+ * 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.content.Context
+import android.graphics.Rect
+import android.util.AttributeSet
+import android.view.View
+import android.view.ViewTreeObserver
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.constraintlayout.widget.ConstraintSet
+import com.android.systemui.statusbar.CrossFadeHelper
+
+/**
+ * A view that handles displaying of children and transitions of them in an optimized way,
+ * minimizing the number of measure passes, while allowing for maximum flexibility
+ * and interruptibility.
+ */
+class TransitionLayout @JvmOverloads constructor(
+    context: Context,
+    attrs: AttributeSet? = null,
+    defStyleAttr: Int = 0
+) : ConstraintLayout(context, attrs, defStyleAttr) {
+
+    private val originalGoneChildrenSet: MutableSet<Int> = mutableSetOf()
+    private var measureAsConstraint: Boolean = false
+    private var currentState: TransitionViewState = TransitionViewState()
+    private var updateScheduled = false
+
+    /**
+     * The measured state of this view which is the one we will lay ourselves out with. This
+     * may differ from the currentState if there is an external animation or transition running.
+     * This state will not be used to measure the widgets, where the current state is preferred.
+     */
+    var measureState: TransitionViewState = TransitionViewState()
+    private val preDrawApplicator = object : ViewTreeObserver.OnPreDrawListener {
+        override fun onPreDraw(): Boolean {
+            updateScheduled = false
+            viewTreeObserver.removeOnPreDrawListener(this)
+            applyCurrentState()
+            return true
+        }
+    }
+
+    override fun onFinishInflate() {
+        super.onFinishInflate()
+        val childCount = childCount
+        for (i in 0 until childCount) {
+            val child = getChildAt(i)
+            if (child.id == View.NO_ID) {
+                child.id = i
+            }
+            if (child.visibility == GONE) {
+                originalGoneChildrenSet.add(child.id)
+            }
+        }
+    }
+
+    /**
+     * Apply the current state to the view and its widgets
+     */
+    private fun applyCurrentState() {
+        val childCount = childCount
+        for (i in 0 until childCount) {
+            val child = getChildAt(i)
+            val widgetState = currentState.widgetStates.get(child.id) ?: continue
+            if (child.measuredWidth != widgetState.measureWidth ||
+                    child.measuredHeight != widgetState.measureHeight) {
+                val measureWidthSpec = MeasureSpec.makeMeasureSpec(widgetState.measureWidth,
+                        MeasureSpec.EXACTLY)
+                val measureHeightSpec = MeasureSpec.makeMeasureSpec(widgetState.measureHeight,
+                        MeasureSpec.EXACTLY)
+                child.measure(measureWidthSpec, measureHeightSpec)
+                child.layout(0, 0, child.measuredWidth, child.measuredHeight)
+            }
+            val left = widgetState.x.toInt()
+            val top = widgetState.y.toInt()
+            child.setLeftTopRightBottom(left, top, left + widgetState.width,
+                    top + widgetState.height)
+            child.scaleX = widgetState.scale
+            child.scaleY = widgetState.scale
+            val clipBounds = child.clipBounds ?: Rect()
+            clipBounds.set(0, 0, widgetState.width, widgetState.height)
+            child.clipBounds = clipBounds
+            CrossFadeHelper.fadeIn(child, widgetState.alpha)
+            child.visibility = if (widgetState.gone || widgetState.alpha == 0.0f) {
+                View.INVISIBLE
+            } else {
+                View.VISIBLE
+            }
+        }
+        updateBounds()
+    }
+
+    private fun applyCurrentStateOnPredraw() {
+        if (!updateScheduled) {
+            updateScheduled = true
+            viewTreeObserver.addOnPreDrawListener(preDrawApplicator)
+        }
+    }
+
+    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        if (measureAsConstraint) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+        } else {
+            for (i in 0 until childCount) {
+                val child = getChildAt(i)
+                val widgetState = currentState.widgetStates.get(child.id) ?: continue
+                val measureWidthSpec = MeasureSpec.makeMeasureSpec(widgetState.measureWidth,
+                        MeasureSpec.EXACTLY)
+                val measureHeightSpec = MeasureSpec.makeMeasureSpec(widgetState.measureHeight,
+                        MeasureSpec.EXACTLY)
+                child.measure(measureWidthSpec, measureHeightSpec)
+            }
+            setMeasuredDimension(measureState.width, measureState.height)
+        }
+    }
+
+    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
+        if (measureAsConstraint) {
+            super.onLayout(changed, left, top, right, bottom)
+        } else {
+            val childCount = childCount
+            for (i in 0 until childCount) {
+                val child = getChildAt(i)
+                child.layout(0, 0, child.measuredWidth, child.measuredHeight)
+            }
+            // Reapply the bounds to update the background
+            applyCurrentState()
+        }
+    }
+
+    private fun updateBounds() {
+        val layoutLeft = left
+        val layoutTop = top
+        setLeftTopRightBottom(layoutLeft, layoutTop, layoutLeft + currentState.width,
+                layoutTop + currentState.height)
+    }
+
+    /**
+     * Calculates a view state for a given ConstraintSet and measurement, saving all positions
+     * of all widgets.
+     *
+     * @param input the measurement input this should be done with
+     * @param constraintSet the constraint set to apply
+     * @param resusableState the result that we can reuse to minimize memory impact
+     */
+    fun calculateViewState(
+        input: MeasurementInput,
+        constraintSet: ConstraintSet,
+        existing: TransitionViewState? = null
+    ): TransitionViewState {
+
+        val result = existing ?: TransitionViewState()
+        // Reset gone children to the original state
+        applySetToFullLayout(constraintSet)
+        val previousHeight = measuredHeight
+        val previousWidth = measuredWidth
+
+        // Let's measure outselves as a ConstraintLayout
+        measureAsConstraint = true
+        measure(input.widthMeasureSpec, input.heightMeasureSpec)
+        val layoutLeft = left
+        val layoutTop = top
+        layout(layoutLeft, layoutTop, layoutLeft + measuredWidth, layoutTop + measuredHeight)
+        measureAsConstraint = false
+        result.initFromLayout(this)
+        ensureViewsNotGone()
+
+        // Let's reset our layout to have the right size again
+        setMeasuredDimension(previousWidth, previousHeight)
+        applyCurrentStateOnPredraw()
+        return result
+    }
+
+    private fun applySetToFullLayout(constraintSet: ConstraintSet) {
+        // Let's reset our views to the initial gone state of the layout, since the constraintset
+        // might only be a subset of the views. Otherwise the gone state would be calculated
+        // wrongly later if we made this invisible in the layout (during apply we make sure they
+        // are invisible instead
+        val childCount = childCount
+        for (i in 0 until childCount) {
+            val child = getChildAt(i)
+            if (originalGoneChildrenSet.contains(child.id)) {
+                child.visibility = View.GONE
+            }
+        }
+        // Let's now apply the constraintSet to get the full state
+        constraintSet.applyTo(this)
+    }
+
+    /**
+     * Ensures that our views are never gone but invisible instead, this allows us to animate them
+     * without remeasuring.
+     */
+    private fun ensureViewsNotGone() {
+        val childCount = childCount
+        for (i in 0 until childCount) {
+            val child = getChildAt(i)
+            val widgetState = currentState.widgetStates.get(child.id)
+            child.visibility = if (widgetState?.gone != false) View.INVISIBLE else View.VISIBLE
+        }
+    }
+
+    /**
+     * Set the state that should be applied to this View
+     *
+     */
+    fun setState(state: TransitionViewState) {
+        currentState = state
+        applyCurrentState()
+    }
+}
+
+class TransitionViewState {
+    var widgetStates: MutableMap<Int, WidgetState> = mutableMapOf()
+    var width: Int = 0
+    var height: Int = 0
+    fun copy(reusedState: TransitionViewState? = null): TransitionViewState {
+        // we need a deep copy of this, so we can't use a data class
+        val copy = reusedState ?: TransitionViewState()
+        copy.width = width
+        copy.height = height
+        for (entry in widgetStates) {
+            copy.widgetStates[entry.key] = entry.value.copy()
+        }
+        return copy
+    }
+
+    fun initFromLayout(transitionLayout: TransitionLayout) {
+        val childCount = transitionLayout.childCount
+        for (i in 0 until childCount) {
+            val child = transitionLayout.getChildAt(i)
+            val widgetState = widgetStates.getOrPut(child.id, {
+                WidgetState(0.0f, 0.0f, 0, 0, 0, 0, 0.0f)
+            })
+            widgetState.initFromLayout(child)
+        }
+        width = transitionLayout.measuredWidth
+        height = transitionLayout.measuredHeight
+    }
+}
+
+data class WidgetState(
+    var x: Float = 0.0f,
+    var y: Float = 0.0f,
+    var width: Int = 0,
+    var height: Int = 0,
+    var measureWidth: Int = 0,
+    var measureHeight: Int = 0,
+    var alpha: Float = 1.0f,
+    var scale: Float = 1.0f,
+    var gone: Boolean = false
+) {
+    fun initFromLayout(view: View) {
+        gone = view.visibility == View.GONE
+        if (gone) {
+            val layoutParams = view.layoutParams as ConstraintLayout.LayoutParams
+            x = layoutParams.constraintWidget.left.toFloat()
+            y = layoutParams.constraintWidget.top.toFloat()
+            width = layoutParams.constraintWidget.width
+            height = layoutParams.constraintWidget.height
+            measureHeight = height
+            measureWidth = width
+            alpha = 0.0f
+            scale = 0.0f
+        } else {
+            x = view.left.toFloat()
+            y = view.top.toFloat()
+            width = view.width
+            height = view.height
+            measureWidth = width
+            measureHeight = height
+            gone = view.visibility == View.GONE
+            alpha = view.alpha
+            // No scale by default. Only during transitions!
+            scale = 1.0f
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt b/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
new file mode 100644
index 0000000..9ee1410
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
@@ -0,0 +1,233 @@
+/*
+ * 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.animation.ValueAnimator
+import android.util.MathUtils
+import com.android.systemui.Interpolators
+
+/**
+ * The fraction after which we start fading in when going from a gone widget to a visible one
+ */
+private const val GONE_FADE_FRACTION = 0.8f
+
+/**
+ * The amont we're scaling appearing views
+ */
+private const val GONE_SCALE_AMOUNT = 0.8f
+
+/**
+ * A controller for a [TransitionLayout] which handles state transitions and keeps the transition
+ * layout up to date with the desired state.
+ */
+open class TransitionLayoutController {
+
+    /**
+     * The layout that this controller controls
+     */
+    private var transitionLayout: TransitionLayout? = null
+    private var currentState = TransitionViewState()
+    private var animationStartState: TransitionViewState? = null
+    private var state = TransitionViewState()
+    private var animator: ValueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f)
+
+    init {
+        animator.apply {
+            addUpdateListener {
+                updateStateFromAnimation()
+            }
+            interpolator = Interpolators.FAST_OUT_SLOW_IN
+        }
+    }
+
+    private fun updateStateFromAnimation() {
+        if (animationStartState == null || !animator.isRunning) {
+            return
+        }
+        val view = transitionLayout ?: return
+        getInterpolatedState(
+                startState = animationStartState!!,
+                endState = state,
+                progress = animator.animatedFraction,
+                resultState = currentState)
+        view.setState(currentState)
+    }
+
+    /**
+     * Get an interpolated state between two viewstates. This interpolates all positions for all
+     * widgets as well as it's bounds based on the given input.
+     */
+    fun getInterpolatedState(
+        startState: TransitionViewState,
+        endState: TransitionViewState,
+        progress: Float,
+        resultState: TransitionViewState
+    ) {
+        val view = transitionLayout ?: return
+        val childCount = view.childCount
+        for (i in 0 until childCount) {
+            val id = view.getChildAt(i).id
+            val resultWidgetState = resultState.widgetStates[id] ?: WidgetState()
+            val widgetStart = startState.widgetStates[id] ?: continue
+            val widgetEnd = endState.widgetStates[id] ?: continue
+            var alphaProgress = progress
+            var widthProgress = progress
+            val resultMeasureWidth: Int
+            val resultMeasureHeight: Int
+            val newScale: Float
+            val resultX: Float
+            val resultY: Float
+            if (widgetStart.gone != widgetEnd.gone) {
+                // A view is appearing or disappearing. Let's not just interpolate between them as
+                // this looks quite ugly
+                val nowGone: Boolean
+                if (widgetStart.gone) {
+
+                    // Only fade it in at the very end
+                    alphaProgress = MathUtils.map(GONE_FADE_FRACTION, 1.0f, 0.0f, 1.0f, progress)
+                    nowGone = progress < GONE_FADE_FRACTION
+
+                    // Scale it just a little, not all the way
+                    val endScale = widgetEnd.scale
+                    newScale = MathUtils.lerp(GONE_SCALE_AMOUNT * endScale, endScale, progress)
+
+                    // don't clip
+                    widthProgress = 1.0f
+
+                    // Let's directly measure it with the end state
+                    resultMeasureWidth = widgetEnd.measureWidth
+                    resultMeasureHeight = widgetEnd.measureHeight
+
+                    // Let's make sure we're centering the view in the gone view instead of having
+                    // the left at 0
+                    resultX = MathUtils.lerp(widgetStart.x - resultMeasureWidth / 2.0f,
+                            widgetEnd.x,
+                            progress)
+                    resultY = MathUtils.lerp(widgetStart.y - resultMeasureHeight / 2.0f,
+                            widgetEnd.y,
+                            progress)
+                } else {
+
+                    // Fadeout in the very beginning
+                    alphaProgress = MathUtils.map(0.0f, 1.0f - GONE_FADE_FRACTION, 0.0f, 1.0f,
+                            progress)
+                    nowGone = progress > 1.0f - GONE_FADE_FRACTION
+
+                    // Scale it just a little, not all the way
+                    val startScale = widgetStart.scale
+                    newScale = MathUtils.lerp(startScale, startScale * GONE_SCALE_AMOUNT, progress)
+
+                    // Don't clip
+                    widthProgress = 0.0f
+
+                    // Let's directly measure it with the start state
+                    resultMeasureWidth = widgetStart.measureWidth
+                    resultMeasureHeight = widgetStart.measureHeight
+
+                    // Let's make sure we're centering the view in the gone view instead of having
+                    // the left at 0
+                    resultX = MathUtils.lerp(widgetStart.x,
+                            widgetEnd.x - resultMeasureWidth / 2.0f,
+                            progress)
+                    resultY = MathUtils.lerp(widgetStart.y,
+                            widgetEnd.y - resultMeasureHeight / 2.0f,
+                            progress)
+                }
+                resultWidgetState.gone = nowGone
+            } else {
+                resultWidgetState.gone = widgetStart.gone
+                // Let's directly measure it with the end state
+                resultMeasureWidth = widgetEnd.measureWidth
+                resultMeasureHeight = widgetEnd.measureHeight
+                newScale = MathUtils.lerp(widgetStart.scale, widgetEnd.scale, progress)
+                resultX = MathUtils.lerp(widgetStart.x, widgetEnd.x, progress)
+                resultY = MathUtils.lerp(widgetStart.y, widgetEnd.y, progress)
+            }
+            resultWidgetState.apply {
+                x = resultX
+                y = resultY
+                alpha = MathUtils.lerp(widgetStart.alpha, widgetEnd.alpha, alphaProgress)
+                width = MathUtils.lerp(widgetStart.width.toFloat(), widgetEnd.width.toFloat(),
+                        widthProgress).toInt()
+                height = MathUtils.lerp(widgetStart.height.toFloat(), widgetEnd.height.toFloat(),
+                        widthProgress).toInt()
+                scale = newScale
+
+                // Let's directly measure it with the end state
+                measureWidth = resultMeasureWidth
+                measureHeight = resultMeasureHeight
+            }
+            resultState.widgetStates[id] = resultWidgetState
+        }
+        resultState.apply {
+            width = MathUtils.lerp(startState.width.toFloat(), endState.width.toFloat(),
+                    progress).toInt()
+            height = MathUtils.lerp(startState.height.toFloat(), endState.height.toFloat(),
+                    progress).toInt()
+        }
+    }
+
+    fun attach(transitionLayout: TransitionLayout) {
+        this.transitionLayout = transitionLayout
+    }
+
+    /**
+     * Set a new state to be applied to the dynamic view.
+     *
+     * @param state the state to be applied
+     * @param animate should this change be animated. If [false] the we will either apply the
+     * state immediately if no animation is running, and if one is running, we will update the end
+     * value to match the new state.
+     * @param applyImmediately should this change be applied immediately, canceling all running
+     * animations
+     */
+    fun setState(
+        state: TransitionViewState,
+        applyImmediately: Boolean,
+        animate: Boolean,
+        duration: Long = 0,
+        delay: Long = 0
+    ) {
+        val animated = animate && currentState.width != 0
+        this.state = state.copy()
+        if (applyImmediately || transitionLayout == null) {
+            animator.cancel()
+            transitionLayout?.setState(this.state)
+            currentState = state.copy(reusedState = currentState)
+        } else if (animated) {
+            animationStartState = currentState.copy()
+            animator.duration = duration
+            animator.startDelay = delay
+            animator.start()
+        } else if (!animator.isRunning) {
+            transitionLayout?.setState(this.state)
+            currentState = state.copy(reusedState = currentState)
+        }
+        // otherwise the desired state was updated and the animation will go to the new target
+    }
+
+    /**
+     * Set a new state that will be used to measure the view itself and is useful during
+     * transitions, where the state set via [setState] may differ from how the view
+     * should be measured.
+     */
+    fun setMeasureState(
+        state: TransitionViewState
+    ) {
+        transitionLayout?.measureState = state
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt b/packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
index bf94c5d..5b6444d 100644
--- a/packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
@@ -19,7 +19,9 @@
 import android.annotation.SuppressLint
 import android.content.Context
 import android.view.View
+import android.view.ViewGroup
 import android.widget.FrameLayout
+import com.android.systemui.R
 
 /**
  * A special view that is designed to host a single "unique object". The unique object is
@@ -34,8 +36,7 @@
 class UniqueObjectHostView(
     context: Context
 ) : FrameLayout(context) {
-    lateinit var measurementCache : GuaranteedMeasurementCache
-    var onMeasureListener: ((MeasurementInput) -> Unit)? = null
+    lateinit var measurementManager: MeasurementManager
 
     @SuppressLint("DrawAllocation")
     override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
@@ -45,64 +46,63 @@
         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)
-        }
+        val measurementInput = MeasurementInput(widthSpec, heightSpec)
+
+        // Let's make sure the measurementManager knows about our size, to ensure that we have
+        // a value available. This might perform a measure internally if we don't have a cached
+        // size.
+        val (cachedWidth, cachedHeight) = measurementManager.onMeasure(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)
+            // We're not currently the host, let's use the dimension from our cache
             // 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)
+            getChildAt(0)?.requiresRemeasuring = false
         }
     }
 
+    override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {
+        if (child?.measuredWidth == 0 || measuredWidth == 0 || child?.requiresRemeasuring == true) {
+            super.addView(child, index, params)
+            return
+        }
+        // Suppress layouts when adding a view. The view should already be laid out with the
+        // right size when being attached to this view
+        invalidate()
+        addViewInLayout(child, index, params, true /* preventRequestLayout */)
+        val left = paddingLeft
+        val top = paddingTop
+        val paddingHorizontal = paddingStart + paddingEnd
+        val paddingVertical = paddingTop + paddingBottom
+        child!!.layout(left,
+                top,
+                left + measuredWidth - paddingHorizontal,
+                top + measuredHeight - paddingVertical)
+    }
+
     private fun isCurrentHost() = childCount != 0
-}
 
-/**
- * A basic view measurement input
- */
-interface MeasurementInput {
-    fun sameAs(input: MeasurementInput?): Boolean {
-        return equals(input)
+    interface MeasurementManager {
+        fun onMeasure(input: MeasurementInput): MeasurementOutput
     }
-    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
+ * Does this view require remeasuring currently outside of the regular measure flow?
  */
-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
+var View.requiresRemeasuring: Boolean
+    get() {
+        val required = getTag(R.id.requires_remeasuring)
+        return required?.equals(true) ?: false
+    }
+    set(value) {
+        setTag(R.id.requires_remeasuring, value)
+    }
diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java
index 7729965..7c9ea6b 100644
--- a/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java
@@ -92,6 +92,15 @@
     }
 
     /**
+     * @deprecated Please specify @Main or @Background when injecting a Handler or use an Executor.
+     */
+    @Deprecated
+    @Provides
+    public static Handler provideHandler() {
+        return new Handler();
+    }
+
+    /**
      * Provide a Background-Thread Executor by default.
      */
     @Provides
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 96e868d..c89f6c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -50,6 +50,7 @@
 import android.os.Handler;
 import android.os.PowerManager;
 import android.service.dreams.IDreamManager;
+import android.service.notification.NotificationListenerService;
 import android.service.notification.ZenModeConfig;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -68,6 +69,7 @@
 import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationRemoveInterceptor;
+import com.android.systemui.statusbar.RankingBuilder;
 import com.android.systemui.statusbar.SuperStatusBarViewFactory;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
@@ -317,7 +319,7 @@
         verify(mNotificationEntryManager).updateNotifications(any());
 
         mBubbleController.removeBubble(
-                mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
         assertNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
         verify(mNotificationEntryManager, times(2)).updateNotifications(anyString());
 
@@ -329,7 +331,7 @@
         mBubbleController.updateBubble(mRow2.getEntry());
         mBubbleController.updateBubble(mRow.getEntry());
         mBubbleController.removeBubble(
-                mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
 
         Bubble b = mBubbleData.getOverflowBubbleWithKey(mRow.getEntry().getKey());
         assertThat(mBubbleData.getOverflowBubbles()).isEqualTo(ImmutableList.of(b));
@@ -350,9 +352,10 @@
         mBubbleController.updateBubble(mRow.getEntry(), /* suppressFlyout */
                 false, /* showInShade */ true);
         mBubbleController.removeBubble(
-                mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
 
-        mBubbleController.removeBubble(mRow.getEntry(), BubbleController.DISMISS_NOTIF_CANCEL);
+        mBubbleController.removeBubble(
+                mRow.getEntry().getKey(), BubbleController.DISMISS_NOTIF_CANCEL);
         verify(mNotificationEntryManager, times(1)).performRemoveNotification(
                 eq(mRow.getEntry().getSbn()), anyInt());
         assertThat(mBubbleData.getOverflowBubbles()).isEmpty();
@@ -365,7 +368,7 @@
         assertTrue(mBubbleController.hasBubbles());
 
         mBubbleController.removeBubble(
-                mRow.getEntry(), BubbleController.DISMISS_USER_CHANGED);
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_CHANGED);
         verify(mNotificationEntryManager, never()).performRemoveNotification(
                 eq(mRow.getEntry().getSbn()), anyInt());
         assertFalse(mBubbleController.hasBubbles());
@@ -563,7 +566,8 @@
 
         // Dismiss currently expanded
         mBubbleController.removeBubble(
-                mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry(),
+                mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey())
+                        .getEntry().getKey(),
                 BubbleController.DISMISS_USER_GESTURE);
         verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
 
@@ -574,7 +578,8 @@
 
         // Dismiss that one
         mBubbleController.removeBubble(
-                mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry(),
+                mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey())
+                        .getEntry().getKey(),
                 BubbleController.DISMISS_USER_GESTURE);
 
         // Make sure state changes and collapse happens
@@ -674,7 +679,7 @@
         mRemoveInterceptor.onNotificationRemoveRequested(
                 mRow.getEntry().getKey(), mRow.getEntry(), REASON_APP_CANCEL);
 
-        mBubbleController.expandStackAndSelectBubble(key);
+        mBubbleController.expandStackAndSelectBubble(mRow.getEntry());
 
         assertTrue(mSysUiStateBubblesExpanded);
     }
@@ -700,7 +705,7 @@
     @Test
     public void testDeleteIntent_removeBubble_aged() throws PendingIntent.CanceledException {
         mBubbleController.updateBubble(mRow.getEntry());
-        mBubbleController.removeBubble(mRow.getEntry(), BubbleController.DISMISS_AGED);
+        mBubbleController.removeBubble(mRow.getEntry().getKey(), BubbleController.DISMISS_AGED);
         verify(mDeleteIntent, never()).send();
     }
 
@@ -708,7 +713,7 @@
     public void testDeleteIntent_removeBubble_user() throws PendingIntent.CanceledException {
         mBubbleController.updateBubble(mRow.getEntry());
         mBubbleController.removeBubble(
-                mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
         verify(mDeleteIntent, times(1)).send();
     }
 
@@ -727,6 +732,9 @@
         assertTrue(mBubbleController.hasBubbles());
 
         mRow.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
+        NotificationListenerService.Ranking ranking = new RankingBuilder(
+                mRow.getEntry().getRanking()).setCanBubble(false).build();
+        mRow.getEntry().setRanking(ranking);
         mEntryListener.onPreEntryUpdated(mRow.getEntry());
 
         assertFalse(mBubbleController.hasBubbles());
@@ -808,7 +816,7 @@
 
         // Dismiss the bubble into overflow.
         mBubbleController.removeBubble(
-                mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
         assertFalse(mBubbleController.hasBubbles());
 
         boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
@@ -829,7 +837,7 @@
                 mRow.getEntry()));
 
         mBubbleController.removeBubble(
-                mRow.getEntry(), BubbleController.DISMISS_NO_LONGER_BUBBLE);
+                mRow.getEntry().getKey(), BubbleController.DISMISS_NO_LONGER_BUBBLE);
         assertFalse(mBubbleController.hasBubbles());
 
         boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
@@ -851,12 +859,12 @@
 
         mBubbleData.setMaxOverflowBubbles(1);
         mBubbleController.removeBubble(
-                mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
         assertEquals(mBubbleData.getBubbles().size(), 2);
         assertEquals(mBubbleData.getOverflowBubbles().size(), 1);
 
         mBubbleController.removeBubble(
-                mRow2.getEntry(), BubbleController.DISMISS_USER_GESTURE);
+                mRow2.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
         // Overflow max of 1 is reached; mRow is oldest, so it gets removed
         verify(mNotificationEntryManager, times(1)).performRemoveNotification(
                 mRow.getEntry().getSbn(), REASON_CANCEL);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
index 66f119a..8224c88e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
@@ -20,11 +20,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
@@ -180,7 +177,8 @@
         mBubbleData.setListener(mListener);
 
         // Test
-        mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleData.notificationEntryRemoved(
+                mEntryA1.getKey(), BubbleController.DISMISS_USER_GESTURE);
 
         // Verify
         verifyUpdateReceived();
@@ -258,14 +256,15 @@
         assertThat(update.updatedBubble.showFlyout()).isFalse();
     }
 
-    // COLLAPSED / ADD
+    //
+    // Overflow
+    //
 
     /**
-     * Verifies that the number of bubbles is not allowed to exceed the maximum. The limit is
-     * enforced by expiring the bubble which was least recently updated (lowest timestamp).
+     * Verifies that when the bubble stack reaches its maximum, the oldest bubble is overflowed.
      */
     @Test
-    public void test_collapsed_addBubble_atMaxBubbles_overflowsOldest() {
+    public void testOverflow_add_stackAtMaxBubbles_overflowsOldest() {
         // Setup
         sendUpdatedEntryAtTime(mEntryA1, 1000);
         sendUpdatedEntryAtTime(mEntryA2, 2000);
@@ -288,8 +287,12 @@
         assertOverflowChangedTo(ImmutableList.of(mBubbleA2));
     }
 
+    /**
+     * Verifies that once the number of overflowed bubbles reaches its maximum, the oldest
+     * overflow bubble is removed.
+     */
     @Test
-    public void testOverflowBubble_maxReached_bubbleRemoved() {
+    public void testOverflow_maxReached_bubbleRemoved() {
         // Setup
         sendUpdatedEntryAtTime(mEntryA1, 1000);
         sendUpdatedEntryAtTime(mEntryA2, 2000);
@@ -297,27 +300,56 @@
         mBubbleData.setListener(mListener);
 
         mBubbleData.setMaxOverflowBubbles(1);
-        mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleData.notificationEntryRemoved(
+                mEntryA1.getKey(), BubbleController.DISMISS_USER_GESTURE);
         verifyUpdateReceived();
         assertOverflowChangedTo(ImmutableList.of(mBubbleA1));
 
         // Overflow max of 1 is reached; A1 is oldest, so it gets removed
-        mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleData.notificationEntryRemoved(
+                mEntryA2.getKey(), BubbleController.DISMISS_USER_GESTURE);
         verifyUpdateReceived();
         assertOverflowChangedTo(ImmutableList.of(mBubbleA2));
     }
 
     /**
-     * Verifies that new bubbles insert to the left when collapsed, carrying along grouped bubbles.
-     * <p>
-     * Placement within the list is based on lastUpdate (post time of the notification), descending
-     * order (with most recent first).
-     *
-     * @see #test_expanded_addBubble_sortAndGrouping_newGroup()
-     * @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
+     * Verifies that overflow bubbles are canceled on notif entry removal.
      */
     @Test
-    public void test_collapsed_addBubble_sortAndGrouping() {
+    public void testOverflow_notifCanceled_removesOverflowBubble() {
+        // Setup
+        sendUpdatedEntryAtTime(mEntryA1, 1000);
+        sendUpdatedEntryAtTime(mEntryA2, 2000);
+        sendUpdatedEntryAtTime(mEntryA3, 3000);
+        sendUpdatedEntryAtTime(mEntryB1, 4000);
+        sendUpdatedEntryAtTime(mEntryB2, 5000);
+        sendUpdatedEntryAtTime(mEntryB3, 6000); // [A2, A3, B1, B2, B3], overflow: [A1]
+        sendUpdatedEntryAtTime(mEntryC1, 7000); // [A3, B1, B2, B3, C1], overflow: [A2, A1]
+        mBubbleData.setListener(mListener);
+
+        // Test
+        mBubbleData.notificationEntryRemoved(mEntryA1.getKey(),
+                BubbleController.DISMISS_NOTIF_CANCEL);
+        verifyUpdateReceived();
+        assertOverflowChangedTo(ImmutableList.of(mBubbleA2));
+
+        // Test
+        mBubbleData.notificationEntryRemoved(mEntryA2.getKey(),
+                BubbleController.DISMISS_GROUP_CANCELLED);
+        verifyUpdateReceived();
+        assertOverflowChangedTo(ImmutableList.of());
+    }
+
+    // COLLAPSED / ADD
+
+    /**
+     * Verifies that new bubbles insert to the left when collapsed.
+     * <p>
+     * Placement within the list is based on {@link Bubble#getLastActivity()}, descending
+     * order (with most recent first).
+     */
+    @Test
+    public void test_collapsed_addBubble() {
         // Setup
         mBubbleData.setListener(mListener);
 
@@ -336,41 +368,7 @@
 
         sendUpdatedEntryAtTime(mEntryA2, 4000);
         verifyUpdateReceived();
-        assertOrderChangedTo(mBubbleA2, mBubbleA1, mBubbleB2, mBubbleB1);
-    }
-
-    /**
-     * Verifies that new bubbles insert to the left when collapsed, carrying along grouped bubbles.
-     * Additionally, any bubble which is ongoing is considered "newer" than any non-ongoing bubble.
-     * <p>
-     * Because of the ongoing bubble, the new bubble cannot be placed in the first position. This
-     * causes the 'B' group to remain last, despite having a new button added.
-     *
-     * @see #test_expanded_addBubble_sortAndGrouping_newGroup()
-     * @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
-     */
-    @Test
-    public void test_collapsed_addBubble_sortAndGrouping_withOngoing() {
-        // Setup
-        mBubbleData.setListener(mListener);
-
-        // Test
-        setOngoing(mEntryA1, true);
-        sendUpdatedEntryAtTime(mEntryA1, 1000);
-        verifyUpdateReceived();
-        assertOrderNotChanged();
-
-        sendUpdatedEntryAtTime(mEntryB1, 2000);
-        verifyUpdateReceived();
-        assertOrderNotChanged();
-
-        sendUpdatedEntryAtTime(mEntryB2, 3000);
-        verifyUpdateReceived();
-        assertOrderChangedTo(mBubbleA1, mBubbleB2, mBubbleB1);
-
-        sendUpdatedEntryAtTime(mEntryA2, 4000);
-        verifyUpdateReceived();
-        assertOrderChangedTo(mBubbleA1, mBubbleA2, mBubbleB2, mBubbleB1);
+        assertOrderChangedTo(mBubbleA2, mBubbleB2, mBubbleB1, mBubbleA1);
     }
 
     /**
@@ -378,7 +376,6 @@
      * the collapsed state.
      *
      * @see #test_collapsed_updateBubble_selectionChanges()
-     * @see #test_collapsed_updateBubble_noSelectionChanges_withOngoing()
      */
     @Test
     public void test_collapsed_addBubble_selectionChanges() {
@@ -403,58 +400,28 @@
         assertSelectionChangedTo(mBubbleA2);
     }
 
-    /**
-     * Verifies that while collapsed, the selection will not change if the selected bubble is
-     * ongoing. It remains the top bubble and as such remains selected.
-     *
-     * @see #test_collapsed_addBubble_selectionChanges()
-     */
-    @Test
-    public void test_collapsed_addBubble_noSelectionChanges_withOngoing() {
-        // Setup
-        setOngoing(mEntryA1, true);
-        sendUpdatedEntryAtTime(mEntryA1, 1000);
-        assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA1);
-        mBubbleData.setListener(mListener);
-
-        // Test
-        sendUpdatedEntryAtTime(mEntryB1, 2000);
-        verifyUpdateReceived();
-        assertSelectionNotChanged();
-
-        sendUpdatedEntryAtTime(mEntryB2, 3000);
-        verifyUpdateReceived();
-        assertSelectionNotChanged();
-
-        sendUpdatedEntryAtTime(mEntryA2, 4000);
-        verifyUpdateReceived();
-        assertSelectionNotChanged();
-
-        assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA1); // selection unchanged
-    }
-
     // COLLAPSED / REMOVE
 
     /**
-     * Verifies that groups may reorder when bubbles are removed, while the stack is in the
-     * collapsed state.
+     * Verifies order of bubbles after a removal.
      */
     @Test
-    public void test_collapsed_removeBubble_sortAndGrouping() {
+    public void test_collapsed_removeBubble_sort() {
         // Setup
         sendUpdatedEntryAtTime(mEntryA1, 1000);
         sendUpdatedEntryAtTime(mEntryB1, 2000);
         sendUpdatedEntryAtTime(mEntryB2, 3000);
-        sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, A1, B2, B1]
+        sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, B2, B1, A1]
         mBubbleData.setListener(mListener);
 
         // Test
-        mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleData.notificationEntryRemoved(
+                mEntryA2.getKey(), BubbleController.DISMISS_USER_GESTURE);
         verifyUpdateReceived();
+        // TODO: this should fail if things work as I expect them to?
         assertOrderChangedTo(mBubbleB2, mBubbleB1, mBubbleA1);
     }
 
-
     /**
      * Verifies that onOrderChanged is not called when a bubble is removed if the removal does not
      * cause other bubbles to change position.
@@ -465,62 +432,17 @@
         sendUpdatedEntryAtTime(mEntryA1, 1000);
         sendUpdatedEntryAtTime(mEntryB1, 2000);
         sendUpdatedEntryAtTime(mEntryB2, 3000);
-        sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, A1, B2, B1]
+        sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, B2, B1, A1]
         mBubbleData.setListener(mListener);
 
         // Test
-        mBubbleData.notificationEntryRemoved(mEntryB1, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleData.notificationEntryRemoved(
+                mEntryA1.getKey(), BubbleController.DISMISS_USER_GESTURE);
         verifyUpdateReceived();
         assertOrderNotChanged();
     }
 
     /**
-     * Verifies that bubble ordering reverts to normal when an ongoing bubble is removed. A group
-     * which has a newer bubble may move to the front after the ongoing bubble is removed.
-     */
-    @Test
-    public void test_collapsed_removeBubble_sortAndGrouping_withOngoing() {
-        // Setup
-        setOngoing(mEntryA1, true);
-        sendUpdatedEntryAtTime(mEntryA1, 1000);
-        sendUpdatedEntryAtTime(mEntryA2, 2000);
-        sendUpdatedEntryAtTime(mEntryB1, 3000);
-        sendUpdatedEntryAtTime(mEntryB2, 4000); // [A1*, A2, B2, B1]
-        mBubbleData.setListener(mListener);
-
-        // Test
-        mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_NOTIF_CANCEL);
-        verifyUpdateReceived();
-        assertOrderChangedTo(mBubbleB2, mBubbleB1, mBubbleA2);
-    }
-
-    /**
-     * Verifies that overflow bubbles are canceled on notif entry removal.
-     */
-    @Test
-    public void test_removeOverflowBubble_forCanceledNotif() {
-        // Setup
-        sendUpdatedEntryAtTime(mEntryA1, 1000);
-        sendUpdatedEntryAtTime(mEntryA2, 2000);
-        sendUpdatedEntryAtTime(mEntryA3, 3000);
-        sendUpdatedEntryAtTime(mEntryB1, 4000);
-        sendUpdatedEntryAtTime(mEntryB2, 5000);
-        sendUpdatedEntryAtTime(mEntryB3, 6000); // [A2, A3, B1, B2, B3], overflow: [A1]
-        sendUpdatedEntryAtTime(mEntryC1, 7000); // [A3, B1, B2, B3, C1], overflow: [A2, A1]
-        mBubbleData.setListener(mListener);
-
-        // Test
-        mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_NOTIF_CANCEL);
-        verifyUpdateReceived();
-        assertOverflowChangedTo(ImmutableList.of(mBubbleA2));
-
-        // Test
-        mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_GROUP_CANCELLED);
-        verifyUpdateReceived();
-        assertOverflowChangedTo(ImmutableList.of());
-    }
-
-    /**
      * Verifies that when the selected bubble is removed with the stack in the collapsed state,
      * the selection moves to the next most-recently updated bubble.
      */
@@ -530,11 +452,12 @@
         sendUpdatedEntryAtTime(mEntryA1, 1000);
         sendUpdatedEntryAtTime(mEntryB1, 2000);
         sendUpdatedEntryAtTime(mEntryB2, 3000);
-        sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, A1, B2, B1]
+        sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, B2, B1, A1]
         mBubbleData.setListener(mListener);
 
         // Test
-        mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_NOTIF_CANCEL);
+        mBubbleData.notificationEntryRemoved(
+                mEntryA2.getKey(), BubbleController.DISMISS_NOTIF_CANCEL);
         verifyUpdateReceived();
         assertSelectionChangedTo(mBubbleB2);
     }
@@ -542,26 +465,26 @@
     // COLLAPSED / UPDATE
 
     /**
-     * Verifies that bubble and group ordering may change with updates while the stack is in the
+     * Verifies that bubble ordering changes with updates while the stack is in the
      * collapsed state.
      */
     @Test
-    public void test_collapsed_updateBubble_orderAndGrouping() {
+    public void test_collapsed_updateBubble() {
         // Setup
         sendUpdatedEntryAtTime(mEntryA1, 1000);
         sendUpdatedEntryAtTime(mEntryB1, 2000);
         sendUpdatedEntryAtTime(mEntryB2, 3000);
-        sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, A1, B2, B1]
+        sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, B2, B1, A1]
         mBubbleData.setListener(mListener);
 
         // Test
         sendUpdatedEntryAtTime(mEntryB1, 5000);
         verifyUpdateReceived();
-        assertOrderChangedTo(mBubbleB1, mBubbleB2, mBubbleA2, mBubbleA1);
+        assertOrderChangedTo(mBubbleB1, mBubbleA2, mBubbleB2, mBubbleA1);
 
         sendUpdatedEntryAtTime(mEntryA1, 6000);
         verifyUpdateReceived();
-        assertOrderChangedTo(mBubbleA1, mBubbleA2, mBubbleB1, mBubbleB2);
+        assertOrderChangedTo(mBubbleA1, mBubbleB1, mBubbleA2, mBubbleB2);
     }
 
     /**
@@ -573,7 +496,7 @@
         sendUpdatedEntryAtTime(mEntryA1, 1000);
         sendUpdatedEntryAtTime(mEntryB1, 2000);
         sendUpdatedEntryAtTime(mEntryB2, 3000);
-        sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, A1, B2, B1]
+        sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, B2, B1, A1]
         mBubbleData.setListener(mListener);
 
         // Test
@@ -587,26 +510,6 @@
     }
 
     /**
-     * Verifies that selection does not change in response to updates when collapsed, if the
-     * selected bubble is ongoing.
-     */
-    @Test
-    public void test_collapsed_updateBubble_noSelectionChanges_withOngoing() {
-        // Setup
-        setOngoing(mEntryA1, true);
-        sendUpdatedEntryAtTime(mEntryA1, 1000);
-        sendUpdatedEntryAtTime(mEntryB1, 2000);
-        sendUpdatedEntryAtTime(mEntryB2, 3000);
-        sendUpdatedEntryAtTime(mEntryA2, 4000); // [A1*, A2, B2, B1]
-        mBubbleData.setListener(mListener);
-
-        // Test
-        sendUpdatedEntryAtTime(mEntryB2, 5000); // [A1*, A2, B2, B1]
-        verifyUpdateReceived();
-        assertSelectionNotChanged();
-    }
-
-    /**
      * Verifies that a request to expand the stack has no effect if there are no bubbles.
      */
     @Test
@@ -618,6 +521,9 @@
         verifyZeroInteractions(mListener);
     }
 
+    /**
+     * Verifies that removing the last bubble clears the selected bubble and collapses the stack.
+     */
     @Test
     public void test_collapsed_removeLastBubble_clearsSelectedBubble() {
         // Setup
@@ -625,27 +531,27 @@
         mBubbleData.setListener(mListener);
 
         // Test
-        mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleData.notificationEntryRemoved(
+                mEntryA1.getKey(), BubbleController.DISMISS_USER_GESTURE);
 
         // Verify the selection was cleared.
         verifyUpdateReceived();
+        assertThat(mBubbleData.isExpanded()).isFalse();
         assertSelectionCleared();
     }
 
-    // EXPANDED / ADD
+    // EXPANDED / ADD / UPDATE
 
     /**
-     * Verifies that bubbles added as part of a new group insert before existing groups while
-     * expanded.
+     * Verifies that bubbles are added at the front of the stack.
      * <p>
-     * Placement within the list is based on lastUpdate (post time of the notification), descending
+     * Placement within the list is based on {@link Bubble#getLastActivity()}, descending
      * order (with most recent first).
      *
-     * @see #test_collapsed_addBubble_sortAndGrouping()
-     * @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
+     * @see #test_collapsed_addBubble()
      */
     @Test
-    public void test_expanded_addBubble_sortAndGrouping_newGroup() {
+    public void test_expanded_addBubble() {
         // Setup
         sendUpdatedEntryAtTime(mEntryA1, 1000);
         sendUpdatedEntryAtTime(mEntryA2, 2000);
@@ -656,65 +562,15 @@
         // Test
         sendUpdatedEntryAtTime(mEntryC1, 4000);
         verifyUpdateReceived();
-        assertOrderChangedTo(mBubbleB1, mBubbleC1, mBubbleA2, mBubbleA1);
+        assertOrderChangedTo(mBubbleC1, mBubbleB1, mBubbleA2, mBubbleA1);
     }
 
     /**
-     * Verifies that bubbles added as part of a new group insert before existing groups while
-     * expanded, but not before any groups with ongoing bubbles.
-     *
-     * @see #test_collapsed_addBubble_sortAndGrouping_withOngoing()
-     * @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
-     */
-    @Test
-    public void test_expanded_addBubble_sortAndGrouping_newGroup_withOngoing() {
-        // Setup
-        setOngoing(mEntryA1, true);
-        sendUpdatedEntryAtTime(mEntryA1, 1000);
-        sendUpdatedEntryAtTime(mEntryA2, 2000);
-        sendUpdatedEntryAtTime(mEntryB1, 3000); // [A1*, A2, B1]
-        changeExpandedStateAtTime(true, 4000L);
-        mBubbleData.setListener(mListener);
-
-        // Test
-        sendUpdatedEntryAtTime(mEntryC1, 4000);
-        verifyUpdateReceived();
-        assertOrderChangedTo(mBubbleA1, mBubbleA2, mBubbleC1, mBubbleB1);
-    }
-
-    /**
-     * Verifies that bubbles added as part of an existing group insert to the beginning of that
-     * group. The order of groups within the list must not change while in the expanded state.
-     *
-     * @see #test_collapsed_addBubble_sortAndGrouping()
-     * @see #test_expanded_addBubble_sortAndGrouping_newGroup()
-     */
-    @Test
-    public void test_expanded_addBubble_sortAndGrouping_existingGroup() {
-        // Setup
-        sendUpdatedEntryAtTime(mEntryA1, 1000);
-        sendUpdatedEntryAtTime(mEntryA2, 2000);
-        sendUpdatedEntryAtTime(mEntryB1, 3000); // [B1, A2, A1]
-        changeExpandedStateAtTime(true, 4000L);
-        mBubbleData.setListener(mListener);
-
-        // Test
-        sendUpdatedEntryAtTime(mEntryA3, 4000);
-        verifyUpdateReceived();
-        assertOrderChangedTo(mBubbleB1, mBubbleA3, mBubbleA2, mBubbleA1);
-    }
-
-    // EXPANDED / UPDATE
-
-    /**
      * Verifies that updates to bubbles while expanded do not result in any change to sorting
-     * or grouping of bubbles or sorting of groups.
-     *
-     * @see #test_collapsed_addBubble_sortAndGrouping()
-     * @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
+     * of bubbles.
      */
     @Test
-    public void test_expanded_updateBubble_sortAndGrouping_noChanges() {
+    public void test_expanded_updateBubble_noChanges() {
         // Setup
         sendUpdatedEntryAtTime(mEntryA1, 1000);
         sendUpdatedEntryAtTime(mEntryA2, 2000);
@@ -733,7 +589,6 @@
      * Verifies that updates to bubbles while expanded do not result in any change to selection.
      *
      * @see #test_collapsed_addBubble_selectionChanges()
-     * @see #test_collapsed_updateBubble_noSelectionChanges_withOngoing()
      */
     @Test
     public void test_expanded_updateBubble_noSelectionChanges() {
@@ -762,26 +617,25 @@
     // EXPANDED / REMOVE
 
     /**
-     * Verifies that removing a bubble while expanded does not result in reordering of groups
-     * or any of the remaining bubbles.
+     * Verifies that removing a bubble while expanded does not result in reordering of bubbles.
      *
-     * @see #test_collapsed_addBubble_sortAndGrouping()
-     * @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
+     * @see #test_collapsed_addBubble()
      */
     @Test
-    public void test_expanded_removeBubble_sortAndGrouping() {
+    public void test_expanded_removeBubble() {
         // Setup
         sendUpdatedEntryAtTime(mEntryA1, 1000);
         sendUpdatedEntryAtTime(mEntryB1, 2000);
         sendUpdatedEntryAtTime(mEntryA2, 3000);
-        sendUpdatedEntryAtTime(mEntryB2, 4000); // [B2, B1, A2, A1]
+        sendUpdatedEntryAtTime(mEntryB2, 4000); // [B2, A2, B1, A1]
         changeExpandedStateAtTime(true, 5000L);
         mBubbleData.setListener(mListener);
 
         // Test
-        mBubbleData.notificationEntryRemoved(mEntryB2, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleData.notificationEntryRemoved(
+                mEntryB2.getKey(), BubbleController.DISMISS_USER_GESTURE);
         verifyUpdateReceived();
-        assertOrderChangedTo(mBubbleB1, mBubbleA2, mBubbleA1);
+        assertOrderChangedTo(mBubbleA2, mBubbleB1, mBubbleA1);
     }
 
     /**
@@ -789,8 +643,7 @@
      * selected. The replacement selection is the bubble which appears at the same index as the
      * previous one, or the previous index if this was the last position.
      *
-     * @see #test_collapsed_addBubble_sortAndGrouping()
-     * @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
+     * @see #test_collapsed_addBubble()
      */
     @Test
     public void test_expanded_removeBubble_selectionChanges_whenSelectedRemoved() {
@@ -800,17 +653,19 @@
         sendUpdatedEntryAtTime(mEntryA2, 3000);
         sendUpdatedEntryAtTime(mEntryB2, 4000);
         changeExpandedStateAtTime(true, 5000L);
-        mBubbleData.setSelectedBubble(mBubbleA2);  // [B2, B1, ^A2, A1]
+        mBubbleData.setSelectedBubble(mBubbleA2);  // [B2, A2^, B1, A1]
         mBubbleData.setListener(mListener);
 
         // Test
-        mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_USER_GESTURE);
-        verifyUpdateReceived();
-        assertSelectionChangedTo(mBubbleA1);
-
-        mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleData.notificationEntryRemoved(
+                mEntryA2.getKey(), BubbleController.DISMISS_USER_GESTURE);
         verifyUpdateReceived();
         assertSelectionChangedTo(mBubbleB1);
+
+        mBubbleData.notificationEntryRemoved(
+                mEntryB1.getKey(), BubbleController.DISMISS_USER_GESTURE);
+        verifyUpdateReceived();
+        assertSelectionChangedTo(mBubbleA1);
     }
 
     @Test
@@ -838,7 +693,6 @@
      * expanded.
      * <p>
      * When the stack transitions to the collapsed state, the selected bubble is brought to the top.
-     * Bubbles within the same group should move up with it.
      * <p>
      * When the stack transitions back to the expanded state, this new order is kept as is.
      */
@@ -849,13 +703,13 @@
         sendUpdatedEntryAtTime(mEntryB1, 2000);
         sendUpdatedEntryAtTime(mEntryA2, 3000);
         sendUpdatedEntryAtTime(mEntryB2, 4000);
-        changeExpandedStateAtTime(true, 5000L); // [B2=4000, B1=2000, A2=3000, A1=1000]
-        sendUpdatedEntryAtTime(mEntryB1, 6000); // [B2=4000, B1=6000*, A2=3000, A1=1000]
+        changeExpandedStateAtTime(true, 5000L); // [B2=4000, A2=3000, B1=2000, A1=1000]
+        sendUpdatedEntryAtTime(mEntryB1, 6000); // [B2=4000, A2=3000, B1=6000, A1=1000]
         setCurrentTime(7000);
         mBubbleData.setSelectedBubble(mBubbleA2);
         mBubbleData.setListener(mListener);
         assertThat(mBubbleData.getBubbles()).isEqualTo(
-                ImmutableList.of(mBubbleB2, mBubbleB1, mBubbleA2, mBubbleA1));
+                ImmutableList.of(mBubbleB2, mBubbleA2, mBubbleB1, mBubbleA1));
 
         // Test
 
@@ -863,18 +717,17 @@
         // stack is expanded. When next collapsed, sorting will be applied and saved, just prior
         // to moving the selected bubble to the top (first).
         //
-        // In this case, the expected re-expand state will be: [A2, A1, B1, B2]
+        // In this case, the expected re-expand state will be: [A2^, B1, B2, A1]
         //
         // collapse -> selected bubble (A2) moves first.
         changeExpandedStateAtTime(false, 8000L);
         verifyUpdateReceived();
-        assertOrderChangedTo(mBubbleA2, mBubbleA1, mBubbleB1, mBubbleB2);
+        assertOrderChangedTo(mBubbleA2, mBubbleB1, mBubbleB2, mBubbleA1);
     }
 
     /**
      * When a change occurs while collapsed (any update, add, remove), the previous expanded
-     * order and grouping becomes invalidated, and the order and grouping when next expanded will
-     * remain the same as collapsed.
+     * order becomes invalidated, the stack is resorted and will reflect that when next expanded.
      */
     @Test
     public void test_expansionChanges_withUpdatesWhileCollapsed() {
@@ -883,10 +736,10 @@
         sendUpdatedEntryAtTime(mEntryB1, 2000);
         sendUpdatedEntryAtTime(mEntryA2, 3000);
         sendUpdatedEntryAtTime(mEntryB2, 4000);
-        changeExpandedStateAtTime(true, 5000L); // [B2=4000, B1=2000, A2=3000, A1=1000]
-        sendUpdatedEntryAtTime(mEntryB1, 6000); // [B2=4000, B1=*6000, A2=3000, A1=1000]
+        changeExpandedStateAtTime(true, 5000L); // [B2=4000, A2=3000,  B1=2000, A1=1000]
+        sendUpdatedEntryAtTime(mEntryB1, 6000); // [B2=4000, A2=3000,  B1=6000, A1=1000]
         setCurrentTime(7000);
-        mBubbleData.setSelectedBubble(mBubbleA2); // [B2, B1, ^A2, A1]
+        mBubbleData.setSelectedBubble(mBubbleA2); // [B2, A2^, B1, A1]
         mBubbleData.setListener(mListener);
 
         // Test
@@ -895,7 +748,7 @@
         // stack is expanded. When next collapsed, sorting will be applied and saved, just prior
         // to moving the selected bubble to the top (first).
         //
-        // In this case, the expected re-expand state will be: [B1, B2, A2*, A1]
+        // In this case, the expected re-expand state will be: [A2^, B1, B2, A1]
         //
         // That state is restored as long as no changes occur (add/remove/update) while in
         // the collapsed state.
@@ -903,11 +756,12 @@
         // collapse -> selected bubble (A2) moves first.
         changeExpandedStateAtTime(false, 8000L);
         verifyUpdateReceived();
-        assertOrderChangedTo(mBubbleA2, mBubbleA1, mBubbleB1, mBubbleB2);
+        assertOrderChangedTo(mBubbleA2, mBubbleB1, mBubbleB2, mBubbleA1);
 
         // An update occurs, which causes sorting, and this invalidates the previously saved order.
-        sendUpdatedEntryAtTime(mEntryA2, 9000);
+        sendUpdatedEntryAtTime(mEntryA1, 9000);
         verifyUpdateReceived();
+        assertOrderChangedTo(mBubbleA1, mBubbleA2, mBubbleB1, mBubbleB2);
 
         // No order changes when expanding because the new sorted order remains.
         changeExpandedStateAtTime(true, 10000L);
@@ -923,7 +777,8 @@
         mBubbleData.setListener(mListener);
 
         // Test
-        mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleData.notificationEntryRemoved(
+                mEntryA1.getKey(), BubbleController.DISMISS_USER_GESTURE);
         verifyUpdateReceived();
         assertExpandedChangedTo(false);
     }
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 73b8760..ead95ca1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -46,6 +46,7 @@
 import android.os.Handler;
 import android.os.PowerManager;
 import android.service.dreams.IDreamManager;
+import android.service.notification.NotificationListenerService;
 import android.service.notification.ZenModeConfig;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -62,6 +63,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.RankingBuilder;
 import com.android.systemui.statusbar.SuperStatusBarViewFactory;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -285,7 +287,8 @@
         assertTrue(mBubbleController.hasBubbles());
         verify(mNotifCallback, times(1)).invalidateNotifications(anyString());
 
-        mBubbleController.removeBubble(mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
+        mBubbleController.removeBubble(
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
         assertNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
         verify(mNotifCallback, times(2)).invalidateNotifications(anyString());
     }
@@ -302,7 +305,8 @@
         mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).setSuppressNotification(true);
 
         // Now remove the bubble
-        mBubbleController.removeBubble(mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
+        mBubbleController.removeBubble(
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
         assertTrue(mBubbleData.hasOverflowBubbleWithKey(mRow.getEntry().getKey()));
 
         // We don't remove the notification since the bubble is still in overflow.
@@ -322,7 +326,8 @@
         mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).setSuppressNotification(true);
 
         // Now remove the bubble
-        mBubbleController.removeBubble(mRow.getEntry(), BubbleController.DISMISS_NOTIF_CANCEL);
+        mBubbleController.removeBubble(
+                mRow.getEntry().getKey(), BubbleController.DISMISS_NOTIF_CANCEL);
         assertFalse(mBubbleData.hasOverflowBubbleWithKey(mRow.getEntry().getKey()));
 
         // Since the notif is dismissed and not in overflow, once the bubble is removed,
@@ -502,7 +507,8 @@
 
         // Dismiss currently expanded
         mBubbleController.removeBubble(
-                mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry(),
+                mBubbleData.getBubbleInStackWithKey(
+                        stackView.getExpandedBubble().getKey()).getEntry().getKey(),
                 BubbleController.DISMISS_USER_GESTURE);
         verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
 
@@ -513,7 +519,8 @@
 
         // Dismiss that one
         mBubbleController.removeBubble(
-                mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry(),
+                mBubbleData.getBubbleInStackWithKey(
+                        stackView.getExpandedBubble().getKey()).getEntry().getKey(),
                 BubbleController.DISMISS_USER_GESTURE);
 
         // Make sure state changes and collapse happens
@@ -613,7 +620,7 @@
     @Test
     public void testDeleteIntent_removeBubble_aged() throws PendingIntent.CanceledException {
         mBubbleController.updateBubble(mRow.getEntry());
-        mBubbleController.removeBubble(mRow.getEntry(), BubbleController.DISMISS_AGED);
+        mBubbleController.removeBubble(mRow.getEntry().getKey(), BubbleController.DISMISS_AGED);
         verify(mDeleteIntent, never()).send();
     }
 
@@ -621,7 +628,7 @@
     public void testDeleteIntent_removeBubble_user() throws PendingIntent.CanceledException {
         mBubbleController.updateBubble(mRow.getEntry());
         mBubbleController.removeBubble(
-                mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
         verify(mDeleteIntent, times(1)).send();
     }
 
@@ -640,6 +647,9 @@
         assertTrue(mBubbleController.hasBubbles());
 
         mRow.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
+        NotificationListenerService.Ranking ranking = new RankingBuilder(
+                mRow.getEntry().getRanking()).setCanBubble(false).build();
+        mRow.getEntry().setRanking(ranking);
         mEntryListener.onEntryUpdated(mRow.getEntry());
 
         assertFalse(mBubbleController.hasBubbles());
@@ -686,7 +696,7 @@
 
         // Dismiss the bubble
         mBubbleController.removeBubble(
-                mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE);
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
         assertFalse(mBubbleController.hasBubbles());
 
         // Dismiss the notification
@@ -707,7 +717,7 @@
 
         // Dismiss the bubble
         mBubbleController.removeBubble(
-                mRow.getEntry(), BubbleController.DISMISS_NOTIF_CANCEL);
+                mRow.getEntry().getKey(), BubbleController.DISMISS_NOTIF_CANCEL);
         assertFalse(mBubbleController.hasBubbles());
 
         // Dismiss the notification
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
index d49d021..f468192 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubblePersistentRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubblePersistentRepositoryTest.kt
@@ -29,9 +29,9 @@
 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")
+            BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1"),
+            BubbleEntity(10, "com.example.chat", "alice and bob", "key-2"),
+            BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3")
     )
     private lateinit var repository: BubblePersistentRepository
 
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
index 7acc937..ee48846 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleVolatileRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleVolatileRepositoryTest.kt
@@ -28,9 +28,9 @@
 @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 bubble1 = BubbleEntity(0, "com.example.messenger", "shortcut-1", "k1")
+    private val bubble2 = BubbleEntity(10, "com.example.chat", "alice and bob", "k2")
+    private val bubble3 = BubbleEntity(0, "com.example.messenger", "shortcut-2", "k3")
     private val bubbles = listOf(bubble1, bubble2, bubble3)
 
     private lateinit var repository: BubbleVolatileRepository
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
index ef4580c..79701ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleXmlHelperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/storage/BubbleXmlHelperTest.kt
@@ -31,17 +31,17 @@
 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")
+        BubbleEntity(0, "com.example.messenger", "shortcut-1", "k1"),
+        BubbleEntity(10, "com.example.chat", "alice and bob", "k2"),
+        BubbleEntity(0, "com.example.messenger", "shortcut-2", "k3")
     )
 
     @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" />
+            <bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" />
+            <bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" />
+            <bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" />
         """.trimIndent()
         ByteArrayOutputStream().use {
             writeXml(it, bubbles)
@@ -56,9 +56,9 @@
         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" />
+            <bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" />
+            <bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" />
+            <bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" />
             </bs>
         """.trimIndent()
         val actual = readXml(ByteArrayInputStream(src.toByteArray(Charsets.UTF_8)))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
new file mode 100644
index 0000000..7fe6827
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.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.controls.dagger
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.controls.controller.ControlsController
+import com.android.systemui.controls.management.ControlsListingController
+import com.android.systemui.controls.ui.ControlsUiController
+import dagger.Lazy
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class ControlsComponentTest : SysuiTestCase() {
+
+    @Mock
+    private lateinit var controller: ControlsController
+    @Mock
+    private lateinit var uiController: ControlsUiController
+    @Mock
+    private lateinit var listingController: ControlsListingController
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+    }
+
+    @Test
+    fun testFeatureEnabled() {
+        val component = ControlsComponent(
+                true,
+                Lazy { controller },
+                Lazy { uiController },
+                Lazy { listingController }
+        )
+
+        assertTrue(component.getControlsController().isPresent)
+        assertEquals(controller, component.getControlsController().get())
+        assertTrue(component.getControlsUiController().isPresent)
+        assertEquals(uiController, component.getControlsUiController().get())
+        assertTrue(component.getControlsListingController().isPresent)
+        assertEquals(listingController, component.getControlsListingController().get())
+    }
+
+    @Test
+    fun testFeatureDisabled() {
+        val component = ControlsComponent(
+                false,
+                Lazy { controller },
+                Lazy { uiController },
+                Lazy { listingController }
+        )
+
+        assertFalse(component.getControlsController().isPresent)
+        assertFalse(component.getControlsUiController().isPresent)
+        assertFalse(component.getControlsListingController().isPresent)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestReceiverTest.kt
index 663f011..ee1cc7b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestReceiverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestReceiverTest.kt
@@ -66,6 +66,7 @@
         MockitoAnnotations.initMocks(this)
 
         mContext.setMockPackageManager(packageManager)
+        `when`(packageManager.hasSystemFeature(PackageManager.FEATURE_CONTROLS)).thenReturn(true)
         mContext.addMockSystemService(ActivityManager::class.java, activityManager)
 
         receiver = ControlsRequestReceiver()
@@ -145,6 +146,14 @@
         } ?: run { fail("Null start intent") }
     }
 
+    @Test
+    fun testFeatureDisabled_activityNotStarted() {
+        `when`(packageManager.hasSystemFeature(PackageManager.FEATURE_CONTROLS)).thenReturn(false)
+        receiver.onReceive(wrapper, intent)
+
+        assertNull(wrapper.intent)
+    }
+
     class MyWrapper(context: Context) : ContextWrapper(context) {
         var intent: Intent? = null
 
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 8db57cd..3254633 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
@@ -59,12 +59,14 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.controls.controller.ControlsController;
+import com.android.systemui.controls.dagger.ControlsComponent;
 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.plugins.GlobalActionsPanelPlugin;
+import com.android.systemui.settings.CurrentUserContextTracker;
 import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -119,6 +121,8 @@
     @Mock GlobalActionsPanelPlugin mWalletPlugin;
     @Mock GlobalActionsPanelPlugin.PanelViewController mWalletController;
     @Mock private Handler mHandler;
+    @Mock private CurrentUserContextTracker mCurrentUserContextTracker;
+    private ControlsComponent mControlsComponent;
 
     private TestableLooper mTestableLooper;
 
@@ -129,6 +133,14 @@
         allowTestableLooperAsMainThread();
 
         when(mRingerModeTracker.getRingerMode()).thenReturn(mRingerModeLiveData);
+        when(mCurrentUserContextTracker.getCurrentUserContext()).thenReturn(mContext);
+        mControlsComponent = new ControlsComponent(
+                true,
+                () -> mControlsController,
+                () -> mControlsUiController,
+                () -> mControlsListingController
+        );
+
         mGlobalActionsDialog = new GlobalActionsDialog(mContext,
                 mWindowManagerFuncs,
                 mAudioManager,
@@ -153,15 +165,14 @@
                 mColorExtractor,
                 mStatusBarService,
                 mNotificationShadeWindowController,
-                mControlsUiController,
                 mWindowManager,
                 mBackgroundExecutor,
-                mControlsListingController,
-                mControlsController,
                 mUiEventLogger,
                 mRingerModeTracker,
                 mSysUiState,
-                mHandler
+                mHandler,
+                mControlsComponent,
+                mCurrentUserContextTracker
         );
         mGlobalActionsDialog.setZeroDialogPressDelayForTesting();
 
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 eb43b81..f38c722 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsImeTest.java
@@ -18,10 +18,13 @@
 
 import static android.view.WindowInsets.Type.ime;
 
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.os.PowerManager;
 import android.os.SystemClock;
 import android.view.View;
 import android.view.WindowInsets;
@@ -54,16 +57,15 @@
      * doesn't interfere with the IME, i.e. soft-keyboard state.
      */
     @Test
-    public void testGlobalActions_doesntStealImeControl() {
+    public void testGlobalActions_doesntStealImeControl() throws Exception {
+        turnScreenOn();
         final TestActivity activity = mActivityTestRule.launchActivity(null);
 
-        activity.waitFor(() -> activity.mHasFocus && activity.mControlsIme && activity.mImeVisible);
+        waitUntil("Ime is visible", activity::isImeVisible);
 
-        InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand(
-                "input keyevent --longpress POWER"
-        );
+        executeShellCommand("input keyevent --longpress POWER");
 
-        activity.waitFor(() -> !activity.mHasFocus);
+        waitUntil("activity loses focus", () -> !activity.mHasFocus);
         // Give the dialog time to animate in, and steal IME focus. Unfortunately, there's currently
         // no better way to wait for this.
         SystemClock.sleep(TimeUnit.SECONDS.toMillis(2));
@@ -76,7 +78,39 @@
         });
     }
 
-    /** Like Instrumentation.runOnMainThread(), but forwards AssertionErrors to the caller. */
+    private void turnScreenOn() throws Exception {
+        PowerManager powerManager = mContext.getSystemService(PowerManager.class);
+        assertNotNull(powerManager);
+        if (powerManager.isInteractive()) {
+            return;
+        }
+        executeShellCommand("input keyevent KEYCODE_WAKEUP");
+        waitUntil("Device not interactive", powerManager::isInteractive);
+        executeShellCommand("am wait-for-broadcast-idle");
+    }
+
+    private static void waitUntil(String message, BooleanSupplier predicate)
+            throws Exception {
+        int sleep = 125;
+        final long timeout = SystemClock.uptimeMillis() + 10_000;  // 10 second timeout
+        while (SystemClock.uptimeMillis() < timeout) {
+            if (predicate.getAsBoolean()) {
+                return; // okay
+            }
+            Thread.sleep(sleep);
+            sleep *= 5;
+            sleep = Math.min(2000, sleep);
+        }
+        fail(message);
+    }
+
+    private static void executeShellCommand(String cmd) {
+        InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand(cmd);
+    }
+
+    /**
+     * Like Instrumentation.runOnMainThread(), but forwards AssertionErrors to the caller.
+     */
     private static void runAssertionOnMainThread(Runnable r) {
         AssertionError[] t = new AssertionError[1];
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
@@ -96,7 +130,6 @@
             WindowInsetsController.OnControllableInsetsChangedListener,
             View.OnApplyWindowInsetsListener {
 
-        private EditText mContent;
         boolean mHasFocus;
         boolean mControlsIme;
         boolean mImeVisible;
@@ -105,13 +138,13 @@
         protected void onCreate(@Nullable Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
 
-            mContent = new EditText(this);
-            mContent.setCursorVisible(false);  // Otherwise, main thread doesn't go idle.
-            setContentView(mContent);
-            mContent.requestFocus();
+            EditText content = new EditText(this);
+            content.setCursorVisible(false);  // Otherwise, main thread doesn't go idle.
+            setContentView(content);
+            content.requestFocus();
 
             getWindow().getDecorView().setOnApplyWindowInsetsListener(this);
-            WindowInsetsController wic = mContent.getWindowInsetsController();
+            WindowInsetsController wic = content.getWindowInsetsController();
             wic.addOnControllableInsetsChangedListener(this);
             wic.show(ime());
         }
@@ -133,16 +166,8 @@
             }
         }
 
-        void waitFor(BooleanSupplier condition) {
-            synchronized (this) {
-                while (!condition.getAsBoolean()) {
-                    try {
-                        wait(TimeUnit.SECONDS.toMillis(5));
-                    } catch (InterruptedException e) {
-                        throw new RuntimeException(e);
-                    }
-                }
-            }
+        boolean isImeVisible() {
+            return mHasFocus && mControlsIme && mImeVisible;
         }
 
         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
index 4d30500..b71a62c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
@@ -31,30 +31,24 @@
 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.animation.TransitionLayout
 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.ArgumentCaptor
 import org.mockito.Mock
 import org.mockito.Mockito.mock
+import org.mockito.Mockito.verify
 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
@@ -78,8 +72,8 @@
     @Mock private lateinit var activityStarter: ActivityStarter
 
     @Mock private lateinit var holder: PlayerViewHolder
-    @Mock private lateinit var motion: MotionLayout
-    private lateinit var background: TextView
+    @Mock private lateinit var view: TransitionLayout
+    @Mock private lateinit var mediaHostStatesManager: MediaHostStatesManager
     private lateinit var appIcon: ImageView
     private lateinit var appName: TextView
     private lateinit var albumView: ImageView
@@ -107,21 +101,15 @@
         bgExecutor = FakeExecutor(FakeSystemClock())
 
         activityStarter = mock(ActivityStarter::class.java)
+        mediaHostStatesManager = mock(MediaHostStatesManager::class.java)
 
-        player = MediaControlPanel(context, fgExecutor, bgExecutor, activityStarter)
+        player = MediaControlPanel(context, fgExecutor, bgExecutor, activityStarter,
+                mediaHostStatesManager)
 
         // 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)
+        view = mock(TransitionLayout::class.java)
+        whenever(holder.player).thenReturn(view)
         appIcon = ImageView(context)
         whenever(holder.appIcon).thenReturn(appIcon)
         appName = TextView(context)
@@ -205,7 +193,9 @@
         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))
+        val list = ArgumentCaptor.forClass(ColorStateList::class.java)
+        verify(view).setBackgroundTintList(list.capture())
+        assertThat(list.value).isEqualTo(ColorStateList.valueOf(BG_COLOR))
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
index 7b80a6e..c0aef8a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.media
 
 import android.app.Notification
+import android.graphics.drawable.Drawable
 import android.media.MediaMetadata
 import android.media.MediaRouter2Manager
 import android.media.RoutingSessionInfo
@@ -73,6 +74,7 @@
     private lateinit var fakeExecutor: FakeExecutor
     @Mock private lateinit var listener: MediaDeviceManager.Listener
     @Mock private lateinit var device: MediaDevice
+    @Mock private lateinit var icon: Drawable
     @Mock private lateinit var route: RoutingSessionInfo
     private lateinit var session: MediaSession
     private lateinit var metadataBuilder: MediaMetadata.Builder
@@ -89,6 +91,7 @@
 
         // Configure mocks.
         whenever(device.name).thenReturn(DEVICE_NAME)
+        whenever(device.iconWithoutBackground).thenReturn(icon)
         whenever(lmmFactory.create(PACKAGE)).thenReturn(lmm)
         whenever(lmm.getCurrentConnectedDevice()).thenReturn(device)
         whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(route)
@@ -157,6 +160,7 @@
         val data = captureDeviceData(KEY)
         assertThat(data.enabled).isTrue()
         assertThat(data.name).isEqualTo(DEVICE_NAME)
+        assertThat(data.icon).isEqualTo(icon)
     }
 
     @Test
@@ -170,6 +174,7 @@
         val data = captureDeviceData(KEY)
         assertThat(data.enabled).isTrue()
         assertThat(data.name).isEqualTo(DEVICE_NAME)
+        assertThat(data.icon).isEqualTo(icon)
     }
 
     @Test
@@ -183,6 +188,7 @@
         val data = captureDeviceData(KEY)
         assertThat(data.enabled).isTrue()
         assertThat(data.name).isEqualTo(DEVICE_NAME)
+        assertThat(data.icon).isEqualTo(icon)
     }
 
     @Test
@@ -204,6 +210,7 @@
         val data = captureDeviceData(KEY)
         assertThat(data.enabled).isFalse()
         assertThat(data.name).isNull()
+        assertThat(data.icon).isNull()
     }
 
     @Test
@@ -221,6 +228,7 @@
         val data = captureDeviceData(KEY)
         assertThat(data.enabled).isFalse()
         assertThat(data.name).isNull()
+        assertThat(data.icon).isNull()
     }
 
     @Test
@@ -238,6 +246,7 @@
         val data = captureDeviceData(KEY)
         assertThat(data.enabled).isFalse()
         assertThat(data.name).isNull()
+        assertThat(data.icon).isNull()
     }
 
     fun captureCallback(): LocalMediaManager.DeviceCallback {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
new file mode 100644
index 0000000..c9e6f55
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
@@ -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.media
+
+import android.graphics.Rect
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.ViewGroup
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.animation.UniqueObjectHostView
+import org.junit.Assert.assertNotNull
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.any
+import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.anyLong
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class MediaHierarchyManagerTest : SysuiTestCase() {
+
+    @Mock
+    private lateinit var lockHost: MediaHost
+    @Mock
+    private lateinit var qsHost: MediaHost
+    @Mock
+    private lateinit var qqsHost: MediaHost
+    @Mock
+    private lateinit var bypassController: KeyguardBypassController
+    @Mock
+    private lateinit var mediaFrame: ViewGroup
+    @Mock
+    private lateinit var keyguardStateController: KeyguardStateController
+    @Mock
+    private lateinit var statusBarStateController: SysuiStatusBarStateController
+    @Mock
+    private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager
+    @Mock
+    private lateinit var mediaViewManager: MediaViewManager
+    @Mock
+    private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
+    @Captor
+    private lateinit var wakefullnessObserver: ArgumentCaptor<(WakefulnessLifecycle.Observer)>
+    @JvmField
+    @Rule
+    val mockito = MockitoJUnit.rule()
+    private lateinit var mediaHiearchyManager: MediaHierarchyManager
+
+    @Before
+    fun setup() {
+        `when`(mediaViewManager.mediaFrame).thenReturn(mediaFrame)
+        mediaHiearchyManager = MediaHierarchyManager(
+                context,
+                statusBarStateController,
+                keyguardStateController,
+                bypassController,
+                mediaViewManager,
+                notificationLockscreenUserManager,
+                wakefulnessLifecycle)
+        verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture())
+        setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN)
+        setupHost(qsHost, MediaHierarchyManager.LOCATION_QS)
+        setupHost(qqsHost, MediaHierarchyManager.LOCATION_QQS)
+        `when`(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
+        // We'll use the viewmanager to verify a few calls below, let's reset this.
+        clearInvocations(mediaViewManager)
+
+    }
+
+    private fun setupHost(host: MediaHost, location: Int) {
+        `when`(host.location).thenReturn(location)
+        `when`(host.currentBounds).thenReturn(Rect())
+        `when`(host.hostView).thenReturn(UniqueObjectHostView(context))
+        mediaHiearchyManager.register(host)
+    }
+
+    @Test
+    fun testHostViewSetOnRegister() {
+        val host = mediaHiearchyManager.register(lockHost)
+        verify(lockHost).hostView = eq(host)
+    }
+
+    @Test
+    fun testBlockedWhenScreenTurningOff() {
+        // Let's set it onto QS:
+        mediaHiearchyManager.qsExpansion = 1.0f
+        verify(mediaViewManager).onDesiredLocationChanged(ArgumentMatchers.anyInt(),
+                any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong())
+        val observer = wakefullnessObserver.value
+        assertNotNull("lifecycle observer wasn't registered", observer)
+        observer.onStartedGoingToSleep()
+        clearInvocations(mediaViewManager)
+        mediaHiearchyManager.qsExpansion = 0.0f
+        verify(mediaViewManager, times(0)).onDesiredLocationChanged(ArgumentMatchers.anyInt(),
+                any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong())
+    }
+
+    @Test
+    fun testAllowedWhenNotTurningOff() {
+        // Let's set it onto QS:
+        mediaHiearchyManager.qsExpansion = 1.0f
+        verify(mediaViewManager).onDesiredLocationChanged(ArgumentMatchers.anyInt(),
+                any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong())
+        val observer = wakefullnessObserver.value
+        assertNotNull("lifecycle observer wasn't registered", observer)
+        clearInvocations(mediaViewManager)
+        mediaHiearchyManager.qsExpansion = 0.0f
+        verify(mediaViewManager).onDesiredLocationChanged(ArgumentMatchers.anyInt(),
+                any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong())
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/PlayerViewHolderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/PlayerViewHolderTest.kt
index 7678525..d6849bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/PlayerViewHolderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/PlayerViewHolderTest.kt
@@ -57,6 +57,6 @@
     @Test
     fun backgroundIsIlluminationDrawable() {
         val holder = PlayerViewHolder.create(inflater, parent)
-        assertThat(holder.background.background as IlluminationDrawable).isNotNull()
+        assertThat(holder.player.background as IlluminationDrawable).isNotNull()
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/PipBoundsHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/PipBoundsHandlerTest.java
index 425bf88..f404f04 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/pip/PipBoundsHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/pip/PipBoundsHandlerTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
 
 import android.content.ComponentName;
 import android.graphics.Rect;
@@ -32,6 +33,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.wm.DisplayController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -63,7 +65,8 @@
     @Before
     public void setUp() throws Exception {
         initializeMockResources();
-        mPipBoundsHandler = new PipBoundsHandler(mContext, new PipSnapAlgorithm(mContext));
+        mPipBoundsHandler = new PipBoundsHandler(mContext, new PipSnapAlgorithm(mContext),
+                mock(DisplayController.class));
         mTestComponentName1 = new ComponentName(mContext, "component1");
         mTestComponentName2 = new ComponentName(mContext, "component2");
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
index 2c4304d..d3b3399 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
@@ -22,7 +22,6 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -37,6 +36,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.UserHandle;
 import android.testing.AndroidTestingRunner;
 
 import androidx.test.filters.SmallTest;
@@ -79,13 +79,12 @@
         when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
         ScreenshotNotificationSmartActionsProvider smartActionsProvider = mock(
                 ScreenshotNotificationSmartActionsProvider.class);
-        when(smartActionsProvider.getActions(any(), any(), any(), any(),
-                eq(false))).thenThrow(
-                RuntimeException.class);
+        when(smartActionsProvider.getActions(any(), any(), any(), any(), any()))
+            .thenThrow(RuntimeException.class);
         CompletableFuture<List<Notification.Action>> smartActionsFuture =
                 ScreenshotSmartActions.getSmartActionsFuture(
                         "", Uri.parse("content://authority/data"), bitmap, smartActionsProvider,
-                        true, false);
+                        true, UserHandle.getUserHandleForUid(UserHandle.myUserId()));
         assertNotNull(smartActionsFuture);
         List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
         assertEquals(Collections.emptyList(), smartActions);
@@ -125,9 +124,8 @@
         CompletableFuture<List<Notification.Action>> smartActionsFuture =
                 ScreenshotSmartActions.getSmartActionsFuture(
                         "", Uri.parse("content://autority/data"), bitmap, mSmartActionsProvider,
-                        true, true);
-        verify(mSmartActionsProvider, never()).getActions(any(), any(), any(), any(),
-                eq(false));
+                        true, UserHandle.getUserHandleForUid(UserHandle.myUserId()));
+        verify(mSmartActionsProvider, never()).getActions(any(), any(), any(), any(), any());
         assertNotNull(smartActionsFuture);
         List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
         assertEquals(Collections.emptyList(), smartActions);
@@ -140,9 +138,8 @@
         when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
         ScreenshotSmartActions.getSmartActionsFuture(
                 "", Uri.parse("content://autority/data"), bitmap, mSmartActionsProvider, true,
-                true);
-        verify(mSmartActionsProvider, times(1))
-                .getActions(any(), any(), any(), any(), eq(true));
+                UserHandle.getUserHandleForUid(UserHandle.myUserId()));
+        verify(mSmartActionsProvider, times(1)).getActions(any(), any(), any(), any(), any());
     }
 
     // Tests for a hardware bitmap, a completed future is returned.
@@ -157,7 +154,7 @@
         CompletableFuture<List<Notification.Action>> smartActionsFuture =
                 ScreenshotSmartActions.getSmartActionsFuture("", null, bitmap,
                         actionsProvider,
-                        true, true);
+                        true, UserHandle.getUserHandleForUid(UserHandle.myUserId()));
         assertNotNull(smartActionsFuture);
         List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
         assertEquals(smartActions.size(), 0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
index 1654a5442..cdef49d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
@@ -19,18 +19,14 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
-import android.os.RemoteException;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
-import android.view.IRemoteAnimationFinishedCallback;
 import android.view.RemoteAnimationAdapter;
-import android.view.RemoteAnimationTarget;
 import android.view.View;
 
 import com.android.systemui.SysuiTestCase;
@@ -40,8 +36,6 @@
 import com.android.systemui.statusbar.phone.NotificationPanelViewController;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController;
-import com.android.systemui.util.concurrency.FakeExecutor;
-import com.android.systemui.util.time.FakeSystemClock;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -74,11 +68,9 @@
     private NotificationPanelViewController mNotificationPanelViewController;
     @Rule
     public MockitoRule rule = MockitoJUnit.rule();
-    private FakeExecutor mExecutor;
 
     @Before
     public void setUp() throws Exception {
-        mExecutor = new FakeExecutor(new FakeSystemClock());
         when(mNotificationShadeWindowViewController.getView())
                 .thenReturn(mNotificationShadeWindowView);
         when(mNotificationShadeWindowView.getResources()).thenReturn(mContext.getResources());
@@ -88,8 +80,8 @@
                 mCallback,
                 mNotificationPanelViewController,
                 mNotificationShadeDepthController,
-                mNotificationContainer,
-                mExecutor);
+                mNotificationContainer);
+
     }
 
     @Test
@@ -121,29 +113,6 @@
         verify(mCallback).onExpandAnimationTimedOut();
     }
 
-    @Test
-    public void testRowLinkBrokenOnAnimationStartFail() throws RemoteException {
-        ActivityLaunchAnimator.AnimationRunner runner = mLaunchAnimator.new AnimationRunner(mRow,
-                mExecutor);
-        // WHEN onAnimationStart with no valid remote target
-        runner.onAnimationStart(new RemoteAnimationTarget[0], new RemoteAnimationTarget[0],
-                mock(IRemoteAnimationFinishedCallback.class));
-        mExecutor.runAllReady();
-        // THEN the row is nulled out so that it won't be retained
-        Assert.assertTrue("The row should be null", runner.getRow() == null);
-    }
-
-    @Test
-    public void testRowLinkBrokenOnAnimationCancelled() throws RemoteException {
-        ActivityLaunchAnimator.AnimationRunner runner = mLaunchAnimator.new AnimationRunner(mRow,
-                mExecutor);
-        // WHEN onAnimationCancelled
-        runner.onAnimationCancelled();
-        mExecutor.runAllReady();
-        // THEN the row is nulled out so that it won't be retained
-        Assert.assertTrue("The row should be null", runner.getRow() == null);
-    }
-
     private void executePostsImmediately(View view) {
         doAnswer((i) -> {
             Runnable run = i.getArgument(0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
index 5cbfcc1..e254cd2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
@@ -117,21 +117,12 @@
 
     /**
      * Sets up the state such that any requests to
-     * {@link NotificationInterruptStateProviderImpl#canAlertAwakeCommon(NotificationEntry)} will
-     * pass as long its provided NotificationEntry fulfills launch fullscreen check.
-     */
-    private void ensureStateForAlertAwakeCommon() {
-        when(mHeadsUpManager.isSnoozed(any())).thenReturn(false);
-    }
-
-    /**
-     * Sets up the state such that any requests to
      * {@link NotificationInterruptStateProviderImpl#shouldHeadsUp(NotificationEntry)} will
      * pass as long its provided NotificationEntry fulfills importance & DND checks.
      */
     private void ensureStateForHeadsUpWhenAwake() throws RemoteException {
         ensureStateForAlertCommon();
-        ensureStateForAlertAwakeCommon();
+        when(mHeadsUpManager.isSnoozed(any())).thenReturn(false);
 
         when(mStatusBarStateController.isDozing()).thenReturn(false);
         when(mDreamManager.isDreaming()).thenReturn(false);
@@ -157,7 +148,6 @@
      */
     private void ensureStateForBubbleUp() {
         ensureStateForAlertCommon();
-        ensureStateForAlertAwakeCommon();
     }
 
     @Test
@@ -392,7 +382,6 @@
     @Test
     public void testShouldNotHeadsUp_snoozedPackage() {
         NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT);
-        ensureStateForAlertAwakeCommon();
 
         when(mHeadsUpManager.isSnoozed(entry.getSbn().getPackageName())).thenReturn(true);
 
@@ -402,7 +391,6 @@
 
     @Test
     public void testShouldNotHeadsUp_justLaunchedFullscreen() {
-        ensureStateForAlertAwakeCommon();
 
         // On screen alerts don't happen when that package has just launched fullscreen.
         NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT);
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 4b21ef2..0272028 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
@@ -60,6 +60,7 @@
 import android.content.pm.ShortcutManager;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
+import android.os.Handler;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -72,7 +73,6 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.settingslib.notification.ConversationIconFactory;
-import com.android.systemui.Dependency;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
@@ -153,13 +153,14 @@
     private Provider<PriorityOnboardingDialogController.Builder> mBuilderProvider = () -> mBuilder;
     @Mock
     private Notification.BubbleMetadata mBubbleMetadata;
+    private Handler mTestHandler;
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         mTestableLooper = TestableLooper.get(this);
 
-        mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
+        mTestHandler = new Handler(mTestableLooper.getLooper());
         mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
         mDependency.injectTestDependency(BubbleController.class, mBubbleController);
         mDependency.injectTestDependency(ShadeController.class, mShadeController);
@@ -253,7 +254,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
         final ImageView view = mNotificationInfo.findViewById(R.id.conversation_icon);
         assertEquals(mIconDrawable, view.getDrawable());
     }
@@ -275,7 +278,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
         final TextView textView = mNotificationInfo.findViewById(R.id.pkg_name);
         assertTrue(textView.getText().toString().contains("App Name"));
         assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
@@ -324,7 +329,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
         final TextView textView = mNotificationInfo.findViewById(R.id.group_name);
         assertTrue(textView.getText().toString().contains(group.getName()));
         assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
@@ -348,7 +355,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
         final TextView textView = mNotificationInfo.findViewById(R.id.group_name);
         assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
         assertEquals(GONE, textView.getVisibility());
@@ -371,7 +380,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
         final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
         assertEquals(GONE, nameView.getVisibility());
     }
@@ -404,7 +415,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
         final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
         assertEquals(VISIBLE, nameView.getVisibility());
         assertTrue(nameView.getText().toString().contains("Proxied"));
@@ -430,7 +443,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
 
         final View settingsButton = mNotificationInfo.findViewById(R.id.info);
         settingsButton.performClick();
@@ -454,7 +469,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
         final View settingsButton = mNotificationInfo.findViewById(R.id.info);
         assertTrue(settingsButton.getVisibility() != View.VISIBLE);
     }
@@ -479,7 +496,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                false);
+                false,
+                mTestHandler,
+                mTestHandler);
         final View settingsButton = mNotificationInfo.findViewById(R.id.info);
         assertTrue(settingsButton.getVisibility() != View.VISIBLE);
     }
@@ -502,7 +521,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
         View view = mNotificationInfo.findViewById(R.id.silence);
         assertThat(view.isSelected()).isTrue();
     }
@@ -528,7 +549,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
         View view = mNotificationInfo.findViewById(R.id.default_behavior);
         assertThat(view.isSelected()).isTrue();
         assertThat(((TextView) view.findViewById(R.id.default_summary)).getText()).isEqualTo(
@@ -557,7 +580,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
         View view = mNotificationInfo.findViewById(R.id.default_behavior);
         assertThat(view.isSelected()).isTrue();
         assertThat(((TextView) view.findViewById(R.id.default_summary)).getText()).isEqualTo(
@@ -585,7 +610,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
 
         View fave = mNotificationInfo.findViewById(R.id.priority);
         fave.performClick();
@@ -627,7 +654,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
 
         mNotificationInfo.findViewById(R.id.default_behavior).performClick();
         mTestableLooper.processAllMessages();
@@ -668,7 +697,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
 
         View silence = mNotificationInfo.findViewById(R.id.silence);
 
@@ -710,7 +741,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
 
         View fave = mNotificationInfo.findViewById(R.id.priority);
         fave.performClick();
@@ -745,7 +778,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
 
         View fave = mNotificationInfo.findViewById(R.id.priority);
         fave.performClick();
@@ -778,7 +813,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
 
         mNotificationInfo.findViewById(R.id.default_behavior).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
@@ -812,7 +849,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
 
         mNotificationInfo.findViewById(R.id.default_behavior).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
@@ -846,7 +885,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
 
         mNotificationInfo.findViewById(R.id.default_behavior).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
@@ -879,7 +920,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
 
         View silence = mNotificationInfo.findViewById(R.id.silence);
         silence.performClick();
@@ -911,7 +954,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
 
         verify(mMockINotificationManager, times(1)).createConversationNotificationChannelForPackage(
                 anyString(), anyInt(), anyString(), any(), eq(CONVERSATION_ID));
@@ -934,7 +979,9 @@
                 mIconFactory,
                 mContext,
                 mBuilderProvider,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
 
         verify(mMockINotificationManager, never()).createConversationNotificationChannelForPackage(
                 anyString(), anyInt(), anyString(), any(), eq(CONVERSATION_ID));
@@ -967,7 +1014,9 @@
                 mIconFactory,
                 mContext,
                 () -> b,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
 
         // WHEN user clicks "priority"
         mNotificationInfo.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE);
@@ -1001,7 +1050,9 @@
                 mIconFactory,
                 mContext,
                 () -> b,
-                true);
+                true,
+                mTestHandler,
+                mTestHandler);
 
         // WHEN user clicks "priority"
         mNotificationInfo.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index eeb912e..da7d249 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -144,7 +144,7 @@
         when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false);
 
         mGutsManager = new NotificationGutsManager(mContext, mVisualStabilityManager,
-                () -> mStatusBar, mHandler, mAccessibilityManager, mHighPriorityProvider,
+                () -> mStatusBar, mHandler, mHandler, mAccessibilityManager, mHighPriorityProvider,
                 mINotificationManager, mLauncherApps, mShortcutManager,
                 mChannelEditorDialogController, mContextTracker, mProvider);
         mGutsManager.setUpWithPresenter(mPresenter, mStackScroller,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
index 06a2eec..323d8bd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -436,8 +436,8 @@
         assertEquals("returns false when view is null", false,
                 NotificationSwipeHelper.isTouchInView(mEvent, null));
 
-        doReturn(5f).when(mEvent).getRawX();
-        doReturn(10f).when(mEvent).getRawY();
+        doReturn(5f).when(mEvent).getX();
+        doReturn(10f).when(mEvent).getY();
 
         doReturn(20).when(mView).getWidth();
         doReturn(20).when(mView).getHeight();
@@ -453,7 +453,7 @@
         assertTrue("Touch is within the view",
                 mSwipeHelper.isTouchInView(mEvent, mView));
 
-        doReturn(50f).when(mEvent).getRawX();
+        doReturn(50f).when(mEvent).getX();
 
         assertFalse("Touch is not within the view",
                 mSwipeHelper.isTouchInView(mEvent, mView));
@@ -464,8 +464,8 @@
         assertEquals("returns false when view is null", false,
                 NotificationSwipeHelper.isTouchInView(mEvent, null));
 
-        doReturn(5f).when(mEvent).getRawX();
-        doReturn(10f).when(mEvent).getRawY();
+        doReturn(5f).when(mEvent).getX();
+        doReturn(10f).when(mEvent).getY();
 
         doReturn(20).when(mNotificationRow).getWidth();
         doReturn(20).when(mNotificationRow).getActualHeight();
@@ -481,7 +481,7 @@
         assertTrue("Touch is within the view",
                 mSwipeHelper.isTouchInView(mEvent, mNotificationRow));
 
-        doReturn(50f).when(mEvent).getRawX();
+        doReturn(50f).when(mEvent).getX();
 
         assertFalse("Touch is not within the view",
                 mSwipeHelper.isTouchInView(mEvent, mNotificationRow));
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
deleted file mode 100644
index a14d575..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.java
+++ /dev/null
@@ -1,168 +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.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 53a1773..acdb2c5 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
@@ -282,7 +282,7 @@
         mNotificationActivityStarter.onNotificationClicked(sbn, mBubbleNotificationRow);
 
         // Then
-        verify(mBubbleController).expandStackAndSelectBubble(eq(sbn.getKey()));
+        verify(mBubbleController).expandStackAndSelectBubble(eq(mBubbleNotificationRow.getEntry()));
 
         // This is called regardless, and simply short circuits when there is nothing to do.
         verify(mShadeController, atLeastOnce()).collapsePanel();
@@ -313,7 +313,7 @@
         mNotificationActivityStarter.onNotificationClicked(sbn, mBubbleNotificationRow);
 
         // Then
-        verify(mBubbleController).expandStackAndSelectBubble(eq(sbn.getKey()));
+        verify(mBubbleController).expandStackAndSelectBubble(mBubbleNotificationRow.getEntry());
 
         verify(mShadeController, atLeastOnce()).collapsePanel();
 
@@ -343,7 +343,7 @@
         mNotificationActivityStarter.onNotificationClicked(sbn, mBubbleNotificationRow);
 
         // Then
-        verify(mBubbleController).expandStackAndSelectBubble(eq(sbn.getKey()));
+        verify(mBubbleController).expandStackAndSelectBubble(mBubbleNotificationRow.getEntry());
 
         verify(mShadeController, atLeastOnce()).collapsePanel();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 27cbb03..5a08c9c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -251,7 +251,6 @@
     @Mock private Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
     private ShadeController mShadeController;
     private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
-    private FakeExecutor mMainExecutor = new FakeExecutor(new FakeSystemClock());
     private InitController mInitController = new InitController();
 
     @Before
@@ -354,7 +353,6 @@
                 new DisplayMetrics(),
                 mMetricsLogger,
                 mUiBgExecutor,
-                mMainExecutor,
                 mNotificationMediaManager,
                 mLockscreenUserManager,
                 mRemoteInputManager,
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index 1ee017b..8ae30a5 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -33,7 +33,7 @@
         "net-utils-framework-common",
     ],
     libs: [
-        "framework-tethering",
+        "framework-tethering.impl",
         "framework-wifi-stubs-systemapi",
         "unsupportedappusage",
     ],
diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp
index ae4bb3e..408725c 100644
--- a/packages/Tethering/common/TetheringLib/Android.bp
+++ b/packages/Tethering/common/TetheringLib/Android.bp
@@ -13,31 +13,28 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-java_library {
+java_sdk_library {
     name: "framework-tethering",
-    sdk_version: "module_current",
+    defaults: ["framework-module-defaults"],
     srcs: [
         ":framework-tethering-srcs",
     ],
+
+    // 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",
+
     jarjar_rules: "jarjar-rules.txt",
     installable: true,
 
-    libs: [
-        "framework-annotations-lib",
-    ],
-
     hostdex: true, // for hiddenapi check
     visibility: ["//frameworks/base/packages/Tethering:__subpackages__"],
+    stubs_library_visibility: ["//visibility:public"],
     apex_available: ["com.android.tethering"],
     permitted_packages: ["android.net"],
 }
 
-stubs_defaults {
-    name: "framework-tethering-stubs-defaults",
-    srcs: [":framework-tethering-srcs"],
-    dist: { dest: "framework-tethering.txt" },
-}
-
 filegroup {
     name: "framework-tethering-srcs",
     srcs: [
@@ -55,83 +52,3 @@
     ],
     path: "src"
 }
-
-droidstubs {
-    name: "framework-tethering-stubs-srcs-publicapi",
-    defaults: [
-        "framework-module-stubs-defaults-publicapi",
-        "framework-tethering-stubs-defaults",
-    ],
-    check_api: {
-        last_released: {
-            api_file: ":framework-tethering.api.public.latest",
-            removed_api_file: ":framework-tethering-removed.api.public.latest",
-        },
-        api_lint: {
-            new_since: ":framework-tethering.api.public.latest",
-        },
-    },
-}
-
-droidstubs {
-    name: "framework-tethering-stubs-srcs-systemapi",
-    defaults: [
-        "framework-module-stubs-defaults-systemapi",
-        "framework-tethering-stubs-defaults",
-    ],
-    check_api: {
-        last_released: {
-            api_file: ":framework-tethering.api.system.latest",
-            removed_api_file: ":framework-tethering-removed.api.system.latest",
-        },
-        api_lint: {
-            new_since: ":framework-tethering.api.system.latest",
-        },
-    },
-}
-
-droidstubs {
-    name: "framework-tethering-api-module_libs_api",
-    defaults: [
-        "framework-module-api-defaults-module_libs_api",
-        "framework-tethering-stubs-defaults",
-    ],
-    check_api: {
-        last_released: {
-            api_file: ":framework-tethering.api.module-lib.latest",
-            removed_api_file: ":framework-tethering-removed.api.module-lib.latest",
-        },
-        api_lint: {
-            new_since: ":framework-tethering.api.module-lib.latest",
-        },
-    },
-}
-
-droidstubs {
-    name: "framework-tethering-stubs-srcs-module_libs_api",
-    defaults: [
-        "framework-module-stubs-defaults-module_libs_api",
-        "framework-tethering-stubs-defaults",
-    ],
-}
-
-java_library {
-    name: "framework-tethering-stubs-publicapi",
-    srcs: [":framework-tethering-stubs-srcs-publicapi"],
-    defaults: ["framework-module-stubs-lib-defaults-publicapi"],
-    dist: { dest: "framework-tethering.jar" },
-}
-
-java_library {
-    name: "framework-tethering-stubs-systemapi",
-    srcs: [":framework-tethering-stubs-srcs-systemapi"],
-    defaults: ["framework-module-stubs-lib-defaults-systemapi"],
-    dist: { dest: "framework-tethering.jar" },
-}
-
-java_library {
-    name: "framework-tethering-stubs-module_libs_api",
-    srcs: [":framework-tethering-stubs-srcs-module_libs_api"],
-    defaults: ["framework-module-stubs-lib-defaults-module_libs_api"],
-    dist: { dest: "framework-tethering.jar" },
-}
diff --git a/packages/Tethering/tests/integration/Android.bp b/packages/Tethering/tests/integration/Android.bp
index 3305ed0..ed69b7d 100644
--- a/packages/Tethering/tests/integration/Android.bp
+++ b/packages/Tethering/tests/integration/Android.bp
@@ -63,7 +63,6 @@
 // NetworkStackTests.
 android_test {
     name: "TetheringCoverageTests",
-    certificate: "platform",
     platform_apis: true,
     test_suites: ["device-tests", "mts"],
     test_config: "AndroidTest_Coverage.xml",
diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp
index 08cfb30..fccc690 100644
--- a/packages/Tethering/tests/unit/Android.bp
+++ b/packages/Tethering/tests/unit/Android.bp
@@ -29,7 +29,7 @@
     sdk_version: "core_platform",
     libs: [
         "framework-minus-apex",
-        "framework-tethering",
+        "framework-tethering.impl",
     ],
     visibility: ["//cts/tests/tests/tethering"],
 }
@@ -59,7 +59,7 @@
         "ext",
         "framework-minus-apex",
         "framework-res",
-        "framework-tethering",
+        "framework-tethering.impl",
         "framework-wifi-stubs-module_libs_api",
     ],
     jni_libs: [
@@ -83,7 +83,7 @@
 
 android_test {
     name: "TetheringTests",
-    certificate: "platform",
+    platform_apis: true,
     test_suites: [
         "device-tests",
         "mts",
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 07bb335..22b082f 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1136,6 +1136,7 @@
                 userState.mEnabledServices,
                 UserHandle.USER_SYSTEM);
         onUserStateChangedLocked(userState);
+        migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, null);
     }
 
     private int getClientStateLocked(AccessibilityUserState userState) {
diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
index 103151d..26e85be 100644
--- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
+++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
@@ -51,7 +51,7 @@
  */
 public class AppPredictionPerUserService extends
         AbstractPerUserSystemService<AppPredictionPerUserService, AppPredictionManagerService>
-             implements RemoteAppPredictionService.RemoteAppPredictionServiceCallbacks {
+        implements RemoteAppPredictionService.RemoteAppPredictionServiceCallbacks {
 
     private static final String TAG = AppPredictionPerUserService.class.getSimpleName();
     private static final String PREDICT_USING_PEOPLE_SERVICE_PREFIX =
@@ -114,8 +114,11 @@
     public void onCreatePredictionSessionLocked(@NonNull AppPredictionContext context,
             @NonNull AppPredictionSessionId sessionId) {
         if (!mSessionInfos.containsKey(sessionId)) {
+            // TODO(b/157500121): remove below forceUsingPeopleService logic after testing
+            //  PeopleService for 2 weeks on Droidfood.
+            final boolean forceUsingPeopleService = context.getUiSurface().equals("share");
             mSessionInfos.put(sessionId, new AppPredictionSessionInfo(sessionId, context,
-                    DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
+                    forceUsingPeopleService || DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
                             PREDICT_USING_PEOPLE_SERVICE_PREFIX + context.getUiSurface(), false),
                     this::removeAppPredictionSessionInfo));
         }
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 06c60a3..37ed6f7 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2588,14 +2588,15 @@
                             id)) {
                         // Regular autofill handled the view and returned null response, but it
                         // triggered augmented autofill
-                        if (!isSameViewEntered) {
+                        if (!isSameViewEntered || mExpiredResponse) {
                             if (sDebug) Slog.d(TAG, "trigger augmented autofill.");
                             triggerAugmentedAutofillLocked(flags);
                         } else {
                             if (sDebug) Slog.d(TAG, "skip augmented autofill for same view.");
                         }
                         return;
-                    } else if (mForAugmentedAutofillOnly && isSameViewEntered) {
+                    } else if (mForAugmentedAutofillOnly && isSameViewEntered
+                            && !mExpiredResponse) {
                         // Regular autofill is disabled.
                         if (sDebug) Slog.d(TAG, "skip augmented autofill for same view.");
                         return;
diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java
index 72e170f..b765d81 100644
--- a/services/core/java/com/android/server/AppStateTracker.java
+++ b/services/core/java/com/android/server/AppStateTracker.java
@@ -448,6 +448,7 @@
             IntentFilter filter = new IntentFilter();
             filter.addAction(Intent.ACTION_USER_REMOVED);
             filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
             mContext.registerReceiver(new MyReceiver(), filter);
 
             refreshForcedAppStandbyUidPackagesLocked();
@@ -688,6 +689,13 @@
                     mIsPluggedIn = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0);
                 }
                 updateForceAllAppStandbyState();
+            } else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
+                    && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+                final String pkgName = intent.getData().getSchemeSpecificPart();
+                if (mExemptedPackages.remove(userId, pkgName)) {
+                    mHandler.notifyExemptChanged();
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 7c61ba2..1e9a9d8 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3102,30 +3102,24 @@
     }
 
     private void notifyDataStallSuspected(DataStallReportParcelable p, int netId) {
+        log("Data stall detected with methods: " + p.detectionMethod);
+
         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;
+        int detectionMethod = 0;
+        if (hasDataStallDetectionMethod(p, DETECTION_METHOD_DNS_EVENTS)) {
+            extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, p.dnsConsecutiveTimeouts);
+            detectionMethod |= DETECTION_METHOD_DNS_EVENTS;
+        }
+        if (hasDataStallDetectionMethod(p, DETECTION_METHOD_TCP_METRICS)) {
+            extras.putInt(KEY_TCP_PACKET_FAIL_RATE, p.tcpPacketFailRate);
+            extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS,
+                    p.tcpMetricsCollectionPeriodMillis);
+            detectionMethod |= DETECTION_METHOD_TCP_METRICS;
         }
 
-        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);
+                p.timestampMillis);
         msg.setData(new Bundle(extras));
 
         // NetworkStateTrackerHandler currently doesn't take any actions based on data
@@ -3134,6 +3128,10 @@
         mConnectivityDiagnosticsHandler.sendMessage(msg);
     }
 
+    private boolean hasDataStallDetectionMethod(DataStallReportParcelable p, int detectionMethod) {
+        return (p.detectionMethod & detectionMethod) != 0;
+    }
+
     private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) {
         return isPrivateDnsValidationRequired(nai.networkCapabilities);
     }
@@ -8189,6 +8187,19 @@
                 + "creators");
         }
 
-        notifyDataStallSuspected(detectionMethod, network.netId, timestampMillis, extras);
+        final DataStallReportParcelable p = new DataStallReportParcelable();
+        p.timestampMillis = timestampMillis;
+        p.detectionMethod = detectionMethod;
+
+        if (hasDataStallDetectionMethod(p, DETECTION_METHOD_DNS_EVENTS)) {
+            p.dnsConsecutiveTimeouts = extras.getInt(KEY_DNS_CONSECUTIVE_TIMEOUTS);
+        }
+        if (hasDataStallDetectionMethod(p, DETECTION_METHOD_TCP_METRICS)) {
+            p.tcpPacketFailRate = extras.getInt(KEY_TCP_PACKET_FAIL_RATE);
+            p.tcpMetricsCollectionPeriodMillis = extras.getInt(
+                    KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS);
+        }
+
+        notifyDataStallSuspected(p, network.netId);
     }
 }
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index e77458c..e303f0d 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -177,9 +177,6 @@
     // 0 if no prune is scheduled.
     @GuardedBy("mLock")
     private long mUptimeAtLastStateSync;
-    // If true, sync explicit health check packages with the ExplicitHealthCheckController.
-    @GuardedBy("mLock")
-    private boolean mSyncRequired = false;
 
     @FunctionalInterface
     @VisibleForTesting
@@ -255,7 +252,6 @@
      */
     public void registerHealthObserver(PackageHealthObserver observer) {
         synchronized (mLock) {
-            mSyncRequired = true;
             ObserverInternal internalObserver = mAllObservers.get(observer.getName());
             if (internalObserver != null) {
                 internalObserver.registeredObserver = observer;
@@ -642,7 +638,7 @@
         synchronized (mLock) {
             if (mIsPackagesReady) {
                 Set<String> packages = getPackagesPendingHealthChecksLocked();
-                if (!packages.equals(mRequestedHealthCheckPackages) || mSyncRequired) {
+                if (!packages.equals(mRequestedHealthCheckPackages) || packages.isEmpty()) {
                     syncRequired = true;
                     mRequestedHealthCheckPackages = packages;
                 }
@@ -654,7 +650,6 @@
             Slog.i(TAG, "Syncing health check requests for packages: "
                     + mRequestedHealthCheckPackages);
             mHealthCheckController.syncRequests(mRequestedHealthCheckPackages);
-            mSyncRequired = false;
         }
     }
 
diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java
index e5c0540..45d53a1 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/services/core/java/com/android/server/SystemService.java
@@ -68,8 +68,7 @@
 public abstract class SystemService {
 
     /** @hide */
-    // TODO(b/133242016) STOPSHIP: change to false before R ships
-    protected static final boolean DEBUG_USER = true;
+    protected static final boolean DEBUG_USER = false;
 
     /*
      * The earliest boot phase the system send to system services on boot.
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index cca6046..ec12aeb 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -4914,8 +4914,13 @@
 
     // TODO: remove this toast after feature development is done
     void showWhileInUseDebugToastLocked(int uid, int op, int mode) {
-        for (int i = mAm.mProcessList.mLruProcesses.size() - 1; i >= 0; i--) {
-            ProcessRecord pr = mAm.mProcessList.mLruProcesses.get(i);
+        final UidRecord uidRec = mAm.mProcessList.getUidRecordLocked(uid);
+        if (uidRec == null) {
+            return;
+        }
+
+        for (int i = uidRec.procRecords.size() - 1; i >= 0; i--) {
+            ProcessRecord pr = uidRec.procRecords.valueAt(i);
             if (pr.uid != uid) {
                 continue;
             }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 671733b..7ef527c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -11112,6 +11112,14 @@
             }
             pw.print("    UID "); UserHandle.formatUid(pw, uidRec.uid);
             pw.print(": "); pw.println(uidRec);
+            pw.print("      curProcState="); pw.print(uidRec.mCurProcState);
+            pw.print(" curCapability=");
+            ActivityManager.printCapabilitiesFull(pw, uidRec.curCapability);
+            pw.println();
+            for (int j = uidRec.procRecords.size() - 1; j >= 0; j--) {
+                pw.print("      proc=");
+                pw.println(uidRec.procRecords.valueAt(j));
+            }
         }
         return printed;
     }
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index f7a158a..a81590c 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -324,8 +324,21 @@
         boolean success = applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());
 
         if (uidRec != null) {
-            updateAppUidRecLocked(app);
-            // If this proc state is changed, need to update its uid record here
+            // After uidRec.reset() above, for UidRecord that has multiple processes (ProcessRecord)
+            // , We need to apply all ProcessRecord into UidRecord.
+            final ArraySet<ProcessRecord> procRecords = app.uidRecord.procRecords;
+            for (int i = procRecords.size() - 1; i >= 0; i--) {
+                final ProcessRecord pr = procRecords.valueAt(i);
+                if (!pr.killedByAm && pr.thread != null) {
+                    if (pr.isolated && pr.numberOfRunningServices() <= 0
+                            && pr.isolatedEntryPoint == null) {
+                        // No op.
+                    } else {
+                        // Keeping this process, update its uid.
+                        updateAppUidRecLocked(pr);
+                    }
+                }
+            }
             if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
                     && (uidRec.setProcState != uidRec.getCurProcState()
                     || uidRec.setCapability != uidRec.curCapability
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 108fb7d..9f2a77c 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2808,6 +2808,7 @@
                     uidRec.curCapability);
         }
         proc.uidRecord = uidRec;
+        uidRec.procRecords.add(proc);
 
         // Reset render thread tid if it was already set, so new process can set it again.
         proc.renderThreadTid = 0;
@@ -2901,6 +2902,7 @@
         }
         if (old != null && old.uidRecord != null) {
             old.uidRecord.numProcs--;
+            old.uidRecord.procRecords.remove(old);
             if (old.uidRecord.numProcs == 0) {
                 // No more processes using this uid, tell clients it is gone.
                 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index acf8b2e..c84ccb2 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -21,6 +21,7 @@
 import android.content.pm.PackageManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.util.ArraySet;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 import android.util.proto.ProtoUtils;
@@ -32,7 +33,7 @@
  */
 public final class UidRecord {
     final int uid;
-    private int mCurProcState;
+    int mCurProcState;
     int setProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
     int curCapability;
     int setCapability;
@@ -44,6 +45,7 @@
     boolean idle;
     boolean setIdle;
     int numProcs;
+    ArraySet<ProcessRecord> procRecords = new ArraySet<>();
 
     /**
      * Sequence number associated with the {@link #mCurProcState}. This is incremented using
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index df4c269..67e27c4 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -45,7 +45,10 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 
 /** @hide */
@@ -59,6 +62,9 @@
     // Timeout for connection to bluetooth headset service
     /*package*/ static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000;
 
+    // Delay before checking it music should be unmuted after processing an A2DP message
+    private static final int BTA2DP_MUTE_CHECK_DELAY_MS = 50;
+
     private final @NonNull AudioService mAudioService;
     private final @NonNull Context mContext;
 
@@ -1050,9 +1056,19 @@
                     final int strategy = msg.arg1;
                     mDeviceInventory.onSaveRemovePreferredDevice(strategy);
                 } break;
+                case MSG_CHECK_MUTE_MUSIC:
+                    checkMessagesMuteMusic();
+                    break;
                 default:
                     Log.wtf(TAG, "Invalid message " + msg.what);
             }
+
+            // Give some time to Bluetooth service to post a connection message
+            // in case of active device switch
+            if (MESSAGES_MUTE_MUSIC.contains(msg.what)) {
+                sendMsg(MSG_CHECK_MUTE_MUSIC, SENDMSG_REPLACE, BTA2DP_MUTE_CHECK_DELAY_MS);
+            }
+
             if (isMessageHandledUnderWakelock(msg.what)) {
                 try {
                     mBrokerEventWakeLock.release();
@@ -1116,6 +1132,7 @@
     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 final int MSG_CHECK_MUTE_MUSIC = 36;
 
 
     private static boolean isMessageHandledUnderWakelock(int msgId) {
@@ -1132,6 +1149,7 @@
             case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION:
             case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION:
             case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
+            case MSG_CHECK_MUTE_MUSIC:
                 return true;
             default:
                 return false;
@@ -1231,6 +1249,37 @@
             mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj),
                     time);
         }
+        if (MESSAGES_MUTE_MUSIC.contains(msg)) {
+            checkMessagesMuteMusic();
+        }
+    }
+
+    /** List of messages for which music is muted while processing is pending */
+    private static final Set<Integer> MESSAGES_MUTE_MUSIC;
+    static {
+        MESSAGES_MUTE_MUSIC = new HashSet<>();
+        MESSAGES_MUTE_MUSIC.add(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED);
+        MESSAGES_MUTE_MUSIC.add(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED);
+        MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONFIG_CHANGE);
+        MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE);
+        MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION);
+        MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION);
+    }
+
+    private AtomicBoolean mMusicMuted = new AtomicBoolean(false);
+
+    /** Mutes or unmutes music according to pending A2DP messages */
+    private void checkMessagesMuteMusic() {
+        boolean mute = false;
+        for (int msg : MESSAGES_MUTE_MUSIC) {
+            if (mBrokerHandler.hasMessages(msg)) {
+                mute = true;
+                break;
+            }
+        }
+        if (mute != mMusicMuted.getAndSet(mute)) {
+            mAudioService.setMusicMute(mute);
+        }
     }
 
     private class SpeakerphoneClient implements IBinder.DeathRecipient {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 7e6f232..ed05fff 100755
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -5069,6 +5069,10 @@
                 profile, suppressNoisyIntent, a2dpVolume);
     }
 
+    /*package*/ void setMusicMute(boolean mute) {
+        mStreamStates[AudioSystem.STREAM_MUSIC].muteInternally(mute);
+    }
+
     /**
      * See AudioManager.handleBluetoothA2dpDeviceConfigChange()
      * @param device
@@ -5471,6 +5475,7 @@
         private int mIndexMax;
 
         private boolean mIsMuted;
+        private boolean mIsMutedInternally;
         private String mVolumeIndexSettingName;
         private int mObservedDevices;
 
@@ -5644,7 +5649,8 @@
             // Only set audio policy BT SCO stream volume to 0 when the stream is actually muted.
             // This allows RX path muting by the audio HAL only when explicitly muted but not when
             // index is just set to 0 to repect BT requirements
-            if (mStreamType == AudioSystem.STREAM_BLUETOOTH_SCO && index == 0 && !mIsMuted) {
+            if (mStreamType == AudioSystem.STREAM_BLUETOOTH_SCO && index == 0
+                    && !isFullyMuted()) {
                 index = 1;
             }
             AudioSystem.setStreamVolumeIndexAS(mStreamType, index, device);
@@ -5653,7 +5659,7 @@
         // must be called while synchronized VolumeStreamState.class
         /*package*/ void applyDeviceVolume_syncVSS(int device, boolean isAvrcpAbsVolSupported) {
             int index;
-            if (mIsMuted) {
+            if (isFullyMuted()) {
                 index = 0;
             } else if (AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
                     && isAvrcpAbsVolSupported) {
@@ -5676,7 +5682,7 @@
                 for (int i = 0; i < mIndexMap.size(); i++) {
                     final int device = mIndexMap.keyAt(i);
                     if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
-                        if (mIsMuted) {
+                        if (isFullyMuted()) {
                             index = 0;
                         } else if (AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
                                 && isAvrcpAbsVolSupported) {
@@ -5693,7 +5699,7 @@
                 }
                 // apply default volume last: by convention , default device volume will be used
                 // by audio policy manager if no explicit volume is present for a given device type
-                if (mIsMuted) {
+                if (isFullyMuted()) {
                     index = 0;
                 } else {
                     index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
@@ -5887,6 +5893,41 @@
             return changed;
         }
 
+        /**
+         * Mute/unmute the stream by AudioService
+         * @param state the new mute state
+         * @return true if the mute state was changed
+         */
+        public boolean muteInternally(boolean state) {
+            boolean changed = false;
+            synchronized (VolumeStreamState.class) {
+                if (state != mIsMutedInternally) {
+                    changed = true;
+                    mIsMutedInternally = state;
+
+                    // Set the new mute volume. This propagates the values to
+                    // the audio system, otherwise the volume won't be changed
+                    // at the lower level.
+                    sendMsg(mAudioHandler,
+                            MSG_SET_ALL_VOLUMES,
+                            SENDMSG_QUEUE,
+                            0,
+                            0,
+                            this, 0);
+                }
+            }
+            if (changed) {
+                sVolumeLogger.log(new VolumeEvent(
+                        VolumeEvent.VOL_MUTE_STREAM_INT, mStreamType, state));
+            }
+            return changed;
+        }
+
+        @GuardedBy("VolumeStreamState.class")
+        public boolean isFullyMuted() {
+            return mIsMuted || mIsMutedInternally;
+        }
+
         public int getStreamType() {
             return mStreamType;
         }
@@ -5923,6 +5964,8 @@
         private void dump(PrintWriter pw) {
             pw.print("   Muted: ");
             pw.println(mIsMuted);
+            pw.print("   Muted Internally: ");
+            pw.println(mIsMutedInternally);
             pw.print("   Min: ");
             pw.print((mIndexMin + 5) / 10);
             if (mIndexMin != mIndexMinNoPerm) {
diff --git a/services/core/java/com/android/server/audio/AudioServiceEvents.java b/services/core/java/com/android/server/audio/AudioServiceEvents.java
index 5913567..f3ff02f 100644
--- a/services/core/java/com/android/server/audio/AudioServiceEvents.java
+++ b/services/core/java/com/android/server/audio/AudioServiceEvents.java
@@ -100,6 +100,7 @@
         static final int VOL_VOICE_ACTIVITY_HEARING_AID = 6;
         static final int VOL_MODE_CHANGE_HEARING_AID = 7;
         static final int VOL_SET_GROUP_VOL = 8;
+        static final int VOL_MUTE_STREAM_INT = 9;
 
         final int mOp;
         final int mStream;
@@ -188,6 +189,18 @@
             logMetricEvent();
         }
 
+        /** used for VOL_MUTE_STREAM_INT */
+        VolumeEvent(int op, int stream, boolean state) {
+            mOp = op;
+            mStream = stream;
+            mVal1 = state ? 1 : 0;
+            mVal2 = 0;
+            mCaller = null;
+            mGroupName = null;
+            mAudioAttributes = null;
+            logMetricEvent();
+        }
+
 
         /**
          * Audio Analytics unique Id.
@@ -278,6 +291,9 @@
                             .set(MediaMetrics.Property.INDEX, mVal1)
                             .record();
                     return;
+                case VOL_MUTE_STREAM_INT:
+                    // No value in logging metrics for this internal event
+                    return;
                 default:
                     return;
             }
@@ -343,6 +359,11 @@
                             .append(" flags:0x").append(Integer.toHexString(mVal2))
                             .append(") from ").append(mCaller)
                             .toString();
+                case VOL_MUTE_STREAM_INT:
+                    return new StringBuilder("VolumeStreamState.muteInternally(stream:")
+                            .append(AudioSystem.streamToString(mStream))
+                            .append(mVal1 == 1 ? ", muted)" : ", unmuted)")
+                            .toString();
                 default: return new StringBuilder("FIXME invalid op:").append(mOp).toString();
             }
         }
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index f3c7874..a33817c 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -65,6 +65,7 @@
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkProvider;
+import android.net.NetworkRequest;
 import android.net.RouteInfo;
 import android.net.UidRange;
 import android.net.VpnManager;
@@ -2225,12 +2226,27 @@
 
         @Override
         public void run() {
-            // Explicitly use only the network that ConnectivityService thinks is the "best." In
-            // other words, only ever use the currently selected default network. This does mean
-            // that in both onLost() and onConnected(), any old sessions MUST be torn down. This
-            // does NOT include VPNs.
+            // Unless the profile is restricted to test networks, explicitly use only the network
+            // that ConnectivityService thinks is the "best." In other words, only ever use the
+            // currently selected default network. This does mean that in both onLost() and
+            // onConnected(), any old sessions MUST be torn down. This does NOT include VPNs.
+            //
+            // When restricted to test networks, select any network with TRANSPORT_TEST. Since the
+            // creator of the profile and the test network creator both have MANAGE_TEST_NETWORKS,
+            // this is considered safe.
             final ConnectivityManager cm = ConnectivityManager.from(mContext);
-            cm.requestNetwork(cm.getDefaultRequest(), mNetworkCallback);
+            final NetworkRequest req;
+
+            if (mProfile.isRestrictedToTestNetworks()) {
+                req = new NetworkRequest.Builder()
+                        .clearCapabilities()
+                        .addTransportType(NetworkCapabilities.TRANSPORT_TEST)
+                        .build();
+            } else {
+                req = cm.getDefaultRequest();
+            }
+
+            cm.requestNetwork(req, mNetworkCallback);
         }
 
         private boolean isActiveNetwork(@Nullable Network network) {
@@ -2868,6 +2884,11 @@
         verifyCallingUidAndPackage(packageName);
         enforceNotRestrictedUser();
 
+        if (profile.isRestrictedToTestNetworks) {
+            mContext.enforceCallingPermission(Manifest.permission.MANAGE_TEST_NETWORKS,
+                    "Test-mode profiles require the MANAGE_TEST_NETWORKS permission");
+        }
+
         final byte[] encodedProfile = profile.encode();
         if (encodedProfile.length > MAX_VPN_PROFILE_SIZE_BYTES) {
             throw new IllegalArgumentException("Profile too big");
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index b9cd43d..787f7f3 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -28,7 +28,6 @@
 import android.util.Slog;
 import android.util.Spline;
 
-import com.android.internal.BrightnessSynchronizer;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
 import com.android.server.display.utils.Plog;
@@ -347,10 +346,11 @@
         }
     }
 
+    // Normalize entire brightness range to 0 - 1.
     protected static float normalizeAbsoluteBrightness(int brightness) {
-        return BrightnessSynchronizer.brightnessIntToFloat(brightness,
-                PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
-                PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
+        brightness = MathUtils.constrain(brightness,
+                PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
+        return (float) brightness / PowerManager.BRIGHTNESS_ON;
     }
 
     private Pair<float[], float[]> insertControlPoint(
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 52116a0..a498e38 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -820,10 +820,15 @@
             final EditorInfo mEditorInfo;
             @NonNull
             final String mRequestWindowName;
+            @Nullable
+            final String mImeControlTargetName;
+            @Nullable
+            final String mImeTargetNameFromWm;
 
             Entry(ClientState client, EditorInfo editorInfo, String focusedWindowName,
                     @SoftInputModeFlags int softInputMode, @SoftInputShowHideReason int reason,
-                    boolean inFullscreenMode, String requestWindowName) {
+                    boolean inFullscreenMode, String requestWindowName,
+                    @Nullable String imeControlTargetName, @Nullable String imeTargetName) {
                 mClientState = client;
                 mEditorInfo = editorInfo;
                 mFocusedWindowName = focusedWindowName;
@@ -833,6 +838,8 @@
                 mWallTime = System.currentTimeMillis();
                 mInFullscreenMode = inFullscreenMode;
                 mRequestWindowName = requestWindowName;
+                mImeControlTargetName = imeControlTargetName;
+                mImeTargetNameFromWm = imeTargetName;
             }
         }
 
@@ -873,6 +880,12 @@
                 pw.println(" requestWindowName=" + entry.mRequestWindowName);
 
                 pw.print(prefix);
+                pw.println(" imeControlTargetName=" + entry.mImeControlTargetName);
+
+                pw.print(prefix);
+                pw.println(" imeTargetNameFromWm=" + entry.mImeTargetNameFromWm);
+
+                pw.print(prefix);
                 pw.print(" editorInfo: ");
                 pw.print(" inputType=" + entry.mEditorInfo.inputType);
                 pw.print(" privateImeOptions=" + entry.mEditorInfo.privateImeOptions);
@@ -4123,7 +4136,11 @@
                             mWindowManagerInternal.getWindowName(mCurFocusedWindow),
                             mCurFocusedWindowSoftInputMode, reason, mInFullscreenMode,
                             mWindowManagerInternal.getWindowName(
-                                    mShowRequestWindowMap.get(args.arg3))));
+                                    mShowRequestWindowMap.get(args.arg3)),
+                            mWindowManagerInternal.getImeControlTargetNameForLogging(
+                                    mCurTokenDisplayId),
+                            mWindowManagerInternal.getImeTargetNameForLogging(
+                                    mCurTokenDisplayId)));
                 } catch (RemoteException e) {
                 }
                 args.recycle();
@@ -4142,7 +4159,11 @@
                             mWindowManagerInternal.getWindowName(mCurFocusedWindow),
                             mCurFocusedWindowSoftInputMode, reason, mInFullscreenMode,
                             mWindowManagerInternal.getWindowName(
-                                    mHideRequestWindowMap.get(args.arg3))));
+                                    mHideRequestWindowMap.get(args.arg3)),
+                            mWindowManagerInternal.getImeControlTargetNameForLogging(
+                                    mCurTokenDisplayId),
+                            mWindowManagerInternal.getImeTargetNameForLogging(
+                                    mCurTokenDisplayId)));
                 } catch (RemoteException e) {
                 }
                 args.recycle();
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index 3dac106..86ad0b3 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -152,12 +152,10 @@
 
     /**
      * Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}.
-     * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map, boolean)
+     * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map)
      */
-    public void apply464xlatAdjustments(NetworkStats baseTraffic,
-            NetworkStats stackedTraffic, boolean useBpfStats) {
-        NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces,
-                useBpfStats);
+    public void apply464xlatAdjustments(NetworkStats baseTraffic, NetworkStats stackedTraffic) {
+        NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces);
     }
 
     public NetworkStatsFactory() {
@@ -380,7 +378,7 @@
         // network, the overhead is their fault.
         // No locking here: apply464xlatAdjustments behaves fine with an add-only
         // ConcurrentHashMap.
-        delta.apply464xlatAdjustments(mStackedIfaces, mUseBpfStats);
+        delta.apply464xlatAdjustments(mStackedIfaces);
 
         // Migrate data usage over a VPN to the TUN network.
         for (VpnInfo info : vpnArray) {
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index dcbdfdf..ba9f486 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -1311,21 +1311,39 @@
                 }
 
                 // Traffic occurring on stacked interfaces is usually clatd.
-                // UID stats are always counted on the stacked interface and never
-                // on the base interface, because the packets on the base interface
-                // do not actually match application sockets until they are translated.
                 //
-                // Interface stats are more complicated. Packets subject to BPF offload
-                // never appear on the base interface and only appear on the stacked
-                // interface, so to ensure those packets increment interface stats, interface
-                // stats from stacked interfaces must be collected.
+                // UID stats are always counted on the stacked interface and never on the base
+                // interface, because the packets on the base interface do not actually match
+                // application sockets (they're not IPv4) and thus the app uid is not known.
+                // For receive this is obvious: packets must be translated from IPv6 to IPv4
+                // before the application socket can be found.
+                // For transmit: either they go through the clat daemon which by virtue of going
+                // through userspace strips the original socket association during the IPv4 to
+                // IPv6 translation process, or they are offloaded by eBPF, which doesn't:
+                // However, on an ebpf device the accounting is done in cgroup ebpf hooks,
+                // which don't trigger again post ebpf translation.
+                // (as such stats accounted to the clat uid are ignored)
+                //
+                // Interface stats are more complicated.
+                //
+                // eBPF offloaded 464xlat'ed packets never hit base interface ip6tables, and thus
+                // *all* statistics are collected by iptables on the stacked v4-* interface.
+                //
+                // Additionally for ingress all packets bound for the clat IPv6 address are dropped
+                // in ip6tables raw prerouting and thus even non-offloaded packets are only
+                // accounted for on the stacked interface.
+                //
+                // For egress, packets subject to eBPF offload never appear on the base interface
+                // and only appear on the stacked interface. Thus to ensure packets increment
+                // interface stats, we must collate data from stacked interfaces. For xt_qtaguid
+                // (or non eBPF offloaded) TX they would appear on both, however egress interface
+                // accounting is explicitly bypassed for traffic from the clat uid.
+                //
                 final List<LinkProperties> stackedLinks = state.linkProperties.getStackedLinks();
                 for (LinkProperties stackedLink : stackedLinks) {
                     final String stackedIface = stackedLink.getInterfaceName();
                     if (stackedIface != null) {
-                        if (mUseBpfTrafficStats) {
-                            findOrCreateNetworkIdentitySet(mActiveIfaces, stackedIface).add(ident);
-                        }
+                        findOrCreateNetworkIdentitySet(mActiveIfaces, stackedIface).add(ident);
                         findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident);
                         if (isMobile) {
                             mobileIfaces.add(stackedIface);
@@ -1864,14 +1882,13 @@
         // fold tethering stats and operations into uid snapshot
         final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID);
         tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL);
-        mStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot,
-                mUseBpfTrafficStats);
+        mStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot);
         uidSnapshot.combineAllValues(tetherSnapshot);
 
         // get a stale copy of uid stats snapshot provided by providers.
         final NetworkStats providerStats = getNetworkStatsFromProviders(STATS_PER_UID);
         providerStats.filter(UID_ALL, ifaces, TAG_ALL);
-        mStatsFactory.apply464xlatAdjustments(uidSnapshot, providerStats, mUseBpfTrafficStats);
+        mStatsFactory.apply464xlatAdjustments(uidSnapshot, providerStats);
         uidSnapshot.combineAllValues(providerStats);
 
         uidSnapshot.combineAllValues(mUidOperations);
diff --git a/services/core/java/com/android/server/notification/BubbleExtractor.java b/services/core/java/com/android/server/notification/BubbleExtractor.java
index d7d413c..0fa339f 100644
--- a/services/core/java/com/android/server/notification/BubbleExtractor.java
+++ b/services/core/java/com/android/server/notification/BubbleExtractor.java
@@ -75,9 +75,19 @@
                 mConfig.getBubblePreference(
                         record.getSbn().getPackageName(), record.getSbn().getUid());
         NotificationChannel recordChannel = record.getChannel();
+        boolean canPresentAsBubble = canPresentAsBubble(record)
+                && !mActivityManager.isLowRamDevice()
+                && record.isConversation()
+                && (record.getNotification().flags & FLAG_FOREGROUND_SERVICE) == 0;
 
-        if (!mConfig.bubblesEnabled() || bubblePreference == BUBBLE_PREFERENCE_NONE) {
+        if (!mConfig.bubblesEnabled()
+                || bubblePreference == BUBBLE_PREFERENCE_NONE
+                || !canPresentAsBubble) {
             record.setAllowBubble(false);
+            if (!canPresentAsBubble) {
+                // clear out bubble metadata since it can't be used
+                record.getNotification().setBubbleMetadata(null);
+            }
         } else if (recordChannel == null) {
             // the app is allowed but there's no channel to check
             record.setAllowBubble(true);
@@ -86,14 +96,15 @@
         } else if (bubblePreference == BUBBLE_PREFERENCE_SELECTED) {
             record.setAllowBubble(recordChannel.canBubble());
         }
+        if (DBG) {
+            Slog.d(TAG, "record: " + record.getKey()
+                    + " appPref: " + bubblePreference
+                    + " canBubble: " + record.canBubble()
+                    + " canPresentAsBubble: " + canPresentAsBubble
+                    + " flagRemoved: " + record.isFlagBubbleRemoved());
+        }
 
-        final boolean fulfillsPolicy = record.canBubble()
-                && record.isConversation()
-                && !mActivityManager.isLowRamDevice()
-                && (record.getNotification().flags & FLAG_FOREGROUND_SERVICE) == 0;
-        final boolean applyFlag = fulfillsPolicy
-                && canPresentAsBubble(record)
-                && !record.isFlagBubbleRemoved();
+        final boolean applyFlag = record.canBubble() && !record.isFlagBubbleRemoved();
         if (applyFlag) {
             record.getNotification().flags |= FLAG_BUBBLE;
         } else {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 86e8734..86d2e63 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -292,6 +292,7 @@
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -530,6 +531,7 @@
     private final SavePolicyFileRunnable mSavePolicyFile = new SavePolicyFileRunnable();
     private NotificationRecordLogger mNotificationRecordLogger;
     private InstanceIdSequence mNotificationInstanceIdSequence;
+    private Set<String> mMsgPkgsAllowedAsConvos = new HashSet();
 
     static class Archive {
         final SparseArray<Boolean> mEnabled;
@@ -2042,6 +2044,9 @@
         mStripRemoteViewsSizeBytes = getContext().getResources().getInteger(
                 com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
 
+        mMsgPkgsAllowedAsConvos = Set.of(
+                getContext().getResources().getStringArray(
+                        com.android.internal.R.array.config_notificationMsgPkgsAllowedAsConvos));
         mStatsManager = statsManager;
     }
 
@@ -5683,6 +5688,7 @@
         r.setIsAppImportanceLocked(mPreferencesHelper.getIsAppImportanceLocked(pkg, callingUid));
         r.setPostSilently(postSilently);
         r.setFlagBubbleRemoved(false);
+        r.setPkgAllowedAsConvo(mMsgPkgsAllowedAsConvos.contains(pkg));
 
         if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
             final boolean fgServiceShown = channel.isFgServiceShown();
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index c107822..bae02ac 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -190,6 +190,7 @@
     private boolean mPostSilently;
     private boolean mHasSentValidMsg;
     private boolean mAppDemotedFromConvo;
+    private boolean mPkgAllowedAsConvo;
     /**
      * Whether this notification (and its channels) should be considered user locked. Used in
      * conjunction with user sentiment calculation.
@@ -1387,21 +1388,33 @@
         mAppDemotedFromConvo = userDemoted;
     }
 
+    public void setPkgAllowedAsConvo(boolean allowedAsConvo) {
+        mPkgAllowedAsConvo = allowedAsConvo;
+    }
+
     /**
      * Whether this notification is a conversation notification.
      */
     public boolean isConversation() {
         Notification notification = getNotification();
-        if (!Notification.MessagingStyle.class.equals(notification.getNotificationStyle())) {
-            // very common; don't bother logging
+        // user kicked it out of convo space
+        if (mChannel.isDemoted() || mAppDemotedFromConvo) {
             return false;
         }
-        if (mChannel.isDemoted()) {
-            return false;
-        }
+        // NAS kicked it out of notification space
         if (mIsNotConversationOverride) {
             return false;
         }
+        if (!Notification.MessagingStyle.class.equals(notification.getNotificationStyle())) {
+            // some non-msgStyle notifs can temporarily appear in the conversation space if category
+            // is right
+            if (mPkgAllowedAsConvo && mTargetSdkVersion < Build.VERSION_CODES.R
+                && Notification.CATEGORY_MESSAGE.equals(getNotification().category)) {
+                return true;
+            }
+            return false;
+        }
+
         if (mTargetSdkVersion >= Build.VERSION_CODES.R
             && Notification.MessagingStyle.class.equals(notification.getNotificationStyle())
             && mShortcutInfo == null) {
@@ -1410,9 +1423,6 @@
         if (mHasSentValidMsg && mShortcutInfo == null) {
             return false;
         }
-        if (mAppDemotedFromConvo) {
-            return false;
-        }
         return true;
     }
 
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 9d56d81..77b030f 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -85,7 +85,8 @@
     private static final int XML_VERSION = 2;
     /** What version to check to do the upgrade for bubbles. */
     private static final int XML_VERSION_BUBBLES_UPGRADE = 1;
-    private static final int UNKNOWN_UID = UserHandle.USER_NULL;
+    @VisibleForTesting
+    static final int UNKNOWN_UID = UserHandle.USER_NULL;
     private static final String NON_BLOCKABLE_CHANNEL_DELIM = ":";
 
     @VisibleForTesting
@@ -224,7 +225,7 @@
                             }
                             boolean skipWarningLogged = false;
                             boolean hasSAWPermission = false;
-                            if (upgradeForBubbles) {
+                            if (upgradeForBubbles && uid != UNKNOWN_UID) {
                                 hasSAWPermission = mAppOps.noteOpNoThrow(
                                         OP_SYSTEM_ALERT_WINDOW, uid, name, null,
                                         "check-notif-bubble") == AppOpsManager.MODE_ALLOWED;
diff --git a/services/core/java/com/android/server/notification/ShortcutHelper.java b/services/core/java/com/android/server/notification/ShortcutHelper.java
index e79d33f..ee02e3f 100644
--- a/services/core/java/com/android/server/notification/ShortcutHelper.java
+++ b/services/core/java/com/android/server/notification/ShortcutHelper.java
@@ -28,6 +28,7 @@
 import android.os.Binder;
 import android.os.Handler;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -111,6 +112,15 @@
                     }
                     if (!foundShortcut) {
                         bubbleKeysToRemove.add(shortcutBubbles.get(shortcutId));
+                        shortcutBubbles.remove(shortcutId);
+                        if (shortcutBubbles.isEmpty()) {
+                            mActiveShortcutBubbles.remove(packageName);
+                            if (mLauncherAppsCallbackRegistered
+                                    && mActiveShortcutBubbles.isEmpty()) {
+                                mLauncherAppsService.unregisterCallback(mLauncherAppsCallback);
+                                mLauncherAppsCallbackRegistered = false;
+                            }
+                        }
                     }
                 }
             }
@@ -198,7 +208,7 @@
         if (shortcutInfo.isLongLived() && !shortcutInfo.isCached()) {
             mShortcutServiceInternal.cacheShortcuts(user.getIdentifier(), "android",
                     shortcutInfo.getPackage(), Collections.singletonList(shortcutInfo.getId()),
-                    shortcutInfo.getUserId());
+                    shortcutInfo.getUserId(), ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
         }
     }
 
@@ -209,15 +219,16 @@
      * @param removedNotification true if this notification is being removed
      * @param handler handler to register the callback with
      */
-    void maybeListenForShortcutChangesForBubbles(NotificationRecord r, boolean removedNotification,
+    void maybeListenForShortcutChangesForBubbles(NotificationRecord r,
+            boolean removedNotification,
             Handler handler) {
         final String shortcutId = r.getNotification().getBubbleMetadata() != null
                 ? r.getNotification().getBubbleMetadata().getShortcutId()
                 : null;
-        if (shortcutId == null) {
-            return;
-        }
-        if (r.getNotification().isBubbleNotification() && !removedNotification) {
+        if (!removedNotification
+                && !TextUtils.isEmpty(shortcutId)
+                && r.getShortcutInfo() != null
+                && r.getShortcutInfo().getId().equals(shortcutId)) {
             // Must track shortcut based bubbles in case the shortcut is removed
             HashMap<String, String> packageBubbles = mActiveShortcutBubbles.get(
                     r.getSbn().getPackageName());
@@ -235,10 +246,21 @@
             HashMap<String, String> packageBubbles = mActiveShortcutBubbles.get(
                     r.getSbn().getPackageName());
             if (packageBubbles != null) {
-                packageBubbles.remove(shortcutId);
-            }
-            if (packageBubbles != null && packageBubbles.isEmpty()) {
-                mActiveShortcutBubbles.remove(r.getSbn().getPackageName());
+                if (!TextUtils.isEmpty(shortcutId)) {
+                    packageBubbles.remove(shortcutId);
+                } else {
+                    // Check if there was a matching entry
+                    for (String pkgShortcutId : packageBubbles.keySet()) {
+                        String entryKey = packageBubbles.get(pkgShortcutId);
+                        if (r.getKey().equals(entryKey)) {
+                            // No longer has shortcut id so remove it
+                            packageBubbles.remove(pkgShortcutId);
+                        }
+                    }
+                }
+                if (packageBubbles.isEmpty()) {
+                    mActiveShortcutBubbles.remove(r.getSbn().getPackageName());
+                }
             }
             if (mLauncherAppsCallbackRegistered && mActiveShortcutBubbles.isEmpty()) {
                 mLauncherAppsService.unregisterCallback(mLauncherAppsCallback);
diff --git a/services/core/java/com/android/server/om/IdmapDaemon.java b/services/core/java/com/android/server/om/IdmapDaemon.java
index 910ed44..19fa920 100644
--- a/services/core/java/com/android/server/om/IdmapDaemon.java
+++ b/services/core/java/com/android/server/om/IdmapDaemon.java
@@ -30,6 +30,7 @@
 
 import com.android.server.FgThread;
 
+import java.io.File;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -124,9 +125,13 @@
         }
     }
 
-    String getIdmapPath(String overlayPath, int userId) throws TimeoutException, RemoteException {
+    boolean idmapExists(String overlayPath, int userId) {
         try (Connection c = connect()) {
-            return mService.getIdmapPath(overlayPath, userId);
+            return new File(mService.getIdmapPath(overlayPath, userId)).isFile();
+        } catch (Exception e) {
+            Slog.wtf(TAG, "failed to check if idmap exists for " + overlayPath + ": "
+                    + e.getMessage());
+            return false;
         }
     }
 
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index 90c85ad..735d669 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -27,10 +27,10 @@
 import android.os.Build.VERSION_CODES;
 import android.os.OverlayablePolicy;
 import android.os.SystemProperties;
-import android.os.UserHandle;
 import android.util.Slog;
 
-import java.io.File;
+import com.android.internal.util.ArrayUtils;
+
 import java.io.IOException;
 
 /**
@@ -55,12 +55,16 @@
         VENDOR_IS_Q_OR_LATER = isQOrLater;
     }
 
-    private final OverlayableInfoCallback mOverlayableCallback;
     private final IdmapDaemon mIdmapDaemon;
+    private final OverlayableInfoCallback mOverlayableCallback;
+    private final String mOverlayableConfigurator;
+    private final String[] mOverlayableConfiguratorTargets;
 
-    IdmapManager(final OverlayableInfoCallback verifyCallback) {
+    IdmapManager(final IdmapDaemon idmapDaemon, final OverlayableInfoCallback verifyCallback) {
         mOverlayableCallback = verifyCallback;
-        mIdmapDaemon = IdmapDaemon.getInstance();
+        mIdmapDaemon = idmapDaemon;
+        mOverlayableConfigurator = verifyCallback.getOverlayableConfigurator();
+        mOverlayableConfiguratorTargets = verifyCallback.getOverlayableConfiguratorTargets() ;
     }
 
     /**
@@ -103,23 +107,11 @@
     }
 
     boolean idmapExists(@NonNull final OverlayInfo oi) {
-        return new File(getIdmapPath(oi.baseCodePath, oi.userId)).isFile();
+        return mIdmapDaemon.idmapExists(oi.baseCodePath, oi.userId);
     }
 
     boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) {
-        return new File(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath(), userId))
-            .isFile();
-    }
-
-    private @NonNull String getIdmapPath(@NonNull final String overlayPackagePath,
-            final int userId) {
-        try {
-            return mIdmapDaemon.getIdmapPath(overlayPackagePath, userId);
-        } catch (Exception e) {
-            Slog.w(TAG, "failed to get idmap path for " + overlayPackagePath + ": "
-                    + e.getMessage());
-            return "";
-        }
+        return mIdmapDaemon.idmapExists(overlayPackage.applicationInfo.getBaseCodePath(), userId);
     }
 
     /**
@@ -198,9 +190,17 @@
         String targetOverlayableName = overlayPackage.targetOverlayableName;
         if (targetOverlayableName != null) {
             try {
+                if (!mOverlayableConfigurator.isEmpty()
+                        && ArrayUtils.contains(mOverlayableConfiguratorTargets,
+                                targetPackage.packageName)
+                        && mOverlayableCallback.signaturesMatching(mOverlayableConfigurator,
+                                overlayPackage.packageName, userId)) {
+                    return true;
+                }
+
                 OverlayableInfo overlayableInfo = mOverlayableCallback.getOverlayableForTarget(
                         targetPackage.packageName, targetOverlayableName, userId);
-                if (overlayableInfo != null) {
+                if (overlayableInfo != null && overlayableInfo.actor != null) {
                     String actorPackageName = OverlayActorEnforcer.getPackageNameForActor(
                             overlayableInfo.actor, mOverlayableCallback.getNamedActors()).first;
                     if (mOverlayableCallback.signaturesMatching(actorPackageName,
diff --git a/services/core/java/com/android/server/om/OverlayActorEnforcer.java b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
index ef6655d..2bc3499 100644
--- a/services/core/java/com/android/server/om/OverlayActorEnforcer.java
+++ b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
@@ -50,8 +50,8 @@
     /**
      * @return nullable actor result with {@link ActorState} failure status
      */
-    static Pair<String, ActorState> getPackageNameForActor(String actorUriString,
-            Map<String, Map<String, String>> namedActors) {
+    static Pair<String, ActorState> getPackageNameForActor(@NonNull String actorUriString,
+            @NonNull Map<String, Map<String, String>> namedActors) {
         Uri actorUri = Uri.parse(actorUriString);
 
         String actorScheme = actorUri.getScheme();
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 6a8e465..086ab81 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -45,6 +45,7 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.UserInfo;
 import android.content.res.ApkAssets;
+import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Environment;
@@ -62,6 +63,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 
+import com.android.internal.R;
 import com.android.internal.content.om.OverlayConfig;
 import com.android.server.FgThread;
 import com.android.server.IoThread;
@@ -246,7 +248,7 @@
                     new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays");
             mPackageManager = new PackageManagerHelperImpl(context);
             mUserManager = UserManagerService.getInstance();
-            IdmapManager im = new IdmapManager(mPackageManager);
+            IdmapManager im = new IdmapManager(IdmapDaemon.getInstance(), mPackageManager);
             mSettings = new OverlayManagerSettings();
             mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings,
                     OverlayConfig.getSystemInstance(), getDefaultOverlayPackages(),
@@ -1119,6 +1121,17 @@
         }
 
         @Override
+        public String getOverlayableConfigurator() {
+            return Resources.getSystem().getString(R.string.config_overlayableConfigurator);
+        }
+
+        @Override
+        public String[] getOverlayableConfiguratorTargets() {
+            return Resources.getSystem().getStringArray(
+                    R.array.config_overlayableConfiguratorTargets);
+        }
+
+        @Override
         public List<PackageInfo> getOverlayPackages(final int userId) {
             final List<PackageInfo> overlays = mPackageManagerInternal.getOverlayPackages(userId);
             for (final PackageInfo info : overlays) {
diff --git a/services/core/java/com/android/server/om/OverlayableInfoCallback.java b/services/core/java/com/android/server/om/OverlayableInfoCallback.java
index 5066ecd..41c341a 100644
--- a/services/core/java/com/android/server/om/OverlayableInfoCallback.java
+++ b/services/core/java/com/android/server/om/OverlayableInfoCallback.java
@@ -80,4 +80,24 @@
      *     in the system returns {@link PackageManager#SIGNATURE_MATCH}
      */
     boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId);
+
+    /**
+     * Retrieves the package name that is recognized as an actor for the packages specified by
+     * {@link #getOverlayableConfiguratorTargets()}.
+     */
+    @NonNull
+    default String getOverlayableConfigurator() {
+        return "";
+    }
+
+    /**
+     * Retrieves the target packages that recognize the {@link #getOverlayableConfigurator} as an
+     * actor for its overlayable declarations. Overlays targeting one of the specified targets that
+     * are signed with the same signature as the overlayable configurator will be granted the
+     * "actor" policy.
+     */
+    @NonNull
+    default String[] getOverlayableConfiguratorTargets() {
+        return new String[0];
+    }
 }
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index c6d08c3..5bbe490 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -18,6 +18,8 @@
 
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
+import static android.content.pm.LauncherApps.FLAG_CACHE_BUBBLE_SHORTCUTS;
+import static android.content.pm.LauncherApps.FLAG_CACHE_NOTIFICATION_SHORTCUTS;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -78,6 +80,7 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.pm.parsing.pkg.AndroidPackage;
@@ -780,26 +783,28 @@
 
         @Override
         public void cacheShortcuts(String callingPackage, String packageName, List<String> ids,
-                UserHandle targetUser) {
+                UserHandle targetUser, int cacheFlags) {
             ensureStrictAccessShortcutsPermission(callingPackage);
             if (!canAccessProfile(targetUser.getIdentifier(), "Cannot cache shortcuts")) {
                 return;
             }
 
-            mShortcutServiceInternal.cacheShortcuts(getCallingUserId(),
-                    callingPackage, packageName, ids, targetUser.getIdentifier());
+            mShortcutServiceInternal.cacheShortcuts(
+                    getCallingUserId(), callingPackage, packageName, ids,
+                    targetUser.getIdentifier(), toShortcutsCacheFlags(cacheFlags));
         }
 
         @Override
         public void uncacheShortcuts(String callingPackage, String packageName, List<String> ids,
-                UserHandle targetUser) {
+                UserHandle targetUser, int cacheFlags) {
             ensureStrictAccessShortcutsPermission(callingPackage);
             if (!canAccessProfile(targetUser.getIdentifier(), "Cannot uncache shortcuts")) {
                 return;
             }
 
-            mShortcutServiceInternal.uncacheShortcuts(getCallingUserId(),
-                    callingPackage, packageName, ids, targetUser.getIdentifier());
+            mShortcutServiceInternal.uncacheShortcuts(
+                    getCallingUserId(), callingPackage, packageName, ids,
+                    targetUser.getIdentifier(), toShortcutsCacheFlags(cacheFlags));
         }
 
         @Override
@@ -1058,6 +1063,18 @@
                     user.getIdentifier(), debugMsg, false);
         }
 
+        private int toShortcutsCacheFlags(int cacheFlags) {
+            int ret = 0;
+            if (cacheFlags == FLAG_CACHE_NOTIFICATION_SHORTCUTS) {
+                ret = ShortcutInfo.FLAG_CACHED_NOTIFICATIONS;
+            } else if (cacheFlags == FLAG_CACHE_BUBBLE_SHORTCUTS) {
+                ret = ShortcutInfo.FLAG_CACHED_BUBBLES;
+            }
+            Preconditions.checkArgumentPositive(ret, "Invalid cache owner");
+
+            return ret;
+        }
+
         @VisibleForTesting
         void postToPackageMonitorHandler(Runnable r) {
             mCallbackHandler.post(r);
@@ -1154,7 +1171,7 @@
                 final int shortcutFlags = (matchDynamic ? ShortcutInfo.FLAG_DYNAMIC : 0)
                         | (matchPinned ? ShortcutInfo.FLAG_PINNED : 0)
                         | (matchManifest ? ShortcutInfo.FLAG_MANIFEST : 0)
-                        | (matchCached ? ShortcutInfo.FLAG_CACHED : 0);
+                        | (matchCached ? ShortcutInfo.FLAG_CACHED_ALL : 0);
 
                 for (int i = 0; i < shortcuts.size(); i++) {
                     final ShortcutInfo si = shortcuts.get(i);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index f8278de..7ab05c4 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -105,8 +105,10 @@
 import android.os.RevocableFileDescriptor;
 import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.os.incremental.IStorageHealthListener;
 import android.os.incremental.IncrementalFileStorages;
 import android.os.incremental.IncrementalManager;
+import android.os.incremental.StorageHealthCheckParams;
 import android.os.storage.StorageManager;
 import android.provider.Settings.Secure;
 import android.stats.devicepolicy.DevicePolicyEnums;
@@ -231,6 +233,10 @@
 
     private static final String SYSTEM_DATA_LOADER_PACKAGE = "android";
 
+    private static final int INCREMENTAL_STORAGE_BLOCKED_TIMEOUT_MS = 2000;
+    private static final int INCREMENTAL_STORAGE_UNHEALTHY_TIMEOUT_MS = 7000;
+    private static final int INCREMENTAL_STORAGE_UNHEALTHY_MONITORING_MS = 60000;
+
     // TODO: enforce INSTALL_ALLOW_TEST
     // TODO: enforce INSTALL_ALLOW_DOWNGRADE
 
@@ -1568,7 +1574,7 @@
         dispatchSessionFinished(error, detailMessage, null);
     }
 
-    private void onDataLoaderUnrecoverable() {
+    private void onStorageUnhealthy() {
         if (TextUtils.isEmpty(mPackageName)) {
             // The package has not been installed.
             return;
@@ -2745,7 +2751,7 @@
 
         final DataLoaderParams params = this.params.dataLoaderParams;
         final boolean manualStartAndDestroy = !isIncrementalInstallation();
-        final IDataLoaderStatusListener listener = new IDataLoaderStatusListener.Stub() {
+        final IDataLoaderStatusListener statusListener = new IDataLoaderStatusListener.Stub() {
             @Override
             public void onStatusChanged(int dataLoaderId, int status) {
                 switch (status) {
@@ -2757,7 +2763,7 @@
                 if (mDestroyed || mDataLoaderFinished) {
                     switch (status) {
                         case IDataLoaderStatusListener.DATA_LOADER_UNRECOVERABLE:
-                            onDataLoaderUnrecoverable();
+                            onStorageUnhealthy();
                             return;
                     }
                     return;
@@ -2840,9 +2846,49 @@
         };
 
         if (!manualStartAndDestroy) {
+            final StorageHealthCheckParams healthCheckParams = new StorageHealthCheckParams();
+            healthCheckParams.blockedTimeoutMs = INCREMENTAL_STORAGE_BLOCKED_TIMEOUT_MS;
+            healthCheckParams.unhealthyTimeoutMs = INCREMENTAL_STORAGE_UNHEALTHY_TIMEOUT_MS;
+            healthCheckParams.unhealthyMonitoringMs = INCREMENTAL_STORAGE_UNHEALTHY_MONITORING_MS;
+
+            final boolean systemDataLoader =
+                    params.getComponentName().getPackageName() == SYSTEM_DATA_LOADER_PACKAGE;
+            final IStorageHealthListener healthListener = new IStorageHealthListener.Stub() {
+                @Override
+                public void onHealthStatus(int storageId, int status) {
+                    if (mDestroyed || mDataLoaderFinished) {
+                        // App's installed.
+                        switch (status) {
+                            case IStorageHealthListener.HEALTH_STATUS_UNHEALTHY:
+                                onStorageUnhealthy();
+                                return;
+                        }
+                        return;
+                    }
+
+                    switch (status) {
+                        case IStorageHealthListener.HEALTH_STATUS_OK:
+                            break;
+                        case IStorageHealthListener.HEALTH_STATUS_READS_PENDING:
+                        case IStorageHealthListener.HEALTH_STATUS_BLOCKED:
+                            if (systemDataLoader) {
+                                // It's OK for ADB data loader to wait for pages.
+                                break;
+                            }
+                            // fallthrough
+                        case IStorageHealthListener.HEALTH_STATUS_UNHEALTHY:
+                            // Even ADB installation can't wait for missing pages for too long.
+                            mDataLoaderFinished = true;
+                            dispatchSessionVerificationFailure(INSTALL_FAILED_MEDIA_UNAVAILABLE,
+                                    "Image is missing pages required for installation.");
+                            break;
+                    }
+                }
+            };
+
             try {
                 mIncrementalFileStorages = IncrementalFileStorages.initialize(mContext, stageDir,
-                        params, listener, addedFiles);
+                        params, statusListener, healthCheckParams, healthListener, addedFiles);
                 return false;
             } catch (IOException e) {
                 throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE, e.getMessage(),
@@ -2850,8 +2896,7 @@
             }
         }
 
-        if (!dataLoaderManager.bindToDataLoader(
-                sessionId, params.getData(), listener)) {
+        if (!dataLoaderManager.bindToDataLoader(sessionId, params.getData(), statusListener)) {
             throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
                     "Failed to initialize data loader");
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index fbe8100..aa7a1ad 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -369,6 +369,7 @@
 import com.android.server.policy.PermissionPolicyInternal;
 import com.android.server.security.VerityUtils;
 import com.android.server.storage.DeviceStorageMonitorInternal;
+import com.android.server.uri.UriGrantsManagerInternal;
 import com.android.server.utils.TimingsTraceAndSlog;
 import com.android.server.wm.ActivityTaskManagerInternal;
 
@@ -4406,6 +4407,11 @@
         if (getInstantAppPackageName(callingUid) != null) {
             throw new SecurityException("Instant applications don't have access to this method");
         }
+        if (!mUserManager.exists(userId)) {
+            throw new SecurityException("User doesn't exist");
+        }
+        mPermissionManager.enforceCrossUserPermission(
+                callingUid, userId, false, false, "checkPackageStartable");
         final boolean userKeyUnlocked = StorageManager.isUserKeyUnlocked(userId);
         synchronized (mLock) {
             final PackageSetting ps = mSettings.mPackages.get(packageName);
@@ -5778,9 +5784,15 @@
 
     @Override
     public ChangedPackages getChangedPackages(int sequenceNumber, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return null;
         }
+        if (!mUserManager.exists(userId)) {
+            return null;
+        }
+        mPermissionManager.enforceCrossUserPermission(
+                callingUid, userId, false, false, "getChangedPackages");
         synchronized (mLock) {
             if (sequenceNumber >= mChangedPackagesSequenceNumber) {
                 return null;
@@ -8800,9 +8812,23 @@
 
     private ProviderInfo resolveContentProviderInternal(String name, int flags, int userId) {
         if (!mUserManager.exists(userId)) return null;
-        flags = updateFlagsForComponent(flags, userId);
         final int callingUid = Binder.getCallingUid();
+        flags = updateFlagsForComponent(flags, userId);
         final ProviderInfo providerInfo = mComponentResolver.queryProvider(name, flags, userId);
+        boolean checkedGrants = false;
+        if (providerInfo != null) {
+            // Looking for cross-user grants before enforcing the typical cross-users permissions
+            if (userId != UserHandle.getUserId(callingUid)) {
+                final UriGrantsManagerInternal mUgmInternal =
+                        LocalServices.getService(UriGrantsManagerInternal.class);
+                checkedGrants =
+                        mUgmInternal.checkAuthorityGrants(callingUid, providerInfo, userId, true);
+            }
+        }
+        if (!checkedGrants) {
+            mPermissionManager.enforceCrossUserPermission(
+                    callingUid, userId, false, false, "resolveContentProvider");
+        }
         if (providerInfo == null) {
             return null;
         }
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 1642607..9e27f65 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -287,7 +287,7 @@
         if (shortcut != null) {
             mShortcutUser.mService.removeIconLocked(shortcut);
             shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED
-                    | ShortcutInfo.FLAG_MANIFEST | ShortcutInfo.FLAG_CACHED);
+                    | ShortcutInfo.FLAG_MANIFEST | ShortcutInfo.FLAG_CACHED_ALL);
         }
         return shortcut;
     }
@@ -323,36 +323,18 @@
         newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
 
         final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
-
-        final boolean replaced;
-
-        final boolean wasPinned;
-        final boolean wasCached;
-
-        if (oldShortcut == null) {
-            replaced = false;
-            wasPinned = false;
-            wasCached = false;
-        } else {
+        if (oldShortcut != null) {
             // It's an update case.
             // Make sure the target is updatable. (i.e. should be mutable.)
             oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
-            replaced = true;
 
-            wasPinned = oldShortcut.isPinned();
-            wasCached = oldShortcut.isCached();
-        }
-
-        // If it was originally pinned, the new one should be pinned too.
-        if (wasPinned) {
-            newShortcut.addFlags(ShortcutInfo.FLAG_PINNED);
-        }
-        if (wasCached) {
-            newShortcut.addFlags(ShortcutInfo.FLAG_CACHED);
+            // If it was originally pinned or cached, the new one should be pinned or cached too.
+            newShortcut.addFlags(oldShortcut.getFlags()
+                    & (ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_CACHED_ALL));
         }
 
         forceReplaceShortcutInner(newShortcut);
-        return replaced;
+        return oldShortcut != null;
     }
 
     /**
@@ -373,9 +355,6 @@
 
         changedShortcuts.clear();
         final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
-        boolean wasPinned = false;
-        boolean wasCached = false;
-
         boolean deleted = false;
 
         if (oldShortcut == null) {
@@ -408,16 +387,9 @@
             // Make sure the target is updatable. (i.e. should be mutable.)
             oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
 
-            wasPinned = oldShortcut.isPinned();
-            wasCached = oldShortcut.isCached();
-        }
-
-        // If it was originally pinned or cached, the new one should be pinned or cached too.
-        if (wasPinned) {
-            newShortcut.addFlags(ShortcutInfo.FLAG_PINNED);
-        }
-        if (wasCached) {
-            newShortcut.addFlags(ShortcutInfo.FLAG_CACHED);
+            // If it was originally pinned or cached, the new one should be pinned or cached too.
+            newShortcut.addFlags(oldShortcut.getFlags()
+                    & (ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_CACHED_ALL));
         }
 
         forceReplaceShortcutInner(newShortcut);
@@ -511,7 +483,7 @@
     public ShortcutInfo deleteLongLivedWithId(@NonNull String shortcutId, boolean ignoreInvisible) {
         final ShortcutInfo shortcut = mShortcuts.get(shortcutId);
         if (shortcut != null) {
-            shortcut.clearFlags(ShortcutInfo.FLAG_CACHED);
+            shortcut.clearFlags(ShortcutInfo.FLAG_CACHED_ALL);
         }
         return deleteOrDisableWithId(
                 shortcutId, /* disable =*/ false, /* overrideImmutable=*/ false, ignoreInvisible,
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 3732b47..3ec1397 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -2407,7 +2407,7 @@
             final int shortcutFlags = (matchDynamic ? ShortcutInfo.FLAG_DYNAMIC : 0)
                     | (matchPinned ? ShortcutInfo.FLAG_PINNED : 0)
                     | (matchManifest ? ShortcutInfo.FLAG_MANIFEST : 0)
-                    | (matchCached ? ShortcutInfo.FLAG_CACHED : 0);
+                    | (matchCached ? ShortcutInfo.FLAG_CACHED_ALL : 0);
 
             return getShortcutsWithQueryLocked(
                     packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
@@ -3045,17 +3045,17 @@
         @Override
         public void cacheShortcuts(int launcherUserId,
                 @NonNull String callingPackage, @NonNull String packageName,
-                @NonNull List<String> shortcutIds, int userId) {
+                @NonNull List<String> shortcutIds, int userId, int cacheFlags) {
             updateCachedShortcutsInternal(launcherUserId, callingPackage, packageName, shortcutIds,
-                    userId, /* doCache= */ true);
+                    userId, cacheFlags, /* doCache= */ true);
         }
 
         @Override
         public void uncacheShortcuts(int launcherUserId,
                 @NonNull String callingPackage, @NonNull String packageName,
-                @NonNull List<String> shortcutIds, int userId) {
+                @NonNull List<String> shortcutIds, int userId, int cacheFlags) {
             updateCachedShortcutsInternal(launcherUserId, callingPackage, packageName, shortcutIds,
-                    userId, /* doCache= */ false);
+                    userId, cacheFlags, /* doCache= */ false);
         }
 
         @Override
@@ -3079,10 +3079,12 @@
 
         private void updateCachedShortcutsInternal(int launcherUserId,
                 @NonNull String callingPackage, @NonNull String packageName,
-                @NonNull List<String> shortcutIds, int userId, boolean doCache) {
+                @NonNull List<String> shortcutIds, int userId, int cacheFlags, boolean doCache) {
             // Calling permission must be checked by LauncherAppsImpl.
             Preconditions.checkStringNotEmpty(packageName, "packageName");
             Objects.requireNonNull(shortcutIds, "shortcutIds");
+            Preconditions.checkState(
+                    (cacheFlags & ShortcutInfo.FLAG_CACHED_ALL) != 0, "invalid cacheFlags");
 
             List<ShortcutInfo> changedShortcuts = null;
             List<ShortcutInfo> removedShortcuts = null;
@@ -3101,13 +3103,13 @@
                 for (int i = 0; i < idSize; i++) {
                     final String id = Preconditions.checkStringNotEmpty(shortcutIds.get(i));
                     final ShortcutInfo si = sp.findShortcutById(id);
-                    if (si == null || doCache == si.isCached()) {
+                    if (si == null || doCache == si.hasFlags(cacheFlags)) {
                         continue;
                     }
 
                     if (doCache) {
                         if (si.isLongLived()) {
-                            si.addFlags(ShortcutInfo.FLAG_CACHED);
+                            si.addFlags(cacheFlags);
                             if (changedShortcuts == null) {
                                 changedShortcuts = new ArrayList<>(1);
                             }
@@ -3118,9 +3120,8 @@
                         }
                     } else {
                         ShortcutInfo removed = null;
-                        if (si.isDynamic()) {
-                            si.clearFlags(ShortcutInfo.FLAG_CACHED);
-                        } else {
+                        si.clearFlags(cacheFlags);
+                        if (!si.isDynamic() && !si.isCached()) {
                             removed = sp.deleteLongLivedWithId(id, /*ignoreInvisible=*/ true);
                         }
                         if (removed != null) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 29428a2..b0e3ecb 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -3507,7 +3507,7 @@
                     Slog.w(LOG_TAG, "could not start pre-created user " + userId, e);
                 }
             } else {
-                dispatchUserAddedIntent(userInfo);
+                dispatchUserAdded(userInfo);
             }
 
         } finally {
@@ -3568,7 +3568,7 @@
             // Could not read the existing permissions, re-grant them.
             mPm.onNewUserCreated(preCreatedUser.id);
         }
-        dispatchUserAddedIntent(preCreatedUser);
+        dispatchUserAdded(preCreatedUser);
         return preCreatedUser;
     }
 
@@ -3600,7 +3600,7 @@
         return (now > EPOCH_PLUS_30_YEARS) ? now : 0;
     }
 
-    private void dispatchUserAddedIntent(@NonNull UserInfo userInfo) {
+    private void dispatchUserAdded(@NonNull UserInfo userInfo) {
         Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
         addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userInfo.id);
         // Also, add the UserHandle for mainline modules which can't use the @hide
@@ -3610,6 +3610,15 @@
                 android.Manifest.permission.MANAGE_USERS);
         MetricsLogger.count(mContext, userInfo.isGuest() ? TRON_GUEST_CREATED
                 : (userInfo.isDemo() ? TRON_DEMO_CREATED : TRON_USER_CREATED), 1);
+
+        if (!userInfo.isProfile()) {
+            // If the user switch hasn't been explicitly toggled on or off by the user, turn it on.
+            if (android.provider.Settings.Global.getString(mContext.getContentResolver(),
+                    android.provider.Settings.Global.USER_SWITCHER_ENABLED) == null) {
+                android.provider.Settings.Global.putInt(mContext.getContentResolver(),
+                        android.provider.Settings.Global.USER_SWITCHER_ENABLED, 1);
+            }
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 1fec8aa..14d043c 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -206,21 +206,9 @@
      */
     private static final Set<String> PROFILE_OWNER_ORGANIZATION_OWNED_GLOBAL_RESTRICTIONS =
             Sets.newArraySet(
-                    UserManager.DISALLOW_CONFIG_DATE_TIME,
-                    UserManager.DISALLOW_CAMERA,
-                    UserManager.DISALLOW_BLUETOOTH,
-                    UserManager.DISALLOW_BLUETOOTH_SHARING,
-                    UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
-                    UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
-                    UserManager.DISALLOW_CONFIG_PRIVATE_DNS,
-                    UserManager.DISALLOW_CONFIG_TETHERING,
-                    UserManager.DISALLOW_DATA_ROAMING,
-                    UserManager.DISALLOW_SAFE_BOOT,
-                    UserManager.DISALLOW_SMS,
-                    UserManager.DISALLOW_USB_FILE_TRANSFER,
                     UserManager.DISALLOW_AIRPLANE_MODE,
-                    UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
-                    UserManager.DISALLOW_UNMUTE_MICROPHONE
+                    UserManager.DISALLOW_CONFIG_DATE_TIME,
+                    UserManager.DISALLOW_CONFIG_PRIVATE_DNS
     );
 
     /**
@@ -236,7 +224,19 @@
                     UserManager.DISALLOW_CONTENT_SUGGESTIONS,
                     UserManager.DISALLOW_DEBUGGING_FEATURES,
                     UserManager.DISALLOW_SHARE_LOCATION,
-                    UserManager.DISALLOW_OUTGOING_CALLS
+                    UserManager.DISALLOW_OUTGOING_CALLS,
+                    UserManager.DISALLOW_CAMERA,
+                    UserManager.DISALLOW_BLUETOOTH,
+                    UserManager.DISALLOW_BLUETOOTH_SHARING,
+                    UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
+                    UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
+                    UserManager.DISALLOW_CONFIG_TETHERING,
+                    UserManager.DISALLOW_DATA_ROAMING,
+                    UserManager.DISALLOW_SAFE_BOOT,
+                    UserManager.DISALLOW_SMS,
+                    UserManager.DISALLOW_USB_FILE_TRANSFER,
+                    UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
+                    UserManager.DISALLOW_UNMUTE_MICROPHONE
     );
 
     /**
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 29c1243..0b3254f 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -179,6 +179,7 @@
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.function.BiConsumer;
 
 /**
  * SystemService containing PullAtomCallbacks that are registered with statsd.
@@ -325,6 +326,7 @@
                     case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG:
                     case FrameworkStatsLog.MOBILE_BYTES_TRANSFER:
                     case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG:
+                    case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED:
                         return pullDataBytesTransfer(atomTag, data);
                     case FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER:
                         return pullBluetoothBytesTransfer(atomTag, data);
@@ -641,11 +643,14 @@
                 collectNetworkStatsSnapshotForAtom(FrameworkStatsLog.MOBILE_BYTES_TRANSFER));
         mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtom(
                 FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG));
+        mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtom(
+                FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED));
 
         registerWifiBytesTransfer();
         registerWifiBytesTransferBackground();
         registerMobileBytesTransfer();
         registerMobileBytesTransferBackground();
+        registerBytesTransferByTagAndMetered();
     }
 
     /**
@@ -787,50 +792,94 @@
     private static class NetworkStatsExt {
         @NonNull
         public final NetworkStats stats;
-        public final int transport;
-        public final boolean withFgbg;
+        public final int[] transports;
+        public final boolean slicedByFgbg;
+        public final boolean slicedByTag;
+        public final boolean slicedByMetered;
 
-        NetworkStatsExt(@NonNull NetworkStats stats, int transport, boolean withFgbg) {
+        NetworkStatsExt(@NonNull NetworkStats stats, int[] transports, boolean slicedByFgbg) {
+            this(stats, transports, slicedByFgbg, /*slicedByTag=*/false, /*slicedByMetered=*/false);
+        }
+
+        NetworkStatsExt(@NonNull NetworkStats stats, int[] transports, boolean slicedByFgbg,
+                boolean slicedByTag, boolean slicedByMetered) {
             this.stats = stats;
-            this.transport = transport;
-            this.withFgbg = withFgbg;
+
+            // Sort transports array so that we can test for equality without considering order.
+            this.transports = Arrays.copyOf(transports, transports.length);
+            Arrays.sort(this.transports);
+
+            this.slicedByFgbg = slicedByFgbg;
+            this.slicedByTag = slicedByTag;
+            this.slicedByMetered = slicedByMetered;
+        }
+
+        public boolean hasSameSlicing(@NonNull NetworkStatsExt other) {
+            return Arrays.equals(transports, other.transports) && slicedByFgbg == other.slicedByFgbg
+                    && slicedByTag == other.slicedByTag && slicedByMetered == other.slicedByMetered;
         }
     }
 
     @NonNull
     private List<NetworkStatsExt> collectNetworkStatsSnapshotForAtom(int atomTag) {
+        List<NetworkStatsExt> ret = new ArrayList<>();
         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);
+            case FrameworkStatsLog.WIFI_BYTES_TRANSFER: {
+                final NetworkStats stats = getUidNetworkStatsSnapshot(TRANSPORT_WIFI,
+                        /*includeTags=*/false);
+                if (stats != null) {
+                    ret.add(new NetworkStatsExt(stats.groupedByUid(), new int[] {TRANSPORT_WIFI},
+                                    /*slicedByFgbg=*/false));
+                }
+                break;
+            }
+            case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: {
+                final NetworkStats stats = getUidNetworkStatsSnapshot(TRANSPORT_WIFI,
+                        /*includeTags=*/false);
+                if (stats != null) {
+                    ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats),
+                                    new int[] {TRANSPORT_WIFI}, /*slicedByFgbg=*/true));
+                }
+                break;
+            }
+            case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: {
+                final NetworkStats stats = getUidNetworkStatsSnapshot(TRANSPORT_CELLULAR,
+                        /*includeTags=*/false);
+                if (stats != null) {
+                    ret.add(new NetworkStatsExt(stats.groupedByUid(),
+                                    new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/false));
+                }
+                break;
+            }
+            case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: {
+                final NetworkStats stats = getUidNetworkStatsSnapshot(TRANSPORT_CELLULAR,
+                        /*includeTags=*/false);
+                if (stats != null) {
+                    ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats),
+                                    new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/true));
+                }
+                break;
+            }
+            case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED: {
+                final NetworkStats wifiStats = getUidNetworkStatsSnapshot(TRANSPORT_WIFI,
+                        /*includeTags=*/true);
+                final NetworkStats cellularStats = getUidNetworkStatsSnapshot(TRANSPORT_CELLULAR,
+                        /*includeTags=*/true);
+                if (wifiStats != null && cellularStats != null) {
+                    final NetworkStats stats = wifiStats.add(cellularStats);
+                    ret.add(new NetworkStatsExt(sliceNetworkStatsByUidTagAndMetered(stats),
+                                    new int[] {TRANSPORT_WIFI, TRANSPORT_CELLULAR},
+                                    /*slicedByFgbg=*/false, /*slicedByTag=*/true,
+                                    /*slicedByMetered=*/true));
+                }
+                break;
+            }
             default:
                 throw new IllegalArgumentException("Unknown atomTag " + atomTag);
         }
-    }
-
-    // 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());
-
-        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);
@@ -842,22 +891,28 @@
 
         for (final NetworkStatsExt item : current) {
             final NetworkStatsExt baseline = CollectionUtils.find(mNetworkStatsBaselines,
-                    it -> it.withFgbg == item.withFgbg && it.transport == item.transport);
+                    it -> it.hasSameSlicing(item));
 
             // 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.");
+                Slog.e(TAG, "baseline is null for " + atomTag + ", return.");
                 return StatsManager.PULL_SKIP;
             }
-            final NetworkStatsExt diff = new NetworkStatsExt(item.stats.subtract(
-                    baseline.stats).removeEmptyEntries(), item.transport, item.withFgbg);
+            final NetworkStatsExt diff = new NetworkStatsExt(
+                    item.stats.subtract(baseline.stats).removeEmptyEntries(), item.transports,
+                    item.slicedByFgbg, item.slicedByTag, item.slicedByMetered);
 
             // If no diff, skip.
             if (diff.stats.size() == 0) continue;
 
-            addNetworkStats(atomTag, pulledData, diff);
+            switch (atomTag) {
+                case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED:
+                    addBytesTransferByTagAndMeteredAtoms(diff, pulledData);
+                    break;
+                default:
+                    addNetworkStats(atomTag, pulledData, diff);
+            }
         }
         return StatsManager.PULL_SUCCESS;
     }
@@ -879,7 +934,7 @@
             }
             e.writeInt(entry.uid);
             e.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
-            if (statsExt.withFgbg) {
+            if (statsExt.slicedByFgbg) {
                 e.writeInt(entry.set);
             }
             e.writeLong(entry.rxBytes);
@@ -890,14 +945,38 @@
         }
     }
 
+    private void addBytesTransferByTagAndMeteredAtoms(@NonNull NetworkStatsExt statsExt,
+            @NonNull List<StatsEvent> pulledData) {
+        final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling
+        for (int i = 0; i < statsExt.stats.size(); i++) {
+            statsExt.stats.getValues(i, entry);
+            StatsEvent e = StatsEvent.newBuilder()
+                    .setAtomId(FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED)
+                    .addBooleanAnnotation(ANNOTATION_ID_TRUNCATE_TIMESTAMP, true)
+                    .writeInt(entry.uid)
+                    .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
+                    .writeBoolean(entry.metered == NetworkStats.METERED_YES)
+                    .writeInt(entry.tag)
+                    .writeLong(entry.rxBytes)
+                    .writeLong(entry.rxPackets)
+                    .writeLong(entry.txBytes)
+                    .writeLong(entry.txPackets)
+                    .build();
+            pulledData.add(e);
+        }
+    }
+
     /**
      * 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) {
+    @Nullable private NetworkStats getUidNetworkStatsSnapshot(int transport, boolean includeTags) {
+        final NetworkTemplate template = (transport == TRANSPORT_CELLULAR)
+                ? NetworkTemplate.buildTemplateMobileWithRatType(
+                        /*subscriptionId=*/null, NETWORK_TYPE_ALL)
+                : NetworkTemplate.buildTemplateWifiWildcard();
 
         final long elapsedMillisSinceBoot = SystemClock.elapsedRealtime();
         final long currentTimeInMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro());
@@ -906,38 +985,72 @@
         try {
             final NetworkStats stats = getNetworkStatsSession().getSummaryForAllUid(template,
                     currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration,
-                    currentTimeInMillis, /*includeTags=*/false);
-            return withFgbg ? rollupNetworkStatsByFgbg(stats) : stats.groupedByUid();
+                    currentTimeInMillis, includeTags);
+            return stats;
         } catch (RemoteException | NullPointerException e) {
-            Slog.e(TAG, "Pulling netstats for " + template
-                    + " fgbg= " + withFgbg + " bytes has error", e);
+            Slog.e(TAG, "Pulling netstats for template=" + template + " and includeTags="
+                    + includeTags  + " causes error", e);
         }
         return null;
     }
 
+    @NonNull private NetworkStats sliceNetworkStatsByUidAndFgbg(@NonNull NetworkStats stats) {
+        return sliceNetworkStats(stats,
+                (newEntry, oldEntry) -> {
+                    newEntry.uid = oldEntry.uid;
+                    newEntry.set = oldEntry.set;
+                });
+    }
+
+    @NonNull private NetworkStats sliceNetworkStatsByUidTagAndMetered(@NonNull NetworkStats stats) {
+        return sliceNetworkStats(stats,
+                (newEntry, oldEntry) -> {
+                    newEntry.uid = oldEntry.uid;
+                    newEntry.tag = oldEntry.tag;
+                    newEntry.metered = oldEntry.metered;
+                });
+    }
+
     /**
-     * Allows rollups per UID but keeping the set (foreground/background) slicing.
-     * Adapted from groupedByUid in frameworks/base/core/java/android/net/NetworkStats.java
+     * Slices NetworkStats along the dimensions specified in the slicer lambda and aggregates over
+     * non-sliced dimensions.
+     *
+     * This function iterates through each NetworkStats.Entry, sets its dimensions equal to the
+     * default state (with the presumption that we don't want to slice on anything), and then
+     * applies the slicer lambda to allow users to control which dimensions to slice on. This is
+     * adapted from groupedByUid within NetworkStats.java
+     *
+     * @param slicer An operation taking into two parameters, new NetworkStats.Entry and old
+     *               NetworkStats.Entry, that should be used to copy state from the old to the new.
+     *               This is useful for slicing by particular dimensions. For example, if we wished
+     *               to slice by uid and tag, we could write the following lambda:
+     *                  (new, old) -> {
+     *                          new.uid = old.uid;
+     *                          new.tag = old.tag;
+     *                  }
+     *               If no slicer is provided, the data is not sliced by any dimensions.
+     * @return new NeworkStats object appropriately sliced
      */
-    @NonNull private NetworkStats rollupNetworkStatsByFgbg(@NonNull NetworkStats stats) {
+    @NonNull private NetworkStats sliceNetworkStats(@NonNull NetworkStats stats,
+            @Nullable BiConsumer<NetworkStats.Entry, NetworkStats.Entry> slicer) {
         final NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1);
 
         final NetworkStats.Entry entry = new NetworkStats.Entry();
+        entry.uid = NetworkStats.UID_ALL;
         entry.iface = NetworkStats.IFACE_ALL;
+        entry.set = NetworkStats.SET_ALL;
         entry.tag = NetworkStats.TAG_NONE;
         entry.metered = NetworkStats.METERED_ALL;
         entry.roaming = NetworkStats.ROAMING_ALL;
+        entry.defaultNetwork = NetworkStats.DEFAULT_NETWORK_ALL;
 
-        int size = stats.size();
-        final NetworkStats.Entry recycle = new NetworkStats.Entry(); // Used for retrieving values
-        for (int i = 0; i < size; i++) {
+        final NetworkStats.Entry recycle = new NetworkStats.Entry(); // used for retrieving values
+        for (int i = 0; i < stats.size(); i++) {
             stats.getValues(i, recycle);
+            if (slicer != null) {
+                slicer.accept(entry, recycle);
+            }
 
-            // Skip specific tags, since already counted in TAG_NONE
-            if (recycle.tag != NetworkStats.TAG_NONE) continue;
-
-            entry.set = recycle.set; // Allows slicing by background/foreground
-            entry.uid = recycle.uid;
             entry.rxBytes = recycle.rxBytes;
             entry.rxPackets = recycle.rxPackets;
             entry.txBytes = recycle.txBytes;
@@ -987,6 +1100,19 @@
         );
     }
 
+    private void registerBytesTransferByTagAndMetered() {
+        int tagId = FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED;
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
+                .setAdditiveFields(new int[] {4, 5, 6, 7})
+                .build();
+        mStatsManager.setPullAtomCallback(
+                tagId,
+                metadata,
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
+        );
+    }
+
     private void registerBluetoothBytesTransfer() {
         int tagId = FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER;
         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index e3b1152c..323ac7b 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.tv;
 
+import static android.media.AudioManager.DEVICE_NONE;
 import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED;
 import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY;
 
@@ -2047,6 +2048,36 @@
             return clientPid;
         }
 
+        /**
+         * Add a hardware device in the TvInputHardwareManager for CTS testing
+         * purpose.
+         *
+         * @param device id of the adding hardware device.
+         */
+        @Override
+        public void addHardwareDevice(int deviceId) {
+            TvInputHardwareInfo info = new TvInputHardwareInfo.Builder()
+                        .deviceId(deviceId)
+                        .type(TvInputHardwareInfo.TV_INPUT_TYPE_HDMI)
+                        .audioType(DEVICE_NONE)
+                        .audioAddress("0")
+                        .hdmiPortId(0)
+                        .build();
+            mTvInputHardwareManager.onDeviceAvailable(info, null);
+            return;
+        }
+
+        /**
+         * Remove a hardware device in the TvInputHardwareManager for CTS testing
+         * purpose.
+         *
+         * @param device id of the removing hardware device.
+         */
+        @Override
+        public void removeHardwareDevice(int deviceId) {
+            mTvInputHardwareManager.onDeviceUnavailable(deviceId);
+        }
+
         private int getClientPidLocked(String sessionId)
                 throws IllegalStateException {
             if (mSessionIdToSessionStateMap.get(sessionId) == null) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 5a6e0a1..982785e 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -3366,8 +3366,6 @@
                 ProtoLog.v(WM_DEBUG_ADD_REMOVE,
                         "Removing starting %s from %s", tStartingWindow, fromActivity);
                 fromActivity.removeChild(tStartingWindow);
-                fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow);
-                fromActivity.mVisibleSetFromTransferredStartingWindow = false;
                 addWindow(tStartingWindow);
 
                 // Propagate other interesting state between the tokens. If the old token is displayed,
@@ -3394,6 +3392,9 @@
                     // we've transferred the animation.
                     mUseTransferredAnimation = true;
                 }
+                // Post cleanup after the visibility and animation are transferred.
+                fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow);
+                fromActivity.mVisibleSetFromTransferredStartingWindow = false;
 
                 mWmService.updateFocusedWindowLocked(
                         UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 9b9b613..361df14 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -943,19 +943,7 @@
         // task's ordering. However, we still need to move 'task' to back. The intention is that
         // this ends up behind the home-task so that it is made invisible; so, if the home task
         // is not a child of this, reparent 'task' to the back of the home task's actual parent.
-        final ActivityStack home = displayArea.getOrCreateRootHomeTask();
-        final WindowContainer homeParent = home.getParent();
-        final Task homeParentTask = homeParent != null ? homeParent.asTask() : null;
-        if (homeParentTask == null) {
-            ((ActivityStack) task).reparent(displayArea, false /* onTop */);
-        } else if (homeParentTask == this) {
-            // Apparently reparent early-outs if same stack, so we have to explicitly reorder.
-            positionChildAtBottom(task);
-        } else {
-            task.reparent((ActivityStack) homeParentTask, false /* toTop */,
-                    REPARENT_LEAVE_STACK_IN_PLACE, false /* animate */, false /* deferResume */,
-                    "moveToBack");
-        }
+        displayArea.positionTaskBehindHome((ActivityStack) task);
     }
 
     // TODO: Should each user have there own stacks?
@@ -2140,7 +2128,7 @@
                 // window manager to keep the previous window it had previously
                 // created, if it still had one.
                 Task prevTask = r.getTask();
-                ActivityRecord prev = prevTask.topRunningActivityWithStartingWindowLocked();
+                ActivityRecord prev = prevTask.topActivityWithStartingWindow();
                 if (prev != null) {
                     // We don't want to reuse the previous starting preview if:
                     // (1) The current activity is in a different task.
@@ -2638,6 +2626,9 @@
             mRootWindowContainer.ensureVisibilityAndConfig(null /* starting */,
                     getDisplay().mDisplayId, false /* markFrozenIfConfigChanged */,
                     false /* deferResume */);
+            // Usually resuming a top activity triggers the next app transition, but nothing's got
+            // resumed in this case, so we need to execute it explicitly.
+            getDisplay().mDisplayContent.executeAppTransition();
         } else {
             mRootWindowContainer.resumeFocusedStacksTopActivities();
         }
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 62979ff..80ca95f 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -72,6 +72,7 @@
 import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
 import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
 import static com.android.server.wm.RootWindowContainer.TAG_STATES;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
 import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK;
 import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE;
 import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
@@ -1441,11 +1442,7 @@
         try {
             stack.setWindowingMode(WINDOWING_MODE_UNDEFINED);
             stack.setBounds(null);
-            if (toDisplay.getDisplayId() != stack.getDisplayId()) {
-                stack.reparent(toDisplay.getDefaultTaskDisplayArea(), false /* onTop */);
-            } else {
-                toDisplay.getDefaultTaskDisplayArea().positionStackAtBottom(stack);
-            }
+            toDisplay.getDefaultTaskDisplayArea().positionTaskBehindHome(stack);
 
             // Follow on the workaround: activities are kept force hidden till the new windowing
             // mode is set.
@@ -1807,15 +1804,11 @@
         ArrayList<ActivityRecord> readyToStopActivities = null;
         for (int i = mStoppingActivities.size() - 1; i >= 0; --i) {
             final ActivityRecord s = mStoppingActivities.get(i);
-            final boolean animating = s.isAnimating(TRANSITION | PARENTS);
+            final boolean animating = s.isAnimating(TRANSITION | PARENTS,
+                    ANIMATION_TYPE_APP_TRANSITION);
             if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + s.nowVisible
                     + " animating=" + animating + " finishing=" + s.finishing);
-
-            final ActivityStack stack = s.getRootTask();
-            final boolean shouldSleepOrShutDown = stack != null
-                    ? stack.shouldSleepOrShutDownActivities()
-                    : mService.isSleepingOrShuttingDownLocked();
-            if (!animating || shouldSleepOrShutDown) {
+            if (!animating || mService.mShuttingDown) {
                 if (!processPausingActivities && s.isState(PAUSING)) {
                     // Defer processing pausing activities in this iteration and reschedule
                     // a delayed idle to reprocess it again
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index c28d47c..c4ccd00 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -467,28 +467,33 @@
             final ActivityRecord[] outActivity = new ActivityRecord[1];
             // Lock the loop to ensure the activities launched in a sequence.
             synchronized (mService.mGlobalLock) {
-                for (int i = 0; i < starters.length; i++) {
-                    final int startResult = starters[i].setResultTo(resultTo)
-                            .setOutActivity(outActivity).execute();
-                    if (startResult < START_SUCCESS) {
-                        // Abort by error result and recycle unused starters.
-                        for (int j = i + 1; j < starters.length; j++) {
-                            mFactory.recycle(starters[j]);
+                mService.deferWindowLayout();
+                try {
+                    for (int i = 0; i < starters.length; i++) {
+                        final int startResult = starters[i].setResultTo(resultTo)
+                                .setOutActivity(outActivity).execute();
+                        if (startResult < START_SUCCESS) {
+                            // Abort by error result and recycle unused starters.
+                            for (int j = i + 1; j < starters.length; j++) {
+                                mFactory.recycle(starters[j]);
+                            }
+                            return startResult;
                         }
-                        return startResult;
-                    }
-                    final ActivityRecord started = outActivity[0];
-                    if (started != null && started.getUid() == filterCallingUid) {
-                        // Only the started activity which has the same uid as the source caller can
-                        // be the caller of next activity.
-                        resultTo = started.appToken;
-                    } else {
-                        resultTo = sourceResultTo;
-                        // Different apps not adjacent to the caller are forced to be new task.
-                        if (i < starters.length - 1) {
-                            starters[i + 1].getIntent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        final ActivityRecord started = outActivity[0];
+                        if (started != null && started.getUid() == filterCallingUid) {
+                            // Only the started activity which has the same uid as the source caller
+                            // can be the caller of next activity.
+                            resultTo = started.appToken;
+                        } else {
+                            resultTo = sourceResultTo;
+                            // Different apps not adjacent to the caller are forced to be new task.
+                            if (i < starters.length - 1) {
+                                starters[i + 1].getIntent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                            }
                         }
                     }
+                } finally {
+                    mService.continueWindowLayout();
                 }
             }
         } finally {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index eb85db6..b6672d3 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -99,6 +99,7 @@
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
 import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
@@ -498,6 +499,8 @@
      */
     private ActivityRecord mFixedRotationLaunchingApp;
 
+    private FixedRotationAnimationController mFixedRotationAnimationController;
+
     final FixedRotationTransitionListener mFixedRotationTransitionListener =
             new FixedRotationTransitionListener();
 
@@ -1106,12 +1109,14 @@
     }
 
     void removeShellRoot(int windowType) {
-        ShellRoot root = mShellRoots.get(windowType);
-        if (root == null) {
-            return;
+        synchronized(mWmService.mGlobalLock) {
+            ShellRoot root = mShellRoots.get(windowType);
+            if (root == null) {
+                return;
+            }
+            root.clear();
+            mShellRoots.remove(windowType);
         }
-        root.clear();
-        mShellRoots.remove(windowType);
     }
 
     void setRemoteInsetsController(IDisplayWindowInsetsController controller) {
@@ -1481,8 +1486,21 @@
         return true;
     }
 
-    @Nullable ActivityRecord getFixedRotationLaunchingApp() {
-        return mFixedRotationLaunchingApp;
+    /** Returns {@code true} if the top activity is transformed with the new rotation of display. */
+    boolean hasTopFixedRotationLaunchingApp() {
+        return mFixedRotationLaunchingApp != null
+                // Ignore animating recents because it hasn't really become the top.
+                && mFixedRotationLaunchingApp != mFixedRotationTransitionListener.mAnimatingRecents;
+    }
+
+    @VisibleForTesting
+    boolean isFixedRotationLaunchingApp(ActivityRecord r) {
+        return mFixedRotationLaunchingApp == r;
+    }
+
+    @VisibleForTesting
+    @Nullable FixedRotationAnimationController getFixedRotationAnimationController() {
+        return mFixedRotationAnimationController;
     }
 
     void setFixedRotationLaunchingAppUnchecked(@Nullable ActivityRecord r) {
@@ -1492,8 +1510,13 @@
     void setFixedRotationLaunchingAppUnchecked(@Nullable ActivityRecord r, int rotation) {
         if (mFixedRotationLaunchingApp == null && r != null) {
             mWmService.mDisplayNotificationController.dispatchFixedRotationStarted(this, rotation);
+            if (mFixedRotationAnimationController == null) {
+                mFixedRotationAnimationController = new FixedRotationAnimationController(this);
+                mFixedRotationAnimationController.hide();
+            }
         } else if (mFixedRotationLaunchingApp != null && r == null) {
             mWmService.mDisplayNotificationController.dispatchFixedRotationFinished(this);
+            finishFixedRotationAnimationIfPossible();
         }
         mFixedRotationLaunchingApp = r;
     }
@@ -1582,6 +1605,15 @@
         }
     }
 
+    /** Re-show the previously hidden windows if all seamless rotated windows are done. */
+    void finishFixedRotationAnimationIfPossible() {
+        final FixedRotationAnimationController controller = mFixedRotationAnimationController;
+        if (controller != null && !mDisplayRotation.hasSeamlessRotatingWindow()) {
+            controller.show();
+            mFixedRotationAnimationController = null;
+        }
+    }
+
     /**
      * Update rotation of the display.
      *
@@ -3494,7 +3526,7 @@
         if (target == mInputMethodTarget && mInputMethodTargetWaitingAnim == targetWaitingAnim) {
             return;
         }
-
+        ProtoLog.i(WM_DEBUG_IME, "setInputMethodTarget %s", target);
         mInputMethodTarget = target;
         mInputMethodTargetWaitingAnim = targetWaitingAnim;
         assignWindowLayers(true /* setLayoutNeeded */);
@@ -3508,6 +3540,7 @@
      */
     void setInputMethodInputTarget(WindowState target) {
         if (mInputMethodInputTarget != target) {
+            ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target);
             mInputMethodInputTarget = target;
             updateImeControlTarget();
         }
@@ -3515,6 +3548,8 @@
 
     private void updateImeControlTarget() {
         mInputMethodControlTarget = computeImeControlTarget();
+        ProtoLog.i(WM_DEBUG_IME, "updateImeControlTarget %s",
+                mInputMethodControlTarget.getWindow());
         mInsetsStateController.onImeControlTargetChanged(mInputMethodControlTarget);
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 702df2a..831491d 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -560,6 +560,7 @@
         }, true /* traverseTopToBottom */);
         mSeamlessRotationCount = 0;
         mRotatingSeamlessly = false;
+        mDisplayContent.finishFixedRotationAnimationIfPossible();
     }
 
     private void prepareSeamlessRotation() {
@@ -573,11 +574,15 @@
         return mRotatingSeamlessly;
     }
 
+    boolean hasSeamlessRotatingWindow() {
+        return mSeamlessRotationCount > 0;
+    }
+
     @VisibleForTesting
     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.getFixedRotationLaunchingApp() != null) {
+        if (mDisplayContent.hasTopFixedRotationLaunchingApp()) {
             return true;
         }
 
@@ -646,6 +651,7 @@
                     "Performing post-rotate rotation after seamless rotation");
             // Finish seamless rotation.
             mRotatingSeamlessly = false;
+            mDisplayContent.finishFixedRotationAnimationIfPossible();
 
             updateRotationAndSendNewConfigIfChanged();
         }
diff --git a/services/core/java/com/android/server/wm/FixedRotationAnimationController.java b/services/core/java/com/android/server/wm/FixedRotationAnimationController.java
new file mode 100644
index 0000000..cc02e99
--- /dev/null
+++ b/services/core/java/com/android/server/wm/FixedRotationAnimationController.java
@@ -0,0 +1,166 @@
+/*
+ * 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.wm;
+
+import static com.android.server.wm.AnimationSpecProto.WINDOW;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_FIXED_TRANSFORM;
+import static com.android.server.wm.WindowAnimationSpecProto.ANIMATION;
+
+import android.content.Context;
+import android.util.ArrayMap;
+import android.util.proto.ProtoOutputStream;
+import android.view.SurfaceControl;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Transformation;
+
+import com.android.internal.R;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Controller to fade out and in system ui when applying a fixed rotation transform to a window
+ * token.
+ *
+ * The system bars will be fade out when the fixed rotation transform starts and will be fade in
+ * once all surfaces have been rotated.
+ */
+public class FixedRotationAnimationController {
+
+    private final Context mContext;
+    private final WindowState mStatusBar;
+    private final WindowState mNavigationBar;
+    private final ArrayList<WindowToken> mAnimatedWindowToken = new ArrayList<>(2);
+    private final ArrayMap<WindowToken, Runnable> mDeferredFinishCallbacks = new ArrayMap<>();
+
+    public FixedRotationAnimationController(DisplayContent displayContent) {
+        mContext = displayContent.mWmService.mContext;
+        final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
+        mStatusBar = displayPolicy.getStatusBar();
+        // Do not animate movable navigation bar (e.g. non-gesture mode).
+        mNavigationBar = !displayPolicy.navigationBarCanMove()
+                ? displayPolicy.getNavigationBar()
+                : null;
+    }
+
+    /** Applies show animation on the previously hidden window tokens. */
+    void show() {
+        for (int i = mAnimatedWindowToken.size() - 1; i >= 0; i--) {
+            final WindowToken windowToken = mAnimatedWindowToken.get(i);
+            fadeWindowToken(true /* show */, windowToken);
+        }
+    }
+
+    /** Applies hide animation on the window tokens which may be seamlessly rotated later. */
+    void hide() {
+        if (mNavigationBar != null) {
+            fadeWindowToken(false /* show */, mNavigationBar.mToken);
+        }
+        if (mStatusBar != null) {
+            fadeWindowToken(false /* show */, mStatusBar.mToken);
+        }
+    }
+
+    private void fadeWindowToken(boolean show, WindowToken windowToken) {
+        if (windowToken == null || windowToken.getParent() == null) {
+            return;
+        }
+
+        final Animation animation = AnimationUtils.loadAnimation(mContext,
+                show ? R.anim.fade_in : R.anim.fade_out);
+        final LocalAnimationAdapter.AnimationSpec windowAnimationSpec =
+                createAnimationSpec(animation);
+
+        final FixedRotationAnimationAdapter animationAdapter = new FixedRotationAnimationAdapter(
+                windowAnimationSpec, windowToken.getSurfaceAnimationRunner(), show, windowToken);
+
+        // We deferred the end of the animation when hiding the token, so we need to end it now that
+        // it's shown again.
+        final SurfaceAnimator.OnAnimationFinishedCallback finishedCallback = show ? (t, r) -> {
+            final Runnable runnable = mDeferredFinishCallbacks.remove(windowToken);
+            if (runnable != null) {
+                runnable.run();
+            }
+        } : null;
+        windowToken.startAnimation(windowToken.getPendingTransaction(), animationAdapter,
+                show /* hidden */, ANIMATION_TYPE_FIXED_TRANSFORM, finishedCallback);
+        mAnimatedWindowToken.add(windowToken);
+    }
+
+    private LocalAnimationAdapter.AnimationSpec createAnimationSpec(Animation animation) {
+        return new LocalAnimationAdapter.AnimationSpec() {
+
+            final Transformation mTransformation = new Transformation();
+
+            @Override
+            public boolean getShowWallpaper() {
+                return true;
+            }
+
+            @Override
+            public long getDuration() {
+                return animation.getDuration();
+            }
+
+            @Override
+            public void apply(SurfaceControl.Transaction t, SurfaceControl leash,
+                    long currentPlayTime) {
+                mTransformation.clear();
+                animation.getTransformation(currentPlayTime, mTransformation);
+                t.setAlpha(leash, mTransformation.getAlpha());
+            }
+
+            @Override
+            public void dump(PrintWriter pw, String prefix) {
+                pw.print(prefix);
+                pw.println(animation);
+            }
+
+            @Override
+            public void dumpDebugInner(ProtoOutputStream proto) {
+                final long token = proto.start(WINDOW);
+                proto.write(ANIMATION, animation.toString());
+                proto.end(token);
+            }
+        };
+    }
+
+    private class FixedRotationAnimationAdapter extends LocalAnimationAdapter {
+        private final boolean mShow;
+        private final WindowToken mToken;
+
+        FixedRotationAnimationAdapter(AnimationSpec windowAnimationSpec,
+                SurfaceAnimationRunner surfaceAnimationRunner, boolean show,
+                WindowToken token) {
+            super(windowAnimationSpec, surfaceAnimationRunner);
+            mShow = show;
+            mToken = token;
+        }
+
+        @Override
+        public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
+            // We defer the end of the hide animation to ensure the tokens stay hidden until
+            // we show them again.
+            if (!mShow) {
+                mDeferredFinishCallbacks.put(mToken, endDeferFinishCallback);
+                return true;
+            }
+            return false;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 7491376..8298763 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -18,9 +18,11 @@
 
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
 
+import android.graphics.PixelFormat;
 import android.view.InsetsSource;
 import android.view.WindowInsets;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.protolog.common.ProtoLog;
 
 /**
@@ -65,9 +67,16 @@
             // Target should still be the same.
             if (isImeTargetFromDisplayContentAndImeSame()) {
                 final InsetsControlTarget target = mDisplayContent.mInputMethodControlTarget;
-                ProtoLog.d(WM_DEBUG_IME, "call showInsets(ime) on %s",
+
+                ProtoLog.i(WM_DEBUG_IME, "call showInsets(ime) on %s",
                         target.getWindow() != null ? target.getWindow().getName() : "");
                 target.showInsets(WindowInsets.Type.ime(), true /* fromIme */);
+                if (target != mImeTargetFromIme && mImeTargetFromIme != null) {
+                    ProtoLog.w(WM_DEBUG_IME,
+                            "showInsets(ime) was requested by different window: %s ",
+                            (mImeTargetFromIme.getWindow() != null
+                                    ? mImeTargetFromIme.getWindow().getName() : ""));
+                }
             }
             abortShowImePostLayout();
         };
@@ -100,7 +109,8 @@
         mShowImeRunner = null;
     }
 
-    private boolean isImeTargetFromDisplayContentAndImeSame() {
+    @VisibleForTesting
+    boolean isImeTargetFromDisplayContentAndImeSame() {
         // IMMS#mLastImeTargetWindow always considers focused window as
         // IME target, however DisplayContent#computeImeTarget() can compute
         // a different IME target.
@@ -111,6 +121,7 @@
         // TODO(b/139861270): Remove the child & sublayer check once IMMS is aware of
         //  actual IME target.
         final WindowState dcTarget = mDisplayContent.mInputMethodTarget;
+        final InsetsControlTarget controlTarget = mDisplayContent.mInputMethodControlTarget;
         if (dcTarget == null || mImeTargetFromIme == null) {
             return false;
         }
@@ -120,6 +131,9 @@
         return (!dcTarget.isClosing() && mImeTargetFromIme == dcTarget)
                 || (mImeTargetFromIme != null && dcTarget.getParentWindow() == mImeTargetFromIme
                         && dcTarget.mSubLayer > mImeTargetFromIme.mSubLayer)
-                || mImeTargetFromIme == mDisplayContent.getImeFallback();
+                || mImeTargetFromIme == mDisplayContent.getImeFallback()
+                // If IME target is transparent but control target matches requesting window.
+                || (controlTarget == mImeTargetFromIme
+                        && PixelFormat.formatHasAlpha(dcTarget.mAttrs.format));
     }
 }
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index a6a21fc..6a49759 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -24,6 +24,7 @@
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
 import static android.view.ViewRootImpl.sNewInsetsMode;
 
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_INSETS_CONTROL;
 import static com.android.server.wm.WindowManagerService.H.LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED;
 
@@ -40,6 +41,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.function.TriConsumer;
+import com.android.server.protolog.common.ProtoLog;
 import com.android.server.wm.SurfaceAnimator.AnimationType;
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
 
@@ -134,6 +136,7 @@
             // animate-out as new one animates-in.
             mWin.cancelAnimation();
         }
+        ProtoLog.d(WM_DEBUG_IME, "InsetsSource setWin %s", win);
         mWin = win;
         mFrameProvider = frameProvider;
         mImeFrameProvider = imeFrameProvider;
@@ -299,6 +302,8 @@
         updateVisibility();
         mControl = new InsetsSourceControl(mSource.getType(), leash,
                 new Point(mWin.getWindowFrames().mFrame.left, mWin.getWindowFrames().mFrame.top));
+        ProtoLog.d(WM_DEBUG_IME,
+                "InsetsSource Control %s for target %s", mControl, mControlTarget);
     }
 
     void startSeamlessRotation() {
@@ -349,6 +354,9 @@
         final boolean isClientControlled = mControlTarget != null
                 && mControlTarget.isClientControlled();
         mSource.setVisible(mServerVisible && (!isClientControlled || mClientVisible));
+        ProtoLog.d(WM_DEBUG_IME,
+                "InsetsSource updateVisibility serverVisible: %s clientVisible: %s",
+                mServerVisible, mClientVisible);
     }
 
     InsetsSourceControl getControl(InsetsControlTarget target) {
@@ -391,6 +399,44 @@
         return mImeOverrideFrame;
     }
 
+    public void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + "InsetsSourceProvider");
+        pw.print(prefix + " mSource="); mSource.dump(prefix + "  ", pw);
+        if (mControl != null) {
+            pw.print(prefix + " mControl=");
+            mControl.dump(prefix + "  ", pw);
+        }
+        pw.print(prefix + " mFakeControl="); mFakeControl.dump(prefix + "  ", pw);
+        pw.print(" mIsLeashReadyForDispatching="); pw.print(mIsLeashReadyForDispatching);
+        pw.print(" mImeOverrideFrame="); pw.print(mImeOverrideFrame.toString());
+        if (mWin != null) {
+            pw.print(prefix + " mWin=");
+            mWin.dump(pw, prefix + "  ", false /* dumpAll */);
+        }
+        if (mAdapter != null) {
+            pw.print(prefix + " mAdapter=");
+            mAdapter.dump(pw, prefix + "  ");
+        }
+        if (mControlTarget != null) {
+            pw.print(prefix + " mControlTarget=");
+            if (mControlTarget.getWindow() != null) {
+                mControlTarget.getWindow().dump(pw, prefix + "  ", false /* dumpAll */);
+            }
+        }
+        if (mPendingControlTarget != null) {
+            pw.print(prefix + " mPendingControlTarget=");
+            if (mPendingControlTarget.getWindow() != null) {
+                mPendingControlTarget.getWindow().dump(pw, prefix + "  ", false /* dumpAll */);
+            }
+        }
+        if (mFakeControlTarget != null) {
+            pw.print(prefix + " mFakeControlTarget=");
+            if (mFakeControlTarget.getWindow() != null) {
+                mFakeControlTarget.getWindow().dump(pw, prefix + "  ", false /* dumpAll */);
+            }
+        }
+    }
+
     private class ControlAdapter implements AnimationAdapter {
 
         private SurfaceControl mCapturedLeash;
@@ -410,6 +456,9 @@
                 t.setAlpha(animationLeash, 1 /* alpha */);
                 t.hide(animationLeash);
             }
+            ProtoLog.i(WM_DEBUG_IME,
+                    "ControlAdapter startAnimation mSource: %s controlTarget: %s", mSource,
+                    mControlTarget);
 
             mCapturedLeash = animationLeash;
             final Rect frame = mWin.getWindowFrames().mFrame;
@@ -424,6 +473,9 @@
                 mControlTarget = null;
                 mAdapter = null;
                 setClientVisible(InsetsState.getDefaultVisibility(mSource.getType()));
+                ProtoLog.i(WM_DEBUG_IME,
+                        "ControlAdapter onAnimationCancelled mSource: %s mControlTarget: %s",
+                        mSource, mControlTarget);
             }
         }
 
@@ -439,6 +491,8 @@
 
         @Override
         public void dump(PrintWriter pw, String prefix) {
+            pw.println(prefix + "ControlAdapter");
+            pw.print(prefix + " mCapturedLeash="); pw.print(mCapturedLeash);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 9798d77..77bc37f 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -29,6 +29,8 @@
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.WindowConfiguration;
@@ -42,6 +44,8 @@
 import android.view.InsetsState.InternalInsetsType;
 import android.view.WindowManager;
 
+import com.android.server.protolog.common.ProtoLog;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.function.Consumer;
@@ -289,7 +293,10 @@
 
         // Make sure that we always have a control target for the IME, even if the IME target is
         // null. Otherwise there is no leash that will hide it and IME becomes "randomly" visible.
-        onControlChanged(ITYPE_IME, imeTarget != null ? imeTarget : mEmptyImeControlTarget);
+        InsetsControlTarget target = imeTarget != null ? imeTarget : mEmptyImeControlTarget;
+        onControlChanged(ITYPE_IME, target);
+        ProtoLog.d(WM_DEBUG_IME, "onImeControlTargetChanged %s",
+                target != null ? target.getWindow() : "null");
         notifyPendingInsetsControlChanged();
     }
 
@@ -440,5 +447,11 @@
             pw.println(InsetsState.typeToString(mTypeControlTargetMap.keyAt(i)) + " -> "
                     + mTypeControlTargetMap.valueAt(i));
         }
+        pw.println(prefix + "  " + "InsetsSourceProviders map:");
+        for (int i = mProviders.size() - 1; i >= 0; i--) {
+            pw.print(prefix + "  ");
+            pw.println(InsetsState.typeToString(mProviders.keyAt(i)) + " -> ");
+            mProviders.valueAt(i).dump(pw, prefix);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 0ecde72..ae5adca 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2187,6 +2187,10 @@
                 // up-to-dated pinned stack information on this newly created stack.
                 r.reparent(stack, MAX_VALUE, reason);
             }
+            // The intermediate windowing mode to be set on the ActivityRecord later.
+            // This needs to happen before the re-parenting, otherwise we will always set the
+            // ActivityRecord to be fullscreen.
+            final int intermediateWindowingMode = stack.getWindowingMode();
             if (stack.getParent() != taskDisplayArea) {
                 // stack is nested, but pinned tasks need to be direct children of their
                 // display area, so reparent.
@@ -2195,7 +2199,7 @@
             // 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());
+            r.setWindowingMode(intermediateWindowingMode);
             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/ShellRoot.java b/services/core/java/com/android/server/wm/ShellRoot.java
index 99f710b..7a38bb6 100644
--- a/services/core/java/com/android/server/wm/ShellRoot.java
+++ b/services/core/java/com/android/server/wm/ShellRoot.java
@@ -156,4 +156,3 @@
         }
     }
 }
-
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 42342a6..0143eb1 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -489,6 +489,12 @@
     static final int ANIMATION_TYPE_INSETS_CONTROL = 1 << 5;
 
     /**
+     * Animation when a fixed rotation transform is applied to a window token.
+     * @hide
+     */
+    static final int ANIMATION_TYPE_FIXED_TRANSFORM = 1 << 6;
+
+    /**
      * Bitmask to include all animation types. This is NOT an {@link AnimationType}
      * @hide
      */
@@ -505,7 +511,8 @@
             ANIMATION_TYPE_DIMMER,
             ANIMATION_TYPE_RECENTS,
             ANIMATION_TYPE_WINDOW_ANIMATION,
-            ANIMATION_TYPE_INSETS_CONTROL
+            ANIMATION_TYPE_INSETS_CONTROL,
+            ANIMATION_TYPE_FIXED_TRANSFORM
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface AnimationType {}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index f8ad6f2..db86ea6 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1309,12 +1309,12 @@
         return isUidPresent;
     }
 
-    ActivityRecord topRunningActivityWithStartingWindowLocked() {
+    ActivityRecord topActivityWithStartingWindow() {
         if (getParent() == null) {
             return null;
         }
         return getActivity((r) -> r.mStartingWindowState == STARTING_WINDOW_SHOWN
-                && r.canBeTopRunning());
+                && r.okToShowLocked());
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 9130483..6dde5b0 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -765,6 +765,32 @@
         onStackOrderChanged(stack);
     }
 
+    /**
+     * Moves/reparents `task` to the back of whatever container the home stack is in. This is for
+     * when we just want to move a task to "the back" vs. a specific place. The primary use-case
+     * is to make sure that moved-to-back apps go into secondary split when in split-screen mode.
+     */
+    void positionTaskBehindHome(ActivityStack task) {
+        final ActivityStack home = getOrCreateRootHomeTask();
+        final WindowContainer homeParent = home.getParent();
+        final Task homeParentTask = homeParent != null ? homeParent.asTask() : null;
+        if (homeParentTask == null) {
+            // reparent throws if parent didn't change...
+            if (task.getParent() == this) {
+                positionStackAtBottom(task);
+            } else {
+                task.reparent(this, false /* onTop */);
+            }
+        } else if (homeParentTask == task.getParent()) {
+            // Apparently reparent early-outs if same stack, so we have to explicitly reorder.
+            ((ActivityStack) homeParentTask).positionChildAtBottom(task);
+        } else {
+            task.reparent((ActivityStack) homeParentTask, false /* toTop */,
+                    Task.REPARENT_LEAVE_STACK_IN_PLACE, false /* animate */,
+                    false /* deferResume */, "positionTaskBehindHome");
+        }
+    }
+
     ActivityStack getStack(int rootTaskId) {
         for (int i = getStackCount() - 1; i >= 0; --i) {
             final ActivityStack stack = getStackAt(i);
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index e011c794..c605e3e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -576,4 +576,24 @@
      * @return The corresponding {@link WindowState#getName()}
      */
     public abstract String getWindowName(@NonNull IBinder binder);
+
+    /**
+     * Return the window name of IME Insets control target.
+     *
+     * @param displayId The ID of the display which input method is currently focused.
+     * @return The corresponding {@link WindowState#getName()}
+     */
+    public abstract @Nullable String getImeControlTargetNameForLogging(int displayId);
+
+    /**
+     * Return the current window name of the input method is on top of.
+     *
+     * Note that the concept of this window is only reparent the target window behind the input
+     * method window, it may different with the window which reported by
+     * {@code InputMethodManagerService#reportStartInput} which has input connection.
+     *
+     * @param displayId The ID of the display which input method is currently focused.
+     * @return The corresponding {@link WindowState#getName()}
+     */
+    public abstract @Nullable String getImeTargetNameForLogging(int displayId);
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 159c59b..f34510e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -6191,6 +6191,7 @@
             final int displayId = dc.getDisplayId();
             final WindowState inputMethodTarget = dc.mInputMethodTarget;
             final WindowState inputMethodInputTarget = dc.mInputMethodInputTarget;
+            final InsetsControlTarget inputMethodControlTarget = dc.mInputMethodControlTarget;
             if (inputMethodTarget != null) {
                 pw.print("  mInputMethodTarget in display# "); pw.print(displayId);
                 pw.print(' '); pw.println(inputMethodTarget);
@@ -6199,6 +6200,10 @@
                 pw.print("  mInputMethodInputTarget in display# "); pw.print(displayId);
                 pw.print(' '); pw.println(inputMethodInputTarget);
             }
+            if (inputMethodControlTarget != null) {
+                pw.print("  inputMethodControlTarget in display# "); pw.print(displayId);
+                pw.print(' '); pw.println(inputMethodControlTarget.getWindow());
+            }
         });
         pw.print("  mInTouchMode="); pw.println(mInTouchMode);
         pw.print("  mLastDisplayFreezeDuration=");
@@ -7750,6 +7755,33 @@
                 return w != null ? w.getName() : null;
             }
         }
+
+        @Override
+        public String getImeControlTargetNameForLogging(int displayId) {
+            synchronized (mGlobalLock) {
+                final DisplayContent dc = mRoot.getDisplayContent(displayId);
+                if (dc == null) {
+                    return null;
+                }
+                final InsetsControlTarget target = dc.mInputMethodControlTarget;
+                if (target == null) {
+                    return null;
+                }
+                final WindowState win = target.getWindow();
+                return win != null ? win.getName() : target.toString();
+            }
+        }
+
+        @Override
+        public String getImeTargetNameForLogging(int displayId) {
+            synchronized (mGlobalLock) {
+                final DisplayContent dc = mRoot.getDisplayContent(displayId);
+                if (dc == null) {
+                    return null;
+                }
+                return dc.mInputMethodTarget != null ? dc.mInputMethodTarget.getName() : null;
+            }
+        }
     }
 
     void registerAppFreezeListener(AppFreezeListener listener) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index 619d87b..bdecb8d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -351,6 +351,11 @@
     }
 
     private int runDumpVisibleWindowViews(PrintWriter pw) {
+        if (!mInternal.checkCallingPermission(android.Manifest.permission.DUMP,
+                "runDumpVisibleWindowViews()")) {
+            throw new SecurityException("Requires DUMP permission");
+        }
+
         try (ZipOutputStream out = new ZipOutputStream(getRawOutputStream())) {
             ArrayList<Pair<String, ByteTransferPipe>> requestList = new ArrayList<>();
             synchronized (mInternal.mGlobalLock) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e9aff88..4f1893e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -113,6 +113,7 @@
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RESIZE;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
@@ -334,6 +335,8 @@
     private boolean mDragResizing;
     private boolean mDragResizingChangeReported = true;
     private int mResizeMode;
+    private boolean mResizeForBlastSyncReported;
+
     /**
      * Special mode that is intended only for the rounded corner overlay: during rotation
      * transition, we un-rotate the window token such that the window appears as it did before the
@@ -1370,11 +1373,14 @@
         // variables, because mFrameSizeChanged only tracks the width and height changing.
         updateLastFrames();
 
+        // Add a window that is using blastSync to the resizing list if it hasn't been reported
+        // already. This because the window is waiting on a finishDrawing from the client.
         if (didFrameInsetsChange
                 || winAnimator.mSurfaceResized
                 || configChanged
                 || dragResizingChanged
-                || mReportOrientationChanged) {
+                || mReportOrientationChanged
+                || requestResizeForBlastSync()) {
             ProtoLog.v(WM_DEBUG_RESIZE,
                         "Resize reasons for w=%s:  %s surfaceResized=%b configChanged=%b "
                                 + "dragResizingChanged=%b reportOrientationChanged=%b",
@@ -3483,6 +3489,7 @@
         mReportOrientationChanged = false;
         mDragResizingChangeReported = true;
         mWinAnimator.mSurfaceResized = false;
+        mResizeForBlastSyncReported = true;
         mWindowFrames.resetInsetsChanged();
 
         final Rect frame = mWindowFrames.mCompatFrame;
@@ -3553,6 +3560,7 @@
      * Called when the insets state changed.
      */
     void notifyInsetsChanged() {
+        ProtoLog.d(WM_DEBUG_IME, "notifyInsetsChanged for %s ", this);
         try {
             mClient.insetsChanged(getInsetsState());
         } catch (RemoteException e) {
@@ -3562,6 +3570,7 @@
 
     @Override
     public void notifyInsetsControlChanged() {
+        ProtoLog.d(WM_DEBUG_IME, "notifyInsetsControlChanged for %s ", this);
         final InsetsStateController stateController =
                 getDisplayContent().getInsetsStateController();
         try {
@@ -5500,7 +5509,9 @@
     }
 
     long getFrameNumber() {
-        return mFrameNumber;
+        // Return the frame number in which changes requested in this layout will be rendered or
+        // -1 if we do not expect the frame to be rendered.
+        return getFrameLw().isEmpty() ? -1 : mFrameNumber;
     }
 
     void setFrameNumber(long frameNumber) {
@@ -5733,6 +5744,7 @@
         if (!willSync) {
             return false;
         }
+        mResizeForBlastSyncReported = false;
 
         mLocalSyncId = mBLASTSyncEngine.startSyncSet(this);
         addChildrenToSyncSet(mLocalSyncId);
@@ -5777,4 +5789,8 @@
         mWaitingListener = null;
         return mWinAnimator.finishDrawingLocked(null);
     }
+
+    private boolean requestResizeForBlastSync() {
+        return useBLASTSync() && !mResizeForBlastSyncReported;
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b7a9ba5..8d32d7c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -11951,11 +11951,11 @@
                     user);
             mInjector.getLocationManager().setLocationEnabledForUser(locationEnabled, user);
 
-            // make a best effort to only show the notification if the admin is actually changing
-            // something. this is subject to race conditions with settings changes, but those are
+            // make a best effort to only show the notification if the admin is actually enabling
+            // location. this is subject to race conditions with settings changes, but those are
             // unlikely to realistically interfere
-            if (wasLocationEnabled != locationEnabled) {
-                showLocationSettingsChangedNotification(user);
+            if (locationEnabled && (wasLocationEnabled != locationEnabled)) {
+                showLocationSettingsEnabledNotification(user);
             }
         });
 
@@ -11968,7 +11968,7 @@
                 .write();
     }
 
-    private void showLocationSettingsChangedNotification(UserHandle user) {
+    private void showLocationSettingsEnabledNotification(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
@@ -12100,8 +12100,11 @@
                     saveSettingsLocked(callingUserId);
                 }
                 mInjector.settingsSecurePutStringForUser(setting, value, callingUserId);
-                if (setting.equals(Settings.Secure.LOCATION_MODE)) {
-                    showLocationSettingsChangedNotification(UserHandle.of(callingUserId));
+                // Notify the user if it's the location mode setting that's been set, to any value
+                // other than 'off'.
+                if (setting.equals(Settings.Secure.LOCATION_MODE)
+                        && (Integer.parseInt(value) != 0)) {
+                    showLocationSettingsEnabledNotification(UserHandle.of(callingUserId));
                 }
             });
         }
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
index 8476674..e790a19 100644
--- a/services/incremental/BinderIncrementalService.cpp
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -118,14 +118,18 @@
 }
 
 binder::Status BinderIncrementalService::createStorage(
-        const std::string& path, const content::pm::DataLoaderParamsParcel& params,
-        const ::android::sp<::android::content::pm::IDataLoaderStatusListener>& listener,
-        int32_t createMode, int32_t* _aidl_return) {
+        const ::std::string& path, const ::android::content::pm::DataLoaderParamsParcel& params,
+        int32_t createMode,
+        const ::android::sp<::android::content::pm::IDataLoaderStatusListener>& statusListener,
+        const ::android::os::incremental::StorageHealthCheckParams& healthCheckParams,
+        const ::android::sp<::android::os::incremental::IStorageHealthListener>& healthListener,
+        int32_t* _aidl_return) {
     *_aidl_return =
             mImpl.createStorage(path, const_cast<content::pm::DataLoaderParamsParcel&&>(params),
-                                listener,
-                                android::incremental::IncrementalService::CreateOptions(
-                                        createMode));
+                                android::incremental::IncrementalService::CreateOptions(createMode),
+                                statusListener,
+                                const_cast<StorageHealthCheckParams&&>(healthCheckParams),
+                                healthListener);
     return ok();
 }
 
@@ -276,8 +280,9 @@
 
 binder::Status BinderIncrementalService::configureNativeBinaries(
         int32_t storageId, const std::string& apkFullPath, const std::string& libDirRelativePath,
-        const std::string& abi, bool* _aidl_return) {
-    *_aidl_return = mImpl.configureNativeBinaries(storageId, apkFullPath, libDirRelativePath, abi);
+        const std::string& abi, bool extractNativeLibs, bool* _aidl_return) {
+    *_aidl_return = mImpl.configureNativeBinaries(storageId, apkFullPath, libDirRelativePath, abi,
+                                                  extractNativeLibs);
     return ok();
 }
 
diff --git a/services/incremental/BinderIncrementalService.h b/services/incremental/BinderIncrementalService.h
index 5a7d5da..68549f5 100644
--- a/services/incremental/BinderIncrementalService.h
+++ b/services/incremental/BinderIncrementalService.h
@@ -41,8 +41,11 @@
     binder::Status openStorage(const std::string& path, int32_t* _aidl_return) final;
     binder::Status createStorage(
             const ::std::string& path, const ::android::content::pm::DataLoaderParamsParcel& params,
-            const ::android::sp<::android::content::pm::IDataLoaderStatusListener>& listener,
-            int32_t createMode, int32_t* _aidl_return) final;
+            int32_t createMode,
+            const ::android::sp<::android::content::pm::IDataLoaderStatusListener>& statusListener,
+            const ::android::os::incremental::StorageHealthCheckParams& healthCheckParams,
+            const ::android::sp<IStorageHealthListener>& healthListener,
+            int32_t* _aidl_return) final;
     binder::Status createLinkedStorage(const std::string& path, int32_t otherStorageId,
                                        int32_t createMode, int32_t* _aidl_return) final;
     binder::Status makeBindMount(int32_t storageId, const std::string& sourcePath,
@@ -55,8 +58,7 @@
     binder::Status makeDirectories(int32_t storageId, const std::string& path,
                                    int32_t* _aidl_return) final;
     binder::Status makeFile(int32_t storageId, const std::string& path,
-                            const ::android::os::incremental::IncrementalNewFileParams& params,
-                            int32_t* _aidl_return) final;
+                            const IncrementalNewFileParams& params, int32_t* _aidl_return) final;
     binder::Status makeFileFromRange(int32_t storageId, const std::string& targetPath,
                                      const std::string& sourcePath, int64_t start, int64_t end,
                                      int32_t* _aidl_return) final;
@@ -75,7 +77,8 @@
 
     binder::Status configureNativeBinaries(int32_t storageId, const std::string& apkFullPath,
                                            const std::string& libDirRelativePath,
-                                           const std::string& abi, bool* _aidl_return) final;
+                                           const std::string& abi, bool extractNativeLibs,
+                                           bool* _aidl_return) final;
     binder::Status waitForNativeBinariesExtraction(int storageId, bool* _aidl_return) final;
 
 private:
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index f0dca77..66c7717 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -410,9 +410,12 @@
     }
 }
 
-StorageId IncrementalService::createStorage(
-        std::string_view mountPoint, DataLoaderParamsParcel&& dataLoaderParams,
-        const DataLoaderStatusListener& dataLoaderStatusListener, CreateOptions options) {
+StorageId IncrementalService::createStorage(std::string_view mountPoint,
+                                            content::pm::DataLoaderParamsParcel&& dataLoaderParams,
+                                            CreateOptions options,
+                                            const DataLoaderStatusListener& statusListener,
+                                            StorageHealthCheckParams&& healthCheckParams,
+                                            const StorageHealthListener& healthListener) {
     LOG(INFO) << "createStorage: " << mountPoint << " | " << int(options);
     if (!path::isAbsolute(mountPoint)) {
         LOG(ERROR) << "path is not absolute: " << mountPoint;
@@ -545,8 +548,8 @@
     // Done here as well, all data structures are in good state.
     secondCleanupOnFailure.release();
 
-    auto dataLoaderStub =
-            prepareDataLoader(*ifs, std::move(dataLoaderParams), &dataLoaderStatusListener);
+    auto dataLoaderStub = prepareDataLoader(*ifs, std::move(dataLoaderParams), &statusListener,
+                                            std::move(healthCheckParams), &healthListener);
     CHECK(dataLoaderStub);
 
     mountIt->second = std::move(ifs);
@@ -1254,7 +1257,7 @@
         dataLoaderParams.arguments = loader.arguments();
     }
 
-    prepareDataLoader(*ifs, std::move(dataLoaderParams), nullptr);
+    prepareDataLoader(*ifs, std::move(dataLoaderParams));
     CHECK(ifs->dataLoaderStub);
 
     std::vector<std::pair<std::string, metadata::BindPoint>> bindPoints;
@@ -1338,14 +1341,18 @@
 
 IncrementalService::DataLoaderStubPtr IncrementalService::prepareDataLoader(
         IncFsMount& ifs, DataLoaderParamsParcel&& params,
-        const DataLoaderStatusListener* externalListener) {
+        const DataLoaderStatusListener* statusListener,
+        StorageHealthCheckParams&& healthCheckParams, const StorageHealthListener* healthListener) {
     std::unique_lock l(ifs.lock);
-    prepareDataLoaderLocked(ifs, std::move(params), externalListener);
+    prepareDataLoaderLocked(ifs, std::move(params), statusListener, std::move(healthCheckParams),
+                            healthListener);
     return ifs.dataLoaderStub;
 }
 
 void IncrementalService::prepareDataLoaderLocked(IncFsMount& ifs, DataLoaderParamsParcel&& params,
-                                                 const DataLoaderStatusListener* externalListener) {
+                                                 const DataLoaderStatusListener* statusListener,
+                                                 StorageHealthCheckParams&& healthCheckParams,
+                                                 const StorageHealthListener* healthListener) {
     if (ifs.dataLoaderStub) {
         LOG(INFO) << "Skipped data loader preparation because it already exists";
         return;
@@ -1360,7 +1367,8 @@
 
     ifs.dataLoaderStub =
             new DataLoaderStub(*this, ifs.mountId, std::move(params), std::move(fsControlParcel),
-                               externalListener, path::join(ifs.root, constants().mount));
+                               statusListener, std::move(healthCheckParams), healthListener,
+                               path::join(ifs.root, constants().mount));
 }
 
 template <class Duration>
@@ -1371,7 +1379,7 @@
 // Extract lib files from zip, create new files in incfs and write data to them
 bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_view apkFullPath,
                                                  std::string_view libDirRelativePath,
-                                                 std::string_view abi) {
+                                                 std::string_view abi, bool extractNativeLibs) {
     auto start = Clock::now();
 
     const auto ifs = getIfs(storage);
@@ -1415,6 +1423,21 @@
             continue;
         }
 
+        if (!extractNativeLibs) {
+            // ensure the file is properly aligned and unpacked
+            if (entry.method != kCompressStored) {
+                LOG(WARNING) << "Library " << fileName << " must be uncompressed to mmap it";
+                return false;
+            }
+            if ((entry.offset & (constants().blockSize - 1)) != 0) {
+                LOG(WARNING) << "Library " << fileName
+                             << " must be page-aligned to mmap it, offset = 0x" << std::hex
+                             << entry.offset;
+                return false;
+            }
+            continue;
+        }
+
         auto startFileTs = Clock::now();
 
         const auto libName = path::basename(fileName);
@@ -1680,19 +1703,24 @@
 IncrementalService::DataLoaderStub::DataLoaderStub(IncrementalService& service, MountId id,
                                                    DataLoaderParamsParcel&& params,
                                                    FileSystemControlParcel&& control,
-                                                   const DataLoaderStatusListener* externalListener,
+                                                   const DataLoaderStatusListener* statusListener,
+                                                   StorageHealthCheckParams&& healthCheckParams,
+                                                   const StorageHealthListener* healthListener,
                                                    std::string&& healthPath)
       : mService(service),
         mId(id),
         mParams(std::move(params)),
         mControl(std::move(control)),
-        mListener(externalListener ? *externalListener : DataLoaderStatusListener()),
+        mStatusListener(statusListener ? *statusListener : DataLoaderStatusListener()),
+        mHealthListener(healthListener ? *healthListener : StorageHealthListener()),
         mHealthPath(std::move(healthPath)) {
+    // TODO(b/153874006): enable external health listener.
+    mHealthListener = {};
     healthStatusOk();
 }
 
 IncrementalService::DataLoaderStub::~DataLoaderStub() {
-    if (mId != kInvalidStorageId) {
+    if (isValid()) {
         cleanupResources();
     }
 }
@@ -1710,13 +1738,14 @@
     mStatusCondition.wait_until(lock, now + 60s, [this] {
         return mCurrentStatus == IDataLoaderStatusListener::DATA_LOADER_DESTROYED;
     });
-    mListener = {};
+    mStatusListener = {};
+    mHealthListener = {};
     mId = kInvalidStorageId;
 }
 
 sp<content::pm::IDataLoader> IncrementalService::DataLoaderStub::getDataLoader() {
     sp<IDataLoader> dataloader;
-    auto status = mService.mDataLoaderManager->getDataLoader(mId, &dataloader);
+    auto status = mService.mDataLoaderManager->getDataLoader(id(), &dataloader);
     if (!status.isOk()) {
         LOG(ERROR) << "Failed to get dataloader: " << status.toString8();
         return {};
@@ -1752,15 +1781,15 @@
     auto oldStatus = mTargetStatus;
     mTargetStatus = status;
     mTargetStatusTs = Clock::now();
-    LOG(DEBUG) << "Target status update for DataLoader " << mId << ": " << oldStatus << " -> "
+    LOG(DEBUG) << "Target status update for DataLoader " << id() << ": " << oldStatus << " -> "
                << status << " (current " << mCurrentStatus << ")";
 }
 
 bool IncrementalService::DataLoaderStub::bind() {
     bool result = false;
-    auto status = mService.mDataLoaderManager->bindToDataLoader(mId, mParams, this, &result);
+    auto status = mService.mDataLoaderManager->bindToDataLoader(id(), mParams, this, &result);
     if (!status.isOk() || !result) {
-        LOG(ERROR) << "Failed to bind a data loader for mount " << mId;
+        LOG(ERROR) << "Failed to bind a data loader for mount " << id();
         return false;
     }
     return true;
@@ -1771,9 +1800,9 @@
     if (!dataloader) {
         return false;
     }
-    auto status = dataloader->create(mId, mParams, mControl, this);
+    auto status = dataloader->create(id(), mParams, mControl, this);
     if (!status.isOk()) {
-        LOG(ERROR) << "Failed to start DataLoader: " << status.toString8();
+        LOG(ERROR) << "Failed to create DataLoader: " << status.toString8();
         return false;
     }
     return true;
@@ -1784,7 +1813,7 @@
     if (!dataloader) {
         return false;
     }
-    auto status = dataloader->start(mId);
+    auto status = dataloader->start(id());
     if (!status.isOk()) {
         LOG(ERROR) << "Failed to start DataLoader: " << status.toString8();
         return false;
@@ -1793,7 +1822,7 @@
 }
 
 bool IncrementalService::DataLoaderStub::destroy() {
-    return mService.mDataLoaderManager->unbindFromDataLoader(mId).isOk();
+    return mService.mDataLoaderManager->unbindFromDataLoader(id()).isOk();
 }
 
 bool IncrementalService::DataLoaderStub::fsmStep() {
@@ -1852,8 +1881,8 @@
         return binder::Status::
                 fromServiceSpecificError(-EINVAL, "onStatusChange came to invalid DataLoaderStub");
     }
-    if (mId != mountId) {
-        LOG(ERROR) << "Mount ID mismatch: expected " << mId << ", but got: " << mountId;
+    if (id() != mountId) {
+        LOG(ERROR) << "Mount ID mismatch: expected " << id() << ", but got: " << mountId;
         return binder::Status::fromServiceSpecificError(-EPERM, "Mount ID mismatch.");
     }
 
@@ -1869,7 +1898,7 @@
         mCurrentStatus = newStatus;
         targetStatus = mTargetStatus;
 
-        listener = mListener;
+        listener = mStatusListener;
 
         if (mCurrentStatus == IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE) {
             // For unavailable, unbind from DataLoader to ensure proper re-commit.
@@ -1877,7 +1906,7 @@
         }
     }
 
-    LOG(DEBUG) << "Current status update for DataLoader " << mId << ": " << oldStatus << " -> "
+    LOG(DEBUG) << "Current status update for DataLoader " << id() << ": " << oldStatus << " -> "
                << newStatus << " (target " << targetStatus << ")";
 
     if (listener) {
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index f3fde2a..05f62b9 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -21,6 +21,8 @@
 #include <android/content/pm/FileSystemControlParcel.h>
 #include <android/content/pm/IDataLoaderStatusListener.h>
 #include <android/os/incremental/BnIncrementalServiceConnector.h>
+#include <android/os/incremental/BnStorageHealthListener.h>
+#include <android/os/incremental/StorageHealthCheckParams.h>
 #include <binder/IAppOpsCallback.h>
 #include <utils/String16.h>
 #include <utils/StrongPointer.h>
@@ -56,10 +58,15 @@
 using Clock = std::chrono::steady_clock;
 using TimePoint = std::chrono::time_point<Clock>;
 using Seconds = std::chrono::seconds;
+using BootClockTsUs = uint64_t;
 
 using IDataLoaderStatusListener = ::android::content::pm::IDataLoaderStatusListener;
 using DataLoaderStatusListener = ::android::sp<IDataLoaderStatusListener>;
 
+using StorageHealthCheckParams = ::android::os::incremental::StorageHealthCheckParams;
+using IStorageHealthListener = ::android::os::incremental::IStorageHealthListener;
+using StorageHealthListener = ::android::sp<IStorageHealthListener>;
+
 class IncrementalService final {
 public:
     explicit IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir);
@@ -72,6 +79,8 @@
     static constexpr StorageId kInvalidStorageId = -1;
     static constexpr StorageId kMaxStorageId = std::numeric_limits<int>::max();
 
+    static constexpr BootClockTsUs kMaxBootClockTsUs = std::numeric_limits<BootClockTsUs>::max();
+
     enum CreateOptions {
         TemporaryBind = 1,
         PermanentBind = 2,
@@ -97,8 +106,9 @@
 
     StorageId createStorage(std::string_view mountPoint,
                             content::pm::DataLoaderParamsParcel&& dataLoaderParams,
-                            const DataLoaderStatusListener& dataLoaderStatusListener,
-                            CreateOptions options = CreateOptions::Default);
+                            CreateOptions options, const DataLoaderStatusListener& statusListener,
+                            StorageHealthCheckParams&& healthCheckParams,
+                            const StorageHealthListener& healthListener);
     StorageId createLinkedStorage(std::string_view mountPoint, StorageId linkedStorage,
                                   CreateOptions options = CreateOptions::Default);
     StorageId openStorage(std::string_view path);
@@ -128,7 +138,8 @@
     bool startLoading(StorageId storage) const;
 
     bool configureNativeBinaries(StorageId storage, std::string_view apkFullPath,
-                                 std::string_view libDirRelativePath, std::string_view abi);
+                                 std::string_view libDirRelativePath, std::string_view abi,
+                                 bool extractNativeLibs);
     bool waitForNativeBinariesExtraction(StorageId storage);
 
     class AppOpsListener : public android::BnAppOpsCallback {
@@ -161,7 +172,9 @@
         DataLoaderStub(IncrementalService& service, MountId id,
                        content::pm::DataLoaderParamsParcel&& params,
                        content::pm::FileSystemControlParcel&& control,
-                       const DataLoaderStatusListener* externalListener, std::string&& healthPath);
+                       const DataLoaderStatusListener* statusListener,
+                       StorageHealthCheckParams&& healthCheckParams,
+                       const StorageHealthListener* healthListener, std::string&& healthPath);
         ~DataLoaderStub();
         // Cleans up the internal state and invalidates DataLoaderStub. Any subsequent calls will
         // result in an error.
@@ -212,7 +225,8 @@
         MountId mId = kInvalidStorageId;
         content::pm::DataLoaderParamsParcel mParams;
         content::pm::FileSystemControlParcel mControl;
-        DataLoaderStatusListener mListener;
+        DataLoaderStatusListener mStatusListener;
+        StorageHealthListener mHealthListener;
 
         std::condition_variable mStatusCondition;
         int mCurrentStatus = content::pm::IDataLoaderStatusListener::DATA_LOADER_DESTROYED;
@@ -291,9 +305,13 @@
 
     DataLoaderStubPtr prepareDataLoader(IncFsMount& ifs,
                                         content::pm::DataLoaderParamsParcel&& params,
-                                        const DataLoaderStatusListener* externalListener = nullptr);
+                                        const DataLoaderStatusListener* statusListener = nullptr,
+                                        StorageHealthCheckParams&& healthCheckParams = {},
+                                        const StorageHealthListener* healthListener = nullptr);
     void prepareDataLoaderLocked(IncFsMount& ifs, content::pm::DataLoaderParamsParcel&& params,
-                                 const DataLoaderStatusListener* externalListener = nullptr);
+                                 const DataLoaderStatusListener* statusListener = nullptr,
+                                 StorageHealthCheckParams&& healthCheckParams = {},
+                                 const StorageHealthListener* healthListener = nullptr);
 
     BindPathMap::const_iterator findStorageLocked(std::string_view path) const;
     StorageId findStorageId(std::string_view path) const;
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index 08fb486..a76aa62 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -175,6 +175,10 @@
     ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const final {
         return incfs::writeBlocks({blocks.data(), size_t(blocks.size())});
     }
+    WaitResult waitForPendingReads(const Control& control, std::chrono::milliseconds timeout,
+                                   std::vector<incfs::ReadInfo>* pendingReadsBuffer) const final {
+        return incfs::waitForPendingReads(control, timeout, pendingReadsBuffer);
+    }
 };
 
 RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager, JNIEnv* env)
diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h
index abbf2f4..a935ab9 100644
--- a/services/incremental/ServiceWrappers.h
+++ b/services/incremental/ServiceWrappers.h
@@ -69,6 +69,7 @@
     using Control = incfs::Control;
     using FileId = incfs::FileId;
     using ErrorCode = incfs::ErrorCode;
+    using WaitResult = incfs::WaitResult;
 
     using ExistingMountCallback =
             std::function<void(std::string_view root, std::string_view backingDir,
@@ -90,6 +91,9 @@
     virtual ErrorCode unlink(const Control& control, std::string_view path) const = 0;
     virtual base::unique_fd openForSpecialOps(const Control& control, FileId id) const = 0;
     virtual ErrorCode writeBlocks(std::span<const incfs::DataBlock> blocks) const = 0;
+    virtual WaitResult waitForPendingReads(
+            const Control& control, std::chrono::milliseconds timeout,
+            std::vector<incfs::ReadInfo>* pendingReadsBuffer) const = 0;
 };
 
 class AppOpsManagerWrapper {
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index 2e4625c..2948b6a 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -284,6 +284,9 @@
     MOCK_CONST_METHOD2(unlink, ErrorCode(const Control& control, std::string_view path));
     MOCK_CONST_METHOD2(openForSpecialOps, base::unique_fd(const Control& control, FileId id));
     MOCK_CONST_METHOD1(writeBlocks, ErrorCode(std::span<const DataBlock> blocks));
+    MOCK_CONST_METHOD3(waitForPendingReads,
+                       WaitResult(const Control& control, std::chrono::milliseconds timeout,
+                                  std::vector<incfs::ReadInfo>* pendingReadsBuffer));
 
     MockIncFs() { ON_CALL(*this, listExistingMounts(_)).WillByDefault(Return()); }
 
@@ -292,12 +295,23 @@
     void openMountSuccess() {
         ON_CALL(*this, openMount(_)).WillByDefault(Invoke(this, &MockIncFs::openMountForHealth));
     }
+    void waitForPendingReadsSuccess() {
+        ON_CALL(*this, waitForPendingReads(_, _, _))
+                .WillByDefault(Invoke(this, &MockIncFs::waitForPendingReadsForHealth));
+    }
 
     static constexpr auto kPendingReadsFd = 42;
     Control openMountForHealth(std::string_view) {
         return UniqueControl(IncFs_CreateControl(-1, kPendingReadsFd, -1));
     }
 
+    WaitResult waitForPendingReadsForHealth(
+            const Control& control, std::chrono::milliseconds timeout,
+            std::vector<incfs::ReadInfo>* pendingReadsBuffer) const {
+        pendingReadsBuffer->push_back({.bootClockTsUs = 0});
+        return android::incfs::WaitResult::HaveData;
+    }
+
     RawMetadata getMountInfoMetadata(const Control& control, std::string_view path) {
         metadata::Mount m;
         m.mutable_storage()->set_id(100);
@@ -499,9 +513,9 @@
     mVold->mountIncFsFails();
     EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(0);
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     ASSERT_LT(storageId, 0);
 }
 
@@ -510,9 +524,9 @@
     EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _)).Times(0);
     EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(0);
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     ASSERT_LT(storageId, 0);
 }
 
@@ -523,9 +537,9 @@
     EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(0);
     EXPECT_CALL(*mVold, unmountIncFs(_));
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     ASSERT_LT(storageId, 0);
 }
 
@@ -537,9 +551,9 @@
     EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(0);
     EXPECT_CALL(*mVold, unmountIncFs(_));
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     ASSERT_LT(storageId, 0);
 }
 
@@ -555,9 +569,9 @@
     EXPECT_CALL(*mDataLoader, destroy(_)).Times(0);
     EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     ASSERT_LT(storageId, 0);
 }
 
@@ -574,9 +588,9 @@
     EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
     EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     ASSERT_GE(storageId, 0);
     mIncrementalService->deleteStorage(storageId);
 }
@@ -594,9 +608,9 @@
     EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
     EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     ASSERT_GE(storageId, 0);
     // Simulated crash/other connection breakage.
     mDataLoaderManager->setDataLoaderStatusDestroyed();
@@ -616,9 +630,9 @@
     EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
     EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     ASSERT_GE(storageId, 0);
     mDataLoaderManager->setDataLoaderStatusCreated();
     ASSERT_TRUE(mIncrementalService->startLoading(storageId));
@@ -639,9 +653,9 @@
     EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
     EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     ASSERT_GE(storageId, 0);
     ASSERT_TRUE(mIncrementalService->startLoading(storageId));
     mDataLoaderManager->setDataLoaderStatusCreated();
@@ -661,9 +675,9 @@
     EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
     EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     ASSERT_GE(storageId, 0);
     mDataLoaderManager->setDataLoaderStatusUnavailable();
 }
@@ -672,6 +686,7 @@
     mVold->mountIncFsSuccess();
     mIncFs->makeFileSuccess();
     mIncFs->openMountSuccess();
+    mIncFs->waitForPendingReadsSuccess();
     mVold->bindMountSuccess();
     mDataLoader->initializeCreateOkNoStatus();
     mDataLoaderManager->bindToDataLoaderSuccess();
@@ -685,9 +700,9 @@
     EXPECT_CALL(*mLooper, addFd(MockIncFs::kPendingReadsFd, _, _, _, _)).Times(1);
     EXPECT_CALL(*mLooper, removeFd(MockIncFs::kPendingReadsFd)).Times(1);
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     ASSERT_GE(storageId, 0);
     mDataLoaderManager->setDataLoaderStatusUnavailable();
     ASSERT_NE(nullptr, mLooper->mCallback);
@@ -712,9 +727,9 @@
     // Not expecting callback removal.
     EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(0);
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     ASSERT_GE(storageId, 0);
     ASSERT_GE(mDataLoader->setStorageParams(true), 0);
 }
@@ -739,9 +754,9 @@
     // After callback is called, disable read logs and remove callback.
     EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(1);
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     ASSERT_GE(storageId, 0);
     ASSERT_GE(mDataLoader->setStorageParams(true), 0);
     ASSERT_NE(nullptr, mAppOpsManager->mStoredCallback.get());
@@ -762,9 +777,9 @@
     EXPECT_CALL(*mAppOpsManager, startWatchingMode(_, _, _)).Times(0);
     EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(0);
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     ASSERT_GE(storageId, 0);
     ASSERT_LT(mDataLoader->setStorageParams(true), 0);
 }
@@ -785,9 +800,9 @@
     EXPECT_CALL(*mAppOpsManager, startWatchingMode(_, _, _)).Times(0);
     EXPECT_CALL(*mAppOpsManager, stopWatchingMode(_)).Times(0);
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     ASSERT_GE(storageId, 0);
     ASSERT_LT(mDataLoader->setStorageParams(true), 0);
 }
@@ -799,9 +814,9 @@
     mDataLoaderManager->bindToDataLoaderSuccess();
     mDataLoaderManager->getDataLoaderSuccess();
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     std::string dir_path("test");
 
     // Expecting incfs to call makeDir on a path like:
@@ -823,9 +838,9 @@
     mDataLoaderManager->bindToDataLoaderSuccess();
     mDataLoaderManager->getDataLoaderSuccess();
     TemporaryDir tempDir;
-    int storageId =
-            mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel), {},
-                                               IncrementalService::CreateOptions::CreateNew);
+    int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+                                                       IncrementalService::CreateOptions::CreateNew,
+                                                       {}, {}, {});
     auto first = "first"sv;
     auto second = "second"sv;
     auto third = "third"sv;
diff --git a/services/people/java/com/android/server/people/data/ConversationInfo.java b/services/people/java/com/android/server/people/data/ConversationInfo.java
index dc3fa2a..1737828 100644
--- a/services/people/java/com/android/server/people/data/ConversationInfo.java
+++ b/services/people/java/com/android/server/people/data/ConversationInfo.java
@@ -142,9 +142,12 @@
         return hasShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED);
     }
 
-    /** Whether the shortcut for this conversation is cached in Shortcut Service. */
-    public boolean isShortcutCached() {
-        return hasShortcutFlags(ShortcutInfo.FLAG_CACHED);
+    /**
+     * Whether the shortcut for this conversation is cached in Shortcut Service, with cache owner
+     * set as notifications.
+     */
+    public boolean isShortcutCachedForNotification() {
+        return hasShortcutFlags(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
     }
 
     /** Whether this conversation is marked as important by the user. */
@@ -223,7 +226,7 @@
         if (isShortcutLongLived()) {
             sb.append("Liv");
         }
-        if (isShortcutCached()) {
+        if (isShortcutCachedForNotification()) {
             sb.append("Cac");
         }
         sb.append("]");
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 bbb0215..63b7162 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -294,14 +294,14 @@
             if (notificationListener != null) {
                 String packageName = packageData.getPackageName();
                 packageData.forAllConversations(conversationInfo -> {
-                    if (conversationInfo.isShortcutCached()
+                    if (conversationInfo.isShortcutCachedForNotification()
                             && conversationInfo.getNotificationChannelId() == null
                             && !notificationListener.hasActiveNotifications(
                                     packageName, conversationInfo.getShortcutId())) {
                         mShortcutServiceInternal.uncacheShortcuts(userId,
                                 mContext.getPackageName(), packageName,
                                 Collections.singletonList(conversationInfo.getShortcutId()),
-                                userId);
+                                userId, ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
                     }
                 });
             }
@@ -821,12 +821,12 @@
                         // The shortcut was cached by Notification Manager synchronously when the
                         // associated notification was posted. Uncache it here when all the
                         // associated notifications are removed.
-                        if (conversationInfo.isShortcutCached()
+                        if (conversationInfo.isShortcutCachedForNotification()
                                 && conversationInfo.getNotificationChannelId() == null) {
                             mShortcutServiceInternal.uncacheShortcuts(mUserId,
                                     mContext.getPackageName(), sbn.getPackageName(),
                                     Collections.singletonList(conversationInfo.getShortcutId()),
-                                    mUserId);
+                                    mUserId, ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
                         }
                     } else {
                         mActiveNotifCounts.put(conversationKey, count);
@@ -891,12 +891,12 @@
                 ConversationInfo conversationInfo =
                         packageData != null ? packageData.getConversationInfo(shortcutId) : null;
                 if (conversationInfo != null
-                        && conversationInfo.isShortcutCached()
+                        && conversationInfo.isShortcutCachedForNotification()
                         && conversationInfo.getNotificationChannelId() == null) {
                     mShortcutServiceInternal.uncacheShortcuts(mUserId,
                             mContext.getPackageName(), packageName,
                             Collections.singletonList(shortcutId),
-                            mUserId);
+                            mUserId, ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
                 }
             }
         }
diff --git a/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java
index d338b58..ade01dc 100644
--- a/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java
@@ -19,7 +19,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
-import static com.android.server.blob.BlobStoreConfig.SESSION_EXPIRY_TIMEOUT_MILLIS;
+import static com.android.server.blob.BlobStoreConfig.DeviceConfigProperties.SESSION_EXPIRY_TIMEOUT_MS;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -93,6 +93,7 @@
         doReturn(true).when(mBlobsDir).exists();
         doReturn(new File[0]).when(mBlobsDir).listFiles();
         doReturn(true).when(() -> BlobStoreConfig.hasLeaseWaitTimeElapsed(anyLong()));
+        doCallRealMethod().when(() -> BlobStoreConfig.hasSessionExpired(anyLong()));
 
         mContext = InstrumentationRegistry.getTargetContext();
         mHandler = new TestHandler(Looper.getMainLooper());
@@ -236,7 +237,7 @@
     public void testHandleIdleMaintenance_deleteStaleSessions() throws Exception {
         // Setup sessions
         final File sessionFile1 = mock(File.class);
-        doReturn(System.currentTimeMillis() - SESSION_EXPIRY_TIMEOUT_MILLIS + 1000)
+        doReturn(System.currentTimeMillis() - SESSION_EXPIRY_TIMEOUT_MS + 1000)
                 .when(sessionFile1).lastModified();
         final long sessionId1 = 342;
         final BlobHandle blobHandle1 = BlobHandle.createWithSha256("digest1".getBytes(),
@@ -256,7 +257,7 @@
         mUserSessions.append(sessionId2, session2);
 
         final File sessionFile3 = mock(File.class);
-        doReturn(System.currentTimeMillis() - SESSION_EXPIRY_TIMEOUT_MILLIS - 2000)
+        doReturn(System.currentTimeMillis() - SESSION_EXPIRY_TIMEOUT_MS - 2000)
                 .when(sessionFile3).lastModified();
         final long sessionId3 = 9484;
         final BlobHandle blobHandle3 = BlobHandle.createWithSha256("digest3".getBytes(),
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 724048b..4a77489 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1997,19 +1997,9 @@
 
     private static final Set<String> PROFILE_OWNER_ORGANIZATION_OWNED_GLOBAL_RESTRICTIONS =
             Sets.newSet(
-                    UserManager.DISALLOW_CONFIG_DATE_TIME,
-                    UserManager.DISALLOW_BLUETOOTH_SHARING,
-                    UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
-                    UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
-                    UserManager.DISALLOW_CONFIG_PRIVATE_DNS,
-                    UserManager.DISALLOW_CONFIG_TETHERING,
-                    UserManager.DISALLOW_DATA_ROAMING,
-                    UserManager.DISALLOW_SAFE_BOOT,
-                    UserManager.DISALLOW_SMS,
-                    UserManager.DISALLOW_USB_FILE_TRANSFER,
                     UserManager.DISALLOW_AIRPLANE_MODE,
-                    UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
-                    UserManager.DISALLOW_UNMUTE_MICROPHONE
+                    UserManager.DISALLOW_CONFIG_DATE_TIME,
+                    UserManager.DISALLOW_CONFIG_PRIVATE_DNS
             );
 
     private static final Set<String> PROFILE_OWNER_ORGANIZATION_OWNED_LOCAL_RESTRICTIONS =
@@ -2021,7 +2011,17 @@
                     UserManager.DISALLOW_CONTENT_SUGGESTIONS,
                     UserManager.DISALLOW_DEBUGGING_FEATURES,
                     UserManager.DISALLOW_SHARE_LOCATION,
-                    UserManager.DISALLOW_OUTGOING_CALLS
+                    UserManager.DISALLOW_OUTGOING_CALLS,
+                    UserManager.DISALLOW_BLUETOOTH_SHARING,
+                    UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
+                    UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
+                    UserManager.DISALLOW_CONFIG_TETHERING,
+                    UserManager.DISALLOW_DATA_ROAMING,
+                    UserManager.DISALLOW_SAFE_BOOT,
+                    UserManager.DISALLOW_SMS,
+                    UserManager.DISALLOW_USB_FILE_TRANSFER,
+                    UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
+                    UserManager.DISALLOW_UNMUTE_MICROPHONE
             );
 
     public void testSetUserRestriction_asPoOfOrgOwnedDevice() throws Exception {
@@ -2045,8 +2045,9 @@
         parentDpm.setCameraDisabled(admin1, true);
         verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
                 eq(CALLER_USER_HANDLE),
-                MockUtils.checkUserRestrictions(UserManager.DISALLOW_CAMERA),
-                MockUtils.checkUserRestrictions(CALLER_USER_HANDLE),
+                MockUtils.checkUserRestrictions(),
+                MockUtils.checkUserRestrictions(UserHandle.USER_SYSTEM,
+                        UserManager.DISALLOW_CAMERA),
                 eq(false));
         DpmTestUtils.assertRestrictions(
                 DpmTestUtils.newRestrictions(UserManager.DISALLOW_CAMERA),
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
index f35eecf..b7692f9 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
@@ -44,9 +44,9 @@
     @Test
     public void testUpdateOverlaysForUser() {
         final OverlayManagerServiceImpl impl = getImpl();
-        installTargetPackage(TARGET, USER);
-        installTargetPackage("some.other.target", USER);
-        installOverlayPackage(OVERLAY, TARGET, USER);
+        addSystemPackage(target(TARGET), USER);
+        addSystemPackage(target("some.other.target"), USER);;
+        addSystemPackage(overlay(OVERLAY, TARGET), USER);
 
         // do nothing, expect no change
         final List<String> a = impl.updateOverlaysForUser(USER);
@@ -54,8 +54,7 @@
         assertTrue(a.contains(TARGET));
 
         // upgrade overlay, keep target
-        beginUpgradeOverlayPackage(OVERLAY, USER);
-        endUpgradeOverlayPackage(OVERLAY, TARGET, USER);
+        addSystemPackage(overlay(OVERLAY, TARGET), USER);
 
         final List<String> b = impl.updateOverlaysForUser(USER);
         assertEquals(1, b.size());
@@ -67,7 +66,7 @@
         assertTrue(c.contains(TARGET));
 
         // upgrade overlay, switch to new target
-        addOverlayPackage(OVERLAY, "some.other.target", USER, true, false, 0);
+        addSystemPackage(overlay(OVERLAY, "some.other.target"), USER);
         final List<String> d = impl.updateOverlaysForUser(USER);
         assertEquals(2, d.size());
         assertTrue(d.containsAll(Arrays.asList(TARGET, "some.other.target")));
@@ -81,23 +80,24 @@
     @Test
     public void testImmutableEnabledChange() {
         final OverlayManagerServiceImpl impl = getImpl();
-        installTargetPackage(TARGET, USER);
+        installNewPackage(target(TARGET), USER);
+        installNewPackage(overlay(OVERLAY, TARGET), USER);
 
-        addOverlayPackage(OVERLAY, TARGET, USER, false, false, 0);
+        configureSystemOverlay(OVERLAY, false /* mutable */, false /* enabled */, 0 /* priority */);
         impl.updateOverlaysForUser(USER);
         final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
         assertNotNull(o1);
         assertFalse(o1.isEnabled());
         assertFalse(o1.isMutable);
 
-        addOverlayPackage(OVERLAY, TARGET, USER, false, true, 0);
+        configureSystemOverlay(OVERLAY, false /* mutable */, true /* enabled */, 0 /* priority */);
         impl.updateOverlaysForUser(USER);
         final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY, USER);
         assertNotNull(o2);
         assertTrue(o2.isEnabled());
         assertFalse(o2.isMutable);
 
-        addOverlayPackage(OVERLAY, TARGET, USER, false, false, 0);
+        configureSystemOverlay(OVERLAY, false /* mutable */, false /* enabled */, 0 /* priority */);
         impl.updateOverlaysForUser(USER);
         final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
         assertNotNull(o3);
@@ -108,23 +108,24 @@
     @Test
     public void testMutableEnabledChangeHasNoEffect() {
         final OverlayManagerServiceImpl impl = getImpl();
-        installTargetPackage(TARGET, USER);
+        installNewPackage(target(TARGET), USER);
+        installNewPackage(overlay(OVERLAY, TARGET), USER);
+        configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 0 /* priority */);
 
-        addOverlayPackage(OVERLAY, TARGET, USER, true, false, 0);
         impl.updateOverlaysForUser(USER);
         final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
         assertNotNull(o1);
         assertFalse(o1.isEnabled());
         assertTrue(o1.isMutable);
 
-        addOverlayPackage(OVERLAY, TARGET, USER, true, true, 0);
+        configureSystemOverlay(OVERLAY, true /* mutable */, true /* enabled */, 0 /* priority */);
         impl.updateOverlaysForUser(USER);
         final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY, USER);
         assertNotNull(o2);
         assertFalse(o2.isEnabled());
         assertTrue(o2.isMutable);
 
-        addOverlayPackage(OVERLAY, TARGET, USER, true, false, 0);
+        configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 0 /* priority */);
         impl.updateOverlaysForUser(USER);
         final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
         assertNotNull(o3);
@@ -135,15 +136,16 @@
     @Test
     public void testMutableEnabledToImmutableEnabled() {
         final OverlayManagerServiceImpl impl = getImpl();
-        installTargetPackage(TARGET, USER);
+        installNewPackage(target(TARGET), USER);
+        installNewPackage(overlay(OVERLAY, TARGET), USER);
 
         final BiConsumer<Boolean, Boolean> setOverlay = (mutable, enabled) -> {
-            addOverlayPackage(OVERLAY, TARGET, USER, mutable, enabled, 0);
+            configureSystemOverlay(OVERLAY, mutable, enabled, 0 /* priority */);
             impl.updateOverlaysForUser(USER);
-            final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
-            assertNotNull(o1);
-            assertEquals(enabled, o1.isEnabled());
-            assertEquals(mutable, o1.isMutable);
+            final OverlayInfo o = impl.getOverlayInfo(OVERLAY, USER);
+            assertNotNull(o);
+            assertEquals(enabled, o.isEnabled());
+            assertEquals(mutable, o.isMutable);
         };
 
         // Immutable/enabled -> mutable/enabled
@@ -178,70 +180,76 @@
     @Test
     public void testMutablePriorityChange() {
         final OverlayManagerServiceImpl impl = getImpl();
-        installTargetPackage(TARGET, USER);
-        addOverlayPackage(OVERLAY, TARGET, USER, true, true, 0);
-        addOverlayPackage(OVERLAY2, TARGET, USER, true, true, 1);
+        installNewPackage(target(TARGET), USER);
+        installNewPackage(overlay(OVERLAY, TARGET), USER);
+        installNewPackage(overlay(OVERLAY2, TARGET), USER);
+        configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 0 /* priority */);
+        configureSystemOverlay(OVERLAY2, true /* mutable */, false /* enabled */, 1 /* priority */);
         impl.updateOverlaysForUser(USER);
 
         final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
         assertNotNull(o1);
         assertEquals(0, o1.priority);
+        assertFalse(o1.isEnabled());
 
         final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY2, USER);
         assertNotNull(o2);
         assertEquals(1, o2.priority);
+        assertFalse(o2.isEnabled());
 
         // Overlay priority changing between reboots should not affect enable state of mutable
-        // overlays
+        // overlays.
         impl.setEnabled(OVERLAY, true, USER);
 
         // Reorder the overlays
-        addOverlayPackage(OVERLAY, TARGET, USER, true, true, 1);
-        addOverlayPackage(OVERLAY2, TARGET, USER, true, true, 0);
+        configureSystemOverlay(OVERLAY, true /* mutable */, false /* enabled */, 1 /* priority */);
+        configureSystemOverlay(OVERLAY2, true /* mutable */, false /* enabled */, 0 /* priority */);
         impl.updateOverlaysForUser(USER);
 
         final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
         assertNotNull(o3);
         assertEquals(1, o3.priority);
+        assertTrue(o3.isEnabled());
 
         final OverlayInfo o4 = impl.getOverlayInfo(OVERLAY2, USER);
         assertNotNull(o4);
         assertEquals(0, o4.priority);
-        assertTrue(o1.isEnabled());
+        assertFalse(o4.isEnabled());
     }
 
     @Test
     public void testImmutablePriorityChange() {
         final OverlayManagerServiceImpl impl = getImpl();
-        installTargetPackage(TARGET, USER);
-        addOverlayPackage(OVERLAY, TARGET, USER, false, true, 0);
-        addOverlayPackage(OVERLAY2, TARGET, USER, false, true, 1);
+        installNewPackage(target(TARGET), USER);
+        installNewPackage(overlay(OVERLAY, TARGET), USER);
+        installNewPackage(overlay(OVERLAY2, TARGET), USER);
+        configureSystemOverlay(OVERLAY, false /* mutable */, true /* enabled */, 0 /* priority */);
+        configureSystemOverlay(OVERLAY2, false /* mutable */, true /* enabled */, 1 /* priority */);
         impl.updateOverlaysForUser(USER);
 
         final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
         assertNotNull(o1);
         assertEquals(0, o1.priority);
+        assertTrue(o1.isEnabled());
 
         final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY2, USER);
         assertNotNull(o2);
         assertEquals(1, o2.priority);
-
-        // Overlay priority changing between reboots should not affect enable state of mutable
-        // overlays
-        impl.setEnabled(OVERLAY, true, USER);
+        assertTrue(o2.isEnabled());
 
         // Reorder the overlays
-        addOverlayPackage(OVERLAY, TARGET, USER, false, true, 1);
-        addOverlayPackage(OVERLAY2, TARGET, USER, false, true, 0);
+        configureSystemOverlay(OVERLAY, false /* mutable */, true /* enabled */, 1 /* priority */);
+        configureSystemOverlay(OVERLAY2, false /* mutable */, true /* enabled */, 0 /* priority */);
         impl.updateOverlaysForUser(USER);
 
         final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
         assertNotNull(o3);
         assertEquals(1, o3.priority);
+        assertTrue(o3.isEnabled());
 
         final OverlayInfo o4 = impl.getOverlayInfo(OVERLAY2, USER);
         assertNotNull(o4);
         assertEquals(0, o4.priority);
-        assertTrue(o1.isEnabled());
+        assertTrue(o4.isEnabled());
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
index cd73432..b25af05 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
@@ -26,6 +26,7 @@
 import static org.junit.Assert.assertTrue;
 
 import android.content.om.OverlayInfo;
+import android.os.OverlayablePolicy;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -49,11 +50,9 @@
     private static final String OVERLAY3 = OVERLAY + "3";
     private static final int USER3 = USER2 + 1;
 
-    // tests: basics
-
     @Test
-    public void testGetOverlayInfo() throws Exception {
-        installOverlayPackage(OVERLAY, TARGET, USER);
+    public void testGetOverlayInfo() {
+        installNewPackage(overlay(OVERLAY, TARGET), USER);
 
         final OverlayManagerServiceImpl impl = getImpl();
         final OverlayInfo oi = impl.getOverlayInfo(OVERLAY, USER);
@@ -64,10 +63,10 @@
     }
 
     @Test
-    public void testGetOverlayInfosForTarget() throws Exception {
-        installOverlayPackage(OVERLAY, TARGET, USER);
-        installOverlayPackage(OVERLAY2, TARGET, USER);
-        installOverlayPackage(OVERLAY3, TARGET, USER2);
+    public void testGetOverlayInfosForTarget() {
+        installNewPackage(overlay(OVERLAY, TARGET), USER);
+        installNewPackage(overlay(OVERLAY2, TARGET), USER);
+        installNewPackage(overlay(OVERLAY3, TARGET), USER2);
 
         final OverlayManagerServiceImpl impl = getImpl();
         final List<OverlayInfo> ois = impl.getOverlayInfosForTarget(TARGET, USER);
@@ -89,11 +88,11 @@
     }
 
     @Test
-    public void testGetOverlayInfosForUser() throws Exception {
-        installTargetPackage(TARGET, USER);
-        installOverlayPackage(OVERLAY, TARGET, USER);
-        installOverlayPackage(OVERLAY2, TARGET, USER);
-        installOverlayPackage(OVERLAY3, TARGET2, USER);
+    public void testGetOverlayInfosForUser() {
+        installNewPackage(target(TARGET), USER);
+        installNewPackage(overlay(OVERLAY, TARGET), USER);
+        installNewPackage(overlay(OVERLAY2, TARGET), USER);
+        installNewPackage(overlay(OVERLAY3, TARGET2), USER);
 
         final OverlayManagerServiceImpl impl = getImpl();
         final Map<String, List<OverlayInfo>> everything = impl.getOverlaysForUser(USER);
@@ -116,91 +115,86 @@
     }
 
     @Test
-    public void testPriority() throws Exception {
-        installOverlayPackage(OVERLAY, TARGET, USER);
-        installOverlayPackage(OVERLAY2, TARGET, USER);
-        installOverlayPackage(OVERLAY3, TARGET, USER);
+    public void testPriority() {
+        installNewPackage(overlay(OVERLAY, TARGET), USER);
+        installNewPackage(overlay(OVERLAY2, TARGET), USER);
+        installNewPackage(overlay(OVERLAY3, TARGET), USER);
 
         final OverlayManagerServiceImpl impl = getImpl();
         final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
         final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY2, USER);
         final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY3, USER);
 
-        assertOverlayInfoList(TARGET, USER, o1, o2, o3);
+        assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3);
 
         assertTrue(impl.setLowestPriority(OVERLAY3, USER));
-        assertOverlayInfoList(TARGET, USER, o3, o1, o2);
+        assertOverlayInfoForTarget(TARGET, USER, o3, o1, o2);
 
         assertTrue(impl.setHighestPriority(OVERLAY3, USER));
-        assertOverlayInfoList(TARGET, USER, o1, o2, o3);
+        assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3);
 
         assertTrue(impl.setPriority(OVERLAY, OVERLAY2, USER));
-        assertOverlayInfoList(TARGET, USER, o2, o1, o3);
+        assertOverlayInfoForTarget(TARGET, USER, o2, o1, o3);
     }
 
     @Test
-    public void testOverlayInfoStateTransitions() throws Exception {
+    public void testOverlayInfoStateTransitions() {
         final OverlayManagerServiceImpl impl = getImpl();
         assertNull(impl.getOverlayInfo(OVERLAY, USER));
 
-        installOverlayPackage(OVERLAY, TARGET, USER);
+        installNewPackage(overlay(OVERLAY, TARGET), USER);
         assertState(STATE_MISSING_TARGET, OVERLAY, USER);
 
-        installTargetPackage(TARGET, USER);
+        final DummyDeviceState.PackageBuilder target = target(TARGET);
+        installNewPackage(target, USER);
         assertState(STATE_DISABLED, OVERLAY, USER);
 
         impl.setEnabled(OVERLAY, true, USER);
         assertState(STATE_ENABLED, OVERLAY, USER);
 
         // target upgrades do not change the state of the overlay
-        beginUpgradeTargetPackage(TARGET, USER);
+        upgradePackage(target, USER);
         assertState(STATE_ENABLED, OVERLAY, USER);
 
-        endUpgradeTargetPackage(TARGET, USER);
-        assertState(STATE_ENABLED, OVERLAY, USER);
-
-        uninstallTargetPackage(TARGET, USER);
+        uninstallPackage(TARGET, USER);
         assertState(STATE_MISSING_TARGET, OVERLAY, USER);
 
-        installTargetPackage(TARGET, USER);
+        installNewPackage(target, USER);
         assertState(STATE_ENABLED, OVERLAY, USER);
     }
 
     @Test
-    public void testOnOverlayPackageUpgraded() throws Exception {
-        final OverlayManagerServiceImpl impl = getImpl();
+    public void testOnOverlayPackageUpgraded() {
         final DummyListener listener = getListener();
-        installTargetPackage(TARGET, USER);
-        installOverlayPackage(OVERLAY, TARGET, USER);
-        impl.onOverlayPackageReplacing(OVERLAY, USER);
+        final DummyDeviceState.PackageBuilder target = target(TARGET);
+        final DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET);
+        installNewPackage(target, USER);
+        installNewPackage(overlay, USER);
         listener.count = 0;
-        impl.onOverlayPackageReplaced(OVERLAY, USER);
-        assertEquals(1, listener.count);
-
-        // upgrade to a version where the overlay has changed its target
-        beginUpgradeOverlayPackage(OVERLAY, USER);
-        listener.count = 0;
-        endUpgradeOverlayPackage(OVERLAY, "some.other.target", USER);
-        // expect once for the old target package, once for the new target package
+        upgradePackage(overlay, USER);
         assertEquals(2, listener.count);
 
-        beginUpgradeOverlayPackage(OVERLAY, USER);
+        // upgrade to a version where the overlay has changed its target
+        // expect once for the old target package, once for the new target package
         listener.count = 0;
-        endUpgradeOverlayPackage(OVERLAY, "some.other.target", USER);
-        assertEquals(1, listener.count);
+        final DummyDeviceState.PackageBuilder overlay2 = overlay(OVERLAY, "some.other.target");
+        upgradePackage(overlay2, USER);
+        assertEquals(3, listener.count);
+
+        listener.count = 0;
+        upgradePackage(overlay2, USER);
+        assertEquals(2, listener.count);
     }
 
-    // tests: listener interface
-
     @Test
-    public void testListener() throws Exception {
+    public void testListener() {
         final OverlayManagerServiceImpl impl = getImpl();
         final DummyListener listener = getListener();
-        installOverlayPackage(OVERLAY, TARGET, USER);
+        installNewPackage(overlay(OVERLAY, TARGET), USER);
         assertEquals(1, listener.count);
         listener.count = 0;
 
-        installTargetPackage(TARGET, USER);
+        installNewPackage(target(TARGET), USER);
         assertEquals(1, listener.count);
         listener.count = 0;
 
@@ -211,4 +205,49 @@
         impl.setEnabled(OVERLAY, true, USER);
         assertEquals(0, listener.count);
     }
+
+    @Test
+    public void testConfigurator() {
+        final DummyPackageManagerHelper packageManager = getPackageManager();
+        packageManager.overlayableConfigurator = "actor";
+        packageManager.overlayableConfiguratorTargets = new String[]{TARGET};
+        reinitializeImpl();
+
+        installNewPackage(target("actor").setCertificate("one"), USER);
+        installNewPackage(target(TARGET)
+                .addOverlayable("TestResources")
+                .setCertificate("two"), USER);
+
+        final DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET, "TestResources")
+                .setCertificate("one");
+        installNewPackage(overlay, USER);
+
+        final DummyIdmapDaemon idmapDaemon = getIdmapDaemon();
+        final DummyIdmapDaemon.IdmapHeader idmap = idmapDaemon.getIdmap(overlay.build().apkPath);
+        assertNotNull(idmap);
+        assertEquals(OverlayablePolicy.ACTOR_SIGNATURE,
+                idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE);
+    }
+
+    @Test
+    public void testConfiguratorDifferentSignatures() {
+        final DummyPackageManagerHelper packageManager = getPackageManager();
+        packageManager.overlayableConfigurator = "actor";
+        packageManager.overlayableConfiguratorTargets = new String[]{TARGET};
+        reinitializeImpl();
+
+        installNewPackage(target("actor").setCertificate("one"), USER);
+        installNewPackage(target(TARGET)
+                .addOverlayable("TestResources")
+                .setCertificate("two"), USER);
+
+        final DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET, "TestResources")
+                .setCertificate("two");
+        installNewPackage(overlay, USER);
+
+        final DummyIdmapDaemon idmapDaemon = getIdmapDaemon();
+        final DummyIdmapDaemon.IdmapHeader idmap = idmapDaemon.getIdmap(overlay.build().apkPath);
+        assertNotNull(idmap);
+        assertEquals(0, idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
index 9eda718..ec6a481 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
@@ -17,6 +17,7 @@
 package com.android.server.om;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -26,17 +27,19 @@
 import android.content.om.OverlayableInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 
 import androidx.annotation.Nullable;
 
 import com.android.internal.content.om.OverlayConfig;
 
+import org.junit.Assert;
 import org.junit.Before;
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Iterator;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -47,29 +50,48 @@
     private OverlayManagerServiceImpl mImpl;
     private DummyDeviceState mState;
     private DummyListener mListener;
+    private DummyPackageManagerHelper mPackageManager;
+    private DummyIdmapDaemon mIdmapDaemon;
+    private OverlayConfig mOverlayConfig;
 
     @Before
     public void setUp() {
         mState = new DummyDeviceState();
         mListener = new DummyListener();
-        final DummyPackageManagerHelper pmh = new DummyPackageManagerHelper(mState);
+        mPackageManager = new DummyPackageManagerHelper(mState);
+        mIdmapDaemon = new DummyIdmapDaemon(mState);
+        mOverlayConfig = mock(OverlayConfig.class);
+        when(mOverlayConfig.getPriority(any())).thenReturn(OverlayConfig.DEFAULT_PRIORITY);
+        when(mOverlayConfig.isEnabled(any())).thenReturn(false);
+        when(mOverlayConfig.isMutable(any())).thenReturn(true);
+        reinitializeImpl();
+    }
 
-        mImpl = new OverlayManagerServiceImpl(pmh,
-                new DummyIdmapManager(mState, pmh),
+    void reinitializeImpl() {
+        mImpl = new OverlayManagerServiceImpl(mPackageManager,
+                new IdmapManager(mIdmapDaemon, mPackageManager),
                 new OverlayManagerSettings(),
-                mState.mOverlayConfig,
+                mOverlayConfig,
                 new String[0],
                 mListener);
     }
 
-    public OverlayManagerServiceImpl getImpl() {
+    OverlayManagerServiceImpl getImpl() {
         return mImpl;
     }
 
-    public DummyListener getListener() {
+    DummyListener getListener() {
         return mListener;
     }
 
+    DummyPackageManagerHelper getPackageManager() {
+        return mPackageManager;
+    }
+
+    DummyIdmapDaemon getIdmapDaemon() {
+        return mIdmapDaemon;
+    }
+
     void assertState(@State int expected, final String overlayPackageName, int userId) {
         final OverlayInfo info = mImpl.getOverlayInfo(overlayPackageName, userId);
         if (info == null) {
@@ -81,7 +103,7 @@
         assertEquals(msg, expected, info.state);
     }
 
-    void assertOverlayInfoList(final String targetPackageName, int userId,
+    void assertOverlayInfoForTarget(final String targetPackageName, int userId,
             OverlayInfo... overlayInfos) {
         final List<OverlayInfo> expected =
                 mImpl.getOverlayInfosForTarget(targetPackageName, userId);
@@ -89,198 +111,202 @@
         assertEquals(expected, actual);
     }
 
-    /**
-     * Creates an overlay configured through {@link OverlayConfig}.
-     *
-     * @throws IllegalStateException if the package is already installed
-     */
-    void addOverlayPackage(String packageName, String targetPackageName, int userId,
-            boolean mutable, boolean enabled, int priority) {
-        mState.addOverlay(packageName, targetPackageName, userId, mutable, enabled, priority);
+    DummyDeviceState.PackageBuilder target(String packageName) {
+        return new DummyDeviceState.PackageBuilder(packageName, null /* targetPackageName */,
+                null /* targetOverlayableName */);
+    }
+
+    DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName) {
+        return overlay(packageName, targetPackageName, null /* targetOverlayableName */);
+    }
+
+    DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName,
+            String targetOverlayableName) {
+        return new DummyDeviceState.PackageBuilder(packageName, targetPackageName,
+                targetOverlayableName);
+    }
+
+    void addSystemPackage(DummyDeviceState.PackageBuilder pkg, int userId) {
+        mState.add(pkg, userId);
+    }
+
+    void configureSystemOverlay(String packageName, boolean mutable, boolean enabled,
+            int priority) {
+        when(mOverlayConfig.getPriority(packageName)).thenReturn(priority);
+        when(mOverlayConfig.isEnabled(packageName)).thenReturn(enabled);
+        when(mOverlayConfig.isMutable(packageName)).thenReturn(mutable);
     }
 
     /**
-     * Adds the target package to the device.
+     * Adds the package to the device.
      *
      * This corresponds to when the OMS receives the
      * {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast.
      *
-     * @throws IllegalStateException if the package is not currently installed
+     * @throws IllegalStateException if the package is currently installed
      */
-    void installTargetPackage(String packageName, int userId) {
-        if (mState.select(packageName, userId) != null) {
-            throw new IllegalStateException("package already installed");
+    void installNewPackage(DummyDeviceState.PackageBuilder pkg, int userId) {
+        if (mState.select(pkg.packageName, userId) != null) {
+            throw new IllegalStateException("package " + pkg.packageName + " already installed");
         }
-        mState.addTarget(packageName, userId);
-        mImpl.onTargetPackageAdded(packageName, userId);
+        mState.add(pkg, userId);
+        if (pkg.targetPackage == null) {
+            mImpl.onTargetPackageAdded(pkg.packageName, userId);
+        } else {
+            mImpl.onOverlayPackageAdded(pkg.packageName, userId);
+        }
     }
 
     /**
-     * Begins upgrading the target package.
+     * Begins upgrading the package.
      *
      * This corresponds to when the OMS receives the
      * {@link android.content.Intent#ACTION_PACKAGE_REMOVED} broadcast with the
-     * {@link android.content.Intent#EXTRA_REPLACING} extra.
-     *
-     * @throws IllegalStateException if the package is not currently installed
-     */
-    void beginUpgradeTargetPackage(String packageName, int userId) {
-        if (mState.select(packageName, userId) == null) {
-            throw new IllegalStateException("package not installed");
-        }
-        mImpl.onTargetPackageReplacing(packageName, userId);
-    }
-
-    /**
-     * Ends upgrading the target package.
-     *
-     * This corresponds to when the OMS receives the
+     * {@link android.content.Intent#EXTRA_REPLACING} extra and then receives the
      * {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast with the
      * {@link android.content.Intent#EXTRA_REPLACING} extra.
      *
      * @throws IllegalStateException if the package is not currently installed
      */
-    void endUpgradeTargetPackage(String packageName, int userId) {
-        if (mState.select(packageName, userId) == null) {
-            throw new IllegalStateException("package not installed");
+    void upgradePackage(DummyDeviceState.PackageBuilder pkg, int userId) {
+        final DummyDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId);
+        if (replacedPackage == null) {
+            throw new IllegalStateException("package " + pkg.packageName + " not installed");
         }
-        mState.addTarget(packageName, userId);
-        mImpl.onTargetPackageReplaced(packageName, userId);
+        if (replacedPackage.targetPackageName != null) {
+            mImpl.onOverlayPackageReplacing(pkg.packageName, userId);
+        }
+
+        mState.add(pkg, userId);
+        if (pkg.targetPackage == null) {
+            mImpl.onTargetPackageReplaced(pkg.packageName, userId);
+        } else {
+            mImpl.onOverlayPackageReplaced(pkg.packageName, userId);
+        }
     }
 
     /**
-     * Removes the target package from the device.
+     * Removes the package from the device.
      *
      * This corresponds to when the OMS receives the
      * {@link android.content.Intent#ACTION_PACKAGE_REMOVED} broadcast.
      *
      * @throws IllegalStateException if the package is not currently installed
      */
-    void uninstallTargetPackage(String packageName, int userId) {
-        if (mState.select(packageName, userId) == null) {
-            throw new IllegalStateException("package not installed");
+    void uninstallPackage(String packageName, int userId) {
+        final DummyDeviceState.Package pkg = mState.select(packageName, userId);
+        if (pkg == null) {
+            throw new IllegalStateException("package " + packageName+ " not installed");
         }
-        mState.remove(packageName, userId);
-        mImpl.onTargetPackageRemoved(packageName, userId);
+        mState.remove(pkg.packageName);
+        if (pkg.targetPackageName == null) {
+            mImpl.onTargetPackageRemoved(pkg.packageName, userId);
+        } else {
+            mImpl.onOverlayPackageRemoved(pkg.packageName, userId);
+        }
     }
 
-    /**
-     * Adds the overlay package to the device.
-     *
-     * This corresponds to when the OMS receives the
-     * {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast.
-     *
-     * @throws IllegalStateException if the package is already installed
-     */
-    void installOverlayPackage(String packageName, String targetPackageName, int userId) {
-        if (mState.select(packageName, userId) != null) {
-            throw new IllegalStateException("package already installed");
-        }
-        mState.addOverlay(packageName, targetPackageName, userId);
-        mImpl.onOverlayPackageAdded(packageName, userId);
-    }
+    /** Represents the state of packages installed on a fake device. */
+    static class DummyDeviceState {
+        private ArrayMap<String, Package> mPackages = new ArrayMap<>();
 
-    /**
-     * Begins upgrading the overlay package.
-     *
-     * This corresponds to when the OMS receives the
-     * {@link android.content.Intent#ACTION_PACKAGE_REMOVED} broadcast with the
-     * {@link android.content.Intent#EXTRA_REPLACING} extra.
-     *
-     * @throws IllegalStateException if the package is not currently installed
-     */
-    void beginUpgradeOverlayPackage(String packageName, int userId) {
-        if (mState.select(packageName, userId) == null) {
-            throw new IllegalStateException("package not installed, cannot upgrade");
-        }
+        void add(PackageBuilder pkgBuilder, int userId) {
+            final Package pkg = pkgBuilder.build();
+            final Package previousPkg = select(pkg.packageName, userId);
+            mPackages.put(pkg.packageName, pkg);
 
-        mImpl.onOverlayPackageReplacing(packageName, userId);
-    }
-
-    /**
-     * Ends upgrading the overlay package, potentially changing its target package.
-     *
-     * This corresponds to when the OMS receives the
-     * {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast with the
-     * {@link android.content.Intent#EXTRA_REPLACING} extra.
-     *
-     * @throws IllegalStateException if the package is not currently installed
-     */
-    void endUpgradeOverlayPackage(String packageName, String targetPackageName, int userId) {
-        if (mState.select(packageName, userId) == null) {
-            throw new IllegalStateException("package not installed, cannot upgrade");
-        }
-
-        mState.addOverlay(packageName, targetPackageName, userId);
-        mImpl.onOverlayPackageReplaced(packageName, userId);
-    }
-
-    private static final class DummyDeviceState {
-        private List<Package> mPackages = new ArrayList<>();
-        private OverlayConfig mOverlayConfig = mock(OverlayConfig.class);
-
-        /** Adds a non-overlay to the device. */
-        public void addTarget(String packageName, int userId) {
-            remove(packageName, userId);
-            mPackages.add(new Package(packageName, userId, null, false, false, 0));
-        }
-
-        /** Adds an overlay to the device. */
-        public void addOverlay(String packageName, String targetPackageName, int userId) {
-            addOverlay(packageName, targetPackageName, userId, true, false, OverlayConfig.DEFAULT_PRIORITY);
-        }
-
-        /** Adds a configured overlay to the device. */
-        public void addOverlay(String packageName, String targetPackageName, int userId,
-                boolean mutable, boolean enabled, int priority) {
-            remove(packageName, userId);
-            mPackages.add(new Package(packageName, userId, targetPackageName, mutable, enabled,
-                    priority));
-            when(mOverlayConfig.getPriority(packageName)).thenReturn(priority);
-            when(mOverlayConfig.isEnabled(packageName)).thenReturn(enabled);
-            when(mOverlayConfig.isMutable(packageName)).thenReturn(mutable);
-        }
-
-        /** Remove a package from the device. */
-        public void remove(String packageName, int userId) {
-            final Iterator<Package> iter = mPackages.iterator();
-            while (iter.hasNext()) {
-                final Package pkg = iter.next();
-                if (pkg.packageName.equals(packageName) && pkg.userId == userId) {
-                    iter.remove();
-                    return;
-                }
+            pkg.installedUserIds.add(userId);
+            if (previousPkg != null) {
+                pkg.installedUserIds.addAll(previousPkg.installedUserIds);
             }
         }
 
-        /** Retrieves all packages on device for a particular user. */
-        public List<Package> select(int userId) {
-            return mPackages.stream().filter(p -> p.userId == userId).collect(Collectors.toList());
+        void remove(String packageName) {
+            mPackages.remove(packageName);
         }
 
-        /** Retrieves the package with the specified package name for a particular user. */
-        public Package select(String packageName, int userId) {
-            return mPackages.stream().filter(
-                    p -> p.packageName.equals(packageName) && p.userId == userId)
-                    .findFirst().orElse(null);
+        void uninstall(String packageName, int userId) {
+            final Package pkg = mPackages.get(packageName);
+            if (pkg != null) {
+                pkg.installedUserIds.remove(userId);
+            }
         }
 
-        private static final class Package {
-            public final String packageName;
-            public final int userId;
-            public final String targetPackageName;
-            public final boolean mutable;
-            public final boolean enabled;
-            public final int priority;
+        List<Package> select(int userId) {
+            return mPackages.values().stream().filter(p -> p.installedUserIds.contains(userId))
+                    .collect(Collectors.toList());
+        }
 
-            private Package(String packageName, int userId, String targetPackageName,
-                    boolean mutable, boolean enabled, int priority) {
+        Package select(String packageName, int userId) {
+            final Package pkg = mPackages.get(packageName);
+            return pkg != null && pkg.installedUserIds.contains(userId) ? pkg : null;
+        }
+
+        private Package selectFromPath(String path) {
+            return mPackages.values().stream()
+                    .filter(p -> p.apkPath.equals(path)).findFirst().orElse(null);
+        }
+
+        static final class PackageBuilder {
+            private String packageName;
+            private String targetPackage;
+            private String certificate = "[default]";
+            private int version = 0;
+            private ArrayList<String> overlayableNames = new ArrayList<>();
+            private String targetOverlayableName;
+
+            private PackageBuilder(String packageName, String targetPackage,
+                    String targetOverlayableName) {
                 this.packageName = packageName;
-                this.userId = userId;
+                this.targetPackage = targetPackage;
+                this.targetOverlayableName = targetOverlayableName;
+            }
+
+            PackageBuilder setCertificate(String certificate) {
+                this.certificate = certificate;
+                return this;
+            }
+
+            PackageBuilder addOverlayable(String overlayableName) {
+                overlayableNames.add(overlayableName);
+                return this;
+            }
+
+            PackageBuilder setVersion(int version) {
+                this.version = version;
+                return this;
+            }
+
+            Package build() {
+                final String apkPath = String.format("%s/%s/base.apk",
+                        targetPackage == null ? "/system/app/:" : "/vendor/overlay/:",
+                        packageName);
+                final Package newPackage = new Package(packageName, targetPackage,
+                        targetOverlayableName, version, apkPath, certificate);
+                newPackage.overlayableNames.addAll(overlayableNames);
+                return newPackage;
+            }
+        }
+
+        static final class Package {
+            final String packageName;
+            final String targetPackageName;
+            final String targetOverlayableName;
+            final int versionCode;
+            final String apkPath;
+            final String certificate;
+            final ArrayList<String> overlayableNames = new ArrayList<>();
+            private final ArraySet<Integer> installedUserIds = new ArraySet<>();
+
+            private Package(String packageName, String targetPackageName,
+                    String targetOverlayableName, int versionCode, String apkPath,
+                    String certificate) {
+                this.packageName = packageName;
                 this.targetPackageName = targetPackageName;
-                this.mutable = mutable;
-                this.enabled = enabled;
-                this.priority = priority;
+                this.targetOverlayableName = targetOverlayableName;
+                this.versionCode = versionCode;
+                this.apkPath = apkPath;
+                this.certificate = certificate;
             }
         }
     }
@@ -288,6 +314,8 @@
     static final class DummyPackageManagerHelper implements PackageManagerHelper,
             OverlayableInfoCallback {
         private final DummyDeviceState mState;
+        String[] overlayableConfiguratorTargets = new String[0];
+        String overlayableConfigurator = "";
 
         private DummyPackageManagerHelper(DummyDeviceState state) {
             mState = state;
@@ -300,13 +328,12 @@
                 return null;
             }
             final ApplicationInfo ai = new ApplicationInfo();
-            ai.sourceDir = String.format("%s/%s/base.apk",
-                    pkg.targetPackageName == null ? "/system/app/" : "/vendor/overlay/",
-                    pkg.packageName);
+            ai.sourceDir = pkg.apkPath;
             PackageInfo pi = new PackageInfo();
             pi.applicationInfo = ai;
             pi.packageName = pkg.packageName;
             pi.overlayTarget = pkg.targetPackageName;
+            pi.targetOverlayableName = pkg.targetOverlayableName;
             pi.overlayCategory = "dummy-category-" + pkg.targetPackageName;
             return pi;
         }
@@ -314,14 +341,16 @@
         @Override
         public boolean signaturesMatching(@NonNull String packageName1,
                 @NonNull String packageName2, int userId) {
-            return false;
+            final DummyDeviceState.Package pkg1 = mState.select(packageName1, userId);
+            final DummyDeviceState.Package pkg2 = mState.select(packageName2, userId);
+            return pkg1 != null && pkg2 != null && pkg1.certificate.equals(pkg2.certificate);
         }
 
         @Override
         public List<PackageInfo> getOverlayPackages(int userId) {
             return mState.select(userId).stream()
                     .filter(p -> p.targetPackageName != null)
-                    .map(p -> getPackageInfo(p.packageName, p.userId))
+                    .map(p -> getPackageInfo(p.packageName, userId))
                     .collect(Collectors.toList());
         }
 
@@ -329,7 +358,11 @@
         @Override
         public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
                 @NonNull String targetOverlayableName, int userId) {
-            throw new UnsupportedOperationException();
+            final DummyDeviceState.Package pkg = mState.select(packageName, userId);
+            if (pkg == null || !pkg.overlayableNames.contains(targetOverlayableName)) {
+                return null;
+            }
+            return new OverlayableInfo(targetOverlayableName, null /* actor */);
         }
 
         @Nullable
@@ -341,69 +374,98 @@
         @NonNull
         @Override
         public Map<String, Map<String, String>> getNamedActors() {
-            throw new UnsupportedOperationException();
+            return Collections.emptyMap();
         }
 
         @Override
         public boolean doesTargetDefineOverlayable(String targetPackageName, int userId) {
-            throw new UnsupportedOperationException();
+            final DummyDeviceState.Package pkg = mState.select(targetPackageName, userId);
+            return pkg != null && pkg.overlayableNames.contains(targetPackageName);
         }
 
         @Override
         public void enforcePermission(String permission, String message) throws SecurityException {
             throw new UnsupportedOperationException();
         }
+
+        @Override
+        public String[] getOverlayableConfiguratorTargets() {
+            return overlayableConfiguratorTargets;
+        }
+
+        @Override
+        public String getOverlayableConfigurator() {
+            return overlayableConfigurator;
+        }
     }
 
-    static class DummyIdmapManager extends IdmapManager {
+    static class DummyIdmapDaemon extends IdmapDaemon {
         private final DummyDeviceState mState;
-        private Set<String> mIdmapFiles = new ArraySet<>();
+        private final ArrayMap<String, IdmapHeader> mIdmapFiles = new ArrayMap<>();
 
-        private DummyIdmapManager(DummyDeviceState state,
-                DummyPackageManagerHelper packageManagerHelper) {
-            super(packageManagerHelper);
-            mState = state;
+        DummyIdmapDaemon(DummyDeviceState state) {
+            this.mState = state;
+        }
+
+        private int getCrc(@NonNull final String path) {
+            final DummyDeviceState.Package pkg = mState.selectFromPath(path);
+            Assert.assertNotNull(pkg);
+            return pkg.versionCode;
         }
 
         @Override
-        boolean createIdmap(@NonNull final PackageInfo targetPackage,
-                @NonNull final PackageInfo overlayPackage, int userId) {
-            final DummyDeviceState.Package t = mState.select(targetPackage.packageName, userId);
-            if (t == null) {
+        String createIdmap(String targetPath, String overlayPath, int policies, boolean enforce,
+                int userId) {
+            mIdmapFiles.put(overlayPath, new IdmapHeader(getCrc(targetPath),
+                    getCrc(overlayPath), targetPath, policies, enforce));
+            return overlayPath;
+        }
+
+        @Override
+        boolean removeIdmap(String overlayPath, int userId) {
+            return mIdmapFiles.remove(overlayPath) != null;
+        }
+
+        @Override
+        boolean verifyIdmap(String targetPath, String overlayPath, int policies, boolean enforce,
+                int userId) {
+            final IdmapHeader idmap = mIdmapFiles.get(overlayPath);
+            if (idmap == null) {
                 return false;
             }
-            final DummyDeviceState.Package o = mState.select(overlayPackage.packageName, userId);
-            if (o == null) {
-                return false;
+            return idmap.isUpToDate(getCrc(targetPath), getCrc(overlayPath), targetPath);
+        }
+
+        @Override
+        boolean idmapExists(String overlayPath, int userId) {
+            return mIdmapFiles.containsKey(overlayPath);
+        }
+
+        IdmapHeader getIdmap(String overlayPath) {
+            return mIdmapFiles.get(overlayPath);
+        }
+
+        static class IdmapHeader {
+            private final int targetCrc;
+            private final int overlayCrc;
+            final String targetPath;
+            final int policies;
+            final boolean enforceOverlayable;
+
+            private IdmapHeader(int targetCrc, int overlayCrc, String targetPath, int policies,
+                    boolean enforceOverlayable) {
+                this.targetCrc = targetCrc;
+                this.overlayCrc = overlayCrc;
+                this.targetPath = targetPath;
+                this.policies = policies;
+                this.enforceOverlayable = enforceOverlayable;
             }
-            final String key = createKey(overlayPackage.packageName, userId);
-            return mIdmapFiles.add(key);
-        }
 
-        @Override
-        boolean removeIdmap(@NonNull final OverlayInfo oi, final int userId) {
-            final String key = createKey(oi.packageName, oi.userId);
-            if (!mIdmapFiles.contains(key)) {
-                return false;
+            private boolean isUpToDate(int expectedTargetCrc, int expectedOverlayCrc,
+                    String expectedTargetPath) {
+                return expectedTargetCrc == targetCrc && expectedOverlayCrc == overlayCrc
+                        && expectedTargetPath.equals(targetPath);
             }
-            mIdmapFiles.remove(key);
-            return true;
-        }
-
-        @Override
-        boolean idmapExists(@NonNull final OverlayInfo oi) {
-            final String key = createKey(oi.packageName, oi.userId);
-            return mIdmapFiles.contains(key);
-        }
-
-        @Override
-        boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) {
-            final String key = createKey(overlayPackage.packageName, userId);
-            return mIdmapFiles.contains(key);
-        }
-
-        private String createKey(@NonNull final String packageName, final int userId) {
-            return String.format("%s:%d", packageName, userId);
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java b/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java
index 70d6cf8..c5d9487 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java
@@ -46,7 +46,8 @@
                 .setContactUri(CONTACT_URI)
                 .setContactPhoneNumber(PHONE_NUMBER)
                 .setNotificationChannelId(NOTIFICATION_CHANNEL_ID)
-                .setShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED | ShortcutInfo.FLAG_CACHED)
+                .setShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED
+                        | ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)
                 .setImportant(true)
                 .setNotificationSilenced(true)
                 .setBubbled(true)
@@ -62,7 +63,7 @@
         assertEquals(PHONE_NUMBER, conversationInfo.getContactPhoneNumber());
         assertEquals(NOTIFICATION_CHANNEL_ID, conversationInfo.getNotificationChannelId());
         assertTrue(conversationInfo.isShortcutLongLived());
-        assertTrue(conversationInfo.isShortcutCached());
+        assertTrue(conversationInfo.isShortcutCachedForNotification());
         assertTrue(conversationInfo.isImportant());
         assertTrue(conversationInfo.isNotificationSilenced());
         assertTrue(conversationInfo.isBubbled());
@@ -84,7 +85,7 @@
         assertNull(conversationInfo.getContactPhoneNumber());
         assertNull(conversationInfo.getNotificationChannelId());
         assertFalse(conversationInfo.isShortcutLongLived());
-        assertFalse(conversationInfo.isShortcutCached());
+        assertFalse(conversationInfo.isShortcutCachedForNotification());
         assertFalse(conversationInfo.isImportant());
         assertFalse(conversationInfo.isNotificationSilenced());
         assertFalse(conversationInfo.isBubbled());
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index 1a2032a..b2f7abb 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -405,7 +405,7 @@
 
         ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        shortcut.setCached();
+        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
         mDataManager.addOrUpdateConversationInfo(shortcut);
 
         NotificationListenerService listenerService =
@@ -419,7 +419,8 @@
         assertEquals(1, activeNotificationOpenTimeSlots.size());
         verify(mShortcutServiceInternal).uncacheShortcuts(
                 anyInt(), any(), eq(TEST_PKG_NAME),
-                eq(Collections.singletonList(TEST_SHORTCUT_ID)), eq(USER_ID_PRIMARY));
+                eq(Collections.singletonList(TEST_SHORTCUT_ID)), eq(USER_ID_PRIMARY),
+                eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
     }
 
     @Test
@@ -434,7 +435,7 @@
                 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
 
         // Post one notification.
-        shortcut.setCached();
+        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
         mDataManager.addOrUpdateConversationInfo(shortcut);
         listenerService.onNotificationPosted(mStatusBarNotification);
 
@@ -445,14 +446,15 @@
         listenerService.onNotificationRemoved(mStatusBarNotification, null,
                 NotificationListenerService.REASON_CANCEL);
         verify(mShortcutServiceInternal, never()).uncacheShortcuts(
-                anyInt(), any(), anyString(), any(), anyInt());
+                anyInt(), any(), anyString(), any(), anyInt(), anyInt());
 
         // Removing the second notification un-caches the shortcut.
         listenerService.onNotificationRemoved(mStatusBarNotification, null,
                 NotificationListenerService.REASON_CANCEL_ALL);
         verify(mShortcutServiceInternal).uncacheShortcuts(
                 anyInt(), any(), eq(TEST_PKG_NAME),
-                eq(Collections.singletonList(TEST_SHORTCUT_ID)), eq(USER_ID_PRIMARY));
+                eq(Collections.singletonList(TEST_SHORTCUT_ID)), eq(USER_ID_PRIMARY),
+                eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
     }
 
     @Test
@@ -467,7 +469,7 @@
                 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
 
         listenerService.onNotificationPosted(mStatusBarNotification);
-        shortcut.setCached();
+        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
         mDataManager.addOrUpdateConversationInfo(shortcut);
 
         listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
@@ -477,7 +479,8 @@
                 NotificationListenerService.REASON_CANCEL_ALL);
         verify(mShortcutServiceInternal, never()).uncacheShortcuts(
                 anyInt(), any(), eq(TEST_PKG_NAME),
-                eq(Collections.singletonList(TEST_SHORTCUT_ID)), eq(USER_ID_PRIMARY));
+                eq(Collections.singletonList(TEST_SHORTCUT_ID)), eq(USER_ID_PRIMARY),
+                eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
     }
 
     @Test
@@ -569,13 +572,14 @@
                 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
 
         listenerService.onNotificationPosted(mStatusBarNotification);
-        shortcut.setCached();
+        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
         mDataManager.addOrUpdateConversationInfo(shortcut);
 
         mShutdownBroadcastReceiver.onReceive(mContext, new Intent());
         verify(mShortcutServiceInternal).uncacheShortcuts(
                 anyInt(), any(), eq(TEST_PKG_NAME),
-                eq(Collections.singletonList(TEST_SHORTCUT_ID)), eq(USER_ID_PRIMARY));
+                eq(Collections.singletonList(TEST_SHORTCUT_ID)), eq(USER_ID_PRIMARY),
+                eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
     }
 
     @Test
@@ -590,7 +594,7 @@
                 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
 
         listenerService.onNotificationPosted(mStatusBarNotification);
-        shortcut.setCached();
+        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
         mDataManager.addOrUpdateConversationInfo(shortcut);
 
         listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
@@ -599,7 +603,8 @@
         mShutdownBroadcastReceiver.onReceive(mContext, new Intent());
         verify(mShortcutServiceInternal, never()).uncacheShortcuts(
                 anyInt(), any(), eq(TEST_PKG_NAME),
-                eq(Collections.singletonList(TEST_SHORTCUT_ID)), eq(USER_ID_PRIMARY));
+                eq(Collections.singletonList(TEST_SHORTCUT_ID)), eq(USER_ID_PRIMARY),
+                eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
     }
 
     @Test
@@ -767,14 +772,15 @@
 
         ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        shortcut.setCached();
+        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
         mDataManager.addOrUpdateConversationInfo(shortcut);
 
         mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal);
 
         verify(mShortcutServiceInternal).uncacheShortcuts(
                 anyInt(), any(), eq(TEST_PKG_NAME),
-                eq(Collections.singletonList(TEST_SHORTCUT_ID)), eq(USER_ID_PRIMARY));
+                eq(Collections.singletonList(TEST_SHORTCUT_ID)), eq(USER_ID_PRIMARY),
+                eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
     }
 
     @Test
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 db02524..90989b9 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -137,6 +137,9 @@
 @SmallTest
 public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
 
+    private static final int CACHE_OWNER_0 = LauncherApps.FLAG_CACHE_NOTIFICATION_SHORTCUTS;
+    private static final int CACHE_OWNER_1 = LauncherApps.FLAG_CACHE_BUBBLE_SHORTCUTS;
+
     @Override
     protected void tearDown() throws Exception {
         deleteUriFile("file32x32.jpg");
@@ -487,7 +490,8 @@
         mManager.pushDynamicShortcut(s8);
         assertEquals(4, getCallerShortcut("s8").getRank());
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s8"), HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s8"), HANDLE_USER_0,
+                    CACHE_OWNER_0);
         });
 
         mManager.pushDynamicShortcut(s9);
@@ -1452,8 +1456,10 @@
 
         // Cache 1 and 2
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2"),
-                    HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1"),
+                    HANDLE_USER_0, CACHE_OWNER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"),
+                    HANDLE_USER_0, CACHE_OWNER_1);
         });
 
         setCaller(CALLING_PACKAGE_1);
@@ -1532,8 +1538,10 @@
 
         // Cache some, but non long lived shortcuts will be ignored.
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2", "s4"),
-                    HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2"),
+                    HANDLE_USER_0, CACHE_OWNER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2", "s4"),
+                    HANDLE_USER_0, CACHE_OWNER_1);
         });
 
         setCaller(CALLING_PACKAGE_1);
@@ -1555,10 +1563,18 @@
         assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
                 "s2", "s4");
 
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s2", "s4"),
+                    HANDLE_USER_0, CACHE_OWNER_0);
+        });
+        // s2 still cached by owner1. s4 wasn't cached by owner0 so didn't get removed.
+        assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
+                "s2", "s4");
+
         // uncache a non-dynamic shortcut. Should be removed.
         runWithCaller(LAUNCHER_1, USER_0, () -> {
             mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s4"),
-                    HANDLE_USER_0);
+                    HANDLE_USER_0, CACHE_OWNER_1);
         });
         assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
                 "s2");
@@ -1566,7 +1582,7 @@
         // Cache another shortcut
         runWithCaller(LAUNCHER_1, USER_0, () -> {
             mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s3"),
-                    HANDLE_USER_0);
+                    HANDLE_USER_0, CACHE_OWNER_0);
         });
         assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
                 "s2", "s3");
@@ -1594,7 +1610,7 @@
         // Cache All
         runWithCaller(LAUNCHER_1, USER_0, () -> {
             mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2", "s3", "s4"),
-                    HANDLE_USER_0);
+                    HANDLE_USER_0, CACHE_OWNER_0);
         });
 
         setCaller(CALLING_PACKAGE_1);
@@ -1792,8 +1808,10 @@
         setCaller(LAUNCHER_1);
 
         // Cache some shortcuts. Only long lived shortcuts can get cached.
-        mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1"), getCallingUser());
-        mLauncherApps.cacheShortcuts(CALLING_PACKAGE_3, list("s3"), getCallingUser());
+        mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1"), getCallingUser(),
+                CACHE_OWNER_0);
+        mLauncherApps.cacheShortcuts(CALLING_PACKAGE_3, list("s3"), getCallingUser(),
+                CACHE_OWNER_0);
 
         // Cached ones only
         assertShortcutIds(assertAllNotKeyFieldsOnly(
@@ -8732,7 +8750,8 @@
         assertTrue(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s3", USER_0,
                 filter_any));
 
-        mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2"), HANDLE_USER_0);
+        mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2"), HANDLE_USER_0,
+                CACHE_OWNER_0);
         mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
 
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
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 6219665..6a2b8e0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java
@@ -25,6 +25,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.ComponentName;
+import android.content.pm.LauncherApps;
 import android.content.pm.LauncherApps.ShortcutChangeCallback;
 import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.pm.ShortcutInfo;
@@ -46,6 +47,9 @@
     private static final ShortcutQuery QUERY_MATCH_ALL = createShortcutQuery(
             ShortcutQuery.FLAG_MATCH_ALL_KINDS_WITH_ALL_PINNED);
 
+    private static final int CACHE_OWNER_0 = LauncherApps.FLAG_CACHE_NOTIFICATION_SHORTCUTS;
+    private static final int CACHE_OWNER_1 = LauncherApps.FLAG_CACHE_BUBBLE_SHORTCUTS;
+
     private final TestLooper mTestLooper = new TestLooper();
 
     public void testShortcutChangeCallback_setDynamicShortcuts() {
@@ -113,7 +117,8 @@
 
         runWithCaller(LAUNCHER_1, USER_0, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_0);
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0,
+                    CACHE_OWNER_0);
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
@@ -211,7 +216,42 @@
         runWithCaller(LAUNCHER_1, USER_0, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_0,
+                    CACHE_OWNER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_0,
+                    CACHE_OWNER_1);
+        });
+
+        mTestLooper.dispatchAll();
+
+        ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
+        verify(callback, times(2)).onShortcutsAddedOrUpdated(
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+        verify(callback, times(0)).onShortcutsRemoved(any(), any(), any());
+
+        assertWith(shortcuts.getValue())
+                .areAllWithKeyFieldsOnly()
+                .haveIds("s1", "s3");
+    }
+
+    public void testShortcutChangeCallback_cacheShortcuts_alreadyCached() {
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(makeLongLivedShortcut("s1"),
+                    makeLongLivedShortcut("s2"), makeLongLivedShortcut("s3"))));
+        });
+
+        ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_0,
+                    CACHE_OWNER_0);
+            mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
+                    mTestLooper.getNewExecutor());
+            // Should not cause any callback events
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_0,
+                    CACHE_OWNER_0);
+            // Should cause a change event
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_0,
+                    CACHE_OWNER_1);
         });
 
         mTestLooper.dispatchAll();
@@ -234,10 +274,12 @@
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2"), HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2"), HANDLE_USER_0,
+                    CACHE_OWNER_0);
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
-            mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0);
+            mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0,
+                    CACHE_OWNER_0);
         });
 
         mTestLooper.dispatchAll();
@@ -259,8 +301,11 @@
         });
 
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2", "s3"), HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2", "s3"), HANDLE_USER_0,
+                    CACHE_OWNER_0);
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_0,
+                    CACHE_OWNER_1);
         });
 
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -271,7 +316,8 @@
         runWithCaller(LAUNCHER_1, USER_0, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
-            mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s2", "s3"), HANDLE_USER_0);
+            mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2", "s3"), HANDLE_USER_0,
+                    CACHE_OWNER_0);
         });
 
         mTestLooper.dispatchAll();
@@ -284,9 +330,10 @@
         verify(callback, times(1)).onShortcutsRemoved(
                 eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_0));
 
+        // s1 is still cached for owner1, s2 is pinned.
         assertWith(changedShortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
-                .haveIds("s2");
+                .haveIds("s1", "s2");
 
         assertWith(removedShortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
@@ -453,7 +500,8 @@
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0,
+                    CACHE_OWNER_0);
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
@@ -511,7 +559,8 @@
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0,
+                    CACHE_OWNER_0);
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
@@ -547,7 +596,8 @@
         });
 
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0,
+                    CACHE_OWNER_0);
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
         });
 
@@ -614,7 +664,8 @@
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0,
+                    CACHE_OWNER_0);
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
@@ -680,7 +731,8 @@
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0,
+                    CACHE_OWNER_0);
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
@@ -747,7 +799,8 @@
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0,
+                    CACHE_OWNER_0);
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java
index 38b71b7..13457f0 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java
@@ -26,6 +26,8 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 
 import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -166,6 +168,8 @@
         setUpBubblesEnabled(true /* feature */,
                 BUBBLE_PREFERENCE_ALL /* app */,
                 ALLOW_BUBBLE_OFF /* channel */);
+        when(mActivityManager.isLowRamDevice()).thenReturn(false);
+        setUpShortcutBubble(true /* isValid */);
         NotificationRecord r = getNotificationRecord(true /* bubble */);
         mBubbleExtractor.process(r);
 
@@ -178,6 +182,8 @@
         setUpBubblesEnabled(true /* feature */,
                 BUBBLE_PREFERENCE_ALL /* app */,
                 DEFAULT_ALLOW_BUBBLE /* channel */);
+        when(mActivityManager.isLowRamDevice()).thenReturn(false);
+        setUpShortcutBubble(true /* isValid */);
         NotificationRecord r = getNotificationRecord(true /* bubble */);
 
         mBubbleExtractor.process(r);
@@ -190,6 +196,8 @@
         setUpBubblesEnabled(true /* feature */,
                 BUBBLE_PREFERENCE_ALL /* app */,
                 ALLOW_BUBBLE_ON /* channel */);
+        when(mActivityManager.isLowRamDevice()).thenReturn(false);
+        setUpShortcutBubble(true /* isValid */);
         NotificationRecord r = getNotificationRecord(true /* bubble */);
 
         mBubbleExtractor.process(r);
@@ -202,6 +210,8 @@
         setUpBubblesEnabled(false /* feature */,
                 BUBBLE_PREFERENCE_ALL /* app */,
                 ALLOW_BUBBLE_ON /* channel */);
+        when(mActivityManager.isLowRamDevice()).thenReturn(false);
+        setUpShortcutBubble(true /* isValid */);
         NotificationRecord r = getNotificationRecord(true /* bubble */);
 
         mBubbleExtractor.process(r);
@@ -215,6 +225,8 @@
         setUpBubblesEnabled(true /* feature */,
                 BUBBLE_PREFERENCE_NONE /* app */,
                 ALLOW_BUBBLE_ON /* channel */);
+        when(mActivityManager.isLowRamDevice()).thenReturn(false);
+        setUpShortcutBubble(true /* isValid */);
         NotificationRecord r = getNotificationRecord(true /* bubble */);
 
         mBubbleExtractor.process(r);
@@ -228,6 +240,8 @@
         setUpBubblesEnabled(true /* feature */,
                 BUBBLE_PREFERENCE_NONE /* app */,
                 DEFAULT_ALLOW_BUBBLE /* channel */);
+        when(mActivityManager.isLowRamDevice()).thenReturn(false);
+        setUpShortcutBubble(true /* isValid */);
         NotificationRecord r = getNotificationRecord(true /* bubble */);
 
         mBubbleExtractor.process(r);
@@ -241,6 +255,8 @@
         setUpBubblesEnabled(true /* feature */,
                 BUBBLE_PREFERENCE_SELECTED /* app */,
                 DEFAULT_ALLOW_BUBBLE /* channel */);
+        when(mActivityManager.isLowRamDevice()).thenReturn(false);
+        setUpShortcutBubble(true /* isValid */);
         NotificationRecord r = getNotificationRecord(true /* bubble */);
 
         mBubbleExtractor.process(r);
@@ -254,6 +270,8 @@
         setUpBubblesEnabled(true /* feature */,
                 BUBBLE_PREFERENCE_SELECTED /* app */,
                 ALLOW_BUBBLE_OFF /* channel */);
+        when(mActivityManager.isLowRamDevice()).thenReturn(false);
+        setUpShortcutBubble(true /* isValid */);
         NotificationRecord r = getNotificationRecord(true /* bubble */);
 
         mBubbleExtractor.process(r);
@@ -267,6 +285,9 @@
         setUpBubblesEnabled(true /* feature */,
                 BUBBLE_PREFERENCE_SELECTED /* app */,
                 ALLOW_BUBBLE_ON /* channel */);
+        when(mActivityManager.isLowRamDevice()).thenReturn(false);
+        setUpShortcutBubble(true /* isValid */);
+
         NotificationRecord r = getNotificationRecord(true /* bubble */);
 
         mBubbleExtractor.process(r);
@@ -279,6 +300,9 @@
         setUpBubblesEnabled(false /* feature */,
                 BUBBLE_PREFERENCE_SELECTED /* app */,
                 ALLOW_BUBBLE_ON /* channel */);
+        when(mActivityManager.isLowRamDevice()).thenReturn(false);
+        setUpShortcutBubble(true /* isValid */);
+
         NotificationRecord r = getNotificationRecord(true /* bubble */);
 
         mBubbleExtractor.process(r);
@@ -305,6 +329,7 @@
         mBubbleExtractor.process(r);
 
         assertTrue(r.canBubble());
+        assertNotNull(r.getNotification().getBubbleMetadata());
         assertFalse(r.getNotification().isBubbleNotification());
     }
 
@@ -320,6 +345,7 @@
         mBubbleExtractor.process(r);
 
         assertTrue(r.canBubble());
+        assertNotNull(r.getNotification().getBubbleMetadata());
         assertTrue(r.getNotification().isBubbleNotification());
     }
 
@@ -335,6 +361,7 @@
         mBubbleExtractor.process(r);
 
         assertTrue(r.canBubble());
+        assertNotNull(r.getNotification().getBubbleMetadata());
         assertTrue(r.getNotification().isBubbleNotification());
     }
 
@@ -350,7 +377,8 @@
         r.setShortcutInfo(null);
         mBubbleExtractor.process(r);
 
-        assertTrue(r.canBubble());
+        assertFalse(r.canBubble());
+        assertNull(r.getNotification().getBubbleMetadata());
         assertFalse(r.getNotification().isBubbleNotification());
     }
 
@@ -366,7 +394,8 @@
         r.setShortcutInfo(null);
         mBubbleExtractor.process(r);
 
-        assertTrue(r.canBubble());
+        assertFalse(r.canBubble());
+        assertNull(r.getNotification().getBubbleMetadata());
         assertFalse(r.getNotification().isBubbleNotification());
     }
 
@@ -381,7 +410,8 @@
         NotificationRecord r = getNotificationRecord(true /* bubble */);
         mBubbleExtractor.process(r);
 
-        assertTrue(r.canBubble());
+        assertFalse(r.canBubble());
+        assertNull(r.getNotification().getBubbleMetadata());
         assertFalse(r.getNotification().isBubbleNotification());
     }
 
@@ -395,7 +425,8 @@
         NotificationRecord r = getNotificationRecord(false /* bubble */);
         mBubbleExtractor.process(r);
 
-        assertTrue(r.canBubble());
+        assertFalse(r.canBubble());
+        assertNull(r.getNotification().getBubbleMetadata());
         assertFalse(r.getNotification().isBubbleNotification());
     }
 
@@ -414,7 +445,8 @@
 
         mBubbleExtractor.process(r);
 
-        assertTrue(r.canBubble());
+        assertFalse(r.canBubble());
+        assertNull(r.getNotification().getBubbleMetadata());
         assertFalse(r.getNotification().isBubbleNotification());
     }
 
@@ -429,7 +461,8 @@
         NotificationRecord r = getNotificationRecord(true /* bubble */);
         mBubbleExtractor.process(r);
 
-        assertTrue(r.canBubble());
+        assertFalse(r.canBubble());
+        assertNull(r.getNotification().getBubbleMetadata());
         assertFalse(r.getNotification().isBubbleNotification());
     }
 
@@ -445,7 +478,8 @@
         NotificationRecord r = getNotificationRecord(true /* bubble */);
         mBubbleExtractor.process(r);
 
-        assertTrue(r.canBubble());
+        assertFalse(r.canBubble());
+        assertNull(r.getNotification().getBubbleMetadata());
         assertFalse(r.getNotification().isBubbleNotification());
     }
 
@@ -462,7 +496,8 @@
         NotificationRecord r = getNotificationRecord(true /* bubble */);
         mBubbleExtractor.process(r);
 
-        assertTrue(r.canBubble());
+        assertFalse(r.canBubble());
+        assertNull(r.getNotification().getBubbleMetadata());
         assertFalse(r.getNotification().isBubbleNotification());
     }
 }
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 ced7804..cf63682 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -6135,8 +6135,6 @@
                 "tag", mUid, 0, nb.build(), new UserHandle(mUid), null, 0);
         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
 
-
-
         // Test: Send the bubble notification
         mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
                 nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
@@ -6154,7 +6152,7 @@
         // Make sure the shortcut is cached.
         verify(mShortcutServiceInternal).cacheShortcuts(
                 anyInt(), any(), eq(PKG), eq(Collections.singletonList(VALID_CONVO_SHORTCUT_ID)),
-                eq(USER_SYSTEM));
+                eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
 
         // Test: Remove the shortcut
         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
@@ -6168,12 +6166,12 @@
         verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
 
         // We're no longer a bubble
-        Notification notif2 = mService.getNotificationRecord(
-                nr.getSbn().getKey()).getNotification();
-        assertFalse(notif2.isBubbleNotification());
+        NotificationRecord notif2 = mService.getNotificationRecord(
+                nr.getSbn().getKey());
+        assertNull(notif2.getShortcutInfo());
+        assertFalse(notif2.getNotification().isBubbleNotification());
     }
 
-
     @Test
     public void testNotificationBubbles_shortcut_stopListeningWhenNotifRemoved()
             throws RemoteException {
@@ -6227,7 +6225,7 @@
         // Make sure the shortcut is cached.
         verify(mShortcutServiceInternal).cacheShortcuts(
                 anyInt(), any(), eq(PKG), eq(Collections.singletonList(shortcutId)),
-                eq(USER_SYSTEM));
+                eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
 
         // Test: Remove the notification
         mBinderService.cancelNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
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 6df3c7b..976f408 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
@@ -1191,4 +1191,56 @@
 
         assertFalse(record.isConversation());
     }
+
+    @Test
+    public void isConversation_pkgAllowed_isMsgType() {
+        StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, null /* group */);
+        sbn.getNotification().category = Notification.CATEGORY_MESSAGE;
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+
+        record.setPkgAllowedAsConvo(true);
+
+        assertTrue(record.isConversation());
+    }
+
+    @Test
+    public void isConversation_pkgAllowed_isMNotsgType() {
+        StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, null /* group */);
+        sbn.getNotification().category = Notification.CATEGORY_ALARM;
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+
+        record.setPkgAllowedAsConvo(true);
+
+        assertFalse(record.isConversation());
+    }
+
+    @Test
+    public void isConversation_pkgNotAllowed_isMsgType() {
+        StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, null /* group */);
+        sbn.getNotification().category = Notification.CATEGORY_MESSAGE;
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+
+        record.setPkgAllowedAsConvo(false);
+
+        assertFalse(record.isConversation());
+    }
+
+    @Test
+    public void isConversation_pkgAllowed_isMsgType_targetsR() {
+        StatusBarNotification sbn = getNotification(PKG_R, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, null /* group */);
+        sbn.getNotification().category = Notification.CATEGORY_MESSAGE;
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+
+        record.setPkgAllowedAsConvo(true);
+
+        assertFalse(record.isConversation());
+    }
 }
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 078c21e..1d6f823 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -31,6 +31,7 @@
 
 import static com.android.server.notification.PreferencesHelper.DEFAULT_BUBBLE_PREFERENCE;
 import static com.android.server.notification.PreferencesHelper.NOTIFICATION_CHANNEL_COUNT_LIMIT;
+import static com.android.server.notification.PreferencesHelper.UNKNOWN_UID;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -2511,6 +2512,26 @@
     }
 
     @Test
+    public void testBubblePrefence_noSAWCheckForUnknownUid() throws Exception {
+        final String xml = "<ranking version=\"1\">\n"
+                + "<package name=\"" + PKG_O + "\" uid=\"" + UNKNOWN_UID + "\">\n"
+                + "<channel id=\"someId\" name=\"hi\""
+                + " importance=\"3\"/>"
+                + "</package>"
+                + "</ranking>";
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())),
+                null);
+        parser.nextTag();
+        mHelper.readXml(parser, false, UserHandle.USER_ALL);
+
+        assertEquals(DEFAULT_BUBBLE_PREFERENCE, mHelper.getBubblePreference(PKG_O, UID_O));
+        assertEquals(0, mHelper.getAppLockedFields(PKG_O, UID_O));
+        verify(mAppOpsManager, never()).noteOpNoThrow(eq(OP_SYSTEM_ALERT_WINDOW), anyInt(),
+                anyString(), eq(null), anyString());
+    }
+
+    @Test
     public void testBubblePreference_xml() throws Exception {
         mHelper.setBubblesAllowed(PKG_O, UID_O, BUBBLE_PREFERENCE_NONE);
         assertEquals(mHelper.getBubblePreference(PKG_O, UID_O), BUBBLE_PREFERENCE_NONE);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java
index eb2d9fe..c700a09 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ShortcutHelperTest.java
@@ -48,6 +48,7 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 @SmallTest
@@ -73,6 +74,8 @@
     StatusBarNotification mSbn;
     @Mock
     Notification.BubbleMetadata mBubbleMetadata;
+    @Mock
+    ShortcutInfo mShortcutInfo;
 
     ShortcutHelper mShortcutHelper;
 
@@ -86,13 +89,13 @@
         when(mNr.getSbn()).thenReturn(mSbn);
         when(mSbn.getPackageName()).thenReturn(PKG);
         when(mNr.getNotification()).thenReturn(mNotif);
+        when(mNr.getShortcutInfo()).thenReturn(mShortcutInfo);
+        when(mShortcutInfo.getId()).thenReturn(SHORTCUT_ID);
         when(mNotif.getBubbleMetadata()).thenReturn(mBubbleMetadata);
         when(mBubbleMetadata.getShortcutId()).thenReturn(SHORTCUT_ID);
     }
 
     private LauncherApps.Callback addShortcutBubbleAndVerifyListener() {
-        when(mNotif.isBubbleNotification()).thenReturn(true);
-
         mShortcutHelper.maybeListenForShortcutChangesForBubbles(mNr,
                 false /* removed */,
                 null /* handler */);
@@ -124,12 +127,12 @@
     }
 
     @Test
-    public void testBubbleNoLongerBubble_listenerRemoved() {
+    public void testBubbleNoLongerHasBubbleMetadata_listenerRemoved() {
         // First set it up to listen
         addShortcutBubbleAndVerifyListener();
 
         // Then make it not a bubble
-        when(mNotif.isBubbleNotification()).thenReturn(false);
+        when(mNotif.getBubbleMetadata()).thenReturn(null);
         mShortcutHelper.maybeListenForShortcutChangesForBubbles(mNr,
                 false /* removed */,
                 null /* handler */);
@@ -138,6 +141,45 @@
     }
 
     @Test
+    public void testBubbleNoLongerHasShortcutId_listenerRemoved() {
+        // First set it up to listen
+        addShortcutBubbleAndVerifyListener();
+
+        // Clear out shortcutId
+        when(mBubbleMetadata.getShortcutId()).thenReturn(null);
+        mShortcutHelper.maybeListenForShortcutChangesForBubbles(mNr,
+                false /* removed */,
+                null /* handler */);
+
+        verify(mLauncherApps, times(1)).unregisterCallback(any());
+    }
+
+    @Test
+    public void testNotifNoLongerHasShortcut_listenerRemoved() {
+        // First set it up to listen
+        addShortcutBubbleAndVerifyListener();
+
+        // Clear out shortcutId
+        when(mNr.getShortcutInfo()).thenReturn(null);
+        mShortcutHelper.maybeListenForShortcutChangesForBubbles(mNr,
+                false /* removed */,
+                null /* handler */);
+
+        verify(mLauncherApps, times(1)).unregisterCallback(any());
+    }
+
+    @Test
+    public void testOnShortcutsChanged_listenerRemoved() {
+        // First set it up to listen
+        LauncherApps.Callback callback = addShortcutBubbleAndVerifyListener();
+
+        // App shortcuts are removed:
+        callback.onShortcutsChanged(PKG, Collections.emptyList(),  mock(UserHandle.class));
+
+        verify(mLauncherApps, times(1)).unregisterCallback(any());
+    }
+
+    @Test
     public void testListenerNotifiedOnShortcutRemoved() {
         LauncherApps.Callback callback = addShortcutBubbleAndVerifyListener();
 
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 063568d..4f14cd0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1412,7 +1412,7 @@
 
         // The launching rotated app should not be cleared when waiting for remote rotation.
         display.continueUpdateOrientationForDiffOrienLaunchingApp();
-        assertNotNull(display.getFixedRotationLaunchingApp());
+        assertTrue(display.isFixedRotationLaunchingApp(mActivity));
 
         // Simulate the rotation has been updated to previous one, e.g. sensor updates before the
         // remote rotation is completed.
@@ -1441,7 +1441,7 @@
         display.setFixedRotationLaunchingAppUnchecked(mActivity);
         display.sendNewConfiguration();
 
-        assertNull(display.getFixedRotationLaunchingApp());
+        assertFalse(display.hasTopFixedRotationLaunchingApp());
         assertFalse(mActivity.hasFixedRotationTransform());
     }
 
@@ -1497,7 +1497,7 @@
         // 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());
+        assertTrue(mActivity.mDisplayContent.isFixedRotationLaunchingApp(mActivity));
     }
 
     /**
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 07050d9..36d4888 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -35,6 +35,7 @@
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
+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.mock;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
@@ -47,6 +48,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
@@ -390,6 +392,46 @@
                 onAnimationFinishedCallback));
     }
 
+    @Test
+    public void testTransferStartingWindowFromFinishingActivity() {
+        mActivity.addStartingWindow(mPackageName, android.R.style.Theme, null /* compatInfo */,
+                "Test", 0 /* labelRes */, 0 /* icon */, 0 /* logo */, 0 /* windowFlags */,
+                null /* transferFrom */, true /* newTask */, true /* taskSwitch */,
+                false /* processRunning */, false /* allowTaskSnapshot */,
+                false /* activityCreate */);
+        waitUntilHandlersIdle();
+        assertHasStartingWindow(mActivity);
+        mActivity.mStartingWindowState = ActivityRecord.STARTING_WINDOW_SHOWN;
+
+        doCallRealMethod().when(mStack).startActivityLocked(
+                any(), any(), anyBoolean(), anyBoolean(), any());
+        // Make mVisibleSetFromTransferredStartingWindow true.
+        final ActivityRecord middle = new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
+                .setTask(mTask).build();
+        mStack.startActivityLocked(middle, null /* focusedTopActivity */,
+                false /* newTask */, false /* keepCurTransition */, null /* options */);
+        middle.makeFinishingLocked();
+
+        assertNull(mActivity.startingWindow);
+        assertHasStartingWindow(middle);
+
+        final ActivityRecord top = new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
+                .setTask(mTask).build();
+        // Expect the visibility should be updated to true when transferring starting window from
+        // a visible activity.
+        top.setVisible(false);
+        // The finishing middle should be able to transfer starting window to top.
+        mStack.startActivityLocked(top, null /* focusedTopActivity */,
+                false /* newTask */, false /* keepCurTransition */, null /* options */);
+
+        assertNull(middle.startingWindow);
+        assertHasStartingWindow(top);
+        assertTrue(top.isVisible());
+        // The activity was visible by mVisibleSetFromTransferredStartingWindow, so after its
+        // starting window is transferred, it should restore to invisible.
+        assertFalse(middle.isVisible());
+    }
+
     private ActivityRecord createIsolatedTestActivityRecord() {
         final ActivityStack taskStack = createTaskStackOnDisplay(mDisplayContent);
         final Task task = createTaskInStack(taskStack, 0 /* userId */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 4e82ceb..7be2b73 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -57,6 +57,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_FIXED_TRANSFORM;
 import static com.android.server.wm.WindowContainer.POSITION_TOP;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
 
@@ -1060,6 +1061,11 @@
     @Test
     public void testApplyTopFixedRotationTransform() {
         mWm.mIsFixedRotationTransformEnabled = true;
+        final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
+        // Only non-movable (gesture) navigation bar will be animated by fixed rotation animation.
+        doReturn(false).when(displayPolicy).navigationBarCanMove();
+        displayPolicy.addWindowLw(mStatusBarWindow, mStatusBarWindow.mAttrs);
+        displayPolicy.addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs);
         final Configuration config90 = new Configuration();
         mDisplayContent.computeScreenConfiguration(config90, ROTATION_90);
 
@@ -1080,6 +1086,12 @@
                 ROTATION_0 /* oldRotation */, ROTATION_90 /* newRotation */,
                 false /* forceUpdate */));
 
+        assertNotNull(mDisplayContent.getFixedRotationAnimationController());
+        assertTrue(mStatusBarWindow.getParent().isAnimating(WindowContainer.AnimationFlags.PARENTS,
+                ANIMATION_TYPE_FIXED_TRANSFORM));
+        assertTrue(mNavBarWindow.getParent().isAnimating(WindowContainer.AnimationFlags.PARENTS,
+                ANIMATION_TYPE_FIXED_TRANSFORM));
+
         final Rect outFrame = new Rect();
         final Rect outInsets = new Rect();
         final Rect outStableInsets = new Rect();
@@ -1132,6 +1144,25 @@
         assertFalse(app.hasFixedRotationTransform());
         assertFalse(app2.hasFixedRotationTransform());
         assertEquals(config90.orientation, mDisplayContent.getConfiguration().orientation);
+        assertNull(mDisplayContent.getFixedRotationAnimationController());
+    }
+
+    @Test
+    public void testRotateSeamlesslyWithFixedRotation() {
+        final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
+        final ActivityRecord app = mAppWindow.mActivityRecord;
+        mDisplayContent.setFixedRotationLaunchingAppUnchecked(app);
+        mAppWindow.mAttrs.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
+
+        // Use seamless rotation if the top app is rotated.
+        assertTrue(displayRotation.shouldRotateSeamlessly(ROTATION_0 /* oldRotation */,
+                ROTATION_90 /* newRotation */, false /* forceUpdate */));
+
+        mDisplayContent.mFixedRotationTransitionListener.onStartRecentsAnimation(app);
+
+        // Use normal rotation because animating recents is an intermediate state.
+        assertFalse(displayRotation.shouldRotateSeamlessly(ROTATION_0 /* oldRotation */,
+                ROTATION_90 /* newRotation */, false /* forceUpdate */));
     }
 
     @Test
@@ -1310,7 +1341,7 @@
     }
 
     private static int getRotatedOrientation(DisplayContent dc) {
-        return dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
+        return dc.mBaseDisplayWidth > dc.mBaseDisplayHeight
                 ? SCREEN_ORIENTATION_PORTRAIT
                 : SCREEN_ORIENTATION_LANDSCAPE;
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java
new file mode 100644
index 0000000..ca739c0
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java
@@ -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.server.wm;
+
+import static android.view.InsetsState.ITYPE_IME;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+
+import static org.junit.Assert.assertTrue;
+
+import android.graphics.PixelFormat;
+import android.platform.test.annotations.Presubmit;
+import android.view.InsetsSource;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@Presubmit
+@RunWith(WindowTestRunner.class)
+public class ImeInsetsSourceProviderTest extends WindowTestsBase {
+
+    private InsetsSource mImeSource = new InsetsSource(ITYPE_IME);
+    private ImeInsetsSourceProvider mImeProvider;
+
+    @Before
+    public void setUp() throws Exception {
+        mImeSource.setVisible(true);
+        mImeProvider = new ImeInsetsSourceProvider(mImeSource,
+                mDisplayContent.getInsetsStateController(), mDisplayContent);
+    }
+
+    @Test
+    public void testTransparentControlTargetWindowCanShowIme() {
+        final WindowState appWin = createWindow(null, TYPE_APPLICATION, "app");
+        final WindowState popup = createWindow(appWin, TYPE_APPLICATION, "popup");
+        mDisplayContent.mInputMethodControlTarget = popup;
+        mDisplayContent.mInputMethodTarget = appWin;
+        popup.mAttrs.format = PixelFormat.TRANSPARENT;
+        mImeProvider.scheduleShowImePostLayout(appWin);
+        assertTrue(mImeProvider.isImeTargetFromDisplayContentAndImeSame());
+    }
+}
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 f330f0f..ca6679d 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.getFixedRotationLaunchingApp());
+        assertTrue(mDefaultDisplay.isFixedRotationLaunchingApp(homeActivity));
 
         // 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.getFixedRotationLaunchingApp());
+        assertFalse(mDefaultDisplay.hasTopFixedRotationLaunchingApp());
     }
 
     @Test
@@ -367,7 +367,7 @@
                 (mDefaultDisplay.getRotation() + 1) % 4);
 
         assertTrue(activity.hasFixedRotationTransform());
-        assertEquals(activity, mDefaultDisplay.getFixedRotationLaunchingApp());
+        assertTrue(mDefaultDisplay.isFixedRotationLaunchingApp(activity));
 
         // 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.getFixedRotationLaunchingApp());
+        assertFalse(mDefaultDisplay.hasTopFixedRotationLaunchingApp());
     }
 
     @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.getFixedRotationLaunchingApp());
+        assertTrue(mDefaultDisplay.isFixedRotationLaunchingApp(homeActivity));
 
         mDefaultDisplay.mFixedRotationTransitionListener.onAppTransitionFinishedLocked(
                 homeActivity.token);
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 8ce5daa..e9ed20b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -603,6 +603,29 @@
     }
 
     @Test
+    public void testRequestResizeForBlastSync() {
+        final WindowState win = mChildAppWindowAbove;
+        makeWindowVisible(win, win.getParentWindow());
+        win.mLayoutSeq = win.getDisplayContent().mLayoutSeq;
+        win.reportResized();
+        win.updateResizingWindowIfNeeded();
+        assertThat(mWm.mResizingWindows).doesNotContain(win);
+
+        // Check that the window is in resizing if using blast sync.
+        win.reportResized();
+        win.prepareForSync(mock(BLASTSyncEngine.TransactionReadyListener.class), 1);
+        win.updateResizingWindowIfNeeded();
+        assertThat(mWm.mResizingWindows).contains(win);
+
+        // Don't re-add the window again if it's been reported to the client and still waiting on
+        // the client draw for blast sync.
+        win.reportResized();
+        mWm.mResizingWindows.remove(win);
+        win.updateResizingWindowIfNeeded();
+        assertThat(mWm.mResizingWindows).doesNotContain(win);
+    }
+
+    @Test
     public void testGetTransformationMatrix() {
         final int PARENT_WINDOW_OFFSET = 1;
         final int DISPLAY_IN_PARENT_WINDOW_OFFSET = 2;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index ef282ba..cf07221 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -56,6 +56,8 @@
 import android.os.RemoteCallback;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
@@ -1391,6 +1393,13 @@
         }
 
         @Override
+        public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+                String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+            new VoiceInteractionManagerServiceShellCommand(mServiceStub)
+                    .exec(this, in, out, err, args, callback, resultReceiver);
+        }
+
+        @Override
         public void setUiHints(Bundle hints) {
             synchronized (this) {
                 enforceIsCurrentVoiceInteractionService();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java
new file mode 100644
index 0000000..3f4ddb6
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java
@@ -0,0 +1,135 @@
+/*
+ * 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.voiceinteraction;
+
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+import android.util.Slog;
+
+import com.android.internal.app.IVoiceInteractionSessionShowCallback;
+import com.android.server.voiceinteraction.VoiceInteractionManagerService.VoiceInteractionManagerServiceStub;
+
+import java.io.PrintWriter;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Shell command for {@link VoiceInteractionManagerService}.
+ */
+final class VoiceInteractionManagerServiceShellCommand extends ShellCommand {
+    private static final String TAG = "VoiceInteractionManager";
+    private static final long TIMEOUT_MS = 5_000;
+
+    private final VoiceInteractionManagerServiceStub mService;
+
+    VoiceInteractionManagerServiceShellCommand(VoiceInteractionManagerServiceStub service) {
+        mService = service;
+    }
+
+    @Override
+    public int onCommand(String cmd) {
+        if (cmd == null) {
+            return handleDefaultCommands(cmd);
+        }
+        PrintWriter pw = getOutPrintWriter();
+        switch (cmd) {
+            case "show":
+                return requestShow(pw);
+            case "hide":
+                return requestHide(pw);
+            default:
+                return handleDefaultCommands(cmd);
+        }
+    }
+
+    @Override
+    public void onHelp() {
+        try (PrintWriter pw = getOutPrintWriter();) {
+            pw.println("VoiceInteraction Service (voiceinteraction) commands:");
+            pw.println("  help");
+            pw.println("    Prints this help text.");
+            pw.println("");
+            pw.println("  show");
+            pw.println("    Shows a session for the active service");
+            pw.println("");
+            pw.println("  hide");
+            pw.println("    Hides the current session");
+            pw.println("");
+        }
+    }
+
+    private int requestShow(PrintWriter pw) {
+        Slog.i(TAG, "requestShow()");
+        CountDownLatch latch = new CountDownLatch(1);
+        AtomicInteger result = new AtomicInteger();
+
+        IVoiceInteractionSessionShowCallback callback =
+                new IVoiceInteractionSessionShowCallback.Stub() {
+            @Override
+            public void onFailed() throws RemoteException {
+                Slog.w(TAG, "onFailed()");
+                pw.println("callback failed");
+                result.set(1);
+                latch.countDown();
+            }
+
+            @Override
+            public void onShown() throws RemoteException {
+                Slog.d(TAG, "onShown()");
+                result.set(0);
+                latch.countDown();
+            }
+        };
+
+        try {
+            Bundle args = new Bundle();
+            boolean ok = mService.showSessionForActiveService(args, /* sourceFlags= */ 0, callback,
+                    /* activityToken= */ null);
+
+            if (!ok) {
+                pw.println("showSessionForActiveService() returned false");
+                return 1;
+            }
+
+            if (!latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                pw.printf("Callback not called in %d ms\n", TIMEOUT_MS);
+                return 1;
+            }
+        } catch (Exception e) {
+            return handleError(pw, "showSessionForActiveService()", e);
+        }
+
+        return 0;
+    }
+
+    private int requestHide(PrintWriter pw) {
+        Slog.i(TAG, "requestHide()");
+        try {
+            mService.hideCurrentSession();
+        } catch (Exception e) {
+            return handleError(pw, "requestHide()", e);
+        }
+        return 0;
+    }
+
+    private static int handleError(PrintWriter pw, String message, Exception e) {
+        Slog.e(TAG,  "error calling " + message, e);
+        pw.printf("Error calling %s: %s\n", message, e);
+        return 1;
+    }
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index f5ed64e..fadebaa 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -12716,7 +12716,6 @@
             @Nullable String mvnoMatchData) {
         try {
             if (!mccmnc.equals(getSimOperator())) {
-                Log.d(TAG, "The mccmnc does not match");
                 return false;
             }
             ITelephony service = getITelephony();
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 43db1d9ce..f6c14e6 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -518,9 +518,6 @@
      * @param executor The executor the callback events should be run on.
      * @param c The MmTel {@link CapabilityCallback} to be registered.
      * @see #unregisterMmTelCapabilityCallback(CapabilityCallback)
-     * @throws IllegalArgumentException if the subscription associated with this callback is not
-     * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or
-     * {@link CapabilityCallback} callback.
      * @throws ImsException if the subscription associated with this callback is valid, but
      * the {@link ImsService} associated with the subscription is not available. This can happen if
      * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
@@ -543,18 +540,13 @@
         ITelephony iTelephony = getITelephony();
         if (iTelephony == null) {
             throw new ImsException("Could not find Telephony Service.",
-                    ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
+                    ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
 
         try {
             iTelephony.registerMmTelCapabilityCallback(mSubId, c.getBinder());
         } catch (ServiceSpecificException e) {
-            if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
-                // Rethrow as runtime error to keep API compatible.
-                throw new IllegalArgumentException(e.getMessage());
-            } else {
-                throw new ImsException(e.getMessage(), e.errorCode);
-            }
+            throw new ImsException(e.getMessage(), e.errorCode);
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }  catch (IllegalStateException e) {
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 7d750b7..1a58f17 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -115,7 +115,7 @@
     private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 3000; // 3s between launching apps
     private static final int PROFILE_SAVE_SLEEP_TIMEOUT = 1000; // Allow 1s for the profile to save
     private static final int IORAP_TRACE_DURATION_TIMEOUT = 7000; // Allow 7s for trace to complete.
-    private static final int IORAP_TRIAL_LAUNCH_ITERATIONS = 3;  // min 3 launches to merge traces.
+    private static final int IORAP_TRIAL_LAUNCH_ITERATIONS = 5;  // min 5 launches to merge traces.
     private static final int IORAP_COMPILE_CMD_TIMEOUT = 60;  // in seconds: 1 minutes
     private static final int IORAP_COMPILE_MIN_TRACES = 1;  // configure iorapd to need 1 trace.
     private static final int IORAP_COMPILE_RETRIES = 3;  // retry compiler 3 times if it fails.
diff --git a/tests/BlobStoreTestUtils/Android.bp b/tests/BlobStoreTestUtils/Android.bp
index 829c883..53d3638 100644
--- a/tests/BlobStoreTestUtils/Android.bp
+++ b/tests/BlobStoreTestUtils/Android.bp
@@ -15,6 +15,10 @@
 java_library {
   name: "BlobStoreTestUtils",
   srcs: ["src/**/*.java"],
-  static_libs: ["truth-prebuilt"],
+  static_libs: [
+    "truth-prebuilt",
+    "androidx.test.uiautomator_uiautomator",
+    "androidx.test.ext.junit",
+  ],
   sdk_version: "test_current",
 }
\ No newline at end of file
diff --git a/tests/BlobStoreTestUtils/src/com/android/utils/blob/DummyBlobData.java b/tests/BlobStoreTestUtils/src/com/android/utils/blob/DummyBlobData.java
index 371375c..4a0ca66 100644
--- a/tests/BlobStoreTestUtils/src/com/android/utils/blob/DummyBlobData.java
+++ b/tests/BlobStoreTestUtils/src/com/android/utils/blob/DummyBlobData.java
@@ -42,6 +42,7 @@
     private final File mFile;
     private final long mFileSize;
     private final CharSequence mLabel;
+    private final long mExpiryDurationMs;
 
     byte[] mFileDigest;
     long mExpiryTimeMs;
@@ -51,6 +52,7 @@
         mFile = new File(builder.getContext().getFilesDir(), builder.getFileName());
         mFileSize = builder.getFileSize();
         mLabel = builder.getLabel();
+        mExpiryDurationMs = builder.getExpiryDurationMs();
     }
 
     public static class Builder {
@@ -59,6 +61,7 @@
         private long mFileSize = DEFAULT_SIZE_BYTES;
         private CharSequence mLabel = "Test label";
         private String mFileName = "blob_" + System.nanoTime();
+        private long mExpiryDurationMs = TimeUnit.DAYS.toMillis(1);
 
         public Builder(Context context) {
             mContext = context;
@@ -104,6 +107,15 @@
             return mFileName;
         }
 
+        public Builder setExpiryDurationMs(long durationMs) {
+            mExpiryDurationMs = durationMs;
+            return this;
+        }
+
+        public long getExpiryDurationMs() {
+            return mExpiryDurationMs;
+        }
+
         public DummyBlobData build() {
             return new DummyBlobData(this);
         }
@@ -114,7 +126,7 @@
             writeRandomData(file, mFileSize);
         }
         mFileDigest = FileUtils.digest(mFile, "SHA-256");
-        mExpiryTimeMs = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1);
+        mExpiryTimeMs = System.currentTimeMillis() + mExpiryDurationMs;
     }
 
     public BlobHandle getBlobHandle() throws Exception {
diff --git a/tests/BlobStoreTestUtils/src/com/android/utils/blob/Utils.java b/tests/BlobStoreTestUtils/src/com/android/utils/blob/Utils.java
index 6927e86..b9bd661 100644
--- a/tests/BlobStoreTestUtils/src/com/android/utils/blob/Utils.java
+++ b/tests/BlobStoreTestUtils/src/com/android/utils/blob/Utils.java
@@ -24,6 +24,10 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
 
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -32,6 +36,8 @@
 import java.io.OutputStream;
 
 public class Utils {
+    public static final String TAG = "BlobStoreTest";
+
     public static final int BUFFER_SIZE_BYTES = 16 * 1024;
 
     public static final long KB_IN_BYTES = 1000;
@@ -68,7 +74,8 @@
 
     public static void assertLeasedBlobs(BlobStoreManager blobStoreManager,
             BlobHandle... expectedBlobHandles) throws IOException {
-        assertThat(blobStoreManager.getLeasedBlobs()).containsExactly(expectedBlobHandles);
+        assertThat(blobStoreManager.getLeasedBlobs()).containsExactly(
+                (Object[]) expectedBlobHandles);
     }
 
     public static void assertNoLeasedBlobs(BlobStoreManager blobStoreManager)
@@ -141,4 +148,16 @@
         assertThat(leaseInfo.getDescriptionResId()).isEqualTo(descriptionResId);
         assertThat(leaseInfo.getDescription()).isEqualTo(description);
     }
+
+    public static void triggerIdleMaintenance() throws IOException {
+        runShellCmd("cmd blob_store idle-maintenance");
+    }
+
+    public static String runShellCmd(String cmd) throws IOException {
+        final UiDevice uiDevice = UiDevice.getInstance(
+                InstrumentationRegistry.getInstrumentation());
+        final String result = uiDevice.executeShellCommand(cmd).trim();
+        Log.i(TAG, "Output of '" + cmd + "': '" + result + "'");
+        return result;
+    }
 }
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index d011dbb..ae93a81 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -1113,6 +1113,7 @@
         mTestLooper.dispatchAll();
 
         List<Set> expectedSyncRequests = List.of(
+                Set.of(),
                 Set.of(APP_A),
                 Set.of(APP_A, APP_B),
                 Set.of(APP_A, APP_B, APP_C),
diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
index 98f705f..735fa7c 100644
--- a/tests/net/java/android/net/NetworkStatsTest.java
+++ b/tests/net/java/android/net/NetworkStatsTest.java
@@ -909,8 +909,8 @@
                 13805 /* txPackets */,
                 0 /* operations */);
 
-        // Traffic measured for the root uid on the base interface if eBPF is in use.
-        final NetworkStats.Entry ebpfRootUidEntry = new NetworkStats.Entry(
+        // Traffic measured for the root uid on the base interface.
+        final NetworkStats.Entry rootUidEntry = new NetworkStats.Entry(
                 baseIface, rootUid, SET_DEFAULT, TAG_NONE,
                 163577 /* rxBytes */,
                 187 /* rxPackets */,
@@ -918,17 +918,6 @@
                 97 /* txPackets */,
                 0 /* operations */);
 
-        // Traffic measured for the root uid on the base interface if xt_qtaguid is in use.
-        // Incorrectly includes appEntry's bytes and packets, plus IPv4-IPv6 translation
-        // overhead (20 bytes per packet), in rx direction.
-        final NetworkStats.Entry xtRootUidEntry = new NetworkStats.Entry(
-                baseIface, rootUid, SET_DEFAULT, TAG_NONE,
-                31113087 /* rxBytes */,
-                22588 /* rxPackets */,
-                17607 /* txBytes */,
-                97 /* txPackets */,
-                0 /* operations */);
-
         final NetworkStats.Entry otherEntry = new NetworkStats.Entry(
                 otherIface, appUid, SET_DEFAULT, TAG_NONE,
                 2600  /* rxBytes */,
@@ -937,21 +926,14 @@
                 3 /* txPackets */,
                 0 /* operations */);
 
-        final NetworkStats statsXt = new NetworkStats(TEST_START, 3)
+        final NetworkStats stats = new NetworkStats(TEST_START, 3)
                 .insertEntry(appEntry)
-                .insertEntry(xtRootUidEntry)
+                .insertEntry(rootUidEntry)
                 .insertEntry(otherEntry);
 
-        final NetworkStats statsEbpf = new NetworkStats(TEST_START, 3)
-                .insertEntry(appEntry)
-                .insertEntry(ebpfRootUidEntry)
-                .insertEntry(otherEntry);
+        stats.apply464xlatAdjustments(stackedIface);
 
-        statsXt.apply464xlatAdjustments(stackedIface, false);
-        statsEbpf.apply464xlatAdjustments(stackedIface, true);
-
-        assertEquals(3, statsXt.size());
-        assertEquals(3, statsEbpf.size());
+        assertEquals(3, stats.size());
         final NetworkStats.Entry expectedAppUid = new NetworkStats.Entry(
                 v4Iface, appUid, SET_DEFAULT, TAG_NONE,
                 30949510,
@@ -966,12 +948,9 @@
                 17607,
                 97,
                 0);
-        assertEquals(expectedAppUid, statsXt.getValues(0, null));
-        assertEquals(expectedRootUid, statsXt.getValues(1, null));
-        assertEquals(otherEntry, statsXt.getValues(2, null));
-        assertEquals(expectedAppUid, statsEbpf.getValues(0, null));
-        assertEquals(expectedRootUid, statsEbpf.getValues(1, null));
-        assertEquals(otherEntry, statsEbpf.getValues(2, null));
+        assertEquals(expectedAppUid, stats.getValues(0, null));
+        assertEquals(expectedRootUid, stats.getValues(1, null));
+        assertEquals(otherEntry, stats.getValues(2, null));
     }
 
     @Test
@@ -996,7 +975,7 @@
                 .insertEntry(secondEntry);
 
         // Empty map: no adjustment
-        stats.apply464xlatAdjustments(new ArrayMap<>(), false);
+        stats.apply464xlatAdjustments(new ArrayMap<>());
 
         assertEquals(2, stats.size());
         assertEquals(firstEntry, stats.getValues(0, null));
diff --git a/tests/net/java/com/android/internal/net/VpnProfileTest.java b/tests/net/java/com/android/internal/net/VpnProfileTest.java
index ceca6f0..e5daa71 100644
--- a/tests/net/java/com/android/internal/net/VpnProfileTest.java
+++ b/tests/net/java/com/android/internal/net/VpnProfileTest.java
@@ -33,7 +33,9 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 
 /** Unit tests for {@link VpnProfile}. */
 @SmallTest
@@ -41,6 +43,9 @@
 public class VpnProfileTest {
     private static final String DUMMY_PROFILE_KEY = "Test";
 
+    private static final int ENCODED_INDEX_AUTH_PARAMS_INLINE = 23;
+    private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24;
+
     @Test
     public void testDefaults() throws Exception {
         final VpnProfile p = new VpnProfile(DUMMY_PROFILE_KEY);
@@ -67,10 +72,11 @@
         assertFalse(p.isMetered);
         assertEquals(1360, p.maxMtu);
         assertFalse(p.areAuthParamsInline);
+        assertFalse(p.isRestrictedToTestNetworks);
     }
 
     private VpnProfile getSampleIkev2Profile(String key) {
-        final VpnProfile p = new VpnProfile(key);
+        final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */);
 
         p.name = "foo";
         p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
@@ -116,7 +122,7 @@
 
     @Test
     public void testParcelUnparcel() {
-        assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 22);
+        assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23);
     }
 
     @Test
@@ -159,14 +165,41 @@
         assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooManyValues));
     }
 
+    private String getEncodedDecodedIkev2ProfileMissingValues(int... missingIndices) {
+        // Sort to ensure when we remove, we can do it from greatest first.
+        Arrays.sort(missingIndices);
+
+        final String encoded = new String(getSampleIkev2Profile(DUMMY_PROFILE_KEY).encode());
+        final List<String> parts =
+                new ArrayList<>(Arrays.asList(encoded.split(VpnProfile.VALUE_DELIMITER)));
+
+        // Remove from back first to ensure indexing is consistent.
+        for (int i = missingIndices.length - 1; i >= 0; i--) {
+            parts.remove(missingIndices[i]);
+        }
+
+        return String.join(VpnProfile.VALUE_DELIMITER, parts.toArray(new String[0]));
+    }
+
     @Test
     public void testEncodeDecodeInvalidNumberOfValues() {
-        final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
-        final String encoded = new String(profile.encode());
-        final byte[] tooFewValues =
-                encoded.substring(0, encoded.lastIndexOf(VpnProfile.VALUE_DELIMITER)).getBytes();
+        final String tooFewValues =
+                getEncodedDecodedIkev2ProfileMissingValues(
+                        ENCODED_INDEX_AUTH_PARAMS_INLINE,
+                        ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */);
 
-        assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues));
+        assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()));
+    }
+
+    @Test
+    public void testEncodeDecodeMissingIsRestrictedToTestNetworks() {
+        final String tooFewValues =
+                getEncodedDecodedIkev2ProfileMissingValues(
+                        ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */);
+
+        // Verify decoding without isRestrictedToTestNetworks defaults to false
+        final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
+        assertFalse(decoded.isRestrictedToTestNetworks);
     }
 
     @Test
diff --git a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
index 4473492..e4996d9 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
@@ -446,7 +446,7 @@
         assertStatsEntry(stats, "v4-wlan0", 1000, SET_DEFAULT, 0x0, 30812L, 2310L);
         assertStatsEntry(stats, "v4-wlan0", 10102, SET_DEFAULT, 0x0, 10022L, 3330L);
         assertStatsEntry(stats, "v4-wlan0", 10060, SET_DEFAULT, 0x0, 9532772L, 254112L);
-        assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, 15229L, 0L);
+        assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, 0L, 0L);
         assertStatsEntry(stats, "wlan0", 1000, SET_DEFAULT, 0x0, 6126L, 2013L);
         assertStatsEntry(stats, "wlan0", 10013, SET_DEFAULT, 0x0, 0L, 144L);
         assertStatsEntry(stats, "wlan0", 10018, SET_DEFAULT, 0x0, 5980263L, 167667L);
@@ -468,9 +468,7 @@
         long appRxBytesAfter = 439237478L;
         assertEquals("App traffic should be ~100MB", 110553449, appRxBytesAfter - appRxBytesBefore);
 
-        long rootRxBytesBefore = 1394011L;
-        long rootRxBytesAfter = 1398634L;
-        assertEquals("UID 0 traffic should be ~0", 4623, rootRxBytesAfter - rootRxBytesBefore);
+        long rootRxBytes = 330187296L;
 
         mFactory.noteStackedIface("v4-wlan0", "wlan0");
         NetworkStats stats;
@@ -478,12 +476,12 @@
         // Stats snapshot before the download
         stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat_100mb_download_before);
         assertStatsEntry(stats, "v4-wlan0", 10106, SET_FOREGROUND, 0x0, appRxBytesBefore, 5199872L);
-        assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytesBefore, 0L);
+        assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytes, 0L);
 
         // Stats snapshot after the download
         stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat_100mb_download_after);
         assertStatsEntry(stats, "v4-wlan0", 10106, SET_FOREGROUND, 0x0, appRxBytesAfter, 7867488L);
-        assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytesAfter, 0L);
+        assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytes, 0L);
     }
 
     /**
diff --git a/tests/net/res/raw/xt_qtaguid_with_clat b/tests/net/res/raw/xt_qtaguid_with_clat
index 6cd7499..f04b32f 100644
--- a/tests/net/res/raw/xt_qtaguid_with_clat
+++ b/tests/net/res/raw/xt_qtaguid_with_clat
@@ -7,7 +7,7 @@
 7 v4-wlan0 0x0 10060 1 1448660 1041 31192 753 1448660 1041 0 0 0 0 31192 753 0 0 0 0
 8 v4-wlan0 0x0 10102 0 9702 16 2870 23 9702 16 0 0 0 0 2870 23 0 0 0 0
 9 v4-wlan0 0x0 10102 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-10 wlan0 0x0 0 0 11058671 7892 0 0 11043898 7811 13117 61 1656 20 0 0 0 0 0 0
+10 wlan0 0x0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 11 wlan0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 12 wlan0 0x0 1000 0 6126 13 2013 16 5934 11 192 2 0 0 1821 14 192 2 0 0
 13 wlan0 0x0 1000 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
@@ -41,5 +41,3 @@
 41 dummy0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 42 lo 0x0 0 0 1288 16 1288 16 0 0 532 8 756 8 0 0 532 8 756 8
 43 lo 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-44 wlan0 0x0 1029 0 0 0 312046 5113 0 0 0 0 0 0 306544 5046 3230 38 2272 29
-45 wlan0 0x0 1029 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
\ No newline at end of file
diff --git a/tests/net/res/raw/xt_qtaguid_with_clat_100mb_download_after b/tests/net/res/raw/xt_qtaguid_with_clat_100mb_download_after
index 9f86153..12d98ca 100644
--- a/tests/net/res/raw/xt_qtaguid_with_clat_100mb_download_after
+++ b/tests/net/res/raw/xt_qtaguid_with_clat_100mb_download_after
@@ -9,7 +9,7 @@
 9 v4-wlan0 0x0 10057 1 728 7 392 7 0 0 728 7 0 0 0 0 392 7 0 0
 10 v4-wlan0 0x0 10106 0 2232 18 2232 18 0 0 2232 18 0 0 0 0 2232 18 0 0
 11 v4-wlan0 0x0 10106 1 432952718 314238 5442288 121260 432950238 314218 2480 20 0 0 5433900 121029 8388 231 0 0
-12 wlan0 0x0 0 0 440746376 329772 0 0 439660007 315369 232001 1276 854368 13127 0 0 0 0 0 0
+12 wlan0 0x0 0 0 330187296 250652 0 0 329106990 236273 226202 1255 854104 13124 0 0 0 0 0 0
 13 wlan0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 14 wlan0 0x0 1000 0 77113 272 56151 575 77113 272 0 0 0 0 19191 190 36960 385 0 0
 15 wlan0 0x0 1000 1 20227 80 8356 72 18539 74 1688 6 0 0 7562 66 794 6 0 0
diff --git a/tests/net/res/raw/xt_qtaguid_with_clat_simple b/tests/net/res/raw/xt_qtaguid_with_clat_simple
index b37fae6..a1d6d411 100644
--- a/tests/net/res/raw/xt_qtaguid_with_clat_simple
+++ b/tests/net/res/raw/xt_qtaguid_with_clat_simple
@@ -1,5 +1,4 @@
 idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets
 2 v4-wlan0 0x0 10060 0 42600 213 4100 41 42600 213 0 0 0 0 4100 41 0 0 0 0
 3 v4-wlan0 0x0 10060 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-4 wlan0 0x0 0 0 46860 213 0 0 46860 213 0 0 0 0 0 0 0 0 0 0
-5 wlan0 0x0 1029 0 0 0 4920 41 0 0 0 0 0 0 4920 41 0 0 0 0
+4 wlan0 0x0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0