Merge "Update letterbox restart dialog style to match other Android U dialogs" into udc-dev
diff --git a/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java b/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java
index fd8ddbc..6c8af39 100644
--- a/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java
@@ -59,6 +59,10 @@
      */
     void reportAppUsage(String packageName, int userId);
 
+    /** @return {@code true} if the app is considered buggy from JobScheduler's perspective. */
+    boolean isAppConsideredBuggy(int callingUserId, @NonNull String callingPackageName,
+            int timeoutBlameUserId, @NonNull String timeoutBlamePackageName);
+
     /**
      * @return {@code true} if the given notification is associated with any user-initiated jobs.
      */
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobNotificationCoordinator.java b/apex/jobscheduler/service/java/com/android/server/job/JobNotificationCoordinator.java
index 8a5d094..ae86afb 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobNotificationCoordinator.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobNotificationCoordinator.java
@@ -123,21 +123,21 @@
         if (oldDetails == null) {
             if (jobStatus.startedAsUserInitiatedJob) {
                 Counter.logIncrementWithUid(
-                        "job_scheduler.value_cntr_w_uid_initial_setNotification_call_required",
+                        "job_scheduler.value_cntr_w_uid_initial_set_notification_call_required",
                         jobStatus.getUid());
             } else {
                 Counter.logIncrementWithUid(
-                        "job_scheduler.value_cntr_w_uid_initial_setNotification_call_optional",
+                        "job_scheduler.value_cntr_w_uid_initial_set_notification_call_optional",
                         jobStatus.getUid());
             }
         } else {
             if (jobStatus.startedAsUserInitiatedJob) {
                 Counter.logIncrementWithUid(
-                        "job_scheduler.value_cntr_w_uid_subsequent_setNotification_call_required",
+                        "job_scheduler.value_cntr_w_uid_subsequent_set_notification_call_required",
                         jobStatus.getUid());
             } else {
                 Counter.logIncrementWithUid(
-                        "job_scheduler.value_cntr_w_uid_subsequent_setNotification_call_optional",
+                        "job_scheduler.value_cntr_w_uid_subsequent_set_notification_call_optional",
                         jobStatus.getUid());
             }
             if (oldDetails.notificationId != notificationId) {
@@ -145,7 +145,7 @@
                 removeNotificationAssociation(hostingContext, JobParameters.STOP_REASON_UNDEFINED,
                         jobStatus);
                 Counter.logIncrementWithUid(
-                        "job_scheduler.value_cntr_w_uid_setNotification_changed_notification_ids",
+                        "job_scheduler.value_cntr_w_uid_set_notification_changed_notification_ids",
                         jobStatus.getUid());
             }
         }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 4f5eb37..f99bcf1 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -322,16 +322,25 @@
     private static final String QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG = ".schedulePersisted()";
     private static final String QUOTA_TRACKER_SCHEDULE_LOGGED =
             ".schedulePersisted out-of-quota logged";
+    private static final String QUOTA_TRACKER_TIMEOUT_UIJ_TAG = "timeout-uij";
+    private static final String QUOTA_TRACKER_TIMEOUT_EJ_TAG = "timeout-ej";
+    private static final String QUOTA_TRACKER_TIMEOUT_REG_TAG = "timeout-reg";
+    private static final String QUOTA_TRACKER_TIMEOUT_TOTAL_TAG = "timeout-total";
+    private static final String QUOTA_TRACKER_ANR_TAG = "anr";
     private static final Category QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED = new Category(
             ".schedulePersisted()");
     private static final Category QUOTA_TRACKER_CATEGORY_SCHEDULE_LOGGED = new Category(
             ".schedulePersisted out-of-quota logged");
-    private static final Categorizer QUOTA_CATEGORIZER = (userId, packageName, tag) -> {
-        if (QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG.equals(tag)) {
-            return QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED;
-        }
-        return QUOTA_TRACKER_CATEGORY_SCHEDULE_LOGGED;
-    };
+    private static final Category QUOTA_TRACKER_CATEGORY_TIMEOUT_UIJ =
+            new Category(QUOTA_TRACKER_TIMEOUT_UIJ_TAG);
+    private static final Category QUOTA_TRACKER_CATEGORY_TIMEOUT_EJ =
+            new Category(QUOTA_TRACKER_TIMEOUT_EJ_TAG);
+    private static final Category QUOTA_TRACKER_CATEGORY_TIMEOUT_REG =
+            new Category(QUOTA_TRACKER_TIMEOUT_REG_TAG);
+    private static final Category QUOTA_TRACKER_CATEGORY_TIMEOUT_TOTAL =
+            new Category(QUOTA_TRACKER_TIMEOUT_TOTAL_TAG);
+    private static final Category QUOTA_TRACKER_CATEGORY_ANR = new Category(QUOTA_TRACKER_ANR_TAG);
+    private static final Category QUOTA_TRACKER_CATEGORY_DISABLED = new Category("disabled");
 
     /**
      * Queue of pending jobs. The JobServiceContext class will receive jobs from this list
@@ -493,10 +502,18 @@
                     }
                     switch (name) {
                         case Constants.KEY_ENABLE_API_QUOTAS:
+                        case Constants.KEY_ENABLE_EXECUTION_SAFEGUARDS_UDC:
                         case Constants.KEY_API_QUOTA_SCHEDULE_COUNT:
                         case Constants.KEY_API_QUOTA_SCHEDULE_WINDOW_MS:
                         case Constants.KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT:
                         case Constants.KEY_API_QUOTA_SCHEDULE_THROW_EXCEPTION:
+                        case Constants.KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT:
+                        case Constants.KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT:
+                        case Constants.KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT:
+                        case Constants.KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT:
+                        case Constants.KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS:
+                        case Constants.KEY_EXECUTION_SAFEGUARDS_UDC_ANR_COUNT:
+                        case Constants.KEY_EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS:
                             if (!apiQuotaScheduleUpdated) {
                                 mConstants.updateApiQuotaConstantsLocked();
                                 updateQuotaTracker();
@@ -583,10 +600,26 @@
 
     @VisibleForTesting
     void updateQuotaTracker() {
-        mQuotaTracker.setEnabled(mConstants.ENABLE_API_QUOTAS);
+        mQuotaTracker.setEnabled(
+                mConstants.ENABLE_API_QUOTAS || mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC);
         mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED,
                 mConstants.API_QUOTA_SCHEDULE_COUNT,
                 mConstants.API_QUOTA_SCHEDULE_WINDOW_MS);
+        mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_TIMEOUT_UIJ,
+                mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT,
+                mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS);
+        mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_TIMEOUT_EJ,
+                mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT,
+                mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS);
+        mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_TIMEOUT_REG,
+                mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT,
+                mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS);
+        mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_TIMEOUT_TOTAL,
+                mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT,
+                mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS);
+        mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_ANR,
+                mConstants.EXECUTION_SAFEGUARDS_UDC_ANR_COUNT,
+                mConstants.EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS);
     }
 
     /**
@@ -616,6 +649,8 @@
                 "conn_low_signal_strength_relax_frac";
         private static final String KEY_PREFETCH_FORCE_BATCH_RELAX_THRESHOLD_MS =
                 "prefetch_force_batch_relax_threshold_ms";
+        // This has been enabled for 3+ full releases. We're unlikely to disable it.
+        // TODO(141645789): remove this flag
         private static final String KEY_ENABLE_API_QUOTAS = "enable_api_quotas";
         private static final String KEY_API_QUOTA_SCHEDULE_COUNT = "aq_schedule_count";
         private static final String KEY_API_QUOTA_SCHEDULE_WINDOW_MS = "aq_schedule_window_ms";
@@ -623,6 +658,22 @@
                 "aq_schedule_throw_exception";
         private static final String KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT =
                 "aq_schedule_return_failure";
+        private static final String KEY_ENABLE_EXECUTION_SAFEGUARDS_UDC =
+                "enable_execution_safeguards_udc";
+        private static final String KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT =
+                "es_u_timeout_uij_count";
+        private static final String KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT =
+                "es_u_timeout_ej_count";
+        private static final String KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT =
+                "es_u_timeout_reg_count";
+        private static final String KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT =
+                "es_u_timeout_total_count";
+        private static final String KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS =
+                "es_u_timeout_window_ms";
+        private static final String KEY_EXECUTION_SAFEGUARDS_UDC_ANR_COUNT =
+                "es_u_anr_count";
+        private static final String KEY_EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS =
+                "es_u_anr_window_ms";
 
         private static final String KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS =
                 "runtime_free_quota_max_limit_ms";
@@ -662,6 +713,17 @@
         private static final long DEFAULT_API_QUOTA_SCHEDULE_WINDOW_MS = MINUTE_IN_MILLIS;
         private static final boolean DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION = true;
         private static final boolean DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = false;
+        private static final boolean DEFAULT_ENABLE_EXECUTION_SAFEGUARDS_UDC = true;
+        private static final int DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT = 2;
+        // EJs have a shorter timeout, so set a higher limit for them to start with.
+        private static final int DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT = 5;
+        private static final int DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT = 3;
+        private static final int DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT = 10;
+        private static final long DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS =
+                24 * HOUR_IN_MILLIS;
+        private static final int DEFAULT_EXECUTION_SAFEGUARDS_UDC_ANR_COUNT = 3;
+        private static final long DEFAULT_EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS =
+                6 * HOUR_IN_MILLIS;
         @VisibleForTesting
         public static final long DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS = 30 * MINUTE_IN_MILLIS;
         @VisibleForTesting
@@ -774,6 +836,55 @@
         public boolean API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT =
                 DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT;
 
+        /**
+         * Whether to enable the execution safeguards added in UDC.
+         */
+        public boolean ENABLE_EXECUTION_SAFEGUARDS_UDC = DEFAULT_ENABLE_EXECUTION_SAFEGUARDS_UDC;
+        /**
+         * The maximum number of times an app can have a user-iniated job time out before the system
+         * begins removing some of the app's privileges.
+         */
+        public int EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT =
+                DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT;
+        /**
+         * The maximum number of times an app can have an expedited job time out before the system
+         * begins removing some of the app's privileges.
+         */
+        public int EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT =
+                DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT;
+        /**
+         * The maximum number of times an app can have a regular job time out before the system
+         * begins removing some of the app's privileges.
+         */
+        public int EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT =
+                DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT;
+        /**
+         * The maximum number of times an app can have jobs time out before the system
+         * attempts to restrict most of the app's privileges.
+         */
+        public int EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT =
+                DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT;
+        /**
+         * The time window that {@link #EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT},
+         * {@link #EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT},
+         * {@link #EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT}, and
+         * {@link #EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT} should be evaluated over.
+         */
+        public long EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS =
+                DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS;
+
+        /**
+         * The maximum number of times an app can ANR from JobScheduler's perspective before
+         * JobScheduler will attempt to restrict the app.
+         */
+        public int EXECUTION_SAFEGUARDS_UDC_ANR_COUNT = DEFAULT_EXECUTION_SAFEGUARDS_UDC_ANR_COUNT;
+        /**
+         * The time window that {@link #EXECUTION_SAFEGUARDS_UDC_ANR_COUNT}
+         * should be evaluated over.
+         */
+        public long EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS =
+                DEFAULT_EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS;
+
         /** The maximum amount of time we will let a job run for when quota is "free". */
         public long RUNTIME_FREE_QUOTA_MAX_LIMIT_MS = DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
 
@@ -915,6 +1026,9 @@
         private void updateApiQuotaConstantsLocked() {
             ENABLE_API_QUOTAS = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
                     KEY_ENABLE_API_QUOTAS, DEFAULT_ENABLE_API_QUOTAS);
+            ENABLE_EXECUTION_SAFEGUARDS_UDC = DeviceConfig.getBoolean(
+                    DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+                    KEY_ENABLE_EXECUTION_SAFEGUARDS_UDC, DEFAULT_ENABLE_EXECUTION_SAFEGUARDS_UDC);
             // Set a minimum value on the quota limit so it's not so low that it interferes with
             // legitimate use cases.
             API_QUOTA_SCHEDULE_COUNT = Math.max(250,
@@ -931,6 +1045,40 @@
                     DeviceConfig.NAMESPACE_JOB_SCHEDULER,
                     KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT,
                     DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT);
+
+            // Set a minimum value on the timeout limit so it's not so low that it interferes with
+            // legitimate use cases.
+            EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT = Math.max(2,
+                    DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+                            KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT,
+                            DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT));
+            EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT = Math.max(2,
+                    DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+                            KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT,
+                            DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT));
+            EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT = Math.max(2,
+                    DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+                            KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT,
+                            DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT));
+            final int highestTimeoutCount = Math.max(EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT,
+                    Math.max(EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT,
+                            EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT));
+            EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT = Math.max(highestTimeoutCount,
+                    DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+                            KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT,
+                            DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT));
+            EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS = DeviceConfig.getLong(
+                    DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+                    KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS,
+                    DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS);
+            EXECUTION_SAFEGUARDS_UDC_ANR_COUNT = Math.max(1,
+                    DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+                            KEY_EXECUTION_SAFEGUARDS_UDC_ANR_COUNT,
+                            DEFAULT_EXECUTION_SAFEGUARDS_UDC_ANR_COUNT));
+            EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS = DeviceConfig.getLong(
+                    DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+                    KEY_EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS,
+                    DEFAULT_EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS);
         }
 
         private void updateRuntimeConstantsLocked() {
@@ -1029,6 +1177,23 @@
             pw.print(KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT,
                     API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT).println();
 
+            pw.print(KEY_ENABLE_EXECUTION_SAFEGUARDS_UDC, ENABLE_EXECUTION_SAFEGUARDS_UDC)
+                    .println();
+            pw.print(KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT,
+                    EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT).println();
+            pw.print(KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT,
+                    EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT).println();
+            pw.print(KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT,
+                    EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT).println();
+            pw.print(KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT,
+                    EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT).println();
+            pw.print(KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS,
+                    EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS).println();
+            pw.print(KEY_EXECUTION_SAFEGUARDS_UDC_ANR_COUNT,
+                    EXECUTION_SAFEGUARDS_UDC_ANR_COUNT).println();
+            pw.print(KEY_EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS,
+                    EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS).println();
+
             pw.print(KEY_RUNTIME_MIN_GUARANTEE_MS, RUNTIME_MIN_GUARANTEE_MS).println();
             pw.print(KEY_RUNTIME_MIN_EJ_GUARANTEE_MS, RUNTIME_MIN_EJ_GUARANTEE_MS).println();
             pw.print(KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS, RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
@@ -1631,7 +1796,8 @@
                     jobStatus.getEstimatedNetworkDownloadBytes(),
                     jobStatus.getEstimatedNetworkUploadBytes(),
                     jobStatus.getWorkCount(),
-                    ActivityManager.processStateAmToProto(mUidProcStates.get(jobStatus.getUid())));
+                    ActivityManager.processStateAmToProto(mUidProcStates.get(jobStatus.getUid())),
+                    jobStatus.getNamespaceHash());
 
             // If the job is immediately ready to run, then we can just immediately
             // put it in the pending list and try to schedule it.  This is especially
@@ -2059,7 +2225,8 @@
                     cancelled.getEstimatedNetworkDownloadBytes(),
                     cancelled.getEstimatedNetworkUploadBytes(),
                     cancelled.getWorkCount(),
-                    ActivityManager.processStateAmToProto(mUidProcStates.get(cancelled.getUid())));
+                    ActivityManager.processStateAmToProto(mUidProcStates.get(cancelled.getUid())),
+                    cancelled.getNamespaceHash());
         }
         // If this is a replacement, bring in the new version of the job
         if (incomingJob != null) {
@@ -2250,12 +2417,52 @@
         // Set up the app standby bucketing tracker
         mStandbyTracker = new StandbyTracker();
         mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
-        mQuotaTracker = new CountQuotaTracker(context, QUOTA_CATEGORIZER);
-        mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED,
-                mConstants.API_QUOTA_SCHEDULE_COUNT,
-                mConstants.API_QUOTA_SCHEDULE_WINDOW_MS);
+
+        final Categorizer quotaCategorizer = (userId, packageName, tag) -> {
+            if (QUOTA_TRACKER_TIMEOUT_UIJ_TAG.equals(tag)) {
+                return mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC
+                        ? QUOTA_TRACKER_CATEGORY_TIMEOUT_UIJ
+                        : QUOTA_TRACKER_CATEGORY_DISABLED;
+            }
+            if (QUOTA_TRACKER_TIMEOUT_EJ_TAG.equals(tag)) {
+                return mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC
+                        ? QUOTA_TRACKER_CATEGORY_TIMEOUT_EJ
+                        : QUOTA_TRACKER_CATEGORY_DISABLED;
+            }
+            if (QUOTA_TRACKER_TIMEOUT_REG_TAG.equals(tag)) {
+                return mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC
+                        ? QUOTA_TRACKER_CATEGORY_TIMEOUT_REG
+                        : QUOTA_TRACKER_CATEGORY_DISABLED;
+            }
+            if (QUOTA_TRACKER_TIMEOUT_TOTAL_TAG.equals(tag)) {
+                return mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC
+                        ? QUOTA_TRACKER_CATEGORY_TIMEOUT_TOTAL
+                        : QUOTA_TRACKER_CATEGORY_DISABLED;
+            }
+            if (QUOTA_TRACKER_ANR_TAG.equals(tag)) {
+                return mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC
+                        ? QUOTA_TRACKER_CATEGORY_ANR
+                        : QUOTA_TRACKER_CATEGORY_DISABLED;
+            }
+            if (QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG.equals(tag)) {
+                return mConstants.ENABLE_API_QUOTAS
+                        ? QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED
+                        : QUOTA_TRACKER_CATEGORY_DISABLED;
+            }
+            if (QUOTA_TRACKER_SCHEDULE_LOGGED.equals(tag)) {
+                return mConstants.ENABLE_API_QUOTAS
+                        ? QUOTA_TRACKER_CATEGORY_SCHEDULE_LOGGED
+                        : QUOTA_TRACKER_CATEGORY_DISABLED;
+            }
+            Slog.wtf(TAG, "Unexpected category tag: " + tag);
+            return QUOTA_TRACKER_CATEGORY_DISABLED;
+        };
+        mQuotaTracker = new CountQuotaTracker(context, quotaCategorizer);
+        updateQuotaTracker();
         // Log at most once per minute.
+        // Set outside updateQuotaTracker() since this is intentionally not configurable.
         mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_SCHEDULE_LOGGED, 1, 60_000);
+        mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_DISABLED, Integer.MAX_VALUE, 60_000);
 
         mAppStandbyInternal = LocalServices.getService(AppStandbyInternal.class);
         mAppStandbyInternal.addListener(mStandbyTracker);
@@ -2760,6 +2967,48 @@
                 0 /* Reset cumulativeExecutionTime because of successful execution */);
     }
 
+    @VisibleForTesting
+    void maybeProcessBuggyJob(@NonNull JobStatus jobStatus, int debugStopReason) {
+        boolean jobTimedOut = debugStopReason == JobParameters.INTERNAL_STOP_REASON_TIMEOUT;
+        // If madeActive = 0, the job never actually started.
+        if (!jobTimedOut && jobStatus.madeActive > 0) {
+            final long executionDurationMs = sUptimeMillisClock.millis() - jobStatus.madeActive;
+            // The debug reason may be different if we stopped the job for some other reason
+            // (eg. constraints), so look at total execution time to be safe.
+            if (jobStatus.startedAsUserInitiatedJob) {
+                // TODO: factor in different min guarantees for different UI job types
+                jobTimedOut = executionDurationMs >= mConstants.RUNTIME_MIN_UI_GUARANTEE_MS;
+            } else if (jobStatus.startedAsExpeditedJob) {
+                jobTimedOut = executionDurationMs >= mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS;
+            } else {
+                jobTimedOut = executionDurationMs >= mConstants.RUNTIME_MIN_GUARANTEE_MS;
+            }
+        }
+        if (jobTimedOut) {
+            final int userId = jobStatus.getTimeoutBlameUserId();
+            final String pkg = jobStatus.getTimeoutBlamePackageName();
+            mQuotaTracker.noteEvent(userId, pkg,
+                    jobStatus.startedAsUserInitiatedJob
+                            ? QUOTA_TRACKER_TIMEOUT_UIJ_TAG
+                            : (jobStatus.startedAsExpeditedJob
+                                    ? QUOTA_TRACKER_TIMEOUT_EJ_TAG
+                                    : QUOTA_TRACKER_TIMEOUT_REG_TAG));
+            if (!mQuotaTracker.noteEvent(userId, pkg, QUOTA_TRACKER_TIMEOUT_TOTAL_TAG)) {
+                mAppStandbyInternal.restrictApp(
+                        pkg, userId, UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY);
+            }
+        }
+
+        if (debugStopReason == JobParameters.INTERNAL_STOP_REASON_ANR) {
+            final int callingUserId = jobStatus.getUserId();
+            final String callingPkg = jobStatus.getServiceComponent().getPackageName();
+            if (!mQuotaTracker.noteEvent(callingUserId, callingPkg, QUOTA_TRACKER_ANR_TAG)) {
+                mAppStandbyInternal.restrictApp(callingPkg, callingUserId,
+                        UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY);
+            }
+        }
+    }
+
     // JobCompletedListener implementations.
 
     /**
@@ -2782,6 +3031,8 @@
         mLastCompletedJobTimeElapsed[mLastCompletedJobIndex] = sElapsedRealtimeClock.millis();
         mLastCompletedJobIndex = (mLastCompletedJobIndex + 1) % NUM_COMPLETED_JOB_HISTORY;
 
+        maybeProcessBuggyJob(jobStatus, debugStopReason);
+
         if (debugStopReason == JobParameters.INTERNAL_STOP_REASON_UNINSTALL
                 || debugStopReason == JobParameters.INTERNAL_STOP_REASON_DATA_CLEARED) {
             // The job should have already been cleared from the rest of the JS tracking. No need
@@ -3509,26 +3760,36 @@
             if (job.shouldTreatAsUserInitiatedJob()
                     && checkRunUserInitiatedJobsPermission(
                             job.getSourceUid(), job.getSourcePackageName())) {
+                // The calling package is the one doing the work, so use it in the
+                // timeout quota checks.
+                final boolean isWithinTimeoutQuota = mQuotaTracker.isWithinQuota(
+                        job.getTimeoutBlameUserId(), job.getTimeoutBlamePackageName(),
+                        QUOTA_TRACKER_TIMEOUT_UIJ_TAG);
+                final long upperLimitMs = isWithinTimeoutQuota
+                        ? mConstants.RUNTIME_UI_LIMIT_MS
+                        : mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
                 if (job.getJob().getRequiredNetwork() != null) {
                     // User-initiated data transfers.
                     if (mConstants.RUNTIME_USE_DATA_ESTIMATES_FOR_LIMITS) {
                         final long estimatedTransferTimeMs =
                                 mConnectivityController.getEstimatedTransferTimeMs(job);
                         if (estimatedTransferTimeMs == ConnectivityController.UNKNOWN_TIME) {
-                            return mConstants.RUNTIME_MIN_UI_DATA_TRANSFER_GUARANTEE_MS;
+                            return Math.min(upperLimitMs,
+                                    mConstants.RUNTIME_MIN_UI_DATA_TRANSFER_GUARANTEE_MS);
                         }
                         // Try to give the job at least as much time as we think the transfer
                         // will take, but cap it at the maximum limit.
                         final long factoredTransferTimeMs = (long) (estimatedTransferTimeMs
                                 * mConstants.RUNTIME_MIN_UI_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR);
-                        return Math.min(mConstants.RUNTIME_UI_LIMIT_MS,
+                        return Math.min(upperLimitMs,
                                 Math.max(factoredTransferTimeMs,
                                         mConstants.RUNTIME_MIN_UI_DATA_TRANSFER_GUARANTEE_MS));
                     }
-                    return Math.max(mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
-                            mConstants.RUNTIME_MIN_UI_DATA_TRANSFER_GUARANTEE_MS);
+                    return Math.min(upperLimitMs,
+                            Math.max(mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+                                    mConstants.RUNTIME_MIN_UI_DATA_TRANSFER_GUARANTEE_MS));
                 }
-                return mConstants.RUNTIME_MIN_UI_GUARANTEE_MS;
+                return Math.min(upperLimitMs, mConstants.RUNTIME_MIN_UI_GUARANTEE_MS);
             } else if (job.shouldTreatAsExpeditedJob()) {
                 // Don't guarantee RESTRICTED jobs more than 5 minutes.
                 return job.getEffectiveStandbyBucket() != RESTRICTED_INDEX
@@ -3545,13 +3806,24 @@
         synchronized (mLock) {
             if (job.shouldTreatAsUserInitiatedJob()
                     && checkRunUserInitiatedJobsPermission(
-                            job.getSourceUid(), job.getSourcePackageName())) {
+                            job.getSourceUid(), job.getSourcePackageName())
+                    && mQuotaTracker.isWithinQuota(job.getTimeoutBlameUserId(),
+                            job.getTimeoutBlamePackageName(),
+                            QUOTA_TRACKER_TIMEOUT_UIJ_TAG)) {
                 return mConstants.RUNTIME_UI_LIMIT_MS;
             }
             if (job.shouldTreatAsUserInitiatedJob()) {
                 return mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
             }
-            return Math.min(mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+            // Only let the app use the higher runtime if it hasn't repeatedly timed out.
+            final String timeoutTag = job.shouldTreatAsExpeditedJob()
+                    ? QUOTA_TRACKER_TIMEOUT_EJ_TAG : QUOTA_TRACKER_TIMEOUT_REG_TAG;
+            final long upperLimitMs =
+                    mQuotaTracker.isWithinQuota(job.getTimeoutBlameUserId(),
+                            job.getTimeoutBlamePackageName(), timeoutTag)
+                            ? mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS
+                            : mConstants.RUNTIME_MIN_GUARANTEE_MS;
+            return Math.min(upperLimitMs,
                     mConstants.USE_TARE_POLICY
                             ? mTareController.getMaxJobExecutionTimeMsLocked(job)
                             : mQuotaController.getMaxJobExecutionTimeMsLocked(job));
@@ -3795,6 +4067,17 @@
         }
 
         @Override
+        public boolean isAppConsideredBuggy(int callingUserId, @NonNull String callingPackageName,
+                int timeoutBlameUserId, @NonNull String timeoutBlamePackageName) {
+            return !mQuotaTracker.isWithinQuota(callingUserId, callingPackageName,
+                            QUOTA_TRACKER_ANR_TAG)
+                    || !mQuotaTracker.isWithinQuota(callingUserId, callingPackageName,
+                            QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG)
+                    || !mQuotaTracker.isWithinQuota(timeoutBlameUserId, timeoutBlamePackageName,
+                            QUOTA_TRACKER_TIMEOUT_TOTAL_TAG);
+        }
+
+        @Override
         public boolean isNotificationAssociatedWithAnyUserInitiatedJobs(int notificationId,
                 int userId, @NonNull String packageName) {
             if (packageName == null) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index 90f1523..5f795b6 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -499,7 +499,8 @@
                     job.getEstimatedNetworkDownloadBytes(),
                     job.getEstimatedNetworkUploadBytes(),
                     job.getWorkCount(),
-                    ActivityManager.processStateAmToProto(mService.getUidProcState(job.getUid())));
+                    ActivityManager.processStateAmToProto(mService.getUidProcState(job.getUid())),
+                    job.getNamespaceHash());
             sEnqueuedJwiAtJobStart.logSampleWithUid(job.getUid(), job.getWorkCount());
             final String sourcePackage = job.getSourcePackageName();
             if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) {
@@ -1330,7 +1331,7 @@
                 // FINISHED/NO-RETRY.
                 onSlowAppResponseLocked(/* reschedule */ false, /* updateStopReasons */ true,
                         /* texCounterMetricId */
-                        "job_scheduler.value_cntr_w_uid_slow_app_response_onStartJob",
+                        "job_scheduler.value_cntr_w_uid_slow_app_response_on_start_job",
                         /* debugReason */ "timed out while starting",
                         /* anrMessage */ "No response to onStartJob",
                         CompatChanges.isChangeEnabled(ANR_PRE_UDC_APIS_ON_SLOW_RESPONSES,
@@ -1342,7 +1343,7 @@
                 // other reason.
                 onSlowAppResponseLocked(/* reschedule */ true, /* updateStopReasons */ false,
                         /* texCounterMetricId */
-                        "job_scheduler.value_cntr_w_uid_slow_app_response_onStopJob",
+                        "job_scheduler.value_cntr_w_uid_slow_app_response_on_stop_job",
                         /* debugReason */ "timed out while stopping",
                         /* anrMessage */ "No response to onStopJob",
                         CompatChanges.isChangeEnabled(ANR_PRE_UDC_APIS_ON_SLOW_RESPONSES,
@@ -1399,7 +1400,7 @@
                 } else if (mAwaitingNotification) {
                     onSlowAppResponseLocked(/* reschedule */ true, /* updateStopReasons */ true,
                             /* texCounterMetricId */
-                            "job_scheduler.value_cntr_w_uid_slow_app_response_setNotification",
+                            "job_scheduler.value_cntr_w_uid_slow_app_response_set_notification",
                             /* debugReason */ "timed out while stopping",
                             /* anrMessage */ "required notification not provided",
                             /* triggerAnr */ true);
@@ -1557,7 +1558,8 @@
                 completedJob.getEstimatedNetworkUploadBytes(),
                 completedJob.getWorkCount(),
                 ActivityManager
-                        .processStateAmToProto(mService.getUidProcState(completedJob.getUid())));
+                        .processStateAmToProto(mService.getUidProcState(completedJob.getUid())),
+                completedJob.getNamespaceHash());
         if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) {
             Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_SYSTEM_SERVER, "JobScheduler",
                     getId());
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index a8b4c69..3baa9e6 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -43,6 +43,7 @@
 import android.os.UserHandle;
 import android.provider.MediaStore;
 import android.text.format.DateFormat;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.IndentingPrintWriter;
 import android.util.Pair;
@@ -51,6 +52,7 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FrameworkStatsLog;
@@ -65,10 +67,12 @@
 import dalvik.annotation.optimization.NeverCompile;
 
 import java.io.PrintWriter;
+import java.security.MessageDigest;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Objects;
+import java.util.Random;
 import java.util.function.Predicate;
 
 /**
@@ -88,6 +92,13 @@
     private static final String TAG = "JobScheduler.JobStatus";
     static final boolean DEBUG = JobSchedulerService.DEBUG;
 
+    private static MessageDigest sMessageDigest;
+    /** Cache of namespace to hash to reduce how often we need to generate the namespace hash. */
+    @GuardedBy("sNamespaceHashCache")
+    private static final ArrayMap<String, String> sNamespaceHashCache = new ArrayMap<>();
+    /** Maximum size of {@link #sNamespaceHashCache}. */
+    private static final int MAX_NAMESPACE_CACHE_SIZE = 128;
+
     private static final int NUM_CONSTRAINT_CHANGE_HISTORY = 10;
 
     public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE;
@@ -231,6 +242,8 @@
     final String sourceTag;
     @Nullable
     private final String mNamespace;
+    @Nullable
+    private final String mNamespaceHash;
     /** An ID that can be used to uniquely identify the job when logging statsd metrics. */
     private final long mLoggingJobId;
 
@@ -570,6 +583,7 @@
         this.callingUid = callingUid;
         this.standbyBucket = standbyBucket;
         mNamespace = namespace;
+        mNamespaceHash = generateNamespaceHash(namespace);
         mLoggingJobId = generateLoggingId(namespace, job.getId());
 
         int tempSourceUid = -1;
@@ -814,6 +828,56 @@
         return ((long) namespace.hashCode()) << 31 | jobId;
     }
 
+    @Nullable
+    private static String generateNamespaceHash(@Nullable String namespace) {
+        if (namespace == null) {
+            return null;
+        }
+        if (namespace.trim().isEmpty()) {
+            // Input is composed of all spaces (or nothing at all).
+            return namespace;
+        }
+        synchronized (sNamespaceHashCache) {
+            final int idx = sNamespaceHashCache.indexOfKey(namespace);
+            if (idx >= 0) {
+                return sNamespaceHashCache.valueAt(idx);
+            }
+        }
+        String hash = null;
+        try {
+            // .hashCode() can result in conflicts that would make distinguishing between
+            // namespaces hard and reduce the accuracy of certain metrics. Use SHA-256
+            // to generate the hash since the probability of collision is extremely low.
+            if (sMessageDigest == null) {
+                sMessageDigest = MessageDigest.getInstance("SHA-256");
+            }
+            final byte[] digest = sMessageDigest.digest(namespace.getBytes());
+            // Convert to hexadecimal representation
+            StringBuilder hexBuilder = new StringBuilder(digest.length);
+            for (byte byteChar : digest) {
+                hexBuilder.append(String.format("%02X", byteChar));
+            }
+            hash = hexBuilder.toString();
+        } catch (Exception e) {
+            Slog.wtf(TAG, "Couldn't hash input", e);
+        }
+        if (hash == null) {
+            // If we get to this point, something went wrong with the MessageDigest above.
+            // Don't return the raw input value (which would defeat the purpose of hashing).
+            return "failed_namespace_hash";
+        }
+        hash = hash.intern();
+        synchronized (sNamespaceHashCache) {
+            if (sNamespaceHashCache.size() >= MAX_NAMESPACE_CACHE_SIZE) {
+                // Drop a random mapping instead of dropping at a predefined index to avoid
+                // potentially always dropping the same mapping.
+                sNamespaceHashCache.removeAt((new Random()).nextInt(MAX_NAMESPACE_CACHE_SIZE));
+            }
+            sNamespaceHashCache.put(namespace, hash);
+        }
+        return hash;
+    }
+
     public void enqueueWorkLocked(JobWorkItem work) {
         if (pendingWork == null) {
             pendingWork = new ArrayList<>();
@@ -1024,13 +1088,77 @@
         return UserHandle.getUserId(callingUid);
     }
 
+    private boolean shouldBlameSourceForTimeout() {
+        // If the system scheduled the job on behalf of an app, assume the app is the one
+        // doing the work and blame the app directly. This is the case with things like
+        // syncs via SyncManager.
+        // If the system didn't schedule the job on behalf of an app, then
+        // blame the app doing the actual work. Proxied jobs are a little tricky.
+        // Proxied jobs scheduled by built-in system apps like DownloadManager may be fine
+        // and we could consider exempting those jobs. For example, in DownloadManager's
+        // case, all it does is download files and the code is vetted. A timeout likely
+        // means it's downloading a large file, which isn't an error. For now, DownloadManager
+        // is an exempted app, so this shouldn't be an issue.
+        // However, proxied jobs coming from other system apps (such as those that can
+        // be updated separately from an OTA) may not be fine and we would want to apply
+        // this policy to those jobs/apps.
+        // TODO(284512488): consider exempting DownloadManager or other system apps
+        return UserHandle.isCore(callingUid);
+    }
+
+    /**
+     * Returns the package name that should most likely be blamed for the job timing out.
+     */
+    public String getTimeoutBlamePackageName() {
+        if (shouldBlameSourceForTimeout()) {
+            return sourcePackageName;
+        }
+        return getServiceComponent().getPackageName();
+    }
+
+    /**
+     * Returns the UID that should most likely be blamed for the job timing out.
+     */
+    public int getTimeoutBlameUid() {
+        if (shouldBlameSourceForTimeout()) {
+            return sourceUid;
+        }
+        return callingUid;
+    }
+
+    /**
+     * Returns the userId that should most likely be blamed for the job timing out.
+     */
+    public int getTimeoutBlameUserId() {
+        if (shouldBlameSourceForTimeout()) {
+            return sourceUserId;
+        }
+        return UserHandle.getUserId(callingUid);
+    }
+
     /**
      * Returns an appropriate standby bucket for the job, taking into account any standby
      * exemptions.
      */
     public int getEffectiveStandbyBucket() {
+        final JobSchedulerInternal jsi = LocalServices.getService(JobSchedulerInternal.class);
+        final boolean isBuggy = jsi.isAppConsideredBuggy(
+                getUserId(), getServiceComponent().getPackageName(),
+                getTimeoutBlameUserId(), getTimeoutBlamePackageName());
+
         final int actualBucket = getStandbyBucket();
         if (actualBucket == EXEMPTED_INDEX) {
+            // EXEMPTED apps always have their jobs exempted, even if they're buggy, because the
+            // user has explicitly told the system to avoid restricting the app for power reasons.
+            if (isBuggy) {
+                final String pkg;
+                if (getServiceComponent().getPackageName().equals(sourcePackageName)) {
+                    pkg = sourcePackageName;
+                } else {
+                    pkg = getServiceComponent().getPackageName() + "/" + sourcePackageName;
+                }
+                Slog.w(TAG, "Exempted app " + pkg + " considered buggy");
+            }
             return actualBucket;
         }
         if (uidActive || getJob().isExemptedFromAppStandby()) {
@@ -1038,13 +1166,18 @@
             // like other ACTIVE apps.
             return ACTIVE_INDEX;
         }
+        // If the app is considered buggy, but hasn't yet been put in the RESTRICTED bucket
+        // (potentially because it's used frequently by the user), limit its effective bucket
+        // so that it doesn't get to run as much as a normal ACTIVE app.
+        final int highestBucket = isBuggy ? WORKING_INDEX : ACTIVE_INDEX;
         if (actualBucket != RESTRICTED_INDEX && actualBucket != NEVER_INDEX
                 && mHasMediaBackupExemption) {
-            // Cap it at WORKING_INDEX as media back up jobs are important to the user, and the
+            // Treat it as if it's at least WORKING_INDEX since media backup jobs are important
+            // to the user, and the
             // source package may not have been used directly in a while.
-            return Math.min(WORKING_INDEX, actualBucket);
+            return Math.max(highestBucket, Math.min(WORKING_INDEX, actualBucket));
         }
-        return actualBucket;
+        return Math.max(highestBucket, actualBucket);
     }
 
     /** Returns the real standby bucket of the job. */
@@ -1117,10 +1250,16 @@
         return true;
     }
 
+    @Nullable
     public String getNamespace() {
         return mNamespace;
     }
 
+    @Nullable
+    public String getNamespaceHash() {
+        return mNamespaceHash;
+    }
+
     public String getSourceTag() {
         return sourceTag;
     }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 07958dd..1c29982 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -773,6 +773,14 @@
             // If quota is currently "free", then the job can run for the full amount of time,
             // regardless of bucket (hence using charging instead of isQuotaFreeLocked()).
             if (mService.isBatteryCharging()
+                    // The top and foreground cases here were added because apps in those states
+                    // aren't really restricted and the work could be something the user is
+                    // waiting for. Now that user-initiated jobs are a defined concept, we may
+                    // not need these exemptions as much. However, UIJs are currently limited
+                    // (as of UDC) to data transfer work. There may be other work that could
+                    // rely on this exception. Once we add more UIJ types, we can re-evaluate
+                    // the need for these exceptions.
+                    // TODO: re-evaluate the need for these exceptions
                     || mTopAppCache.get(jobStatus.getSourceUid())
                     || isTopStartedJobLocked(jobStatus)
                     || isUidInForeground(jobStatus.getSourceUid())) {
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 55e6815..7d38377 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -3025,7 +3025,7 @@
         public static final long DEFAULT_INITIAL_FOREGROUND_SERVICE_START_TIMEOUT =
                 COMPRESS_TIME ? ONE_MINUTE : 30 * ONE_MINUTE;
         public static final long DEFAULT_AUTO_RESTRICTED_BUCKET_DELAY_MS =
-                COMPRESS_TIME ? ONE_MINUTE : ONE_DAY;
+                COMPRESS_TIME ? ONE_MINUTE : ONE_HOUR;
         public static final boolean DEFAULT_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS = true;
         public static final long DEFAULT_BROADCAST_RESPONSE_WINDOW_DURATION_MS =
                 2 * ONE_MINUTE;
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 9eb9d66..9bd2970 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -3568,6 +3568,8 @@
     field public static final int ACCESSIBILITY_TITLE_CHANGED = 33554432; // 0x2000000
     field public static final int FLAG_SLIPPERY = 536870912; // 0x20000000
     field public CharSequence accessibilityTitle;
+    field public float preferredMaxDisplayRefreshRate;
+    field public float preferredMinDisplayRefreshRate;
     field public int privateFlags;
   }
 
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 12026aa..4cad585 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -568,13 +568,13 @@
      * repetition. lastPlayTime is similar and is used to calculate how many repeats have been
      * done between the two times.
      */
-    void animateValuesInRange(long currentPlayTime, long lastPlayTime, boolean notify) {}
+    void animateValuesInRange(long currentPlayTime, long lastPlayTime) {}
 
     /**
      * Internal use only. This animates any animation that has ended since lastPlayTime.
      * If an animation hasn't been finished, no change will be made.
      */
-    void animateSkipToEnds(long currentPlayTime, long lastPlayTime, boolean notify) {}
+    void animateSkipToEnds(long currentPlayTime, long lastPlayTime) {}
 
     /**
      * Internal use only. Adds all start times (after delay) to and end times to times.
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index f69bbfd3..2198fcd 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -111,19 +111,20 @@
             float pathErrorScale) throws NotFoundException {
         final ConfigurationBoundResourceCache<Animator> animatorCache = resources
                 .getAnimatorCache();
-        Animator animator = animatorCache.getInstance(id, resources, theme);
-        if (animator != null) {
+        ConfigurationBoundResourceCache.Entry<Animator> animatorEntry =
+                animatorCache.getInstance(id, resources, theme);
+        if (animatorEntry.hasValue()) {
             if (DBG_ANIMATOR_INFLATER) {
                 Log.d(TAG, "loaded animator from cache, " + resources.getResourceName(id));
             }
-            return animator;
+            return animatorEntry.getValue();
         } else if (DBG_ANIMATOR_INFLATER) {
             Log.d(TAG, "cache miss for animator " + resources.getResourceName(id));
         }
         XmlResourceParser parser = null;
         try {
             parser = resources.getAnimation(id);
-            animator = createAnimatorFromXml(resources, theme, parser, pathErrorScale);
+            Animator animator = createAnimatorFromXml(resources, theme, parser, pathErrorScale);
             if (animator != null) {
                 animator.appendChangingConfigurations(getChangingConfigs(resources, id));
                 final ConstantState<Animator> constantState = animator.createConstantState();
@@ -131,7 +132,7 @@
                     if (DBG_ANIMATOR_INFLATER) {
                         Log.d(TAG, "caching animator for res " + resources.getResourceName(id));
                     }
-                    animatorCache.put(id, theme, constantState);
+                    animatorCache.put(id, theme, constantState, animatorEntry.getGeneration());
                     // create a new animator so that cached version is never used by the user
                     animator = constantState.newInstance(resources, theme);
                 }
@@ -160,20 +161,22 @@
         final ConfigurationBoundResourceCache<StateListAnimator> cache = resources
                 .getStateListAnimatorCache();
         final Theme theme = context.getTheme();
-        StateListAnimator animator = cache.getInstance(id, resources, theme);
-        if (animator != null) {
-            return animator;
+        ConfigurationBoundResourceCache.Entry<StateListAnimator> animatorEntry =
+                cache.getInstance(id, resources, theme);
+        if (animatorEntry.hasValue()) {
+            return animatorEntry.getValue();
         }
         XmlResourceParser parser = null;
         try {
             parser = resources.getAnimation(id);
-            animator = createStateListAnimatorFromXml(context, parser, Xml.asAttributeSet(parser));
+            StateListAnimator animator =
+                    createStateListAnimatorFromXml(context, parser, Xml.asAttributeSet(parser));
             if (animator != null) {
                 animator.appendChangingConfigurations(getChangingConfigs(resources, id));
                 final ConstantState<StateListAnimator> constantState = animator
                         .createConstantState();
                 if (constantState != null) {
-                    cache.put(id, theme, constantState);
+                    cache.put(id, theme, constantState, animatorEntry.getGeneration());
                     // return a clone so that the animator in constant state is never used.
                     animator = constantState.newInstance(resources, theme);
                 }
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 60659dc..70c3d7a 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -825,8 +825,7 @@
     private void animateBasedOnPlayTime(
             long currentPlayTime,
             long lastPlayTime,
-            boolean inReverse,
-            boolean notify
+            boolean inReverse
     ) {
         if (currentPlayTime < 0 || lastPlayTime < -1) {
             throw new UnsupportedOperationException("Error: Play time should never be negative.");
@@ -857,8 +856,8 @@
             while (index < endIndex) {
                 long playTime = startEndTimes[index];
                 if (lastPlayTime != playTime) {
-                    animateSkipToEnds(playTime, lastPlayTime, notify);
-                    animateValuesInRange(playTime, lastPlayTime, notify);
+                    animateSkipToEnds(playTime, lastPlayTime);
+                    animateValuesInRange(playTime, lastPlayTime);
                     lastPlayTime = playTime;
                 }
                 index++;
@@ -868,15 +867,15 @@
                 index--;
                 long playTime = startEndTimes[index];
                 if (lastPlayTime != playTime) {
-                    animateSkipToEnds(playTime, lastPlayTime, notify);
-                    animateValuesInRange(playTime, lastPlayTime, notify);
+                    animateSkipToEnds(playTime, lastPlayTime);
+                    animateValuesInRange(playTime, lastPlayTime);
                     lastPlayTime = playTime;
                 }
             }
         }
         if (currentPlayTime != lastPlayTime) {
-            animateSkipToEnds(currentPlayTime, lastPlayTime, notify);
-            animateValuesInRange(currentPlayTime, lastPlayTime, notify);
+            animateSkipToEnds(currentPlayTime, lastPlayTime);
+            animateValuesInRange(currentPlayTime, lastPlayTime);
         }
     }
 
@@ -896,13 +895,11 @@
     }
 
     @Override
-    void animateSkipToEnds(long currentPlayTime, long lastPlayTime, boolean notify) {
+    void animateSkipToEnds(long currentPlayTime, long lastPlayTime) {
         initAnimation();
 
         if (lastPlayTime > currentPlayTime) {
-            if (notify) {
-                notifyStartListeners(true);
-            }
+            notifyStartListeners(true);
             for (int i = mEvents.size() - 1; i >= 0; i--) {
                 AnimationEvent event = mEvents.get(i);
                 Node node = event.mNode;
@@ -916,31 +913,25 @@
                     if (currentPlayTime <= start && start < lastPlayTime) {
                         animator.animateSkipToEnds(
                                 0,
-                                lastPlayTime - node.mStartTime,
-                                notify
+                                lastPlayTime - node.mStartTime
                         );
-                        if (notify) {
-                            mPlayingSet.remove(node);
-                        }
+                        mPlayingSet.remove(node);
                     } else if (start <= currentPlayTime && currentPlayTime <= end) {
                         animator.animateSkipToEnds(
                                 currentPlayTime - node.mStartTime,
-                                lastPlayTime - node.mStartTime,
-                                notify
+                                lastPlayTime - node.mStartTime
                         );
-                        if (notify && !mPlayingSet.contains(node)) {
+                        if (!mPlayingSet.contains(node)) {
                             mPlayingSet.add(node);
                         }
                     }
                 }
             }
-            if (currentPlayTime <= 0 && notify) {
+            if (currentPlayTime <= 0) {
                 notifyEndListeners(true);
             }
         } else {
-            if (notify) {
-                notifyStartListeners(false);
-            }
+            notifyStartListeners(false);
             int eventsSize = mEvents.size();
             for (int i = 0; i < eventsSize; i++) {
                 AnimationEvent event = mEvents.get(i);
@@ -955,45 +946,39 @@
                     if (lastPlayTime < end && end <= currentPlayTime) {
                         animator.animateSkipToEnds(
                                 end - node.mStartTime,
-                                lastPlayTime - node.mStartTime,
-                                notify
+                                lastPlayTime - node.mStartTime
                         );
-                        if (notify) {
-                            mPlayingSet.remove(node);
-                        }
+                        mPlayingSet.remove(node);
                     } else if (start <= currentPlayTime && currentPlayTime <= end) {
                         animator.animateSkipToEnds(
                                 currentPlayTime - node.mStartTime,
-                                lastPlayTime - node.mStartTime,
-                                notify
+                                lastPlayTime - node.mStartTime
                         );
-                        if (notify && !mPlayingSet.contains(node)) {
+                        if (!mPlayingSet.contains(node)) {
                             mPlayingSet.add(node);
                         }
                     }
                 }
             }
-            if (currentPlayTime >= getTotalDuration() && notify) {
+            if (currentPlayTime >= getTotalDuration()) {
                 notifyEndListeners(false);
             }
         }
     }
 
     @Override
-    void animateValuesInRange(long currentPlayTime, long lastPlayTime, boolean notify) {
+    void animateValuesInRange(long currentPlayTime, long lastPlayTime) {
         initAnimation();
 
-        if (notify) {
-            if (lastPlayTime < 0 || (lastPlayTime == 0 && currentPlayTime > 0)) {
-                notifyStartListeners(false);
-            } else {
-                long duration = getTotalDuration();
-                if (duration >= 0
-                        && (lastPlayTime > duration || (lastPlayTime == duration
-                        && currentPlayTime < duration))
-                ) {
-                    notifyStartListeners(true);
-                }
+        if (lastPlayTime < 0 || (lastPlayTime == 0 && currentPlayTime > 0)) {
+            notifyStartListeners(false);
+        } else {
+            long duration = getTotalDuration();
+            if (duration >= 0
+                    && (lastPlayTime > duration || (lastPlayTime == duration
+                    && currentPlayTime < duration))
+            ) {
+                notifyStartListeners(true);
             }
         }
 
@@ -1014,8 +999,7 @@
                 ) {
                     animator.animateValuesInRange(
                             currentPlayTime - node.mStartTime,
-                            Math.max(-1, lastPlayTime - node.mStartTime),
-                            notify
+                            Math.max(-1, lastPlayTime - node.mStartTime)
                     );
                 }
             }
@@ -1111,7 +1095,7 @@
             }
         }
         mSeekState.setPlayTime(playTime, mReversing);
-        animateBasedOnPlayTime(playTime, lastPlayTime, mReversing, true);
+        animateBasedOnPlayTime(playTime, lastPlayTime, mReversing);
     }
 
     /**
@@ -1144,16 +1128,7 @@
     private void initChildren() {
         if (!isInitialized()) {
             mChildrenInitialized = true;
-
-            // We have to initialize all the start values so that they are based on the previous
-            // values.
-            long[] times = ensureChildStartAndEndTimes();
-
-            long previousTime = -1;
-            for (long time : times) {
-                animateBasedOnPlayTime(time, previousTime, false, false);
-                previousTime = time;
-            }
+            skipToEndValue(false);
         }
     }
 
@@ -1489,6 +1464,7 @@
         anim.mPauseTime = -1;
         anim.mSeekState = new SeekState();
         anim.mSelfPulse = true;
+        anim.mStartListenersCalled = false;
         anim.mPlayingSet = new ArrayList<Node>();
         anim.mNodeMap = new ArrayMap<Animator, Node>();
         anim.mNodes = new ArrayList<Node>(nodeCount);
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index ead238f..5de7f38 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -1417,21 +1417,19 @@
      * will be called.
      */
     @Override
-    void animateValuesInRange(long currentPlayTime, long lastPlayTime, boolean notify) {
+    void animateValuesInRange(long currentPlayTime, long lastPlayTime) {
         if (currentPlayTime < 0 || lastPlayTime < -1) {
             throw new UnsupportedOperationException("Error: Play time should never be negative.");
         }
 
         initAnimation();
         long duration = getTotalDuration();
-        if (notify) {
-            if (lastPlayTime < 0 || (lastPlayTime == 0 && currentPlayTime > 0)) {
-                notifyStartListeners(false);
-            } else if (lastPlayTime > duration
-                    || (lastPlayTime == duration && currentPlayTime < duration)
-            ) {
-                notifyStartListeners(true);
-            }
+        if (lastPlayTime < 0 || (lastPlayTime == 0 && currentPlayTime > 0)) {
+            notifyStartListeners(false);
+        } else if (lastPlayTime > duration
+                || (lastPlayTime == duration && currentPlayTime < duration)
+        ) {
+            notifyStartListeners(true);
         }
         if (duration >= 0) {
             lastPlayTime = Math.min(duration, lastPlayTime);
@@ -1448,7 +1446,7 @@
             iteration = Math.min(iteration, mRepeatCount);
             lastIteration = Math.min(lastIteration, mRepeatCount);
 
-            if (notify && iteration != lastIteration) {
+            if (iteration != lastIteration) {
                 notifyListeners(AnimatorCaller.ON_REPEAT, false);
             }
         }
@@ -1464,7 +1462,7 @@
     }
 
     @Override
-    void animateSkipToEnds(long currentPlayTime, long lastPlayTime, boolean notify) {
+    void animateSkipToEnds(long currentPlayTime, long lastPlayTime) {
         boolean inReverse = currentPlayTime < lastPlayTime;
         boolean doSkip;
         if (currentPlayTime <= 0 && lastPlayTime > 0) {
@@ -1474,13 +1472,9 @@
             doSkip = duration >= 0 && currentPlayTime >= duration && lastPlayTime < duration;
         }
         if (doSkip) {
-            if (notify) {
-                notifyStartListeners(inReverse);
-            }
+            notifyStartListeners(inReverse);
             skipToEndValue(inReverse);
-            if (notify) {
-                notifyEndListeners(inReverse);
-            }
+            notifyEndListeners(inReverse);
         }
     }
 
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 57935e3..70e924a 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -2933,62 +2933,21 @@
             }
         }
 
-        if (!isComponentExist(context, cn)) {
-            cn = null;
-        }
-
-        return cn;
-    }
-
-    /**
-     * Return {@link ComponentName} of the CMF default wallpaper, or
-     * {@link #getDefaultWallpaperComponent(Context)} if none is defined.
-     *
-     * @hide
-     */
-    public static ComponentName getCmfDefaultWallpaperComponent(Context context) {
-        ComponentName cn = null;
-        String[] cmfWallpaperMap = context.getResources().getStringArray(
-                com.android.internal.R.array.cmf_default_wallpaper_component);
-        if (cmfWallpaperMap == null || cmfWallpaperMap.length == 0) {
-            Log.d(TAG, "No CMF wallpaper config");
-            return getDefaultWallpaperComponent(context);
-        }
-
-        for (String entry : cmfWallpaperMap) {
-            String[] cmfWallpaper;
-            if (!TextUtils.isEmpty(entry)) {
-                cmfWallpaper = entry.split(",");
-                if (cmfWallpaper != null && cmfWallpaper.length == 2 && VALUE_CMF_COLOR.equals(
-                        cmfWallpaper[0]) && !TextUtils.isEmpty(cmfWallpaper[1])) {
-                    cn = ComponentName.unflattenFromString(cmfWallpaper[1]);
-                    break;
-                }
+        // Check if the package exists
+        if (cn != null) {
+            try {
+                final PackageManager packageManager = context.getPackageManager();
+                packageManager.getPackageInfo(cn.getPackageName(),
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
+            } catch (PackageManager.NameNotFoundException e) {
+                cn = null;
             }
         }
 
-        if (!isComponentExist(context, cn)) {
-            cn = null;
-        }
-
         return cn;
     }
 
-    private static boolean isComponentExist(Context context, ComponentName cn) {
-        if (cn == null) {
-            return false;
-        }
-        try {
-            final PackageManager packageManager = context.getPackageManager();
-            packageManager.getPackageInfo(cn.getPackageName(),
-                    PackageManager.MATCH_DIRECT_BOOT_AWARE
-                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
-        } catch (PackageManager.NameNotFoundException e) {
-            return false;
-        }
-        return true;
-    }
-
     /**
      * Register a callback for lock wallpaper observation. Only the OS may use this.
      *
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index b2a9230..da5e40a 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -11369,7 +11369,8 @@
      * @throws SecurityException     if the caller is not a profile owner on an organization-owned
      *                               managed profile.
      * @throws IllegalStateException if called after the device setup has been completed.
-     * @throws UnsupportedOperationException if the api is not enabled.
+     * @throws UnsupportedOperationException if managed subscriptions policy is not explicitly
+     *         enabled by the device policy management role holder during device setup.
      * @see ManagedSubscriptionsPolicy
      */
     public void setManagedSubscriptionsPolicy(@Nullable ManagedSubscriptionsPolicy policy) {
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 7be00a0..3487e0b 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -827,6 +827,12 @@
      */
     public static final int PRIVATE_FLAG_EXT_ALLOWLISTED_FOR_HIDDEN_APIS = 1 << 4;
 
+    /**
+     * Whether AbiOverride was used when installing this application.
+     * @hide
+     */
+    public static final int PRIVATE_FLAG_EXT_CPU_OVERRIDE = 1 << 5;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "PRIVATE_FLAG_EXT_" }, value = {
             PRIVATE_FLAG_EXT_PROFILEABLE,
@@ -834,6 +840,7 @@
             PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE,
             PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK,
             PRIVATE_FLAG_EXT_ALLOWLISTED_FOR_HIDDEN_APIS,
+            PRIVATE_FLAG_EXT_CPU_OVERRIDE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ApplicationInfoPrivateFlagsExt {}
diff --git a/core/java/android/content/pm/UserProperties.java b/core/java/android/content/pm/UserProperties.java
index 77b1954..2669040 100644
--- a/core/java/android/content/pm/UserProperties.java
+++ b/core/java/android/content/pm/UserProperties.java
@@ -184,7 +184,7 @@
      * device policies from its parent profile.
      *
      *<p> All the user restrictions and device policies would be not propagated to the profile
-     * with this property value. The {(TODO:b/256978256) @link DevicePolicyEngine}
+     * with this property value. The {@link com.android.server.devicepolicy.DevicePolicyEngine}
      * uses this property to determine and propagate only select ones to the given profile.
      *
      * @hide
diff --git a/core/java/android/content/res/ConfigurationBoundResourceCache.java b/core/java/android/content/res/ConfigurationBoundResourceCache.java
index 5e10a57..4da3c18 100644
--- a/core/java/android/content/res/ConfigurationBoundResourceCache.java
+++ b/core/java/android/content/res/ConfigurationBoundResourceCache.java
@@ -37,16 +37,16 @@
      * @param key a key that uniquely identifies the drawable resource
      * @param resources a Resources object from which to create new instances.
      * @param theme the theme where the resource will be used
-     * @return a new instance of the resource, or {@code null} if not in
+     * @return an Entry wrapping a new instance of the resource, or {@code null} if not in
      *         the cache
      */
-    public T getInstance(long key, Resources resources, Resources.Theme theme) {
-        final ConstantState<T> entry = get(key, theme);
-        if (entry != null) {
-            return entry.newInstance(resources, theme);
+    public Entry<T> getInstance(long key, Resources resources, Resources.Theme theme) {
+        final Entry<ConstantState<T>> e = get(key, theme);
+        if (e.hasValue()) {
+            return new Entry<>(e.getValue().newInstance(resources, theme), e.getGeneration());
         }
 
-        return null;
+        return new Entry<>(null, e.getGeneration());
     }
 
     @Override
diff --git a/core/java/android/content/res/DrawableCache.java b/core/java/android/content/res/DrawableCache.java
index d0ebe33..b51d14a 100644
--- a/core/java/android/content/res/DrawableCache.java
+++ b/core/java/android/content/res/DrawableCache.java
@@ -40,14 +40,32 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public Drawable getInstance(long key, Resources resources, Resources.Theme theme) {
-        final Drawable.ConstantState entry = get(key, theme);
-        if (entry != null) {
-            return entry.newDrawable(resources, theme);
+        final Entry<Drawable.ConstantState> entry = get(key, theme);
+        if (entry.getValue() != null) {
+            return entry.getValue().newDrawable(resources, theme);
         }
 
         return null;
     }
 
+    /**
+     * If the resource is cached, creates and returns a new instance of it.
+     *
+     * @param key a key that uniquely identifies the drawable resource
+     * @param resources a Resources object from which to create new instances.
+     * @param theme the theme where the resource will be used
+     * @return an Entry wrapping a a new instance of the resource, or {@code null} if not in
+     *         the cache
+     */
+    public Entry<Drawable> getDrawable(long key, Resources resources, Resources.Theme theme) {
+        final Entry<Drawable.ConstantState> e = get(key, theme);
+        if (e.hasValue()) {
+            return new Entry<>(e.getValue().newDrawable(resources, theme), e.getGeneration());
+        }
+
+        return new Entry<>(null, e.getGeneration());
+    }
+
     @Override
     public boolean shouldInvalidateEntry(Drawable.ConstantState entry, int configChanges) {
         return Configuration.needNewResources(configChanges, entry.getChangingConfigurations());
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 3a2863e..25154d5 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -650,15 +650,21 @@
                 key = (((long) value.assetCookie) << 32) | value.data;
             }
 
+            int cacheGeneration;
             // First, check whether we have a cached version of this drawable
             // that was inflated against the specified theme. Skip the cache if
             // we're currently preloading or we're not using the cache.
             if (!mPreloading && useCache) {
-                final Drawable cachedDrawable = caches.getInstance(key, wrapper, theme);
-                if (cachedDrawable != null) {
-                    cachedDrawable.setChangingConfigurations(value.changingConfigurations);
-                    return cachedDrawable;
+                final ThemedResourceCache.Entry<Drawable> cachedDrawable =
+                        caches.getDrawable(key, wrapper, theme);
+                if (cachedDrawable.hasValue()) {
+                    cachedDrawable.getValue().setChangingConfigurations(
+                            value.changingConfigurations);
+                    return cachedDrawable.getValue();
                 }
+                cacheGeneration = cachedDrawable.getGeneration();
+            } else {
+                cacheGeneration = ThemedResourceCache.UNDEFINED_GENERATION;
             }
 
             // Next, check preloaded drawables. Preloaded drawables may contain
@@ -702,7 +708,8 @@
             if (dr != null) {
                 dr.setChangingConfigurations(value.changingConfigurations);
                 if (useCache) {
-                    cacheDrawable(value, isColorDrawable, caches, theme, canApplyTheme, key, dr);
+                    cacheDrawable(value, isColorDrawable, caches, theme, canApplyTheme, key, dr,
+                            cacheGeneration);
                     if (needsNewDrawableAfterCache) {
                         Drawable.ConstantState state = dr.getConstantState();
                         if (state != null) {
@@ -733,7 +740,7 @@
     }
 
     private void cacheDrawable(TypedValue value, boolean isColorDrawable, DrawableCache caches,
-            Resources.Theme theme, boolean usesTheme, long key, Drawable dr) {
+            Resources.Theme theme, boolean usesTheme, long key, Drawable dr, int cacheGeneration) {
         final Drawable.ConstantState cs = dr.getConstantState();
         if (cs == null) {
             return;
@@ -761,7 +768,7 @@
             }
         } else {
             synchronized (mAccessLock) {
-                caches.put(key, theme, cs, usesTheme);
+                caches.put(key, theme, cs, cacheGeneration, usesTheme);
             }
         }
     }
@@ -1002,14 +1009,16 @@
             TypedValue value, int id) {
         final long key = (((long) value.assetCookie) << 32) | value.data;
         final ConfigurationBoundResourceCache<ComplexColor> cache = mComplexColorCache;
-        ComplexColor complexColor = cache.getInstance(key, wrapper, theme);
-        if (complexColor != null) {
-            return complexColor;
+        ThemedResourceCache.Entry<ComplexColor> complexColorEntry =
+                cache.getInstance(key, wrapper, theme);
+        if (complexColorEntry.hasValue()) {
+            return complexColorEntry.getValue();
         }
 
         final android.content.res.ConstantState<ComplexColor> factory =
                 sPreloadedComplexColors.get(key);
 
+        ComplexColor complexColor = null;
         if (factory != null) {
             complexColor = factory.newInstance(wrapper, theme);
         }
@@ -1026,7 +1035,8 @@
                     sPreloadedComplexColors.put(key, complexColor.getConstantState());
                 }
             } else {
-                cache.put(key, theme, complexColor.getConstantState());
+                cache.put(key, theme, complexColor.getConstantState(),
+                        complexColorEntry.getGeneration());
             }
         }
         return complexColor;
diff --git a/core/java/android/content/res/ThemedResourceCache.java b/core/java/android/content/res/ThemedResourceCache.java
index 3270944..e7fd275 100644
--- a/core/java/android/content/res/ThemedResourceCache.java
+++ b/core/java/android/content/res/ThemedResourceCache.java
@@ -33,11 +33,37 @@
  * @param <T> type of data to cache
  */
 abstract class ThemedResourceCache<T> {
+    public static final int UNDEFINED_GENERATION = -1;
     @UnsupportedAppUsage
     private ArrayMap<ThemeKey, LongSparseArray<WeakReference<T>>> mThemedEntries;
     private LongSparseArray<WeakReference<T>> mUnthemedEntries;
     private LongSparseArray<WeakReference<T>> mNullThemedEntries;
 
+    private int mGeneration;
+
+    public static class Entry<S> {
+        private S mValue;
+        private int mGeneration;
+
+
+        public S getValue() {
+            return mValue;
+        }
+
+        public boolean hasValue() {
+            return mValue != null;
+        }
+
+        public int getGeneration() {
+            return mGeneration;
+        }
+
+        Entry(S value, int generation) {
+            this.mValue = value;
+            this.mGeneration = generation;
+        }
+    }
+
     /**
      * Adds a new theme-dependent entry to the cache.
      *
@@ -45,9 +71,10 @@
      * @param theme the theme against which this entry was inflated, or
      *              {@code null} if the entry has no theme applied
      * @param entry the entry to cache
+     * @param generation The generation of the cache to compare against before storing
      */
-    public void put(long key, @Nullable Theme theme, @NonNull T entry) {
-        put(key, theme, entry, true);
+    public void put(long key, @Nullable Theme theme, @NonNull T entry, int generation) {
+        put(key, theme, entry, generation, true);
     }
 
     /**
@@ -57,10 +84,12 @@
      * @param theme the theme against which this entry was inflated, or
      *              {@code null} if the entry has no theme applied
      * @param entry the entry to cache
+     * @param generation The generation of the cache to compare against before storing
      * @param usesTheme {@code true} if the entry is affected theme changes,
      *                  {@code false} otherwise
      */
-    public void put(long key, @Nullable Theme theme, @NonNull T entry, boolean usesTheme) {
+    public void put(long key, @Nullable Theme theme, @NonNull T entry, int generation,
+            boolean usesTheme) {
         if (entry == null) {
             return;
         }
@@ -72,7 +101,8 @@
             } else {
                 entries = getThemedLocked(theme, true);
             }
-            if (entries != null) {
+            if (entries != null
+                    && ((generation == mGeneration) || (generation == UNDEFINED_GENERATION)))  {
                 entries.put(key, new WeakReference<>(entry));
             }
         }
@@ -86,7 +116,7 @@
      * @return a cached entry, or {@code null} if not in the cache
      */
     @Nullable
-    public T get(long key, @Nullable Theme theme) {
+    public Entry get(long key, @Nullable Theme theme) {
         // The themed (includes null-themed) and unthemed caches are mutually
         // exclusive, so we'll give priority to whichever one we think we'll
         // hit first. Since most of the framework drawables are themed, that's
@@ -96,7 +126,7 @@
             if (themedEntries != null) {
                 final WeakReference<T> themedEntry = themedEntries.get(key);
                 if (themedEntry != null) {
-                    return themedEntry.get();
+                    return new Entry(themedEntry.get(), mGeneration);
                 }
             }
 
@@ -104,12 +134,12 @@
             if (unthemedEntries != null) {
                 final WeakReference<T> unthemedEntry = unthemedEntries.get(key);
                 if (unthemedEntry != null) {
-                    return unthemedEntry.get();
+                    return new Entry(unthemedEntry.get(), mGeneration);
                 }
             }
         }
 
-        return null;
+        return new Entry(null, mGeneration);
     }
 
     /**
@@ -121,6 +151,7 @@
     @UnsupportedAppUsage
     public void onConfigurationChange(@Config int configChanges) {
         prune(configChanges);
+        mGeneration++;
     }
 
     /**
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index b453304..76efce5 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -53,8 +53,6 @@
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 
-import libcore.util.EmptyArray;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
@@ -667,7 +665,7 @@
         } else if (category == null || DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED.equals(category)) {
             return getDisplays(displayIds, Objects::nonNull);
         }
-        return (Display[]) EmptyArray.OBJECT;
+        return new Display[0];
     }
 
     private Display[] getDisplays(int[] displayIds, Predicate<Display> predicate) {
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 931adb5..ef274a5 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -23,6 +23,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.app.Activity;
+import android.app.ActivityOptions;
 import android.app.Application.ActivityLifecycleCallbacks;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
@@ -535,7 +536,11 @@
                     return null;
                 }
                 try {
-                    mContext.startIntentSender(intent, null, 0, 0, 0);
+                    ActivityOptions activityOptions = ActivityOptions.makeBasic()
+                            .setPendingIntentBackgroundActivityStartMode(
+                                    ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
+                    mContext.startIntentSender(intent, null, 0, 0, 0,
+                            activityOptions.toBundle());
                     return new PrintJob(printJob, this);
                 } catch (SendIntentException sie) {
                     Log.e(LOG_TAG, "Couldn't start print job config activity.", sie);
diff --git a/core/java/android/service/notification/TEST_MAPPING b/core/java/android/service/notification/TEST_MAPPING
new file mode 100644
index 0000000..59b2bc1
--- /dev/null
+++ b/core/java/android/service/notification/TEST_MAPPING
@@ -0,0 +1,49 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsNotificationTestCases",
+      "options": [
+        {
+          "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        },
+        {
+          "exclude-annotation": "org.junit.Ignore"
+        },
+        {
+          "exclude-annotation": "android.platform.test.annotations.LargeTest"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.LargeTest"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksUiServicesTests",
+      "options": [
+        {
+          "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        },
+        {
+          "exclude-annotation": "org.junit.Ignore"
+        },
+        {
+          "exclude-annotation": "android.platform.test.annotations.LargeTest"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.LargeTest"
+        }
+      ]
+    }
+  ],
+  "postsubmit": [
+    {
+      "name": "CtsNotificationTestCases"
+    }
+  ]
+}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 7e4e402..5019b85 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -1099,21 +1099,25 @@
         // TODO: Support a ResultReceiver for IME.
         // TODO(b/123718661): Make show() work for multi-session IME.
         int typesReady = 0;
+        final boolean imeVisible = mState.isSourceOrDefaultVisible(
+                mImeSourceConsumer.getId(), ime());
         for (int type = FIRST; type <= LAST; type = type << 1) {
             if ((types & type) == 0) {
                 continue;
             }
             @AnimationType final int animationType = getAnimationType(type);
             final boolean requestedVisible = (type & mRequestedVisibleTypes) != 0;
-            final boolean isImeAnimation = type == ime();
-            if (requestedVisible && animationType == ANIMATION_TYPE_NONE
-                    || animationType == ANIMATION_TYPE_SHOW) {
+            final boolean isIme = type == ime();
+            var alreadyVisible = requestedVisible && (!isIme || imeVisible)
+                    && animationType == ANIMATION_TYPE_NONE;
+            var alreadyAnimatingShow = animationType == ANIMATION_TYPE_SHOW;
+            if (alreadyVisible || alreadyAnimatingShow) {
                 // 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",
                         type, animationType, requestedVisible));
-                if (isImeAnimation) {
+                if (isIme) {
                     ImeTracker.forLogging().onCancelled(statsToken,
                             ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
                 }
@@ -1121,13 +1125,13 @@
             }
             if (fromIme && animationType == ANIMATION_TYPE_USER) {
                 // App is already controlling the IME, don't cancel it.
-                if (isImeAnimation) {
+                if (isIme) {
                     ImeTracker.forLogging().onFailed(
                             statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
                 }
                 continue;
             }
-            if (isImeAnimation) {
+            if (isIme) {
                 ImeTracker.forLogging().onProgress(
                         statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
             }
diff --git a/core/java/android/view/InsetsFrameProvider.java b/core/java/android/view/InsetsFrameProvider.java
index 470c280..37b6c77 100644
--- a/core/java/android/view/InsetsFrameProvider.java
+++ b/core/java/android/view/InsetsFrameProvider.java
@@ -223,6 +223,10 @@
         if (mArbitraryRectangle != null) {
             sb.append(", mArbitraryRectangle=").append(mArbitraryRectangle.toShortString());
         }
+        if (mMinimalInsetsSizeInDisplayCutoutSafe != null) {
+            sb.append(", mMinimalInsetsSizeInDisplayCutoutSafe=")
+                    .append(mMinimalInsetsSizeInDisplayCutoutSafe);
+        }
         sb.append("}");
         return sb.toString();
     }
@@ -248,6 +252,7 @@
         mInsetsSize = in.readTypedObject(Insets.CREATOR);
         mInsetsSizeOverrides = in.createTypedArray(InsetsSizeOverride.CREATOR);
         mArbitraryRectangle = in.readTypedObject(Rect.CREATOR);
+        mMinimalInsetsSizeInDisplayCutoutSafe = in.readTypedObject(Insets.CREATOR);
     }
 
     @Override
@@ -258,6 +263,7 @@
         out.writeTypedObject(mInsetsSize, flags);
         out.writeTypedArray(mInsetsSizeOverrides, flags);
         out.writeTypedObject(mArbitraryRectangle, flags);
+        out.writeTypedObject(mMinimalInsetsSizeInDisplayCutoutSafe, flags);
     }
 
     public boolean idEquals(InsetsFrameProvider o) {
@@ -276,13 +282,16 @@
         return mId == other.mId && mSource == other.mSource && mFlags == other.mFlags
                 && Objects.equals(mInsetsSize, other.mInsetsSize)
                 && Arrays.equals(mInsetsSizeOverrides, other.mInsetsSizeOverrides)
-                && Objects.equals(mArbitraryRectangle, other.mArbitraryRectangle);
+                && Objects.equals(mArbitraryRectangle, other.mArbitraryRectangle)
+                && Objects.equals(mMinimalInsetsSizeInDisplayCutoutSafe,
+                        other.mMinimalInsetsSizeInDisplayCutoutSafe);
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mId, mSource, mFlags, mInsetsSize,
-                Arrays.hashCode(mInsetsSizeOverrides), mArbitraryRectangle);
+                Arrays.hashCode(mInsetsSizeOverrides), mArbitraryRectangle,
+                mMinimalInsetsSizeInDisplayCutoutSafe);
     }
 
     public static final @NonNull Parcelable.Creator<InsetsFrameProvider> CREATOR =
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4eb436e..a28be4b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2426,7 +2426,7 @@
      *
      * @hide
      */
-    void notifyRendererOfExpensiveFrame() {
+    public void notifyRendererOfExpensiveFrame() {
         if (mAttachInfo.mThreadedRenderer != null) {
             mAttachInfo.mThreadedRenderer.notifyExpensiveFrame();
         }
@@ -5459,7 +5459,7 @@
     }
 
     private void updateRenderHdrSdrRatio() {
-        mRenderHdrSdrRatio = mDisplay.getHdrSdrRatio();
+        mRenderHdrSdrRatio = Math.min(mDesiredHdrSdrRatio, mDisplay.getHdrSdrRatio());
         mUpdateHdrSdrRatioInfo = true;
     }
 
@@ -5487,22 +5487,14 @@
                 mHdrSdrRatioChangedListener = null;
             } else {
                 mHdrSdrRatioChangedListener = display -> {
-                    setTargetHdrSdrRatio(display.getHdrSdrRatio());
+                    updateRenderHdrSdrRatio();
+                    invalidate();
                 };
                 mDisplay.registerHdrSdrRatioChangedListener(mExecutor, mHdrSdrRatioChangedListener);
             }
         }
     }
 
-    /** happylint */
-    public void setTargetHdrSdrRatio(float ratio) {
-        if (mRenderHdrSdrRatio != ratio) {
-            mRenderHdrSdrRatio = ratio;
-            mUpdateHdrSdrRatioInfo = true;
-            invalidate();
-        }
-    }
-
     @Override
     public void requestChildFocus(View child, View focused) {
         if (DEBUG_INPUT_RESIZE) {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e40f8e7..a917815 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -435,11 +435,15 @@
     int TRANSIT_KEYGUARD_GOING_AWAY = 7;
     /**
      * A window is appearing above a locked keyguard.
+     * @deprecated use {@link #TRANSIT_TO_FRONT} + {@link #TRANSIT_FLAG_KEYGUARD_OCCLUDING} for
+     *             keyguard occluding with Shell transition.
      * @hide
      */
     int TRANSIT_KEYGUARD_OCCLUDE = 8;
     /**
      * A window is made invisible revealing a locked keyguard.
+     * @deprecated use {@link #TRANSIT_TO_BACK} + {@link #TRANSIT_FLAG_KEYGUARD_UNOCCLUDING} for
+     *             keyguard occluding with Shell transition.
      * @hide
      */
     int TRANSIT_KEYGUARD_UNOCCLUDE = 9;
@@ -562,6 +566,25 @@
     int TRANSIT_FLAG_INVISIBLE = (1 << 10); // 0x400
 
     /**
+     * Transition flag: Indicates that keyguard will be showing (locked) with this transition,
+     * which is the opposite of {@link #TRANSIT_FLAG_KEYGUARD_GOING_AWAY}.
+     * @hide
+     */
+    int TRANSIT_FLAG_KEYGUARD_APPEARING = (1 << 11); // 0x800
+
+    /**
+     * Transition flag: Indicates that keyguard is becoming hidden by an app
+     * @hide
+     */
+    int TRANSIT_FLAG_KEYGUARD_OCCLUDING = (1 << 12); // 0x1000
+
+    /**
+     * Transition flag: Indicates that keyguard is being revealed after an app was occluding it.
+     * @hide
+     */
+    int TRANSIT_FLAG_KEYGUARD_UNOCCLUDING = (1 << 13); // 0x2000
+
+    /**
      * @hide
      */
     @IntDef(flag = true, prefix = { "TRANSIT_FLAG_" }, value = {
@@ -576,11 +599,28 @@
             TRANSIT_FLAG_KEYGUARD_GOING_AWAY,
             TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_LAUNCHER_CLEAR_SNAPSHOT,
             TRANSIT_FLAG_INVISIBLE,
+            TRANSIT_FLAG_KEYGUARD_APPEARING,
+            TRANSIT_FLAG_KEYGUARD_OCCLUDING,
+            TRANSIT_FLAG_KEYGUARD_UNOCCLUDING
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface TransitionFlags {}
 
     /**
+     * Transit flags used to signal keyguard visibility is changing for animations.
+     *
+     * <p>These roughly correspond to CLOSE, OPEN, TO_BACK, and TO_FRONT on a hypothetical Keyguard
+     * container. Since Keyguard isn't a container we can't include it in changes and need to send
+     * this information in its own channel.
+     * @hide
+     */
+    int KEYGUARD_VISIBILITY_TRANSIT_FLAGS =
+            (TRANSIT_FLAG_KEYGUARD_GOING_AWAY
+            | TRANSIT_FLAG_KEYGUARD_APPEARING
+            | TRANSIT_FLAG_KEYGUARD_OCCLUDING
+            | TRANSIT_FLAG_KEYGUARD_UNOCCLUDING);
+
+    /**
      * Remove content mode: Indicates remove content mode is currently not defined.
      * @hide
      */
@@ -3763,6 +3803,7 @@
          * This value is ignored if {@link #preferredDisplayModeId} is set.
          * @hide
          */
+        @TestApi
         public float preferredMinDisplayRefreshRate;
 
         /**
@@ -3771,6 +3812,7 @@
          * This value is ignored if {@link #preferredDisplayModeId} is set.
          * @hide
          */
+        @TestApi
         public float preferredMaxDisplayRefreshRate;
 
         /** Indicates whether this window wants the HDR conversion is disabled. */
diff --git a/core/java/android/view/autofill/AutofillFeatureFlags.java b/core/java/android/view/autofill/AutofillFeatureFlags.java
index 5ad74c8..461b78c 100644
--- a/core/java/android/view/autofill/AutofillFeatureFlags.java
+++ b/core/java/android/view/autofill/AutofillFeatureFlags.java
@@ -283,6 +283,9 @@
     private static final String DEFAULT_AFAA_NON_AUTOFILLABLE_IME_ACTIONS = "3,4";
     private static final boolean DEFAULT_AFAA_SHOULD_ENABLE_AUTOFILL_ON_ALL_VIEW_TYPES = true;
     private static final boolean DEFAULT_AFAA_SHOULD_ENABLE_MULTILINE_FILTER = true;
+    private static final boolean
+            DEFAULT_AFAA_SHOULD_INCLUDE_ALL_AUTOFILL_TYPE_NOT_NONE_VIEWS_IN_ASSIST_STRUCTURE = true;
+    // END AUTOFILL FOR ALL APPS DEFAULTS
 
     private AutofillFeatureFlags() {};
 
@@ -414,7 +417,8 @@
     public static boolean shouldIncludeAllViewsAutofillTypeNotNoneInAssistStructrue() {
         return DeviceConfig.getBoolean(
             DeviceConfig.NAMESPACE_AUTOFILL,
-            DEVICE_CONFIG_INCLUDE_ALL_AUTOFILL_TYPE_NOT_NONE_VIEWS_IN_ASSIST_STRUCTURE, false);
+            DEVICE_CONFIG_INCLUDE_ALL_AUTOFILL_TYPE_NOT_NONE_VIEWS_IN_ASSIST_STRUCTURE,
+            DEFAULT_AFAA_SHOULD_INCLUDE_ALL_AUTOFILL_TYPE_NOT_NONE_VIEWS_IN_ASSIST_STRUCTURE);
     }
 
     /**
diff --git a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
index 50e95c8..ee36dc7 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
@@ -17,6 +17,7 @@
 package android.view.inputmethod;
 
 import android.compat.annotation.UnsupportedAppUsage;
+import android.os.BadParcelableException;
 import android.os.Parcel;
 import android.util.Slog;
 
@@ -69,6 +70,9 @@
      */
     public InputMethodSubtypeArray(final Parcel source) {
         mCount = source.readInt();
+        if (mCount < 0) {
+            throw new BadParcelableException("mCount must be non-negative.");
+        }
         if (mCount > 0) {
             mDecompressedSize = source.readInt();
             mCompressedData = source.createByteArray();
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index 8b04d35..63bf562 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -21,6 +21,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityOptions;
 import android.app.PendingIntent;
 import android.app.RemoteAction;
 import android.content.Context;
@@ -301,7 +302,8 @@
         Objects.requireNonNull(intent);
         return v -> {
             try {
-                intent.send();
+                intent.send(ActivityOptions.makeBasic().setPendingIntentBackgroundActivityStartMode(
+                        ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED).toBundle());
             } catch (PendingIntent.CanceledException e) {
                 Log.e(LOG_TAG, "Error sending PendingIntent", e);
             }
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index a92ca8a..d2a16a3 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -99,9 +99,6 @@
     /** The container is the display. */
     public static final int FLAG_IS_DISPLAY = 1 << 5;
 
-    /** The container can show on top of lock screen. */
-    public static final int FLAG_OCCLUDES_KEYGUARD = 1 << 6;
-
     /**
      * Only for IS_DISPLAY containers. Is set if the display has system alert windows. This is
      * used to prevent seamless rotation.
@@ -175,7 +172,6 @@
             FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT,
             FLAG_IS_VOICE_INTERACTION,
             FLAG_IS_DISPLAY,
-            FLAG_OCCLUDES_KEYGUARD,
             FLAG_DISPLAY_HAS_ALERT_WINDOWS,
             FLAG_IS_INPUT_METHOD,
             FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY,
@@ -457,9 +453,6 @@
         if ((flags & FLAG_IS_DISPLAY) != 0) {
             sb.append(sb.length() == 0 ? "" : "|").append("IS_DISPLAY");
         }
-        if ((flags & FLAG_OCCLUDES_KEYGUARD) != 0) {
-            sb.append(sb.length() == 0 ? "" : "|").append("OCCLUDES_KEYGUARD");
-        }
         if ((flags & FLAG_DISPLAY_HAS_ALERT_WINDOWS) != 0) {
             sb.append(sb.length() == 0 ? "" : "|").append("DISPLAY_HAS_ALERT_WINDOWS");
         }
@@ -557,6 +550,16 @@
     }
 
     /**
+     * Updates the callsites of all the surfaces in this transition, which aids in the debugging of
+     * lingering surfaces.
+     */
+    public void setUnreleasedWarningCallSiteForAllSurfaces(String callsite) {
+        for (int i = mChanges.size() - 1; i >= 0; --i) {
+            mChanges.get(i).getLeash().setUnreleasedWarningCallSite(callsite);
+        }
+    }
+
+    /**
      * Makes a copy of this as if it were parcel'd and unparcel'd. This implies that surfacecontrol
      * refcounts are incremented which allows the "remote" receiver to release them without breaking
      * the caller's references. Use this only if you need to "send" this to a local function which
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index 421d998..632208c 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -163,19 +163,25 @@
         // Re-populate the top callback to WM if the removed callback was previously the top one.
         if (previousTopCallback == callback) {
             // We should call onBackCancelled() when an active callback is removed from dispatcher.
-            if (mProgressAnimator.isBackAnimationInProgress()
-                    && callback instanceof OnBackAnimationCallback) {
-                // The ProgressAnimator will handle the new topCallback, so we don't want to call
-                // onBackCancelled() on it. We call immediately the callback instead.
-                OnBackAnimationCallback animatedCallback = (OnBackAnimationCallback) callback;
-                animatedCallback.onBackCancelled();
-                Log.d(TAG, "The callback was removed while a back animation was in progress, "
-                        + "an onBackCancelled() was dispatched.");
-            }
+            sendCancelledIfInProgress(callback);
             setTopOnBackInvokedCallback(getTopCallback());
         }
     }
 
+    private void sendCancelledIfInProgress(@NonNull OnBackInvokedCallback callback) {
+        boolean isInProgress = mProgressAnimator.isBackAnimationInProgress();
+        if (isInProgress && callback instanceof OnBackAnimationCallback) {
+            OnBackAnimationCallback animatedCallback = (OnBackAnimationCallback) callback;
+            animatedCallback.onBackCancelled();
+            if (DEBUG) {
+                Log.d(TAG, "sendCancelIfRunning: callback canceled");
+            }
+        } else {
+            Log.w(TAG, "sendCancelIfRunning: isInProgress=" + isInProgress
+                    + "callback=" + callback);
+        }
+    }
+
     @Override
     public void registerSystemOnBackInvokedCallback(@NonNull OnBackInvokedCallback callback) {
         registerOnBackInvokedCallbackUnchecked(callback, OnBackInvokedDispatcher.PRIORITY_SYSTEM);
@@ -188,9 +194,20 @@
             mImeDispatcher = null;
         }
         if (!mAllCallbacks.isEmpty()) {
+            OnBackInvokedCallback topCallback = getTopCallback();
+            if (topCallback != null) {
+                sendCancelledIfInProgress(topCallback);
+            } else {
+                // Should not be possible
+                Log.e(TAG, "There is no topCallback, even if mAllCallbacks is not empty");
+            }
             // Clear binder references in WM.
             setTopOnBackInvokedCallback(null);
         }
+
+        // We should also stop running animations since all callbacks have been removed.
+        // note: mSpring.skipToEnd(), in ProgressAnimator.reset(), requires the main handler.
+        Handler.getMain().post(mProgressAnimator::reset);
         mAllCallbacks.clear();
         mOnBackInvokedCallbacks.clear();
     }
@@ -342,12 +359,17 @@
         @Override
         public void onBackInvoked() throws RemoteException {
             Handler.getMain().post(() -> {
+                boolean isInProgress = mProgressAnimator.isBackAnimationInProgress();
                 mProgressAnimator.reset();
                 final OnBackInvokedCallback callback = mCallbackRef.get();
                 if (callback == null) {
                     Log.d(TAG, "Trying to call onBackInvoked() on a null callback reference.");
                     return;
                 }
+                if (callback instanceof OnBackAnimationCallback && !isInProgress) {
+                    Log.w(TAG, "ProgressAnimator was not in progress, skip onBackInvoked().");
+                    return;
+                }
                 callback.onBackInvoked();
             });
         }
diff --git a/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java b/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
index 3d95dd3..c9e7600 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
@@ -81,6 +81,10 @@
         /** Gating the logging of DND state change events. */
         public static final Flag LOG_DND_STATE_EVENTS =
                 releasedFlag("persist.sysui.notification.log_dnd_state_events");
+
+        /** Gating the holding of WakeLocks until NLSes are told about a new notification. */
+        public static final Flag WAKE_LOCK_FOR_POSTING_NOTIFICATION =
+                devFlag("persist.sysui.notification.wake_lock_for_posting_notification");
     }
 
     //// == End of flags.  Everything below this line is the implementation. == ////
diff --git a/core/res/res/layout/alert_dialog_button_bar_leanback.xml b/core/res/res/layout/alert_dialog_button_bar_leanback.xml
index ea94af6..466811f 100644
--- a/core/res/res/layout/alert_dialog_button_bar_leanback.xml
+++ b/core/res/res/layout/alert_dialog_button_bar_leanback.xml
@@ -21,13 +21,13 @@
             android:layout_height="wrap_content"
             android:scrollbarAlwaysDrawVerticalTrack="true"
             android:scrollIndicators="top|bottom"
-            android:fillViewport="true"
-            style="?attr/buttonBarStyle">
+            android:fillViewport="true">
     <com.android.internal.widget.ButtonBarLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layoutDirection="locale"
         android:orientation="horizontal"
+        style="?attr/buttonBarStyle"
         android:gravity="start">
 
         <Button
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index b58639f..0197f21 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -2172,7 +2172,7 @@
     <string name="miniresolver_sms_information" msgid="4311292661329483088">"Teie organisatsioon lubab sõnumeid saata ainult töörakendustest."</string>
     <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Kasuta isiklikku brauserit"</string>
     <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Kasuta tööbrauserit"</string>
-    <string name="miniresolver_call" msgid="6386870060423480765">"Helistage"</string>
+    <string name="miniresolver_call" msgid="6386870060423480765">"Helista"</string>
     <string name="miniresolver_switch" msgid="8011924662117617451">"Lülitu"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"SIM-kaardi võrgu avamise PIN-kood"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"SIM-kaardi võrgu alamhulga avamise PIN-kood"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 50685cb..84f56ff 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -687,7 +687,7 @@
     <string name="face_acquired_too_right" msgid="6245286514593540859">"צריך להזיז את הטלפון שמאלה"</string>
     <string name="face_acquired_too_left" msgid="9201762240918405486">"צריך להזיז את הטלפון ימינה"</string>
     <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"יש להביט ישירות אל המכשיר."</string>
-    <string name="face_acquired_not_detected" msgid="1057966913397548150">"אי אפשר לראות את הפנים שלך. יש להחזיק את הטלפון בגובה העיניים."</string>
+    <string name="face_acquired_not_detected" msgid="1057966913397548150">"כדי לראות את הפנים שלך יש להחזיק את הטלפון בגובה העיניים."</string>
     <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"יותר מדי תנועה. יש להחזיק את הטלפון בצורה יציבה."</string>
     <string name="face_acquired_recalibrate" msgid="8724013080976469746">"יש לסרוק שוב את הפנים."</string>
     <string name="face_acquired_too_different" msgid="2520389515612972889">"לא ניתן לזהות את הפנים. יש לנסות שוב."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index ed22dfa..93a7352 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1715,7 +1715,7 @@
     <string name="color_correction_feature_name" msgid="7975133554160979214">"색상 보정"</string>
     <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"한 손 모드"</string>
     <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"더 어둡게"</string>
-    <string name="hearing_aids_feature_name" msgid="1125892105105852542">"보청기"</string>
+    <string name="hearing_aids_feature_name" msgid="1125892105105852542">"청각 보조 기기"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"볼륨 키를 길게 눌렀습니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 설정되었습니다."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"볼륨 키를 길게 눌렀습니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 중지되었습니다."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"볼륨 키에서 손을 뗍니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>을 켜려면 볼륨 키 2개를 3초 동안 길게 누르세요."</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index b0762d2..2ad8a50 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -155,7 +155,7 @@
     <string name="cfTemplateRegisteredTime" msgid="5222794399642525045">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nuk u transferua"</string>
     <string name="fcComplete" msgid="1080909484660507044">"Kodi i funksionit është i plotë."</string>
     <string name="fcError" msgid="5325116502080221346">"Problem me lidhjen ose kod është i pavlefshëm."</string>
-    <string name="httpErrorOk" msgid="6206751415788256357">"Në rregull!"</string>
+    <string name="httpErrorOk" msgid="6206751415788256357">"Në rregull"</string>
     <string name="httpError" msgid="3406003584150566720">"Pati një gabim në rrjet."</string>
     <string name="httpErrorLookup" msgid="3099834738227549349">"Nuk mundi ta gjente URL-në."</string>
     <string name="httpErrorUnsupportedAuthScheme" msgid="3976195595501606787">"Skema e vërtetimit nuk mbështetet."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 871107a..815c9a9 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1715,7 +1715,7 @@
     <string name="color_correction_feature_name" msgid="7975133554160979214">"Färgkorrigering"</string>
     <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enhandsläge"</string>
     <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extradimmat"</string>
-    <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hörapparater"</string>
+    <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hörhjälpmedel"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har aktiverats."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har inaktiverats."</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Släpp volymknapparna. Du kan aktivera <xliff:g id="SERVICE_NAME">%1$s</xliff:g> genom att hålla båda volymknapparna nedtryckta i tre sekunder igen."</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 5b647fa..14ced72 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -461,10 +461,10 @@
     <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"允許應用程式修改平板電腦的通話記錄,包括來電和已撥電話相關資料。請注意,惡意應用程式可能濫用此功能刪除或修改你的通話記錄。"</string>
     <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"允許應用程式修改 Android TV 裝置的通話記錄,包括來電和撥出電話相關資料。惡意應用程式可能會藉此清除或修改你的通話記錄。"</string>
     <string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"允許應用程式修改手機的通話記錄,包括來電和已撥電話相關資料。請注意,惡意應用程式可能濫用此功能刪除或修改你的通話記錄。"</string>
-    <string name="permlab_bodySensors" msgid="662918578601619569">"在使用期間可存取人體感應器資料,例如心跳速率"</string>
-    <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"允許應用程式在使用期間存取人體感應器資料,例如心跳速率、體溫和血氧比例。"</string>
-    <string name="permlab_bodySensors_background" msgid="4912560779957760446">"在背景執行時可存取人體感應器資料,例如心跳速率"</string>
-    <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"允許應用程式在背景執行時存取人體感應器資料,例如心跳速率、體溫和血氧比例。"</string>
+    <string name="permlab_bodySensors" msgid="662918578601619569">"在使用期間可存取人體感應器資料,例如心率"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"允許應用程式在使用期間存取人體感應器資料,例如心率、體溫和血氧比例。"</string>
+    <string name="permlab_bodySensors_background" msgid="4912560779957760446">"在背景執行時可存取人體感應器資料,例如心率"</string>
+    <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"允許應用程式在背景執行時存取人體感應器資料,例如心率、體溫和血氧比例。"</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"讀取日曆活動和詳細資訊"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"這個應用程式可讀取所有儲存在平板電腦上的日曆活動資訊,以及共用或儲存日曆資料。"</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"這個應用程式可讀取所有儲存在 Android TV 裝置上的日曆活動,以及共用或儲存日曆資料。"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 00f8db0..ee8c0f8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1817,16 +1817,6 @@
          specified -->
     <string name="default_wallpaper_component" translatable="false">@null</string>
 
-    <!-- CMF colors to default wallpaper component map, the component with color matching the device
-         color will be the cmf default wallpapers. The default wallpaper will be default wallpaper
-         component if not specified.
-
-         E.g. for SLV color, and com.android.example/com.android.example.SlVDefaultWallpaper
-         <item>SLV,com.android.example/com.android.example.SlVDefaultWallpaper</item> -->
-    <string-array name="cmf_default_wallpaper_component" translatable="false">
-        <!-- Add packages here -->
-    </string-array>
-
     <!-- By default a product has no distinct default lock wallpaper -->
     <item name="default_lock_wallpaper" type="drawable">@null</item>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index fb3acbe..a5b2b85 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5035,8 +5035,8 @@
     <string name="display_rotation_camera_compat_toast_after_rotation">Rotate for a better view</string>
 
     <!-- Text on a toast shown when a camera view is started within the app that may not be able
-         to display the camera preview correctly while in split screen. [CHAR LIMIT=NONE] -->
-    <string name="display_rotation_camera_compat_toast_in_split_screen">Exit split screen for a better view</string>
+         to display the camera preview correctly while in multi-window. [CHAR LIMIT=NONE] -->
+    <string name="display_rotation_camera_compat_toast_in_multi_window">Open <xliff:g id="name" example="MyApp">%s</xliff:g> in full screen for a better view</string>
 
     <!-- Label for button to confirm chosen date or time [CHAR LIMIT=30] -->
     <string name="done_label">Done</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6ab671a..dc4eafd 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2116,7 +2116,6 @@
   <java-symbol type="string" name="data_usage_rapid_body" />
   <java-symbol type="string" name="data_usage_rapid_app_body" />
   <java-symbol type="string" name="default_wallpaper_component" />
-  <java-symbol type="array" name="cmf_default_wallpaper_component" />
   <java-symbol type="string" name="device_storage_monitor_notification_channel" />
   <java-symbol type="string" name="dlg_ok" />
   <java-symbol type="string" name="dump_heap_notification" />
@@ -2533,7 +2532,7 @@
   <java-symbol type="string" name="zen_mode_default_events_name" />
   <java-symbol type="string" name="zen_mode_default_every_night_name" />
   <java-symbol type="string" name="display_rotation_camera_compat_toast_after_rotation" />
-  <java-symbol type="string" name="display_rotation_camera_compat_toast_in_split_screen" />
+  <java-symbol type="string" name="display_rotation_camera_compat_toast_in_multi_window" />
   <java-symbol type="array" name="config_system_condition_providers" />
   <java-symbol type="string" name="muted_by" />
   <java-symbol type="string" name="zen_mode_alarm" />
diff --git a/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java b/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java
index a753870..0525443 100644
--- a/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java
+++ b/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import android.util.Property;
 import android.view.View;
 
 import androidx.test.annotation.UiThreadTest;
@@ -576,6 +577,42 @@
         });
     }
 
+    @Test
+    public void testInitializeWithoutReadingValues() throws Throwable {
+        // Some consumers crash while reading values before the animator starts
+        Property<int[], Integer> property = new Property<>(Integer.class, "firstValue") {
+            @Override
+            public Integer get(int[] target) {
+                throw new IllegalStateException("Shouldn't be called");
+            }
+
+            @Override
+            public void set(int[] target, Integer value) {
+                target[0] = value;
+            }
+        };
+
+        int[] target1 = new int[1];
+        int[] target2 = new int[1];
+        int[] target3 = new int[1];
+        ObjectAnimator animator1 = ObjectAnimator.ofInt(target1, property, 0, 100);
+        ObjectAnimator animator2 = ObjectAnimator.ofInt(target2, property, 0, 100);
+        ObjectAnimator animator3 = ObjectAnimator.ofInt(target3, property, 0, 100);
+        AnimatorSet set = new AnimatorSet();
+        set.playSequentially(animator1, animator2, animator3);
+
+        mActivityRule.runOnUiThread(() -> {
+            set.setCurrentPlayTime(900);
+            assertEquals(100, target1[0]);
+            assertEquals(100, target2[0]);
+            assertEquals(100, target3[0]);
+            set.setCurrentPlayTime(0);
+            assertEquals(0, target1[0]);
+            assertEquals(0, target2[0]);
+            assertEquals(0, target3[0]);
+        });
+    }
+
     /**
      * Check that the animator list contains exactly the given animators and nothing else.
      */
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
index 4f8b855..b5f18c2 100644
--- a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
+++ b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
@@ -45,36 +45,40 @@
     @SmallTest
     public void testGetEmpty() {
         final Resources res = getActivity().getResources();
-        assertNull(mCache.getInstance(-1, res, null));
+        assertNull(mCache.getInstance(-1, res, null).getValue());
     }
 
     @SmallTest
     public void testSetGet() {
-        mCache.put(1, null, new DummyFloatConstantState(5f));
+        mCache.put(1, null, new DummyFloatConstantState(5f),
+                ThemedResourceCache.UNDEFINED_GENERATION);
         final Resources res = getActivity().getResources();
-        assertEquals(5f, mCache.getInstance(1, res, null));
-        assertNotSame(5f, mCache.getInstance(1, res, null));
-        assertEquals(null, mCache.getInstance(1, res, getActivity().getTheme()));
+        assertEquals(5f, mCache.getInstance(1, res, null).getValue());
+        assertNotSame(5f, mCache.getInstance(1, res, null).getValue());
+        assertEquals(false, mCache.getInstance(1, res, getActivity().getTheme()).hasValue());
     }
 
     @SmallTest
     public void testSetGetThemed() {
-        mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f));
+        mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f),
+                ThemedResourceCache.UNDEFINED_GENERATION);
         final Resources res = getActivity().getResources();
-        assertEquals(null, mCache.getInstance(1, res, null));
-        assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()));
-        assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()));
+        assertEquals(false, mCache.getInstance(1, res, null).hasValue());
+        assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()).getValue());
+        assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()).getValue());
     }
 
     @SmallTest
     public void testMultiThreadPutGet() {
-        mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f));
-        mCache.put(1, null, new DummyFloatConstantState(10f));
+        mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f),
+                ThemedResourceCache.UNDEFINED_GENERATION);
+        mCache.put(1, null, new DummyFloatConstantState(10f),
+                ThemedResourceCache.UNDEFINED_GENERATION);
         final Resources res = getActivity().getResources();
-        assertEquals(10f, mCache.getInstance(1, res, null));
-        assertNotSame(10f, mCache.getInstance(1, res, null));
-        assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()));
-        assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()));
+        assertEquals(10f, mCache.getInstance(1, res, null).getValue());
+        assertNotSame(10f, mCache.getInstance(1, res, null).getValue());
+        assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()).getValue());
+        assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()).getValue());
     }
 
     @SmallTest
@@ -86,16 +90,17 @@
         res.getValue(R.dimen.resource_cache_test_generic, staticValue, true);
         float staticDim = TypedValue.complexToDimension(staticValue.data, res.getDisplayMetrics());
         mCache.put(key, getActivity().getTheme(),
-                new DummyFloatConstantState(staticDim, staticValue.changingConfigurations));
+                new DummyFloatConstantState(staticDim, staticValue.changingConfigurations),
+                ThemedResourceCache.UNDEFINED_GENERATION);
         final Configuration cfg = res.getConfiguration();
         Configuration newCnf = new Configuration(cfg);
         newCnf.orientation = cfg.orientation == Configuration.ORIENTATION_LANDSCAPE ?
                 Configuration.ORIENTATION_PORTRAIT
                 : Configuration.ORIENTATION_LANDSCAPE;
         int changes = calcConfigChanges(res, newCnf);
-        assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()));
+        assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()).getValue());
         mCache.onConfigurationChange(changes);
-        assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()));
+        assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()).getValue());
     }
 
     @SmallTest
@@ -108,7 +113,8 @@
         float changingDim = TypedValue.complexToDimension(changingValue.data,
                 res.getDisplayMetrics());
         mCache.put(key, getActivity().getTheme(),
-                new DummyFloatConstantState(changingDim, changingValue.changingConfigurations));
+                new DummyFloatConstantState(changingDim, changingValue.changingConfigurations),
+                ThemedResourceCache.UNDEFINED_GENERATION);
 
         final Configuration cfg = res.getConfiguration();
         Configuration newCnf = new Configuration(cfg);
@@ -116,9 +122,10 @@
                 Configuration.ORIENTATION_PORTRAIT
                 : Configuration.ORIENTATION_LANDSCAPE;
         int changes = calcConfigChanges(res, newCnf);
-        assertEquals(changingDim, mCache.getInstance(key, res, getActivity().getTheme()));
+        assertEquals(changingDim,
+                mCache.getInstance(key, res, getActivity().getTheme()).getValue());
         mCache.onConfigurationChange(changes);
-        assertNull(mCache.get(key, getActivity().getTheme()));
+        assertNull(mCache.get(key, getActivity().getTheme()).getValue());
     }
 
     @SmallTest
@@ -133,9 +140,11 @@
         float changingDim = TypedValue.complexToDimension(changingValue.data,
                 res.getDisplayMetrics());
         mCache.put(R.dimen.resource_cache_test_generic, getActivity().getTheme(),
-                new DummyFloatConstantState(staticDim, staticValue.changingConfigurations));
+                new DummyFloatConstantState(staticDim, staticValue.changingConfigurations),
+                ThemedResourceCache.UNDEFINED_GENERATION);
         mCache.put(R.dimen.resource_cache_test_orientation_dependent, getActivity().getTheme(),
-                new DummyFloatConstantState(changingDim, changingValue.changingConfigurations));
+                new DummyFloatConstantState(changingDim, changingValue.changingConfigurations),
+                ThemedResourceCache.UNDEFINED_GENERATION);
         final Configuration cfg = res.getConfiguration();
         Configuration newCnf = new Configuration(cfg);
         newCnf.orientation = cfg.orientation == Configuration.ORIENTATION_LANDSCAPE ?
@@ -143,15 +152,15 @@
                 : Configuration.ORIENTATION_LANDSCAPE;
         int changes = calcConfigChanges(res, newCnf);
         assertEquals(staticDim, mCache.getInstance(R.dimen.resource_cache_test_generic, res,
-                getActivity().getTheme()));
+                getActivity().getTheme()).getValue());
         assertEquals(changingDim,
                 mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
-                        getActivity().getTheme()));
+                        getActivity().getTheme()).getValue());
         mCache.onConfigurationChange(changes);
         assertEquals(staticDim, mCache.getInstance(R.dimen.resource_cache_test_generic, res,
-                getActivity().getTheme()));
+                getActivity().getTheme()).getValue());
         assertNull(mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
-                getActivity().getTheme()));
+                getActivity().getTheme()).getValue());
     }
 
     @SmallTest
@@ -173,10 +182,12 @@
                     res.getDisplayMetrics());
             final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
             mCache.put(R.dimen.resource_cache_test_generic, theme,
-                    new DummyFloatConstantState(staticDim, staticValues[i].changingConfigurations));
+                    new DummyFloatConstantState(staticDim, staticValues[i].changingConfigurations),
+                    ThemedResourceCache.UNDEFINED_GENERATION);
             mCache.put(R.dimen.resource_cache_test_orientation_dependent, theme,
                     new DummyFloatConstantState(changingDim,
-                            changingValues[i].changingConfigurations));
+                            changingValues[i].changingConfigurations),
+                    ThemedResourceCache.UNDEFINED_GENERATION);
         }
         final Configuration cfg = res.getConfiguration();
         Configuration newCnf = new Configuration(cfg);
@@ -187,18 +198,18 @@
         for (int i = 0; i < 2; i++) {
             final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
             assertEquals(staticDim,
-                    mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme));
+                    mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme).getValue());
             assertEquals(changingDim,
                     mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
-                            theme));
+                            theme).getValue());
         }
         mCache.onConfigurationChange(changes);
         for (int i = 0; i < 2; i++) {
             final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
             assertEquals(staticDim,
-                    mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme));
+                    mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme).getValue());
             assertNull(mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
-                    theme));
+                    theme).getValue());
         }
     }
 
diff --git a/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java b/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java
index e2fb46a..e7b1110 100644
--- a/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java
@@ -16,9 +16,14 @@
 
 package android.view.inputmethod;
 
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
 import static org.junit.Assert.assertEquals;
 
+import android.os.BadParcelableException;
 import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
 import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
 
 import androidx.test.filters.SmallTest;
@@ -31,6 +36,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@Presubmit
 public class InputMethodSubtypeArrayTest {
 
     @Test
@@ -59,6 +65,36 @@
         assertEquals(clonedArray.get(2), clonedClonedArray.get(2));
     }
 
+    @Test
+    public void testNegativeCount() throws Exception {
+        InputMethodSubtypeArray negativeCountArray;
+        try {
+            // Construct a InputMethodSubtypeArray with: mCount = -1
+            var p = Parcel.obtain();
+            p.writeInt(-1);
+            p.setDataPosition(0);
+            negativeCountArray = new InputMethodSubtypeArray(p);
+        } catch (BadParcelableException e) {
+            // Expected with fix: Prevent negative mCount
+            assertThat(e).hasMessageThat().contains("mCount");
+            return;
+        }
+        assertWithMessage("Test set-up failed")
+                .that(negativeCountArray.getCount()).isEqualTo(-1);
+
+        var p = Parcel.obtain();
+        // Writes: int (mCount), int (mDecompressedSize), byte[] (mCompressedData)
+        negativeCountArray.writeToParcel(p);
+        p.setDataPosition(0);
+        // Reads: int (mCount)
+        // Leaves: int (mDecompressedSize), byte[] (mCompressedData)
+        new InputMethodSubtypeArray(p);
+
+        assertWithMessage("Didn't read all data that was previously written")
+                .that(p.dataPosition())
+                .isEqualTo(p.dataSize());
+    }
+
     InputMethodSubtypeArray cloneViaParcel(final InputMethodSubtypeArray original) {
         Parcel parcel = null;
         try {
diff --git a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
index 2ef2d3a..a6e74d0 100644
--- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
+++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.atMost;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.verifyZeroInteractions;
@@ -340,4 +341,42 @@
         verify(mCallback1).onBackCancelled();
         verify(mWindowSession).setOnBackInvokedCallbackInfo(Mockito.eq(mWindow), isNull());
     }
+
+    @Test
+    public void onBackInvoked_calledAfterOnBackStarted() throws RemoteException {
+        mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback1);
+        OnBackInvokedCallbackInfo callbackInfo = assertSetCallbackInfo();
+
+        callbackInfo.getCallback().onBackStarted(mBackEvent);
+
+        waitForIdle();
+        verify(mCallback1).onBackStarted(any(BackEvent.class));
+
+        callbackInfo.getCallback().onBackInvoked();
+
+        waitForIdle();
+        verify(mCallback1).onBackInvoked();
+        verify(mCallback1, never()).onBackCancelled();
+    }
+
+    @Test
+    public void onDetachFromWindow_cancelCallbackAndIgnoreOnBackInvoked() throws RemoteException {
+        mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback1);
+
+        OnBackInvokedCallbackInfo callbackInfo = assertSetCallbackInfo();
+
+        callbackInfo.getCallback().onBackStarted(mBackEvent);
+
+        waitForIdle();
+        verify(mCallback1).onBackStarted(any(BackEvent.class));
+
+        // This should trigger mCallback1.onBackCancelled()
+        mDispatcher.detachFromWindow();
+        // This should be ignored by mCallback1
+        callbackInfo.getCallback().onBackInvoked();
+
+        waitForIdle();
+        verify(mCallback1, never()).onBackInvoked();
+        verify(mCallback1).onBackCancelled();
+    }
 }
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index e4defcf..93e44f1 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1813,6 +1813,12 @@
       "group": "WM_DEBUG_KEEP_SCREEN_ON",
       "at": "com\/android\/server\/wm\/RootWindowContainer.java"
     },
+    "-479665533": {
+      "message": "DisplayRotationCompatPolicy: Multi-window toast not shown as package '%s' cannot be found.",
+      "level": "ERROR",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java"
+    },
     "-464564167": {
       "message": "Current transition prevents automatic focus change",
       "level": "VERBOSE",
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 2307d60..b9d3756 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -997,12 +997,63 @@
         canvas.concat(m);
         canvas.drawBitmap(source, srcR, dstR, paint);
         canvas.setBitmap(null);
+
+        // If the source has a gainmap, apply the same set of transformations to the gainmap
+        // and set it on the output
+        if (source.hasGainmap()) {
+            Bitmap newMapContents = transformGainmap(source, m, neww, newh, paint, srcR, dstR,
+                    deviceR);
+            if (newMapContents != null) {
+                bitmap.setGainmap(new Gainmap(source.getGainmap(), newMapContents));
+            }
+        }
+
         if (isHardware) {
             return bitmap.copy(Config.HARDWARE, false);
         }
         return bitmap;
     }
 
+    private static Bitmap transformGainmap(Bitmap source, Matrix m, int neww, int newh, Paint paint,
+            Rect srcR, RectF dstR, RectF deviceR) {
+        Canvas canvas;
+        Bitmap sourceGainmap = source.getGainmap().getGainmapContents();
+        // Gainmaps can be scaled relative to the base image (eg, 1/4th res)
+        // Preserve that relative scaling between the base & gainmap in the output
+        float scaleX = (sourceGainmap.getWidth() / (float) source.getWidth());
+        float scaleY = (sourceGainmap.getHeight() / (float) source.getHeight());
+        int mapw = Math.round(neww * scaleX);
+        int maph = Math.round(newh * scaleY);
+
+        if (mapw == 0 || maph == 0) {
+            // The gainmap has been scaled away entirely, drop it
+            return null;
+        }
+
+        // Scale the computed `srcR` used for rendering the source bitmap to the destination
+        // to be in gainmap dimensions
+        Rect gSrcR = new Rect((int) (srcR.left * scaleX),
+                (int) (srcR.top * scaleY), (int) (srcR.right * scaleX),
+                (int) (srcR.bottom * scaleY));
+
+        // Note: createBitmap isn't used as that requires a non-null colorspace, however
+        // gainmaps don't have a colorspace. So use `nativeCreate` directly to bypass
+        // that colorspace enforcement requirement (#getColorSpace() allows a null return)
+        Bitmap newMapContents = nativeCreate(null, 0, mapw, mapw, maph,
+                sourceGainmap.getConfig().nativeInt, true, 0);
+        newMapContents.eraseColor(0);
+        canvas = new Canvas(newMapContents);
+        // Scale the translate & matrix to be in gainmap-relative dimensions
+        canvas.scale(scaleX, scaleY);
+        canvas.translate(-deviceR.left, -deviceR.top);
+        canvas.concat(m);
+        canvas.drawBitmap(sourceGainmap, gSrcR, dstR, paint);
+        canvas.setBitmap(null);
+        // Create a new gainmap using a copy of the metadata information from the source but
+        // with the transformed bitmap created above
+        return newMapContents;
+    }
+
     /**
      * Returns a mutable bitmap with the specified width and height.  Its
      * initial density is as per {@link #getDensity}. The newly created
diff --git a/graphics/java/android/graphics/Gainmap.java b/graphics/java/android/graphics/Gainmap.java
index 9ac84a6..f639521 100644
--- a/graphics/java/android/graphics/Gainmap.java
+++ b/graphics/java/android/graphics/Gainmap.java
@@ -122,6 +122,16 @@
     }
 
     /**
+     * Creates a new gainmap using the provided gainmap as the metadata source and the provided
+     * bitmap as the replacement for the gainmapContents
+     * TODO: Make public, it's useful
+     * @hide
+     */
+    public Gainmap(@NonNull Gainmap gainmap, @NonNull Bitmap gainmapContents) {
+        this(gainmapContents, nCreateCopy(gainmap.mNativePtr));
+    }
+
+    /**
      * @return Returns the image data of the gainmap represented as a Bitmap. This is represented
      * as a Bitmap for broad API compatibility, however certain aspects of the Bitmap are ignored
      * such as {@link Bitmap#getColorSpace()} or {@link Bitmap#getGainmap()} as they are not
@@ -325,6 +335,7 @@
 
     private static native long nGetFinalizer();
     private static native long nCreateEmpty();
+    private static native long nCreateCopy(long source);
 
     private static native void nSetBitmap(long ptr, Bitmap bitmap);
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java
index 7b37d59..57d374b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java
@@ -20,6 +20,8 @@
 import static android.window.TransitionInfo.FLAG_FILLS_TASK;
 import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
 
+import static com.android.wm.shell.transition.DefaultTransitionHandler.isSupportedOverrideAnimation;
+
 import static java.util.Objects.requireNonNull;
 
 import android.content.Context;
@@ -113,8 +115,11 @@
             return false;
         }
         final TransitionInfo.AnimationOptions options = info.getAnimationOptions();
-        if (options != null && options.getType() == ANIM_SCENE_TRANSITION) {
-            // Scene-transition will be handled by app side.
+        if (options != null
+                // Scene-transition will be handled by app side.
+                && (options.getType() == ANIM_SCENE_TRANSITION
+                // Use default transition handler to animate override animation.
+                || isSupportedOverrideAnimation(options))) {
             return false;
         }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 9fcd207..e1a3f3a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -55,6 +55,7 @@
 import android.util.IntProperty;
 import android.util.Log;
 import android.util.TypedValue;
+import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -459,7 +460,9 @@
         if (mManageButton != null) {
             int visibility = mManageButton.getVisibility();
             removeView(mManageButton);
-            mManageButton = (AlphaOptimizedButton) LayoutInflater.from(getContext()).inflate(
+            ContextThemeWrapper ctw = new ContextThemeWrapper(getContext(),
+                    com.android.internal.R.style.Theme_DeviceDefault_DayNight);
+            mManageButton = (AlphaOptimizedButton) LayoutInflater.from(ctw).inflate(
                     R.layout.bubble_manage_button, this /* parent */, false /* attach */);
             addView(mManageButton);
             mManageButton.setVisibility(visibility);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
index d6e1a82..467e9c7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
@@ -375,16 +375,15 @@
                     insetsState.getDisplayFrame(),
                     WindowInsets.Type.navigationBars(),
                     false /* ignoreVisibility */);
-            outInsets.set(insets.left, insets.top, insets.right, insets.bottom);
             int position = navigationBarPosition(res, displayWidth, displayHeight, displayRotation);
             int navBarSize =
                     getNavigationBarSize(res, position, displayWidth > displayHeight, uiMode);
             if (position == NAV_BAR_BOTTOM) {
-                outInsets.bottom = Math.max(outInsets.bottom , navBarSize);
+                outInsets.bottom = Math.max(insets.bottom , navBarSize);
             } else if (position == NAV_BAR_RIGHT) {
-                outInsets.right = Math.max(outInsets.right , navBarSize);
+                outInsets.right = Math.max(insets.right , navBarSize);
             } else if (position == NAV_BAR_LEFT) {
-                outInsets.left = Math.max(outInsets.left , navBarSize);
+                outInsets.left = Math.max(insets.left , navBarSize);
             }
         }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 5a9c25f..c491fed 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -70,6 +70,8 @@
 import com.android.wm.shell.freeform.FreeformComponents;
 import com.android.wm.shell.fullscreen.FullscreenTaskListener;
 import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
+import com.android.wm.shell.keyguard.KeyguardTransitionHandler;
+import com.android.wm.shell.keyguard.KeyguardTransitions;
 import com.android.wm.shell.onehanded.OneHanded;
 import com.android.wm.shell.onehanded.OneHandedController;
 import com.android.wm.shell.pip.Pip;
@@ -77,8 +79,6 @@
 import com.android.wm.shell.pip.PipSurfaceTransactionHelper;
 import com.android.wm.shell.pip.PipUiEventLogger;
 import com.android.wm.shell.pip.phone.PipTouchHandler;
-import com.android.wm.shell.keyguard.KeyguardTransitionHandler;
-import com.android.wm.shell.keyguard.KeyguardTransitions;
 import com.android.wm.shell.recents.RecentTasks;
 import com.android.wm.shell.recents.RecentTasksController;
 import com.android.wm.shell.recents.RecentsTransitionHandler;
@@ -102,13 +102,13 @@
 import com.android.wm.shell.unfold.UnfoldTransitionHandler;
 import com.android.wm.shell.windowdecor.WindowDecorViewModel;
 
+import java.util.Optional;
+
 import dagger.BindsOptionalOf;
 import dagger.Lazy;
 import dagger.Module;
 import dagger.Provides;
 
-import java.util.Optional;
-
 /**
  * Provides basic dependencies from {@link com.android.wm.shell}, these dependencies are only
  * accessible from components within the WM subcomponent (can be explicitly exposed to the
@@ -548,13 +548,15 @@
             @ShellMainThread ShellExecutor mainExecutor,
             @ShellMainThread Handler mainHandler,
             @ShellAnimationThread ShellExecutor animExecutor,
-            ShellCommandHandler shellCommandHandler) {
+            ShellCommandHandler shellCommandHandler,
+            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) {
         if (!context.getResources().getBoolean(R.bool.config_registerShellTransitionsOnInit)) {
             // TODO(b/238217847): Force override shell init if registration is disabled
             shellInit = new ShellInit(mainExecutor);
         }
         return new Transitions(context, shellInit, shellController, organizer, pool,
-                displayController, mainExecutor, mainHandler, animExecutor, shellCommandHandler);
+                displayController, mainExecutor, mainHandler, animExecutor, shellCommandHandler,
+                rootTaskDisplayAreaOrganizer);
     }
 
     @WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
index 513638e..cef7e16 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
@@ -17,31 +17,25 @@
 package com.android.wm.shell.keyguard;
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
-import static android.view.WindowManager.TRANSIT_CLOSE;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
-import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_OPEN;
-import static android.view.WindowManager.TRANSIT_SLEEP;
-import static android.view.WindowManager.TRANSIT_TO_BACK;
-import static android.view.WindowManager.TRANSIT_TO_FRONT;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
+import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
-import static android.window.TransitionInfo.FLAG_OCCLUDES_KEYGUARD;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_OCCLUDING;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_UNOCCLUDING;
+import static android.view.WindowManager.TRANSIT_SLEEP;
 
 import static com.android.wm.shell.util.TransitionUtil.isOpeningType;
-import static com.android.wm.shell.util.TransitionUtil.isClosingType;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.os.RemoteException;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.RemoteException;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.view.SurfaceControl;
+import android.view.WindowManager;
 import android.window.IRemoteTransition;
 import android.window.IRemoteTransitionFinishedCallback;
 import android.window.TransitionInfo;
@@ -56,8 +50,6 @@
 import com.android.wm.shell.transition.Transitions;
 import com.android.wm.shell.transition.Transitions.TransitionFinishCallback;
 
-import java.util.Map;
-
 /**
  * The handler for Keyguard enter/exit and occlude/unocclude animations.
  *
@@ -70,7 +62,7 @@
     private final Handler mMainHandler;
     private final ShellExecutor mMainExecutor;
 
-    private final Map<IBinder, IRemoteTransition> mStartedTransitions = new ArrayMap<>();
+    private final ArrayMap<IBinder, StartedTransition> mStartedTransitions = new ArrayMap<>();
 
     /**
      * Local IRemoteTransition implementations registered by the keyguard service.
@@ -81,6 +73,18 @@
     private IRemoteTransition mOccludeByDreamTransition = null;
     private IRemoteTransition mUnoccludeTransition = null;
 
+    private final class StartedTransition {
+        final TransitionInfo mInfo;
+        final SurfaceControl.Transaction mFinishT;
+        final IRemoteTransition mPlayer;
+
+        public StartedTransition(TransitionInfo info,
+                SurfaceControl.Transaction finishT, IRemoteTransition player) {
+            mInfo = info;
+            mFinishT = finishT;
+            mPlayer = player;
+        }
+    }
     public KeyguardTransitionHandler(
             @NonNull ShellInit shellInit,
             @NonNull Transitions transitions,
@@ -105,10 +109,7 @@
     }
 
     public static boolean handles(TransitionInfo info) {
-        return (info.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0
-                || (info.getFlags() & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0
-                || info.getType() == TRANSIT_KEYGUARD_OCCLUDE
-                || info.getType() == TRANSIT_KEYGUARD_UNOCCLUDE;
+        return (info.getFlags() & KEYGUARD_VISIBILITY_TRANSIT_FLAGS) != 0;
     }
 
     @Override
@@ -120,39 +121,14 @@
             return false;
         }
 
-        boolean hasOpeningOcclude = false;
-        boolean hasClosingOcclude = false;
-        boolean hasOpeningDream = false;
-        boolean hasClosingApp = false;
-
-        // Check for occluding/dream/closing apps
-        for (int i = info.getChanges().size() - 1; i >= 0; i--) {
-            final TransitionInfo.Change change = info.getChanges().get(i);
-            if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) {
-                continue;
-            } else if (isOpeningType(change.getMode())) {
-                hasOpeningOcclude |= change.hasFlags(FLAG_OCCLUDES_KEYGUARD);
-                hasOpeningDream |= (change.getTaskInfo() != null
-                        && change.getTaskInfo().getActivityType() == ACTIVITY_TYPE_DREAM);
-            } else if (isClosingType(change.getMode())) {
-                hasClosingOcclude |= change.hasFlags(FLAG_OCCLUDES_KEYGUARD);
-                hasClosingApp = true;
-            }
-        }
-
         // Choose a transition applicable for the changes and keyguard state.
         if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) {
             return startAnimation(mExitTransition,
                     "going-away",
                     transition, info, startTransaction, finishTransaction, finishCallback);
         }
-        if (hasOpeningOcclude || info.getType() == TRANSIT_KEYGUARD_OCCLUDE) {
-            if (hasClosingOcclude) {
-                // Transitions between apps on top of the keyguard can use the default handler.
-                // WM sends a final occlude status update after the transition is finished.
-                return false;
-            }
-            if (hasOpeningDream) {
+        if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_OCCLUDING) != 0) {
+            if (hasOpeningDream(info)) {
                 return startAnimation(mOccludeByDreamTransition,
                         "occlude-by-dream",
                         transition, info, startTransaction, finishTransaction, finishCallback);
@@ -161,12 +137,12 @@
                         "occlude",
                         transition, info, startTransaction, finishTransaction, finishCallback);
             }
-        } else if (hasClosingApp || info.getType() == TRANSIT_KEYGUARD_UNOCCLUDE) {
+        } else if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_UNOCCLUDING) != 0) {
              return startAnimation(mUnoccludeTransition,
                     "unocclude",
                     transition, info, startTransaction, finishTransaction, finishCallback);
         } else {
-            Log.w(TAG, "Failed to play: " + info);
+            Log.i(TAG, "Refused to play keyguard transition: " + info);
             return false;
         }
     }
@@ -194,7 +170,8 @@
                             });
                         }
                     });
-            mStartedTransitions.put(transition, remoteHandler);
+            mStartedTransitions.put(transition,
+                    new StartedTransition(info, finishTransaction, remoteHandler));
         } catch (RemoteException e) {
             Log.wtf(TAG, "RemoteException thrown from local IRemoteTransition", e);
             return false;
@@ -207,20 +184,35 @@
     public void mergeAnimation(@NonNull IBinder nextTransition, @NonNull TransitionInfo nextInfo,
             @NonNull SurfaceControl.Transaction nextT, @NonNull IBinder currentTransition,
             @NonNull TransitionFinishCallback nextFinishCallback) {
-        final IRemoteTransition playing = mStartedTransitions.get(currentTransition);
-
+        final StartedTransition playing = mStartedTransitions.get(currentTransition);
         if (playing == null) {
             ProtoLog.e(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                     "unknown keyguard transition %s", currentTransition);
             return;
         }
-
-        if (nextInfo.getType() == TRANSIT_SLEEP) {
+        if ((nextInfo.getFlags() & WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING) != 0
+                && (playing.mInfo.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) {
+            // Keyguard unlocking has been canceled. Merge the unlock and re-lock transitions to
+            // avoid a flicker where we flash one frame with the screen fully unlocked.
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+                    "canceling keyguard exit transition %s", currentTransition);
+            playing.mFinishT.merge(nextT);
+            try {
+                playing.mPlayer.mergeAnimation(nextTransition, nextInfo, nextT, currentTransition,
+                        new FakeFinishCallback());
+            } catch (RemoteException e) {
+                // There is no good reason for this to happen because the player is a local object
+                // implementing an AIDL interface.
+                Log.wtf(TAG, "RemoteException thrown from KeyguardService transition", e);
+            }
+            nextFinishCallback.onTransitionFinished(null, null);
+        } else if (nextInfo.getType() == TRANSIT_SLEEP) {
             // An empty SLEEP transition comes in as a signal to abort transitions whenever a sleep
             // token is held. In cases where keyguard is showing, we are running the animation for
             // the device sleeping/waking, so it's best to ignore this and keep playing anyway.
             return;
-        } else {
+        } else if (handles(nextInfo)) {
+            // In all other cases, fast-forward to let the next queued transition start playing.
             finishAnimationImmediately(currentTransition, playing);
         }
     }
@@ -228,7 +220,7 @@
     @Override
     public void onTransitionConsumed(IBinder transition, boolean aborted,
             SurfaceControl.Transaction finishTransaction) {
-        final IRemoteTransition playing = mStartedTransitions.remove(transition);
+        final StartedTransition playing = mStartedTransitions.remove(transition);
         if (playing != null) {
             finishAnimationImmediately(transition, playing);
         }
@@ -241,13 +233,26 @@
         return null;
     }
 
-    private void finishAnimationImmediately(IBinder transition, IRemoteTransition playing) {
+    private static boolean hasOpeningDream(@NonNull TransitionInfo info) {
+        for (int i = info.getChanges().size() - 1; i >= 0; i--) {
+            final TransitionInfo.Change change = info.getChanges().get(i);
+            if (isOpeningType(change.getMode())
+                    && change.getTaskInfo() != null
+                    && change.getTaskInfo().getActivityType() == ACTIVITY_TYPE_DREAM) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void finishAnimationImmediately(IBinder transition, StartedTransition playing) {
         final IBinder fakeTransition = new Binder();
         final TransitionInfo fakeInfo = new TransitionInfo(TRANSIT_SLEEP, 0x0);
         final SurfaceControl.Transaction fakeT = new SurfaceControl.Transaction();
         final FakeFinishCallback fakeFinishCb = new FakeFinishCallback();
         try {
-            playing.mergeAnimation(fakeTransition, fakeInfo, fakeT, transition, fakeFinishCb);
+            playing.mPlayer.mergeAnimation(
+                    fakeTransition, fakeInfo, fakeT, transition, fakeFinishCb);
         } catch (RemoteException e) {
             // There is no good reason for this to happen because the player is a local object
             // implementing an AIDL interface.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index db7c3fc..18898f1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -438,6 +438,8 @@
      */
     public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
             PictureInPictureParams pictureInPictureParams) {
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "startSwipePipToHome: %s, state=%s", componentName, mPipTransitionState);
         mPipTransitionState.setInSwipePipToHomeTransition(true);
         sendOnPipTransitionStarted(TRANSITION_DIRECTION_TO_PIP);
         setBoundsStateForEntry(componentName, pictureInPictureParams, activityInfo);
@@ -450,6 +452,8 @@
      */
     public void stopSwipePipToHome(int taskId, ComponentName componentName, Rect destinationBounds,
             SurfaceControl overlay) {
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "stopSwipePipToHome: %s, state=%s", componentName, mPipTransitionState);
         // do nothing if there is no startSwipePipToHome being called before
         if (!mPipTransitionState.getInSwipePipToHomeTransition()) {
             return;
@@ -522,6 +526,8 @@
             return;
         }
 
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "exitPip: %s, state=%s", mTaskInfo.topActivity, mPipTransitionState);
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         if (isLaunchIntoPipTask()) {
             exitLaunchIntoPipTask(wct);
@@ -559,6 +565,8 @@
             // destinationBounds calculated above will be incorrect if this is with rotation.
             wct.setBounds(mToken, null);
         } else {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "exitPip: %s, dest=%s", mTaskInfo.topActivity, destinationBounds);
             final SurfaceControl.Transaction tx =
                     mSurfaceControlTransactionFactory.getTransaction();
             mSurfaceTransactionHelper.scale(tx, mLeash, destinationBounds,
@@ -656,9 +664,13 @@
         animator.setInterpolator(Interpolators.ALPHA_OUT);
         animator.start();
         mPipTransitionState.setTransitionState(PipTransitionState.EXITING_PIP);
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "removePip: %s, state=%s", mTaskInfo.topActivity, mPipTransitionState);
     }
 
     private void removePipImmediately() {
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "removePipImmediately: %s, state=%s", mTaskInfo.topActivity, mPipTransitionState);
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
             final WindowContainerTransaction wct = new WindowContainerTransaction();
             wct.setBounds(mToken, null);
@@ -723,6 +735,8 @@
         }
         mPipUiEventLoggerLogger.log(uiEventEnum);
 
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "onTaskAppeared: %s, state=%s", mTaskInfo.topActivity, mPipTransitionState);
         if (mPipTransitionState.getInSwipePipToHomeTransition()) {
             if (!mWaitForFixedRotation) {
                 onEndOfSwipePipToHomeTransition();
@@ -774,6 +788,9 @@
     }
 
     private void onTaskAppearedWithFixedRotation(int animationType) {
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "onTaskAppearedWithFixedRotation: %s, state=%s animationType=%d",
+                mTaskInfo.topActivity, mPipTransitionState, animationType);
         if (animationType == ANIM_TYPE_ALPHA) {
             ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                     "%s: Defer entering PiP alpha animation, fixed rotation is ongoing", TAG);
@@ -920,6 +937,8 @@
      */
     @Override
     public void onTaskVanished(ActivityManager.RunningTaskInfo info) {
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "onTaskVanished: %s, state=%s", mTaskInfo.topActivity, mPipTransitionState);
         if (mPipTransitionState.getTransitionState() == PipTransitionState.UNDEFINED) {
             return;
         }
@@ -961,6 +980,9 @@
         mPipBoundsState.setOverrideMinSize(
                 mPipBoundsAlgorithm.getMinimalSize(info.topActivityInfo));
         final PictureInPictureParams newParams = info.pictureInPictureParams;
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "onTaskInfoChanged: %s, state=%s oldParams=%s newParams=%s",
+                mTaskInfo.topActivity, mPipTransitionState, mPictureInPictureParams, newParams);
 
         // mPictureInPictureParams is only null if there is no PiP
         if (newParams == null || mPictureInPictureParams == null) {
@@ -1001,6 +1023,8 @@
 
     @Override
     public void onFixedRotationStarted(int displayId, int newRotation) {
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "onFixedRotationStarted: %s, state=%s", mTaskInfo, mPipTransitionState);
         mNextRotation = newRotation;
         mWaitForFixedRotation = true;
 
@@ -1022,6 +1046,8 @@
 
     @Override
     public void onFixedRotationFinished(int displayId) {
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "onFixedRotationFinished: %s, state=%s", mTaskInfo, mPipTransitionState);
         if (!mWaitForFixedRotation) {
             return;
         }
@@ -1057,6 +1083,9 @@
 
     /** Called when exiting PIP transition is finished to do the state cleanup. */
     void onExitPipFinished(TaskInfo info) {
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "onExitPipFinished: %s, state=%s leash=%s",
+                info.topActivity, mPipTransitionState, mLeash);
         if (mLeash == null) {
             // TODO(239461594): Remove once the double call to onExitPipFinished() is fixed
             ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
@@ -1108,6 +1137,9 @@
 
     /** Explicitly set the visibility of PiP window. */
     public void setPipVisibility(boolean visible) {
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "setPipVisibility: %s, state=%s visible=%s",
+                mTaskInfo.topActivity, mPipTransitionState, visible);
         if (!isInPip()) {
             return;
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index f9d615a..bf75132 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -308,8 +308,9 @@
     @Override
     public void end() {
         Animator animator = mPipAnimationController.getCurrentAnimator();
-        if (animator == null) return;
-        animator.end();
+        if (animator != null && animator.isRunning()) {
+            animator.end();
+        }
     }
 
     @Override
@@ -815,6 +816,12 @@
         final ActivityManager.RunningTaskInfo taskInfo = pipChange.getTaskInfo();
         final SurfaceControl leash = pipChange.getLeash();
         final int startRotation = pipChange.getStartRotation();
+        // Check again in case some callers use startEnterAnimation directly so the flag was not
+        // set in startAnimation, e.g. from DefaultMixedHandler.
+        if (!mInFixedRotation) {
+            mEndFixedRotation = pipChange.getEndFixedRotation();
+            mInFixedRotation = mEndFixedRotation != ROTATION_UNDEFINED;
+        }
         final int endRotation = mInFixedRotation ? mEndFixedRotation : pipChange.getEndRotation();
 
         setBoundsStateForEntry(taskInfo.topActivity, taskInfo.pictureInPictureParams,
@@ -843,7 +850,7 @@
                 && taskInfo.pictureInPictureParams.isAutoEnterEnabled()
                 && mPipTransitionState.getInSwipePipToHomeTransition()) {
             handleSwipePipToHomeTransition(startTransaction, finishTransaction, leash,
-                    sourceHintRect, destinationBounds, rotationDelta, taskInfo);
+                    sourceHintRect, destinationBounds, taskInfo);
             return;
         }
 
@@ -934,8 +941,15 @@
             @NonNull SurfaceControl.Transaction startTransaction,
             @NonNull SurfaceControl.Transaction finishTransaction,
             @NonNull SurfaceControl leash, @Nullable Rect sourceHintRect,
-            @NonNull Rect destinationBounds, int rotationDelta,
+            @NonNull Rect destinationBounds,
             @NonNull ActivityManager.RunningTaskInfo pipTaskInfo) {
+        if (mInFixedRotation) {
+            // If rotation changes when returning to home, the transition should contain both the
+            // entering PiP and the display change (PipController#startSwipePipToHome has updated
+            // the display layout to new rotation). So it is not expected to see fixed rotation.
+            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+                    "%s: SwipePipToHome should not use fixed rotation %d", TAG, mEndFixedRotation);
+        }
         final SurfaceControl swipePipToHomeOverlay = mPipOrganizer.mSwipePipToHomeOverlay;
         if (swipePipToHomeOverlay != null) {
             // Launcher fade in the overlay on top of the fullscreen Task. It is possible we
@@ -946,12 +960,7 @@
             mPipOrganizer.mSwipePipToHomeOverlay = null;
         }
 
-        Rect sourceBounds = pipTaskInfo.configuration.windowConfiguration.getBounds();
-        if (!Transitions.SHELL_TRANSITIONS_ROTATION && rotationDelta % 2 == 1) {
-            // PipController#startSwipePipToHome has updated the display layout to new rotation,
-            // so flip the source bounds to match the same orientation.
-            sourceBounds = new Rect(0, 0, sourceBounds.height(), sourceBounds.width());
-        }
+        final Rect sourceBounds = pipTaskInfo.configuration.windowConfiguration.getBounds();
         final PipAnimationController.PipTransitionAnimator animator =
                 mPipAnimationController.getAnimator(pipTaskInfo, leash, sourceBounds, sourceBounds,
                         destinationBounds, sourceHintRect, TRANSITION_DIRECTION_TO_PIP,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java
index db6138a..b5f4483 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java
@@ -140,6 +140,24 @@
         return state == ENTERING_PIP;
     }
 
+    private String stateToString() {
+        switch (mState) {
+            case UNDEFINED: return "undefined";
+            case TASK_APPEARED: return "task-appeared";
+            case ENTRY_SCHEDULED: return "entry-scheduled";
+            case ENTERING_PIP: return "entering-pip";
+            case ENTERED_PIP: return "entered-pip";
+            case EXITING_PIP: return "exiting-pip";
+        }
+        throw new IllegalStateException("Unknown state: " + mState);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("PipTransitionState(mState=%s, mInSwipePipToHomeTransition=%b)",
+                stateToString(), mInSwipePipToHomeTransition);
+    }
+
     public interface OnPipTransitionStateChangedListener {
         void onPipTransitionStateChanged(@TransitionState int oldState,
                 @TransitionState int newState);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
index e7a1395..5e1b6be 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
@@ -31,6 +31,8 @@
 import android.util.Size;
 import android.view.MotionEvent;
 import android.view.SurfaceControl;
+import android.view.View;
+import android.view.ViewRootImpl;
 import android.view.WindowManagerGlobal;
 
 import com.android.internal.protolog.common.ProtoLog;
@@ -131,6 +133,8 @@
 
     private PipMenuView mPipMenuView;
 
+    private SurfaceControl mLeash;
+
     private ActionListener mMediaActionListener = new ActionListener() {
         @Override
         public void onMediaActionsChanged(List<RemoteAction> mediaActions) {
@@ -166,6 +170,7 @@
      */
     @Override
     public void attach(SurfaceControl leash) {
+        mLeash = leash;
         attachPipMenuView();
     }
 
@@ -176,6 +181,7 @@
     public void detach() {
         hideMenu();
         detachPipMenuView();
+        mLeash = null;
     }
 
     void attachPipMenuView() {
@@ -185,6 +191,36 @@
         }
         mPipMenuView = new PipMenuView(mContext, this, mMainExecutor, mMainHandler,
                 mSplitScreenController, mPipUiEventLogger);
+        mPipMenuView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+            @Override
+            public void onViewAttachedToWindow(View v) {
+                v.getViewRootImpl().addSurfaceChangedCallback(
+                        new ViewRootImpl.SurfaceChangedCallback() {
+                            @Override
+                            public void surfaceCreated(SurfaceControl.Transaction t) {
+                                final SurfaceControl sc = getSurfaceControl();
+                                if (sc != null) {
+                                    t.reparent(sc, mLeash);
+                                    // make menu on top of the surface
+                                    t.setLayer(sc, Integer.MAX_VALUE);
+                                }
+                            }
+
+                            @Override
+                            public void surfaceReplaced(SurfaceControl.Transaction t) {
+                            }
+
+                            @Override
+                            public void surfaceDestroyed() {
+                            }
+                        });
+            }
+
+            @Override
+            public void onViewDetachedFromWindow(View v) {
+            }
+        });
+
         mSystemWindows.addView(mPipMenuView,
                 getPipMenuLayoutParams(mContext, MENU_WINDOW_TITLE, 0 /* width */, 0 /* height */),
                 0, SHELL_ROOT_LAYER_PIP);
@@ -321,30 +357,10 @@
             return;
         }
 
-        // If there is no pip leash supplied, that means the PiP leash is already finalized
-        // resizing and the PiP menu is also resized. We then want to do a scale from the current
-        // new menu bounds.
+        // TODO(b/286307861) transaction should be applied outside of PiP menu controller
         if (pipLeash != null && t != null) {
-            mPipMenuView.getBoundsOnScreen(mTmpSourceBounds);
-        } else {
-            mTmpSourceBounds.set(0, 0, destinationBounds.width(), destinationBounds.height());
+            t.apply();
         }
-
-        mTmpSourceRectF.set(mTmpSourceBounds);
-        mTmpDestinationRectF.set(destinationBounds);
-        mMoveTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
-        final SurfaceControl surfaceControl = getSurfaceControl();
-        if (surfaceControl == null) {
-            return;
-        }
-        final SurfaceControl.Transaction menuTx =
-                mSurfaceControlTransactionFactory.getTransaction();
-        menuTx.setMatrix(surfaceControl, mMoveTransform, mTmpTransform);
-        if (pipLeash != null && t != null) {
-            // Merge the two transactions, vsyncId has been set on menuTx.
-            menuTx.merge(t);
-        }
-        menuTx.apply();
     }
 
     /**
@@ -362,18 +378,10 @@
             return;
         }
 
-        final SurfaceControl surfaceControl = getSurfaceControl();
-        if (surfaceControl == null) {
-            return;
-        }
-        final SurfaceControl.Transaction menuTx =
-                mSurfaceControlTransactionFactory.getTransaction();
-        menuTx.setCrop(surfaceControl, destinationBounds);
+        // TODO(b/286307861) transaction should be applied outside of PiP menu controller
         if (pipLeash != null && t != null) {
-            // Merge the two transactions, vsyncId has been set on menuTx.
-            menuTx.merge(t);
+            t.apply();
         }
-        menuTx.apply();
     }
 
     private boolean checkPipMenuState() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 6a861ce..65727b6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -574,6 +574,8 @@
                     @Override
                     public void onActivityPinned(String packageName, int userId, int taskId,
                             int stackId) {
+                        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                                "onActivityPinned: %s", packageName);
                         mTouchHandler.onActivityPinned();
                         mMediaController.onActivityPinned();
                         mAppOpsListener.onActivityPinned(packageName);
@@ -585,6 +587,8 @@
                         final Pair<ComponentName, Integer> topPipActivityInfo =
                                 PipUtils.getTopPipActivity(mContext);
                         final ComponentName topActivity = topPipActivityInfo.first;
+                        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                                "onActivityUnpinned: %s", topActivity);
                         mTouchHandler.onActivityUnpinned(topActivity);
                         mAppOpsListener.onActivityUnpinned();
                         mPipInputConsumer.unregisterInputConsumer();
@@ -593,6 +597,8 @@
                     @Override
                     public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
                             boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
+                        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                                "onActivityRestartAttempt: %s", task.topActivity);
                         if (task.getWindowingMode() != WINDOWING_MODE_PINNED) {
                             return;
                         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index 281cae5..abe2db0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -70,6 +70,7 @@
     private final PipBoundsAlgorithm mPipBoundsAlgorithm;
     private final PipMotionHelper mMotionHelper;
     private final PipBoundsState mPipBoundsState;
+    private final PipTouchState mPipTouchState;
     private final PipTaskOrganizer mPipTaskOrganizer;
     private final PhonePipMenuController mPhonePipMenuController;
     private final PipDismissTargetHandler mPipDismissTargetHandler;
@@ -104,7 +105,6 @@
     private boolean mAllowGesture;
     private boolean mIsAttached;
     private boolean mIsEnabled;
-    private boolean mEnableTouch;
     private boolean mEnablePinchResize;
     private boolean mEnableDragCornerResize;
     private boolean mIsSysUiStateValid;
@@ -122,7 +122,8 @@
 
     public PipResizeGestureHandler(Context context, PipBoundsAlgorithm pipBoundsAlgorithm,
             PipBoundsState pipBoundsState, PipMotionHelper motionHelper,
-            PipTaskOrganizer pipTaskOrganizer, PipDismissTargetHandler pipDismissTargetHandler,
+            PipTouchState pipTouchState, PipTaskOrganizer pipTaskOrganizer,
+            PipDismissTargetHandler pipDismissTargetHandler,
             Function<Rect, Rect> movementBoundsSupplier, Runnable updateMovementBoundsRunnable,
             PipUiEventLogger pipUiEventLogger, PhonePipMenuController menuActivityController,
             ShellExecutor mainExecutor) {
@@ -132,6 +133,7 @@
         mPipBoundsAlgorithm = pipBoundsAlgorithm;
         mPipBoundsState = pipBoundsState;
         mMotionHelper = motionHelper;
+        mPipTouchState = pipTouchState;
         mPipTaskOrganizer = pipTaskOrganizer;
         mPipDismissTargetHandler = pipDismissTargetHandler;
         mMovementBoundsSupplier = movementBoundsSupplier;
@@ -139,7 +141,6 @@
         mPhonePipMenuController = menuActivityController;
         mPipUiEventLogger = pipUiEventLogger;
         mPinchResizingAlgorithm = new PipPinchResizingAlgorithm();
-        mEnableTouch = true;
 
         mUpdateResizeBoundsCallback = (rect) -> {
             mUserResizeBounds.set(rect);
@@ -250,8 +251,8 @@
             return;
         }
 
-        if (!mEnableTouch) {
-            // No need to handle anything if touches are not enabled for resizing.
+        if (!mPipTouchState.getAllowInputEvents()) {
+            // No need to handle anything if touches are not enabled
             return;
         }
 
@@ -588,13 +589,13 @@
                         mLastResizeBounds, movementBounds);
                 mPipBoundsAlgorithm.applySnapFraction(mLastResizeBounds, snapFraction);
 
-                // disable the resizing until the final bounds are updated
-                mEnableTouch = false;
+                // disable any touch events beyond resizing too
+                mPipTouchState.setAllowInputEvents(false);
 
                 mPipTaskOrganizer.scheduleAnimateResizePip(startBounds, mLastResizeBounds,
                         PINCH_RESIZE_SNAP_DURATION, mAngle, mUpdateResizeBoundsCallback, () -> {
-                            // reset the pinch resizing to its default state
-                            mEnableTouch = true;
+                            // enable touch events
+                            mPipTouchState.setAllowInputEvents(true);
                         });
             } else {
                 mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipSizeSpecHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipSizeSpecHandler.java
index 82fe38c..7971c04 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipSizeSpecHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipSizeSpecHandler.java
@@ -135,14 +135,14 @@
                 maxWidth = (int) (mOptimizedAspectRatio * shorterLength
                         + shorterLength * (aspectRatio - mOptimizedAspectRatio) / (1
                         + aspectRatio));
-                maxHeight = (int) (maxWidth / aspectRatio);
+                maxHeight = Math.round(maxWidth / aspectRatio);
             } else {
                 if (aspectRatio > 1f) {
                     maxWidth = shorterLength;
-                    maxHeight = (int) (maxWidth / aspectRatio);
+                    maxHeight = Math.round(maxWidth / aspectRatio);
                 } else {
                     maxHeight = shorterLength;
-                    maxWidth = (int) (maxHeight * aspectRatio);
+                    maxWidth = Math.round(maxHeight * aspectRatio);
                 }
             }
 
@@ -165,10 +165,9 @@
 
             Size maxSize = this.getMaxSize(aspectRatio);
 
-            int defaultWidth = Math.max((int) (maxSize.getWidth() * mDefaultSizePercent),
+            int defaultWidth = Math.max(Math.round(maxSize.getWidth() * mDefaultSizePercent),
                     minSize.getWidth());
-            int defaultHeight = Math.max((int) (maxSize.getHeight() * mDefaultSizePercent),
-                    minSize.getHeight());
+            int defaultHeight = Math.round(defaultWidth / aspectRatio);
 
             return new Size(defaultWidth, defaultHeight);
         }
@@ -188,16 +187,16 @@
 
             Size maxSize = this.getMaxSize(aspectRatio);
 
-            int minWidth = (int) (maxSize.getWidth() * mMinimumSizePercent);
-            int minHeight = (int) (maxSize.getHeight() * mMinimumSizePercent);
+            int minWidth = Math.round(maxSize.getWidth() * mMinimumSizePercent);
+            int minHeight = Math.round(maxSize.getHeight() * mMinimumSizePercent);
 
             // make sure the calculated min size is not smaller than the allowed default min size
             if (aspectRatio > 1f) {
-                minHeight = (int) Math.max(minHeight, mDefaultMinSize);
-                minWidth = (int) (minHeight * aspectRatio);
+                minHeight = Math.max(minHeight, mDefaultMinSize);
+                minWidth = Math.round(minHeight * aspectRatio);
             } else {
-                minWidth = (int) Math.max(minWidth, mDefaultMinSize);
-                minHeight = (int) (minWidth / aspectRatio);
+                minWidth = Math.max(minWidth, mDefaultMinSize);
+                minHeight = Math.round(minWidth / aspectRatio);
             }
             return new Size(minWidth, minHeight);
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index 466da0e..2c4f76b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -199,11 +199,6 @@
         mMotionHelper = pipMotionHelper;
         mPipDismissTargetHandler = new PipDismissTargetHandler(context, pipUiEventLogger,
                 mMotionHelper, mainExecutor);
-        mPipResizeGestureHandler =
-                new PipResizeGestureHandler(context, pipBoundsAlgorithm, pipBoundsState,
-                        mMotionHelper, pipTaskOrganizer, mPipDismissTargetHandler,
-                        this::getMovementBounds, this::updateMovementBounds, pipUiEventLogger,
-                        menuController, mainExecutor);
         mTouchState = new PipTouchState(ViewConfiguration.get(context),
                 () -> {
                     if (mPipBoundsState.isStashed()) {
@@ -220,6 +215,11 @@
                 },
                 menuController::hideMenu,
                 mainExecutor);
+        mPipResizeGestureHandler =
+                new PipResizeGestureHandler(context, pipBoundsAlgorithm, pipBoundsState,
+                        mMotionHelper, mTouchState, pipTaskOrganizer, mPipDismissTargetHandler,
+                        this::getMovementBounds, this::updateMovementBounds, pipUiEventLogger,
+                        menuController, mainExecutor);
         mConnection = new PipAccessibilityInteractionConnection(mContext, pipBoundsState,
                 mMotionHelper, pipTaskOrganizer, mPipBoundsAlgorithm.getSnapAlgorithm(),
                 this::onAccessibilityShowMenu, this::updateMovementBounds,
@@ -556,6 +556,11 @@
             return true;
         }
 
+        // do not process input event if not allowed
+        if (!mTouchState.getAllowInputEvents()) {
+            return true;
+        }
+
         MotionEvent ev = (MotionEvent) inputEvent;
         if (!mPipBoundsState.isStashed() && mPipResizeGestureHandler.willStartResizeGesture(ev)) {
             // Initialize the touch state for the gesture, but immediately reset to invalidate the
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchState.java
index d7d69f2..7f62c62 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchState.java
@@ -37,7 +37,7 @@
     private static final boolean DEBUG = false;
 
     @VisibleForTesting
-    public static final long DOUBLE_TAP_TIMEOUT = 200;
+    public static final long DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout();
     static final long HOVER_EXIT_TIMEOUT = 50;
 
     private final ShellExecutor mMainExecutor;
@@ -55,6 +55,9 @@
     private final PointF mLastDelta = new PointF();
     private final PointF mVelocity = new PointF();
     private boolean mAllowTouches = true;
+
+    // Set to false to block both PipTouchHandler and PipResizeGestureHandler's input processing
+    private boolean mAllowInputEvents = true;
     private boolean mIsUserInteracting = false;
     // Set to true only if the multiple taps occur within the double tap timeout
     private boolean mIsDoubleTap = false;
@@ -77,6 +80,20 @@
     }
 
     /**
+     * @return true if input processing is enabled for PiP in general.
+     */
+    public boolean getAllowInputEvents() {
+        return mAllowInputEvents;
+    }
+
+    /**
+     * @param allowInputEvents true to enable input processing for PiP in general.
+     */
+    public void setAllowInputEvents(boolean allowInputEvents) {
+        mAllowInputEvents = allowInputEvents;
+    }
+
+    /**
      * Resets this state.
      */
     public void reset() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index 8723f9b..a612f5f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -595,9 +595,20 @@
                         cancel(mWillFinishToHome, true /* withScreenshots */, "display change");
                         return;
                     }
-                    // Don't consider order-only changes as changing apps.
-                    if (!TransitionUtil.isOrderOnly(change)) {
+                    // Don't consider order-only & non-leaf changes as changing apps.
+                    if (!TransitionUtil.isOrderOnly(change) && isLeafTask) {
                         hasChangingApp = true;
+                    } else if (isLeafTask && taskInfo.topActivityType == ACTIVITY_TYPE_HOME
+                            && !mRecentsTask.equals(change.getContainer())) {
+                        // Unless it is a 3p launcher. This means that the 3p launcher was already
+                        // visible (eg. the "pausing" task is translucent over the 3p launcher).
+                        // Treat it as if we are "re-opening" the 3p launcher.
+                        if (openingTasks == null) {
+                            openingTasks = new ArrayList<>();
+                            openingTaskIsLeafs = new IntArray();
+                        }
+                        openingTasks.add(change);
+                        openingTaskIsLeafs.add(1);
                     }
                 }
             }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 366f4f1..a1f82ad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -24,7 +24,6 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.RemoteAnimationTarget.MODE_OPENING;
@@ -580,6 +579,7 @@
                 mRecentTasks.get().removeSplitPair(taskId1);
             }
             options1 = options1 != null ? options1 : new Bundle();
+            addActivityOptions(options1, null);
             wct.startTask(taskId1, options1);
             mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
             return;
@@ -601,6 +601,7 @@
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         if (taskId == INVALID_TASK_ID) {
             options1 = options1 != null ? options1 : new Bundle();
+            addActivityOptions(options1, null);
             wct.sendPendingIntent(pendingIntent, fillInIntent, options1);
             mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
             return;
@@ -621,6 +622,7 @@
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         if (taskId == INVALID_TASK_ID) {
             options1 = options1 != null ? options1 : new Bundle();
+            addActivityOptions(options1, null);
             wct.startShortcut(mContext.getPackageName(), shortcutInfo, options1);
             mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
             return;
@@ -679,6 +681,7 @@
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         if (pendingIntent2 == null) {
             options1 = options1 != null ? options1 : new Bundle();
+            addActivityOptions(options1, null);
             if (shortcutInfo1 != null) {
                 wct.startShortcut(mContext.getPackageName(), shortcutInfo1, options1);
             } else {
@@ -1479,6 +1482,10 @@
         }
         // If running background, we need to reparent current top visible task to main stage.
         if (!isSplitScreenVisible()) {
+            // Ensure to evict old splitting tasks because the new split pair might be composed by
+            // one of the splitting tasks, evicting the task when finishing entering transition
+            // won't guarantee to put the task to the indicated new position.
+            mMainStage.evictAllChildren(wct);
             mMainStage.reparentTopTask(wct);
             prepareSplitLayout(wct);
         }
@@ -2308,8 +2315,9 @@
                     mSplitTransitions.setDismissTransition(transition, dismissTop,
                             EXIT_REASON_APP_FINISHED);
                 } else if (!isSplitScreenVisible() && isOpening) {
-                    // If split running backgroud and trigger task is appearing into split,
-                    // prepare to enter split screen.
+                    // If split is running in the background and the trigger task is appearing into
+                    // split, prepare to enter split screen.
+                    setSideStagePosition(SPLIT_POSITION_BOTTOM_OR_RIGHT, out);
                     prepareEnterSplitScreen(out);
                     mSplitTransitions.setEnterTransition(transition, request.getRemoteTransition(),
                             TRANSIT_SPLIT_SCREEN_PAIR_OPEN, !mIsDropEntering);
@@ -2335,6 +2343,7 @@
             if (isOpening && getStageOfTask(triggerTask) != null) {
                 // One task is appearing into split, prepare to enter split screen.
                 out = new WindowContainerTransaction();
+                setSideStagePosition(SPLIT_POSITION_BOTTOM_OR_RIGHT, out);
                 prepareEnterSplitScreen(out);
                 mSplitTransitions.setEnterTransition(transition, request.getRemoteTransition(),
                         TRANSIT_SPLIT_SCREEN_PAIR_OPEN, !mIsDropEntering);
@@ -2407,7 +2416,6 @@
                 if (change.getMode() == TRANSIT_CHANGE
                         && (change.getFlags() & FLAG_IS_DISPLAY) != 0) {
                     mSplitLayout.update(startTransaction);
-                    record.mContainDisplayChange = true;
                 }
 
                 final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
@@ -2439,8 +2447,8 @@
                 final StageTaskListener stage = getStageOfTask(taskInfo);
                 if (stage == null) {
                     if (change.getParent() == null && !isClosingType(change.getMode())
-                            && taskInfo.getWindowingMode() == WINDOWING_MODE_PINNED) {
-                        record.mContainShowPipChange = true;
+                            && taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+                        record.mContainShowFullscreenChange = true;
                     }
                     continue;
                 }
@@ -2459,15 +2467,7 @@
                 }
             }
             final ArraySet<StageTaskListener> dismissStages = record.getShouldDismissedStage();
-            if (!record.mContainDisplayChange && record.mContainShowPipChange) {
-                // This occurred when split enter pip by open another fullscreen app so let
-                // pip tranistion handler to handle this but also start our dismiss transition.
-                // TODO(b/282894249): Should improve this case animation on pip.
-                final WindowContainerTransaction wct = new WindowContainerTransaction();
-                prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct);
-                mSplitTransitions.startDismissTransition(wct, this, STAGE_TYPE_UNDEFINED,
-                        EXIT_REASON_CHILD_TASK_ENTER_PIP);
-            } else if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0
+            if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0
                     || dismissStages.size() == 1) {
                 // If the size of dismissStages == 1, one of the task is closed without prepare
                 // pending transition, which could happen if all activities were finished after
@@ -2480,9 +2480,11 @@
                 final int dismissTop = (dismissStages.size() == 1
                         && getStageType(dismissStages.valueAt(0)) == STAGE_TYPE_MAIN)
                         || mMainStage.getChildCount() == 0 ? STAGE_TYPE_SIDE : STAGE_TYPE_MAIN;
-                prepareExitSplitScreen(dismissTop, wct);
+                // If there is a fullscreen opening change, we should not bring stage to top.
+                prepareExitSplitScreen(record.mContainShowFullscreenChange
+                        ? STAGE_TYPE_UNDEFINED : dismissTop, wct);
                 mSplitTransitions.startDismissTransition(wct, this, dismissTop,
-                        EXIT_REASON_UNKNOWN);
+                        EXIT_REASON_APP_FINISHED);
                 // This can happen in some pathological cases. For example:
                 // 1. main has 2 tasks [Task A (Single-task), Task B], side has one task [Task C]
                 // 2. Task B closes itself and starts Task A in LAUNCH_ADJACENT at the same time
@@ -2497,6 +2499,7 @@
             // handling to the mixed-handler to deal with splitting it up.
             if (mMixedHandler.animatePendingSplitWithDisplayChange(transition, info,
                     startTransaction, finishTransaction, finishCallback)) {
+                mSplitLayout.update(startTransaction);
                 return true;
             }
         }
@@ -2506,8 +2509,7 @@
     }
 
     static class StageChangeRecord {
-        boolean mContainDisplayChange = false;
-        boolean mContainShowPipChange = false;
+        boolean mContainShowFullscreenChange = false;
         static class StageChange {
             final StageTaskListener mStageTaskListener;
             final IntArray mAddedTaskId = new IntArray();
@@ -2882,6 +2884,12 @@
     /** Call this when the recents animation canceled during split-screen. */
     public void onRecentsInSplitAnimationCanceled() {
         mPausingTasks.clear();
+        setSplitsVisible(false);
+
+        final WindowContainerTransaction wct = new WindowContainerTransaction();
+        wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
+                true /* reparentLeafTaskIfRelaunch */);
+        mTaskOrganizer.applyTransaction(wct);
     }
 
     /** Call this when the recents animation during split-screen finishes. */
@@ -2906,8 +2914,8 @@
         }
 
         setSplitsVisible(false);
-        prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, finishWct);
-        logExit(EXIT_REASON_UNKNOWN);
+        finishWct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
+                true /* reparentLeafTaskIfRelaunch */);
     }
 
     /** Call this when the recents animation finishes by doing pair-to-pair switch. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index 64571e0..3ec433e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -31,6 +31,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.IBinder;
+import android.util.Log;
 import android.util.Pair;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
@@ -566,11 +567,18 @@
             @NonNull SurfaceControl.Transaction startTransaction,
             @NonNull SurfaceControl.Transaction finishTransaction,
             @NonNull Transitions.TransitionFinishCallback finishCallback) {
-        boolean consumed = mKeyguardHandler.startAnimation(
-                mixed.mTransition, info, startTransaction, finishTransaction, finishCallback);
-        if (!consumed) {
+        final Transitions.TransitionFinishCallback finishCB = (wct, wctCB) -> {
+            mixed.mInFlightSubAnimations--;
+            if (mixed.mInFlightSubAnimations == 0) {
+                mActiveTransitions.remove(mixed);
+                finishCallback.onTransitionFinished(wct, wctCB);
+            }
+        };
+        if (!mKeyguardHandler.startAnimation(
+                mixed.mTransition, info, startTransaction, finishTransaction, finishCB)) {
             return false;
         }
+        mixed.mInFlightSubAnimations++;
         // Sync pip state.
         if (mPipHandler != null) {
             // We don't know when to apply `startTransaction` so use a separate transaction here.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index 4c678a2..3bf278c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -58,7 +58,6 @@
 import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITION_INTRA_OPEN;
 import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITION_NONE;
 import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITION_OPEN;
-import static com.android.wm.shell.transition.TransitionAnimationHelper.addBackgroundToTransition;
 import static com.android.wm.shell.transition.TransitionAnimationHelper.edgeExtendWindow;
 import static com.android.wm.shell.transition.TransitionAnimationHelper.getTransitionBackgroundColorIfSet;
 import static com.android.wm.shell.transition.TransitionAnimationHelper.loadAttributeAnimation;
@@ -76,6 +75,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.graphics.Color;
 import android.graphics.Insets;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -103,6 +103,7 @@
 import com.android.internal.policy.ScreenDecorationsUtils;
 import com.android.internal.policy.TransitionAnimation;
 import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.ShellExecutor;
@@ -137,6 +138,7 @@
     private final Rect mInsets = new Rect(0, 0, 0, 0);
     private float mTransitionAnimationScaleSetting = 1.0f;
 
+    private final RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
     private final int mCurrentUserId;
 
     private Drawable mEnterpriseThumbnailDrawable;
@@ -157,7 +159,8 @@
             @NonNull DisplayController displayController,
             @NonNull TransactionPool transactionPool,
             @NonNull ShellExecutor mainExecutor, @NonNull Handler mainHandler,
-            @NonNull ShellExecutor animExecutor) {
+            @NonNull ShellExecutor animExecutor,
+            @NonNull RootTaskDisplayAreaOrganizer rootTDAOrganizer) {
         mDisplayController = displayController;
         mTransactionPool = transactionPool;
         mContext = context;
@@ -168,6 +171,7 @@
         mCurrentUserId = UserHandle.myUserId();
         mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
         shellInit.addInitCallback(this::onInit, this);
+        mRootTDAOrganizer = rootTDAOrganizer;
     }
 
     private void onInit() {
@@ -510,10 +514,8 @@
         }
 
         if (backgroundColorForTransition != 0) {
-            for (int i = 0; i < info.getRootCount(); ++i) {
-                addBackgroundToTransition(info.getRoot(i).getLeash(), backgroundColorForTransition,
-                        startTransaction, finishTransaction);
-            }
+            addBackgroundColorOnTDA(info, backgroundColorForTransition, startTransaction,
+                    finishTransaction);
         }
 
         if (postStartTransactionCallbacks.size() > 0) {
@@ -543,6 +545,28 @@
         return true;
     }
 
+    private void addBackgroundColorOnTDA(@NonNull TransitionInfo info,
+            @ColorInt int color, @NonNull SurfaceControl.Transaction startTransaction,
+            @NonNull SurfaceControl.Transaction finishTransaction) {
+        final Color bgColor = Color.valueOf(color);
+        final float[] colorArray = new float[] { bgColor.red(), bgColor.green(), bgColor.blue() };
+
+        for (int i = 0; i < info.getRootCount(); ++i) {
+            final int displayId = info.getRoot(i).getDisplayId();
+            final SurfaceControl.Builder colorLayerBuilder = new SurfaceControl.Builder()
+                    .setName("animation-background")
+                    .setCallsite("DefaultTransitionHandler")
+                    .setColorLayer();
+
+            mRootTDAOrganizer.attachToDisplayArea(displayId, colorLayerBuilder);
+            final SurfaceControl backgroundSurface = colorLayerBuilder.build();
+            startTransaction.setColor(backgroundSurface, colorArray)
+                    .setLayer(backgroundSurface, -1)
+                    .show(backgroundSurface);
+            finishTransaction.remove(backgroundSurface);
+        }
+    }
+
     private static boolean isDreamTransition(@NonNull TransitionInfo info) {
         for (int i = info.getChanges().size() - 1; i >= 0; --i) {
             final TransitionInfo.Change change = info.getChanges().get(i);
@@ -696,9 +720,10 @@
 
         if (a != null) {
             if (!a.isInitialized()) {
-                final int width = endBounds.width();
-                final int height = endBounds.height();
-                a.initialize(width, height, width, height);
+                final Rect animationRange = TransitionUtil.isClosingType(changeMode)
+                        ? change.getStartAbsBounds() : change.getEndAbsBounds();
+                a.initialize(animationRange.width(), animationRange.height(),
+                        endBounds.width(), endBounds.height());
             }
             a.restrictDuration(MAX_ANIMATION_DURATION);
             a.scaleCurrentDuration(mTransitionAnimationScaleSetting);
@@ -873,18 +898,31 @@
         }
     }
 
+    /**
+     * Returns {@code true} if the default transition handler can run the override animation.
+     * @see #loadAnimation(TransitionInfo, TransitionInfo.Change, int, boolean)
+     */
+    public static boolean isSupportedOverrideAnimation(
+            @NonNull TransitionInfo.AnimationOptions options) {
+        final int animType = options.getType();
+        return animType == ANIM_CUSTOM || animType == ANIM_SCALE_UP
+                || animType == ANIM_THUMBNAIL_SCALE_UP || animType == ANIM_THUMBNAIL_SCALE_DOWN
+                || animType == ANIM_CLIP_REVEAL || animType == ANIM_OPEN_CROSS_PROFILE_APPS;
+    }
+
     private static void applyTransformation(long time, SurfaceControl.Transaction t,
-            SurfaceControl leash, Animation anim, Transformation transformation, float[] matrix,
+            SurfaceControl leash, Animation anim, Transformation tmpTransformation, float[] matrix,
             Point position, float cornerRadius, @Nullable Rect immutableClipRect) {
-        anim.getTransformation(time, transformation);
+        tmpTransformation.clear();
+        anim.getTransformation(time, tmpTransformation);
         if (position != null) {
-            transformation.getMatrix().postTranslate(position.x, position.y);
+            tmpTransformation.getMatrix().postTranslate(position.x, position.y);
         }
-        t.setMatrix(leash, transformation.getMatrix(), matrix);
-        t.setAlpha(leash, transformation.getAlpha());
+        t.setMatrix(leash, tmpTransformation.getMatrix(), matrix);
+        t.setAlpha(leash, tmpTransformation.getAlpha());
 
         final Rect clipRect = immutableClipRect == null ? null : new Rect(immutableClipRect);
-        Insets extensionInsets = Insets.min(transformation.getInsets(), Insets.NONE);
+        Insets extensionInsets = Insets.min(tmpTransformation.getInsets(), Insets.NONE);
         if (!extensionInsets.equals(Insets.NONE) && clipRect != null && !clipRect.isEmpty()) {
             // Clip out any overflowing edge extension
             clipRect.inset(extensionInsets);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index de20c2d..cdc82ea 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -69,6 +69,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.ExternalInterfaceBinder;
 import com.android.wm.shell.common.RemoteCallable;
@@ -265,7 +266,8 @@
             @NonNull Handler mainHandler,
             @NonNull ShellExecutor animExecutor) {
         this(context, shellInit, shellController, organizer, pool, displayController, mainExecutor,
-                mainHandler, animExecutor, null);
+                mainHandler, animExecutor, null,
+                new RootTaskDisplayAreaOrganizer(mainExecutor, context));
     }
 
     public Transitions(@NonNull Context context,
@@ -277,7 +279,8 @@
             @NonNull ShellExecutor mainExecutor,
             @NonNull Handler mainHandler,
             @NonNull ShellExecutor animExecutor,
-            @Nullable ShellCommandHandler shellCommandHandler) {
+            @Nullable ShellCommandHandler shellCommandHandler,
+            @NonNull RootTaskDisplayAreaOrganizer rootTDAOrganizer) {
         mOrganizer = organizer;
         mContext = context;
         mMainExecutor = mainExecutor;
@@ -285,7 +288,7 @@
         mDisplayController = displayController;
         mPlayerImpl = new TransitionPlayerImpl();
         mDefaultTransitionHandler = new DefaultTransitionHandler(context, shellInit,
-                displayController, pool, mainExecutor, mainHandler, animExecutor);
+                displayController, pool, mainExecutor, mainHandler, animExecutor, rootTDAOrganizer);
         mRemoteTransitionHandler = new RemoteTransitionHandler(mMainExecutor);
         mShellController = shellController;
         // The very last handler (0 in the list) should be the default one.
@@ -641,6 +644,7 @@
     @VisibleForTesting
     void onTransitionReady(@NonNull IBinder transitionToken, @NonNull TransitionInfo info,
             @NonNull SurfaceControl.Transaction t, @NonNull SurfaceControl.Transaction finishT) {
+        info.setUnreleasedWarningCallSiteForAllSurfaces("Transitions.onTransitionReady");
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "onTransitionReady %s: %s",
                 transitionToken, info);
         final int activeIdx = findByToken(mPendingTransitions, transitionToken);
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipFromSplitScreenOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipFromSplitScreenOnGoToHomeTest.kt
new file mode 100644
index 0000000..f7ce870
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipFromSplitScreenOnGoToHomeTest.kt
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import android.app.Instrumentation
+import android.os.SystemClock
+import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
+import android.tools.device.traces.parsers.toFlickerComponent
+import androidx.test.filters.RequiresDevice
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.BySelector
+import androidx.test.uiautomator.UiObject2
+import androidx.test.uiautomator.Until
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.server.wm.flicker.testapp.ActivityOptions
+import com.android.wm.shell.flicker.LAUNCHER_UI_PACKAGE_NAME
+import org.junit.Assume
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test entering pip from an app via auto-enter property when navigating to home from split screen.
+ *
+ * To run this test: `atest WMShellFlickerTests:AutoEnterPipOnGoToHomeTest`
+ *
+ * Actions:
+ * ```
+ *     Launch an app in full screen
+ *     Select "Auto-enter PiP" radio button
+ *     Open all apps and drag another app icon to enter split screen
+ *     Press Home button or swipe up to go Home and put [pipApp] in pip mode
+ * ```
+ *
+ * Notes:
+ * ```
+ *     1. All assertions are inherited from [EnterPipTest]
+ *     2. Part of the test setup occurs automatically via
+ *        [android.tools.device.flicker.legacy.runner.TransitionRunner],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
+ * ```
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class AutoEnterPipFromSplitScreenOnGoToHomeTest(flicker: FlickerTest) :
+        AutoEnterPipOnGoToHomeTest(flicker) {
+    private val portraitDisplayBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_0)
+    /** Second app used to enter split screen mode */
+    protected val secondAppForSplitScreen = getSplitScreenApp(instrumentation)
+    fun getSplitScreenApp(instrumentation: Instrumentation): StandardAppHelper =
+            SimpleAppHelper(
+                    instrumentation,
+                    ActivityOptions.SplitScreen.Primary.LABEL,
+                    ActivityOptions.SplitScreen.Primary.COMPONENT.toFlickerComponent()
+            )
+
+    /** Defines the transition used to run the test */
+    override val transition: FlickerBuilder.() -> Unit
+        get() = {
+            setup {
+                secondAppForSplitScreen.launchViaIntent(wmHelper)
+                pipApp.launchViaIntent(wmHelper)
+                tapl.goHome()
+                enterSplitScreen()
+                // wait until split screen is established
+                wmHelper
+                        .StateSyncBuilder()
+                        .withWindowSurfaceAppeared(pipApp)
+                        .withWindowSurfaceAppeared(secondAppForSplitScreen)
+                        .withSplitDividerVisible()
+                        .waitForAndVerify()
+                pipApp.enableAutoEnterForPipActivity()
+            }
+            teardown {
+                // close gracefully so that onActivityUnpinned() can be called before force exit
+                pipApp.closePipWindow(wmHelper)
+                pipApp.exit(wmHelper)
+                secondAppForSplitScreen.exit(wmHelper)
+            }
+            transitions { tapl.goHome() }
+        }
+
+    // TODO(b/285400227) merge the code in a common utility - this is copied from SplitScreenUtils
+    private val TIMEOUT_MS = 3_000L
+    private val overviewSnapshotSelector: BySelector
+        get() = By.res(LAUNCHER_UI_PACKAGE_NAME, "snapshot")
+    private fun enterSplitScreen() {
+        // Note: The initial split position in landscape is different between tablet and phone.
+        // In landscape, tablet will let the first app split to right side, and phone will
+        // split to left side.
+        if (tapl.isTablet) {
+            // TAPL's currentTask on tablet is sometimes not what we expected if the overview
+            // contains more than 3 task views. We need to use uiautomator directly to find the
+            // second task to split.
+            tapl.workspace.switchToOverview().overviewActions.clickSplit()
+            val snapshots = tapl.device.wait(Until.findObjects(overviewSnapshotSelector),
+                    TIMEOUT_MS)
+            if (snapshots == null || snapshots.size < 1) {
+                error("Fail to find a overview snapshot to split.")
+            }
+
+            // Find the second task in the upper right corner in split select mode by sorting
+            // 'left' in descending order and 'top' in ascending order.
+            snapshots.sortWith { t1: UiObject2, t2: UiObject2 ->
+                t2.getVisibleBounds().left - t1.getVisibleBounds().left
+            }
+            snapshots.sortWith { t1: UiObject2, t2: UiObject2 ->
+                t1.getVisibleBounds().top - t2.getVisibleBounds().top
+            }
+            snapshots[0].click()
+        } else {
+            tapl.workspace
+                    .switchToOverview()
+                    .currentTask
+                    .tapMenu()
+                    .tapSplitMenuItem()
+                    .currentTask
+                    .open()
+        }
+        SystemClock.sleep(TIMEOUT_MS)
+    }
+
+    @Presubmit
+    @Test
+    override fun pipOverlayLayerAppearThenDisappear() {
+        // when entering from split screen we use alpha animation, without overlay
+    }
+
+    @Presubmit
+    @Test
+    override fun pipLayerOrOverlayRemainInsideVisibleBounds() {
+        // when entering from split screen we use alpha animation, without overlay
+    }
+
+    @Presubmit
+    @Test
+    override fun pipLayerReduces() {
+        // when entering from split screen we use alpha animation, so there is no size change
+        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+        super.pipLayerReduces()
+    }
+
+    @Presubmit
+    @Test
+    override fun pipAppLayerAlwaysVisible() {
+        // pip layer in gesture nav will disappear during transition with alpha animation
+        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+        super.pipAppLayerAlwaysVisible()
+    }
+
+    @Presubmit
+    @Test
+    override fun pipWindowRemainInsideVisibleBounds() {
+        if (tapl.isTablet) {
+            flicker.assertWmVisibleRegion(pipApp) { coversAtMost(displayBounds) }
+        } else {
+            // on phones home does not rotate in landscape, PiP enters back to portrait
+            // orientation so use display bounds from that orientation for assertion
+            flicker.assertWmVisibleRegion(pipApp) { coversAtMost(portraitDisplayBounds) }
+        }
+    }
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): List<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests(
+                    // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
+                    supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
+            )
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
index a4ac261..b95732e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.pip
 
-import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Presubmit
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.device.flicker.legacy.FlickerBuilder
@@ -54,21 +53,25 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class AutoEnterPipOnGoToHomeTest(flicker: FlickerTest) : EnterPipViaAppUiButtonTest(flicker) {
-    /** Defines the transition used to run the test */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            setup {
-                pipApp.launchViaIntent(wmHelper)
-                pipApp.enableAutoEnterForPipActivity()
-            }
-            teardown {
-                // close gracefully so that onActivityUnpinned() can be called before force exit
-                pipApp.closePipWindow(wmHelper)
-                pipApp.exit(wmHelper)
-            }
-            transitions { tapl.goHome() }
+open class AutoEnterPipOnGoToHomeTest(flicker: FlickerTest) : EnterPipViaAppUiButtonTest(flicker) {
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        transitions { tapl.goHome() }
+    }
+
+    override val defaultEnterPip: FlickerBuilder.() -> Unit = {
+        setup {
+            pipApp.launchViaIntent(wmHelper)
+            pipApp.enableAutoEnterForPipActivity()
         }
+    }
+
+    override val defaultTeardown: FlickerBuilder.() -> Unit = {
+        teardown {
+            // close gracefully so that onActivityUnpinned() can be called before force exit
+            pipApp.closePipWindow(wmHelper)
+            pipApp.exit(wmHelper)
+        }
+    }
 
     @Presubmit
     @Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
index 98fc91b..afcc172 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
@@ -54,40 +54,38 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 open class ClosePipBySwipingDownTest(flicker: FlickerTest) : ClosePipTransition(flicker) {
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            super.transition(this)
-            transitions {
-                val pipRegion = wmHelper.getWindowRegion(pipApp).bounds
-                val pipCenterX = pipRegion.centerX()
-                val pipCenterY = pipRegion.centerY()
-                val displayCenterX = device.displayWidth / 2
-                val barComponent =
-                    if (flicker.scenario.isTablet) {
-                        ComponentNameMatcher.TASK_BAR
-                    } else {
-                        ComponentNameMatcher.NAV_BAR
-                    }
-                val barLayerHeight =
-                    wmHelper.currentState.layerState
-                        .getLayerWithBuffer(barComponent)
-                        ?.visibleRegion
-                        ?.height
-                        ?: error("Couldn't find Nav or Task bar layer")
-                // The dismiss button doesn't appear at the complete bottom of the screen,
-                // it appears above the hot seat but `hotseatBarSize` is not available outside
-                // the platform
-                val displayY = (device.displayHeight * 0.9).toInt() - barLayerHeight
-                device.swipe(pipCenterX, pipCenterY, displayCenterX, displayY, 50)
-                // Wait until the other app is no longer visible
-                wmHelper
-                    .StateSyncBuilder()
-                    .withPipGone()
-                    .withWindowSurfaceDisappeared(pipApp)
-                    .withAppTransitionIdle()
-                    .waitForAndVerify()
-            }
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        transitions {
+            val pipRegion = wmHelper.getWindowRegion(pipApp).bounds
+            val pipCenterX = pipRegion.centerX()
+            val pipCenterY = pipRegion.centerY()
+            val displayCenterX = device.displayWidth / 2
+            val barComponent =
+                if (flicker.scenario.isTablet) {
+                    ComponentNameMatcher.TASK_BAR
+                } else {
+                    ComponentNameMatcher.NAV_BAR
+                }
+            val barLayerHeight =
+                wmHelper.currentState.layerState
+                    .getLayerWithBuffer(barComponent)
+                    ?.visibleRegion
+                    ?.height
+                    ?: error("Couldn't find Nav or Task bar layer")
+            // The dismiss button doesn't appear at the complete bottom of the screen,
+            // it appears above the hot seat but `hotseatBarSize` is not available outside
+            // the platform
+            val displayY = (device.displayHeight * 0.9).toInt() - barLayerHeight
+            device.swipe(pipCenterX, pipCenterY, displayCenterX, displayY, 50)
+            // Wait until the other app is no longer visible
+            wmHelper
+                .StateSyncBuilder()
+                .withPipGone()
+                .withWindowSurfaceDisappeared(pipApp)
+                .withAppTransitionIdle()
+                .waitForAndVerify()
         }
+    }
 
     /** Checks that the focus doesn't change between windows during the transition */
     @Presubmit
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
index 2417c45..e52b71e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
@@ -28,11 +28,10 @@
 
 /** Base class for exiting pip (closing pip window) without returning to the app */
 abstract class ClosePipTransition(flicker: FlickerTest) : PipTransition(flicker) {
-    override val transition: FlickerBuilder.() -> Unit
-        get() = buildTransition {
-            setup { this.setRotation(flicker.scenario.startRotation) }
-            teardown { this.setRotation(Rotation.ROTATION_0) }
-        }
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        setup { this.setRotation(flicker.scenario.startRotation) }
+        teardown { this.setRotation(Rotation.ROTATION_0) }
+    }
 
     /**
      * Checks that [pipApp] window is pinned and visible at the start and then becomes unpinned and
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt
index d165832..86fe583 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt
@@ -54,12 +54,9 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 open class ClosePipWithDismissButtonTest(flicker: FlickerTest) : ClosePipTransition(flicker) {
-
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            super.transition(this)
-            transitions { pipApp.closePipWindow(wmHelper) }
-        }
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        transitions { pipApp.closePipWindow(wmHelper) }
+    }
 
     /**
      * Checks that the focus changes between the pip menu window and the launcher when clicking the
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
index f52e877..01d67cc 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
@@ -45,20 +45,24 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 open class EnterPipOnUserLeaveHintTest(flicker: FlickerTest) : EnterPipTransition(flicker) {
-    /** Defines the transition used to run the test */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            setup {
-                pipApp.launchViaIntent(wmHelper)
-                pipApp.enableEnterPipOnUserLeaveHint()
-            }
-            teardown {
-                // close gracefully so that onActivityUnpinned() can be called before force exit
-                pipApp.closePipWindow(wmHelper)
-                pipApp.exit(wmHelper)
-            }
-            transitions { tapl.goHome() }
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        transitions { tapl.goHome() }
+    }
+
+    override val defaultEnterPip: FlickerBuilder.() -> Unit = {
+        setup {
+            pipApp.launchViaIntent(wmHelper)
+            pipApp.enableEnterPipOnUserLeaveHint()
         }
+    }
+
+    override val defaultTeardown: FlickerBuilder.() -> Unit = {
+        teardown {
+            // close gracefully so that onActivityUnpinned() can be called before force exit
+            pipApp.closePipWindow(wmHelper)
+            pipApp.exit(wmHelper)
+        }
+    }
 
     @Presubmit
     @Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
index 4b461370..5480144 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
@@ -73,39 +73,39 @@
     private val startingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_90)
     private val endingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_0)
 
-    /** Defines the transition used to run the test */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            setup {
-                // Launch a portrait only app on the fullscreen stack
-                testApp.launchViaIntent(
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        teardown {
+            testApp.exit(wmHelper)
+        }
+        transitions {
+            // Enter PiP, and assert that the PiP is within bounds now that the device is back
+            // in portrait
+            broadcastActionTrigger.doAction(ACTION_ENTER_PIP)
+            // during rotation the status bar becomes invisible and reappears at the end
+            wmHelper
+                .StateSyncBuilder()
+                .withPipShown()
+                .withNavOrTaskBarVisible()
+                .withStatusBarVisible()
+                .waitForAndVerify()
+        }
+    }
+
+    override val defaultEnterPip: FlickerBuilder.() -> Unit = {
+        setup {
+            // Launch a portrait only app on the fullscreen stack
+            testApp.launchViaIntent(
                     wmHelper,
                     stringExtras = mapOf(EXTRA_FIXED_ORIENTATION to ORIENTATION_PORTRAIT.toString())
-                )
-                // Launch the PiP activity fixed as landscape
-                pipApp.launchViaIntent(
+            )
+            // Launch the PiP activity fixed as landscape, but don't enter PiP
+            pipApp.launchViaIntent(
                     wmHelper,
                     stringExtras =
-                        mapOf(EXTRA_FIXED_ORIENTATION to ORIENTATION_LANDSCAPE.toString())
-                )
-            }
-            teardown {
-                pipApp.exit(wmHelper)
-                testApp.exit(wmHelper)
-            }
-            transitions {
-                // Enter PiP, and assert that the PiP is within bounds now that the device is back
-                // in portrait
-                broadcastActionTrigger.doAction(ACTION_ENTER_PIP)
-                // during rotation the status bar becomes invisible and reappears at the end
-                wmHelper
-                    .StateSyncBuilder()
-                    .withPipShown()
-                    .withNavOrTaskBarVisible()
-                    .withStatusBarVisible()
-                    .waitForAndVerify()
-            }
+                    mapOf(EXTRA_FIXED_ORIENTATION to ORIENTATION_LANDSCAPE.toString())
+            )
         }
+    }
 
     /**
      * This test is not compatible with Tablets. When using [Activity.setRequestedOrientation] to
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
index bfd5778..cdbdb85 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
@@ -26,12 +26,11 @@
 import org.junit.runners.Parameterized
 
 abstract class EnterPipTransition(flicker: FlickerTest) : PipTransition(flicker) {
-    /** {@inheritDoc} */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            setup { pipApp.launchViaIntent(wmHelper) }
-            teardown { pipApp.exit(wmHelper) }
+    override val defaultEnterPip: FlickerBuilder.() -> Unit = {
+        setup {
+            pipApp.launchViaIntent(wmHelper)
         }
+    }
 
     /** Checks [pipApp] window remains visible throughout the animation */
     @Presubmit
@@ -63,7 +62,7 @@
      */
     @Presubmit
     @Test
-    fun pipWindowRemainInsideVisibleBounds() {
+    open fun pipWindowRemainInsideVisibleBounds() {
         flicker.assertWmVisibleRegion(pipApp) { coversAtMost(displayBounds) }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt
index f1925d8..95725b6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt
@@ -51,11 +51,7 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 open class EnterPipViaAppUiButtonTest(flicker: FlickerTest) : EnterPipTransition(flicker) {
-
-    /** {@inheritDoc} */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            super.transition(this)
-            transitions { pipApp.clickEnterPipButton(wmHelper) }
-        }
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        transitions { pipApp.clickEnterPipButton(wmHelper) }
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt
index 3e0e37d..0b3d16a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt
@@ -53,19 +53,16 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 open class ExitPipToAppViaExpandButtonTest(flicker: FlickerTest) : ExitPipToAppTransition(flicker) {
-
-    /** Defines the transition used to run the test */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = buildTransition {
-            setup {
-                // launch an app behind the pip one
-                testApp.launchViaIntent(wmHelper)
-            }
-            transitions {
-                // This will bring PipApp to fullscreen
-                pipApp.expandPipWindowToApp(wmHelper)
-                // Wait until the other app is no longer visible
-                wmHelper.StateSyncBuilder().withWindowSurfaceDisappeared(testApp).waitForAndVerify()
-            }
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        setup {
+            // launch an app behind the pip one
+            testApp.launchViaIntent(wmHelper)
         }
+        transitions {
+            // This will bring PipApp to fullscreen
+            pipApp.expandPipWindowToApp(wmHelper)
+            // Wait until the other app is no longer visible
+            wmHelper.StateSyncBuilder().withWindowSurfaceDisappeared(testApp).waitForAndVerify()
+        }
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt
index 603f995..bb2d40b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt
@@ -52,19 +52,16 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 open class ExitPipToAppViaIntentTest(flicker: FlickerTest) : ExitPipToAppTransition(flicker) {
-
-    /** Defines the transition used to run the test */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = buildTransition {
-            setup {
-                // launch an app behind the pip one
-                testApp.launchViaIntent(wmHelper)
-            }
-            transitions {
-                // This will bring PipApp to fullscreen
-                pipApp.exitPipToFullScreenViaIntent(wmHelper)
-                // Wait until the other app is no longer visible
-                wmHelper.StateSyncBuilder().withWindowSurfaceDisappeared(testApp).waitForAndVerify()
-            }
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        setup {
+            // launch an app behind the pip one
+            testApp.launchViaIntent(wmHelper)
         }
+        transitions {
+            // This will bring PipApp to fullscreen
+            pipApp.exitPipToFullScreenViaIntent(wmHelper)
+            // Wait until the other app is no longer visible
+            wmHelper.StateSyncBuilder().withWindowSurfaceDisappeared(testApp).waitForAndVerify()
+        }
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
index bbb1c6c..fd16b6e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
@@ -56,8 +56,9 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 open class ExpandPipOnDoubleClickTest(flicker: FlickerTest) : PipTransition(flicker) {
-    override val transition: FlickerBuilder.() -> Unit
-        get() = buildTransition { transitions { pipApp.doubleClickPipWindow(wmHelper) } }
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        transitions { pipApp.doubleClickPipWindow(wmHelper) }
+    }
 
     /**
      * Checks that the pip app window remains inside the display bounds throughout the whole
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt
index d860e00..253aa4c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt
@@ -35,8 +35,9 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 open class ExpandPipOnPinchOpenTest(flicker: FlickerTest) : PipTransition(flicker) {
-    override val transition: FlickerBuilder.() -> Unit
-        get() = buildTransition { transitions { pipApp.pinchOpenPipWindow(wmHelper, 0.25f, 30) } }
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        transitions { pipApp.pinchOpenPipWindow(wmHelper, 0.25f, 30) }
+    }
 
     /** Checks that the visible region area of [pipApp] always increases during the animation. */
     @Presubmit
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt
index d8d57d2..094060f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt
@@ -56,15 +56,10 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class MovePipDownOnShelfHeightChange(flicker: FlickerTest) : MovePipShelfHeightTransition(flicker) {
-    /** Defines the transition used to run the test */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = buildTransition {
-            teardown {
-                tapl.pressHome()
-                testApp.exit(wmHelper)
-            }
-            transitions { testApp.launchViaIntent(wmHelper) }
-        }
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        teardown { testApp.exit(wmHelper) }
+        transitions { testApp.launchViaIntent(wmHelper) }
+    }
 
     /** Checks that the visible region of [pipApp] window always moves down during the animation. */
     @Presubmit @Test fun pipWindowMovesDown() = pipWindowMoves(Direction.DOWN)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
index 6b061bbb..ff51c27 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
@@ -41,23 +41,21 @@
 open class MovePipOnImeVisibilityChangeTest(flicker: FlickerTest) : PipTransition(flicker) {
     private val imeApp = ImeAppHelper(instrumentation)
 
-    /** {@inheritDoc} */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = buildTransition {
-            setup {
-                imeApp.launchViaIntent(wmHelper)
-                setRotation(flicker.scenario.startRotation)
-            }
-            teardown { imeApp.exit(wmHelper) }
-            transitions {
-                // open the soft keyboard
-                imeApp.openIME(wmHelper)
-                createTag(TAG_IME_VISIBLE)
-
-                // then close it again
-                imeApp.closeIME(wmHelper)
-            }
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        setup {
+            imeApp.launchViaIntent(wmHelper)
+            setRotation(flicker.scenario.startRotation)
         }
+        teardown { imeApp.exit(wmHelper) }
+        transitions {
+            // open the soft keyboard
+            imeApp.openIME(wmHelper)
+            createTag(TAG_IME_VISIBLE)
+
+            // then close it again
+            imeApp.closeIME(wmHelper)
+        }
+    }
 
     /** Ensure the pip window remains visible throughout any keyboard interactions */
     @Presubmit
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt
index ae3f879..27b061b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt
@@ -57,14 +57,12 @@
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 open class MovePipUpOnShelfHeightChangeTest(flicker: FlickerTest) :
     MovePipShelfHeightTransition(flicker) {
-    /** Defines the transition used to run the test */
-    override val transition: FlickerBuilder.() -> Unit
-        get() =
-            buildTransition() {
-                setup { testApp.launchViaIntent(wmHelper) }
-                transitions { tapl.pressHome() }
-                teardown { testApp.exit(wmHelper) }
-            }
+    override val thisTransition: FlickerBuilder.() -> Unit =
+        {
+            setup { testApp.launchViaIntent(wmHelper) }
+            transitions { tapl.pressHome() }
+            teardown { testApp.exit(wmHelper) }
+        }
 
     /** Checks that the visible region of [pipApp] window always moves up during the animation. */
     @Presubmit @Test fun pipWindowMovesUp() = pipWindowMoves(Direction.UP)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipDragTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipDragTest.kt
index 4e2a4e7..9f81ba8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipDragTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipDragTest.kt
@@ -22,7 +22,6 @@
 import android.tools.device.flicker.legacy.FlickerBuilder
 import android.tools.device.flicker.legacy.FlickerTest
 import android.tools.device.flicker.legacy.FlickerTestFactory
-import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
 import com.android.server.wm.flicker.testapp.ActivityOptions
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -37,28 +36,31 @@
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class PipDragTest(flicker: FlickerTest) : PipTransition(flicker) {
     private var isDraggedLeft: Boolean = true
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            val stringExtras = mapOf(ActivityOptions.Pip.EXTRA_ENTER_PIP to "true")
 
-            setup {
-                tapl.setEnableRotation(true)
-                // Launch the PIP activity and wait for it to enter PiP mode
-                RemoveAllTasksButHomeRule.removeAllTasksButHome()
-                pipApp.launchViaIntentAndWaitForPip(wmHelper, stringExtras = stringExtras)
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        transitions { pipApp.dragPipWindowAwayFromEdgeWithoutRelease(wmHelper, 50) }
+    }
 
-                // determine the direction of dragging to test for
-                isDraggedLeft = pipApp.isCloserToRightEdge(wmHelper)
-            }
-            teardown {
-                // release the primary pointer after dragging without release
-                pipApp.releasePipAfterDragging()
+    override val defaultEnterPip: FlickerBuilder.() -> Unit = {
+        val stringExtras = mapOf(ActivityOptions.Pip.EXTRA_ENTER_PIP to "true")
+        setup {
+            tapl.setEnableRotation(true)
+            pipApp.launchViaIntentAndWaitForPip(wmHelper, stringExtras = stringExtras)
 
-                pipApp.exit(wmHelper)
-                tapl.setEnableRotation(false)
-            }
-            transitions { pipApp.dragPipWindowAwayFromEdgeWithoutRelease(wmHelper, 50) }
+            // determine the direction of dragging to test for
+            isDraggedLeft = pipApp.isCloserToRightEdge(wmHelper)
         }
+    }
+
+    override val defaultTeardown: FlickerBuilder.() -> Unit = {
+        teardown {
+            // release the primary pointer after dragging without release
+            pipApp.releasePipAfterDragging()
+
+            pipApp.exit(wmHelper)
+            tapl.setEnableRotation(false)
+        }
+    }
 
     @Postsubmit
     @Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
index 8eb41b4..60bf5ff 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
@@ -37,8 +37,9 @@
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @FlakyTest(bugId = 270677470)
 class PipPinchInTest(flicker: FlickerTest) : PipTransition(flicker) {
-    override val transition: FlickerBuilder.() -> Unit
-        get() = buildTransition { transitions { pipApp.pinchInPipWindow(wmHelper, 0.4f, 30) } }
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        transitions { pipApp.pinchInPipWindow(wmHelper, 0.4f, 30) }
+    }
 
     /** Checks that the visible region area of [pipApp] always decreases during the animation. */
     @Postsubmit
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
index eb1245b..17a178f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
@@ -56,27 +56,37 @@
         }
     }
 
-    /**
-     * Gets a configuration that handles basic setup and teardown of pip tests and that launches the
-     * Pip app for test
-     *
-     * @param stringExtras Arguments to pass to the PIP launch intent
-     * @param extraSpec Additional segment of flicker specification
-     */
-    @JvmOverloads
-    protected open fun buildTransition(
-        stringExtras: Map<String, String> = mapOf(ActivityOptions.Pip.EXTRA_ENTER_PIP to "true"),
-        extraSpec: FlickerBuilder.() -> Unit = {}
-    ): FlickerBuilder.() -> Unit {
-        return {
-            setup {
-                setRotation(Rotation.ROTATION_0)
-                removeAllTasksButHome()
-                pipApp.launchViaIntentAndWaitForPip(wmHelper, stringExtras = stringExtras)
-            }
-            teardown { pipApp.exit(wmHelper) }
+    /** Defines the transition used to run the test */
+    protected open val thisTransition: FlickerBuilder.() -> Unit = {}
 
-            extraSpec(this)
+    override val transition: FlickerBuilder.() -> Unit
+        get() = {
+            defaultSetup(this)
+            defaultEnterPip(this)
+            thisTransition(this)
+            defaultTeardown(this)
+        }
+
+    /** Defines the default setup steps required by the test */
+    protected open val defaultSetup: FlickerBuilder.() -> Unit = {
+        setup {
+            setRotation(Rotation.ROTATION_0)
+            removeAllTasksButHome()
+        }
+    }
+
+    /** Defines the default method of entering PiP */
+    protected open val defaultEnterPip: FlickerBuilder.() -> Unit = {
+        setup {
+            pipApp.launchViaIntentAndWaitForPip(wmHelper,
+                    stringExtras = mapOf(ActivityOptions.Pip.EXTRA_ENTER_PIP to "true"))
+        }
+    }
+
+    /** Defines the default teardown required to clean up after the test */
+    protected open val defaultTeardown: FlickerBuilder.() -> Unit = {
+        teardown {
+            pipApp.exit(wmHelper)
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt
index 3850c1f..c618e5a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt
@@ -50,41 +50,41 @@
     private val startingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_0)
     private val endingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_90)
 
-    /** {@inheritDoc} */
-    override val transition: FlickerBuilder.() -> Unit
-        get() = {
-            setup {
-                // Launch the PiP activity fixed as landscape.
-                pipApp.launchViaIntent(
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        transitions {
+            // Launch the activity back into fullscreen and ensure that it is now in landscape
+            pipApp.launchViaIntent(wmHelper)
+            // System bar may fade out during fixed rotation.
+            wmHelper
+                .StateSyncBuilder()
+                .withFullScreenApp(pipApp)
+                .withRotation(Rotation.ROTATION_90)
+                .withNavOrTaskBarVisible()
+                .withStatusBarVisible()
+                .waitForAndVerify()
+        }
+    }
+
+    override val defaultEnterPip: FlickerBuilder.() -> Unit = {
+        setup {
+            // Launch the PiP activity fixed as landscape.
+            pipApp.launchViaIntent(
                     wmHelper,
                     stringExtras =
-                        mapOf(EXTRA_FIXED_ORIENTATION to ORIENTATION_LANDSCAPE.toString())
-                )
-                // Enter PiP.
-                broadcastActionTrigger.doAction(ActivityOptions.Pip.ACTION_ENTER_PIP)
-                // System bar may fade out during fixed rotation.
-                wmHelper
+                    mapOf(EXTRA_FIXED_ORIENTATION to ORIENTATION_LANDSCAPE.toString())
+            )
+            // Enter PiP.
+            broadcastActionTrigger.doAction(ActivityOptions.Pip.ACTION_ENTER_PIP)
+            // System bar may fade out during fixed rotation.
+            wmHelper
                     .StateSyncBuilder()
                     .withPipShown()
                     .withRotation(Rotation.ROTATION_0)
                     .withNavOrTaskBarVisible()
                     .withStatusBarVisible()
                     .waitForAndVerify()
-            }
-            teardown { pipApp.exit(wmHelper) }
-            transitions {
-                // Launch the activity back into fullscreen and ensure that it is now in landscape
-                pipApp.launchViaIntent(wmHelper)
-                // System bar may fade out during fixed rotation.
-                wmHelper
-                    .StateSyncBuilder()
-                    .withFullScreenApp(pipApp)
-                    .withRotation(Rotation.ROTATION_90)
-                    .withNavOrTaskBarVisible()
-                    .withStatusBarVisible()
-                    .waitForAndVerify()
-            }
         }
+    }
 
     /**
      * This test is not compatible with Tablets. When using [Activity.setRequestedOrientation] to
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt
index 703784d..43d6c8f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt
@@ -63,14 +63,13 @@
     private val screenBoundsStart = WindowUtils.getDisplayBounds(flicker.scenario.startRotation)
     private val screenBoundsEnd = WindowUtils.getDisplayBounds(flicker.scenario.endRotation)
 
-    override val transition: FlickerBuilder.() -> Unit
-        get() = buildTransition {
-            setup {
-                testApp.launchViaIntent(wmHelper)
-                setRotation(flicker.scenario.startRotation)
-            }
-            transitions { setRotation(flicker.scenario.endRotation) }
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        setup {
+            testApp.launchViaIntent(wmHelper)
+            setRotation(flicker.scenario.startRotation)
         }
+        transitions { setRotation(flicker.scenario.endRotation) }
+    }
 
     /** Checks that [testApp] layer is within [screenBoundsStart] at the start of the transition */
     @Presubmit
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java
index ada3455..1dfdbf6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java
@@ -29,6 +29,7 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.MotionEvent;
+import android.view.ViewConfiguration;
 
 import androidx.test.filters.SmallTest;
 
@@ -90,6 +91,8 @@
 
     private PipDisplayLayoutState mPipDisplayLayoutState;
 
+    private PipTouchState mPipTouchState;
+
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
@@ -104,8 +107,12 @@
         final PipMotionHelper motionHelper = new PipMotionHelper(mContext, mPipBoundsState,
                 mPipTaskOrganizer, mPhonePipMenuController, pipSnapAlgorithm,
                 mMockPipTransitionController, mFloatingContentCoordinator);
+
+        mPipTouchState = new PipTouchState(ViewConfiguration.get(mContext),
+                () -> {}, () -> {}, mMainExecutor);
         mPipResizeGestureHandler = new PipResizeGestureHandler(mContext, pipBoundsAlgorithm,
-                mPipBoundsState, motionHelper, mPipTaskOrganizer, mPipDismissTargetHandler,
+                mPipBoundsState, motionHelper, mPipTouchState, mPipTaskOrganizer,
+                mPipDismissTargetHandler,
                 (Rect bounds) -> new Rect(), () -> {}, mPipUiEventLogger, mPhonePipMenuController,
                 mMainExecutor) {
             @Override
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipSizeSpecHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipSizeSpecHandlerTest.java
index 425bbf0..1379aed 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipSizeSpecHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipSizeSpecHandlerTest.java
@@ -106,21 +106,21 @@
         sExpectedDefaultSizes = new HashMap<>();
         sExpectedMinSizes = new HashMap<>();
 
-        sExpectedMaxSizes.put(16f / 9, new Size(1000, 562));
-        sExpectedDefaultSizes.put(16f / 9, new Size(600, 337));
-        sExpectedMinSizes.put(16f / 9, new Size(499, 281));
+        sExpectedMaxSizes.put(16f / 9, new Size(1000, 563));
+        sExpectedDefaultSizes.put(16f / 9, new Size(600, 338));
+        sExpectedMinSizes.put(16f / 9, new Size(501, 282));
 
         sExpectedMaxSizes.put(4f / 3, new Size(892, 669));
         sExpectedDefaultSizes.put(4f / 3, new Size(535, 401));
-        sExpectedMinSizes.put(4f / 3, new Size(445, 334));
+        sExpectedMinSizes.put(4f / 3, new Size(447, 335));
 
         sExpectedMaxSizes.put(3f / 4, new Size(669, 892));
         sExpectedDefaultSizes.put(3f / 4, new Size(401, 535));
-        sExpectedMinSizes.put(3f / 4, new Size(334, 445));
+        sExpectedMinSizes.put(3f / 4, new Size(335, 447));
 
         sExpectedMaxSizes.put(9f / 16, new Size(562, 999));
         sExpectedDefaultSizes.put(9f / 16, new Size(337, 599));
-        sExpectedMinSizes.put(9f / 16, new Size(281, 499));
+        sExpectedMinSizes.put(9f / 16, new Size(281, 500));
     }
 
     private void forEveryTestCaseCheck(Map<Float, Size> expectedSizes,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
index 963632b..961e3e9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -51,7 +51,6 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
-import static org.mockito.Mockito.after;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.inOrder;
@@ -93,7 +92,6 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import com.android.server.testutils.StubTransaction;
 import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.TestShellExecutor;
 import com.android.wm.shell.TransitionInfoBuilder;
@@ -105,6 +103,7 @@
 import com.android.wm.shell.sysui.ShellController;
 import com.android.wm.shell.sysui.ShellInit;
 import com.android.wm.shell.sysui.ShellSharedConstants;
+import com.android.wm.shell.util.StubTransaction;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/StubTransaction.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/StubTransaction.java
new file mode 100644
index 0000000..855f541
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/StubTransaction.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.util;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.ColorSpace;
+import android.graphics.GraphicBuffer;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.hardware.HardwareBuffer;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.view.InputWindowHandle;
+import android.view.Surface;
+import android.view.SurfaceControl;
+
+import java.util.HashSet;
+import java.util.concurrent.Executor;
+
+/**
+ * Stubbed {@link SurfaceControl.Transaction} class that can be used when unit
+ * testing to avoid calls to native code.
+ *
+ * Note: This is a copy of com.android.server.testutils.StubTransaction
+ */
+public class StubTransaction extends SurfaceControl.Transaction {
+
+    private HashSet<Runnable> mWindowInfosReportedListeners = new HashSet<>();
+
+    @Override
+    public void apply() {
+        for (Runnable listener : mWindowInfosReportedListeners) {
+            listener.run();
+        }
+    }
+
+    @Override
+    public void close() {
+    }
+
+    @Override
+    public void apply(boolean sync) {
+        apply();
+    }
+
+    @Override
+    public SurfaceControl.Transaction setVisibility(SurfaceControl sc, boolean visible) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction show(SurfaceControl sc) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction hide(SurfaceControl sc) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setPosition(SurfaceControl sc, float x, float y) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setBufferSize(SurfaceControl sc,
+            int w, int h) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setLayer(SurfaceControl sc, int z) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setRelativeLayer(SurfaceControl sc, SurfaceControl relativeTo,
+            int z) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setTransparentRegionHint(SurfaceControl sc,
+            Region transparentRegion) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setAlpha(SurfaceControl sc, float alpha) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setInputWindowInfo(SurfaceControl sc,
+            InputWindowHandle handle) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setGeometry(SurfaceControl sc, Rect sourceCrop,
+            Rect destFrame, @Surface.Rotation int orientation) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setMatrix(SurfaceControl sc,
+            float dsdx, float dtdx, float dtdy, float dsdy) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setMatrix(SurfaceControl sc, Matrix matrix, float[] float9) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setColorTransform(SurfaceControl sc, float[] matrix,
+            float[] translation) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setWindowCrop(SurfaceControl sc, Rect crop) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setWindowCrop(SurfaceControl sc, int width, int height) {
+        return this;
+    }
+
+    @Override
+    @NonNull
+    public SurfaceControl.Transaction setCrop(@NonNull SurfaceControl sc, @Nullable Rect crop) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setCornerRadius(SurfaceControl sc, float cornerRadius) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setBackgroundBlurRadius(SurfaceControl sc, int radius) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setLayerStack(SurfaceControl sc, int layerStack) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction reparent(SurfaceControl sc, SurfaceControl newParent) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setColor(SurfaceControl sc, float[] color) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setSecure(SurfaceControl sc, boolean isSecure) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setOpaque(SurfaceControl sc, boolean isOpaque) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setDisplaySurface(IBinder displayToken, Surface surface) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setDisplayLayerStack(IBinder displayToken, int layerStack) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setDisplayFlags(IBinder displayToken, int flags) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setDisplayProjection(IBinder displayToken,
+            int orientation, Rect layerStackRect, Rect displayRect) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setDisplaySize(IBinder displayToken, int width, int height) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setAnimationTransaction() {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setMetadata(SurfaceControl sc, int key, int data) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setMetadata(SurfaceControl sc, int key, Parcel data) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction merge(SurfaceControl.Transaction other) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction remove(SurfaceControl sc) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction addTransactionCommittedListener(Executor executor,
+            SurfaceControl.TransactionCommittedListener listener) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setColorSpaceAgnostic(SurfaceControl sc, boolean agnostic) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setFrameRateSelectionPriority(SurfaceControl sc,
+            int priority) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setFrameRate(SurfaceControl sc, float frameRate,
+            int compatibility, int changeFrameRateStrategy) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction unsetColor(SurfaceControl sc) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setShadowRadius(SurfaceControl sc, float shadowRadius) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setFixedTransformHint(SurfaceControl sc,
+            @Surface.Rotation int transformHint) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction unsetFixedTransformHint(@NonNull SurfaceControl sc) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setBuffer(SurfaceControl sc, GraphicBuffer buffer) {
+        return this;
+    }
+
+    @Override
+    @NonNull
+    public SurfaceControl.Transaction setBuffer(@NonNull SurfaceControl sc,
+            @Nullable HardwareBuffer buffer) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setColorSpace(SurfaceControl sc, ColorSpace colorSpace) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setTrustedOverlay(SurfaceControl sc,
+            boolean isTrustedOverlay) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction addWindowInfosReportedListener(@NonNull Runnable listener) {
+        mWindowInfosReportedListeners.add(listener);
+        return this;
+    }
+}
diff --git a/libs/androidfw/CursorWindow.cpp b/libs/androidfw/CursorWindow.cpp
index 3527eee..2a6dc7b 100644
--- a/libs/androidfw/CursorWindow.cpp
+++ b/libs/androidfw/CursorWindow.cpp
@@ -108,7 +108,7 @@
 
     {
         // Migrate existing contents into new ashmem region
-        uint32_t slotsSize = mSize - mSlotsOffset;
+        uint32_t slotsSize = sizeOfSlots();
         uint32_t newSlotsOffset = mInflatedSize - slotsSize;
         memcpy(static_cast<uint8_t*>(newData),
                 static_cast<uint8_t*>(mData), mAllocOffset);
@@ -216,11 +216,9 @@
         if (parcel->writeDupFileDescriptor(mAshmemFd)) goto fail;
     } else {
         // Since we know we're going to be read-only on the remote side,
-        // we can compact ourselves on the wire, with just enough padding
-        // to ensure our slots stay aligned
-        size_t slotsSize = mSize - mSlotsOffset;
-        size_t compactedSize = mAllocOffset + slotsSize;
-        compactedSize = (compactedSize + 3) & ~3;
+        // we can compact ourselves on the wire.
+        size_t slotsSize = sizeOfSlots();
+        size_t compactedSize = sizeInUse();
         if (parcel->writeUint32(compactedSize)) goto fail;
         if (parcel->writeBool(false)) goto fail;
         void* dest = parcel->writeInplace(compactedSize);
diff --git a/libs/androidfw/include/androidfw/CursorWindow.h b/libs/androidfw/include/androidfw/CursorWindow.h
index 6e55a9a..9ec026a 100644
--- a/libs/androidfw/include/androidfw/CursorWindow.h
+++ b/libs/androidfw/include/androidfw/CursorWindow.h
@@ -90,6 +90,9 @@
     inline uint32_t getNumRows() { return mNumRows; }
     inline uint32_t getNumColumns() { return mNumColumns; }
 
+    inline size_t sizeOfSlots() const { return mSize - mSlotsOffset; }
+    inline size_t sizeInUse() const { return mAllocOffset + sizeOfSlots(); }
+
     status_t clear();
     status_t setNumColumns(uint32_t numColumns);
 
diff --git a/libs/androidfw/tests/CursorWindow_test.cpp b/libs/androidfw/tests/CursorWindow_test.cpp
index d1cfd03..3cdb31e 100644
--- a/libs/androidfw/tests/CursorWindow_test.cpp
+++ b/libs/androidfw/tests/CursorWindow_test.cpp
@@ -21,9 +21,16 @@
 
 #include "TestHelpers.h"
 
+// Verify that the memory in use is a multiple of 4 bytes
+#define ASSERT_ALIGNED(w) \
+    ASSERT_EQ(((w)->sizeInUse() & 3), 0); \
+    ASSERT_EQ(((w)->freeSpace() & 3), 0); \
+    ASSERT_EQ(((w)->sizeOfSlots() & 3), 0)
+
 #define CREATE_WINDOW_1K \
     CursorWindow* w; \
-    CursorWindow::create(String8("test"), 1 << 10, &w);
+    CursorWindow::create(String8("test"), 1 << 10, &w); \
+    ASSERT_ALIGNED(w);
 
 #define CREATE_WINDOW_1K_3X3 \
     CursorWindow* w; \
@@ -31,11 +38,13 @@
     ASSERT_EQ(w->setNumColumns(3), OK); \
     ASSERT_EQ(w->allocRow(), OK); \
     ASSERT_EQ(w->allocRow(), OK); \
-    ASSERT_EQ(w->allocRow(), OK);
+    ASSERT_EQ(w->allocRow(), OK); \
+    ASSERT_ALIGNED(w);
 
 #define CREATE_WINDOW_2M \
     CursorWindow* w; \
-    CursorWindow::create(String8("test"), 1 << 21, &w);
+    CursorWindow::create(String8("test"), 1 << 21, &w); \
+    ASSERT_ALIGNED(w);
 
 static constexpr const size_t kHalfInlineSize = 8192;
 static constexpr const size_t kGiantSize = 1048576;
@@ -49,6 +58,7 @@
     ASSERT_EQ(w->getNumColumns(), 0);
     ASSERT_EQ(w->size(), 1 << 10);
     ASSERT_EQ(w->freeSpace(), 1 << 10);
+    ASSERT_ALIGNED(w);
 }
 
 TEST(CursorWindowTest, SetNumColumns) {
@@ -60,6 +70,7 @@
     ASSERT_NE(w->setNumColumns(5), OK);
     ASSERT_NE(w->setNumColumns(3), OK);
     ASSERT_EQ(w->getNumColumns(), 4);
+    ASSERT_ALIGNED(w);
 }
 
 TEST(CursorWindowTest, SetNumColumnsAfterRow) {
@@ -70,6 +81,7 @@
     ASSERT_EQ(w->allocRow(), OK);
     ASSERT_NE(w->setNumColumns(4), OK);
     ASSERT_EQ(w->getNumColumns(), 0);
+    ASSERT_ALIGNED(w);
 }
 
 TEST(CursorWindowTest, AllocRow) {
@@ -83,14 +95,17 @@
     ASSERT_EQ(w->allocRow(), OK);
     ASSERT_LT(w->freeSpace(), before);
     ASSERT_EQ(w->getNumRows(), 1);
+    ASSERT_ALIGNED(w);
 
     // Verify we can unwind
     ASSERT_EQ(w->freeLastRow(), OK);
     ASSERT_EQ(w->freeSpace(), before);
     ASSERT_EQ(w->getNumRows(), 0);
+    ASSERT_ALIGNED(w);
 
     // Can't unwind when no rows left
     ASSERT_NE(w->freeLastRow(), OK);
+    ASSERT_ALIGNED(w);
 }
 
 TEST(CursorWindowTest, AllocRowBounds) {
@@ -100,6 +115,7 @@
     ASSERT_EQ(w->setNumColumns(60), OK);
     ASSERT_EQ(w->allocRow(), OK);
     ASSERT_NE(w->allocRow(), OK);
+    ASSERT_ALIGNED(w);
 }
 
 TEST(CursorWindowTest, StoreNull) {
@@ -116,6 +132,7 @@
         auto field = w->getFieldSlot(0, 0);
         ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_NULL);
     }
+    ASSERT_ALIGNED(w);
 }
 
 TEST(CursorWindowTest, StoreLong) {
@@ -134,6 +151,7 @@
         ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_INTEGER);
         ASSERT_EQ(w->getFieldSlotValueLong(field), 0xcafe);
     }
+    ASSERT_ALIGNED(w);
 }
 
 TEST(CursorWindowTest, StoreString) {
@@ -155,6 +173,7 @@
         auto actual = w->getFieldSlotValueString(field, &size);
         ASSERT_EQ(std::string(actual), "cafe");
     }
+    ASSERT_ALIGNED(w);
 }
 
 TEST(CursorWindowTest, StoreBounds) {
@@ -175,6 +194,7 @@
     ASSERT_EQ(w->getFieldSlot(-1, 0), nullptr);
     ASSERT_EQ(w->getFieldSlot(0, -1), nullptr);
     ASSERT_EQ(w->getFieldSlot(-1, -1), nullptr);
+    ASSERT_ALIGNED(w);
 }
 
 TEST(CursorWindowTest, Inflate) {
@@ -234,6 +254,7 @@
         ASSERT_NE(actual, buf);
         ASSERT_EQ(memcmp(buf, actual, kHalfInlineSize), 0);
     }
+    ASSERT_ALIGNED(w);
 }
 
 TEST(CursorWindowTest, ParcelEmpty) {
@@ -249,10 +270,12 @@
     ASSERT_EQ(w->getNumColumns(), 0);
     ASSERT_EQ(w->size(), 0);
     ASSERT_EQ(w->freeSpace(), 0);
+    ASSERT_ALIGNED(w);
 
     // We can't mutate the window after parceling
     ASSERT_NE(w->setNumColumns(4), OK);
     ASSERT_NE(w->allocRow(), OK);
+    ASSERT_ALIGNED(w);
 }
 
 TEST(CursorWindowTest, ParcelSmall) {
@@ -311,6 +334,7 @@
         ASSERT_EQ(actualSize, 0);
         ASSERT_NE(actual, nullptr);
     }
+    ASSERT_ALIGNED(w);
 }
 
 TEST(CursorWindowTest, ParcelLarge) {
@@ -364,6 +388,7 @@
         ASSERT_EQ(actualSize, 0);
         ASSERT_NE(actual, nullptr);
     }
+    ASSERT_ALIGNED(w);
 }
 
 } // android
diff --git a/libs/hwui/jni/Gainmap.cpp b/libs/hwui/jni/Gainmap.cpp
index 0f8a85d..cec0ee7 100644
--- a/libs/hwui/jni/Gainmap.cpp
+++ b/libs/hwui/jni/Gainmap.cpp
@@ -86,6 +86,16 @@
     return static_cast<jlong>(reinterpret_cast<uintptr_t>(gainmap));
 }
 
+jlong Gainmap_createCopy(JNIEnv*, jobject, jlong sourcePtr) {
+    Gainmap* gainmap = new Gainmap();
+    gainmap->incStrong(0);
+    if (sourcePtr) {
+        Gainmap* src = fromJava(sourcePtr);
+        gainmap->info = src->info;
+    }
+    return static_cast<jlong>(reinterpret_cast<uintptr_t>(gainmap));
+}
+
 static void Gainmap_setBitmap(JNIEnv* env, jobject, jlong gainmapPtr, jobject jBitmap) {
     android::Bitmap* bitmap = GraphicsJNI::getNativeBitmap(env, jBitmap);
     fromJava(gainmapPtr)->bitmap = sk_ref_sp(bitmap);
@@ -237,6 +247,7 @@
 static const JNINativeMethod gGainmapMethods[] = {
         {"nGetFinalizer", "()J", (void*)Gainmap_getNativeFinalizer},
         {"nCreateEmpty", "()J", (void*)Gainmap_createEmpty},
+        {"nCreateCopy", "(J)J", (void*)Gainmap_createCopy},
         {"nSetBitmap", "(JLandroid/graphics/Bitmap;)V", (void*)Gainmap_setBitmap},
         {"nSetRatioMin", "(JFFF)V", (void*)Gainmap_setRatioMin},
         {"nGetRatioMin", "(J[F)V", (void*)Gainmap_getRatioMin},
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 32680da..38bb447 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -359,6 +359,51 @@
  codec to use a previously created {@linkplain #createPersistentInputSurface persistent input
  surface} by calling {@link #setInputSurface}.
 
+ <h4 id=EncoderProfiles><a name="EncoderProfiles"></a>Encoder Profiles</h4>
+ <p>
+ When using an encoder, it is recommended to set the desired codec {@link MediaFormat#KEY_PROFILE
+ profile} during {@link #configure configure()}. (This is only meaningful for
+ {@link MediaFormat#KEY_MIME media formats} for which profiles are defined.)
+ <p>
+ If a profile is not specified during {@code configure}, the encoder will choose a profile for the
+ session based on the available information. We will call this value the <i>default profile</i>.
+ The selection of the default profile is device specific and may not be deterministic
+ (could be ad hoc or even experimental). The encoder may choose a default profile that is not
+ suitable for the intended encoding session, which may result in the encoder ultimately rejecting
+ the session.
+ <p>
+ The encoder may reject the encoding session if the configured (or default if unspecified) profile
+ does not support the codec input (mainly the {@link MediaFormat#KEY_COLOR_FORMAT color format} for
+ video/image codecs, or the {@link MediaFormat#KEY_PCM_ENCODING sample encoding} and the {@link
+ MediaFormat#KEY_CHANNEL_COUNT number of channels} for audio codecs, but also possibly
+ {@link MediaFormat#KEY_WIDTH width}, {@link MediaFormat#KEY_HEIGHT height},
+ {@link MediaFormat#KEY_FRAME_RATE frame rate}, {@link MediaFormat#KEY_BIT_RATE bitrate} or
+ {@link MediaFormat#KEY_SAMPLE_RATE sample rate}.)
+ Alternatively, the encoder may choose to (but is not required to) convert the input to support the
+ selected (or default) profile - or adjust the chosen profile based on the presumed or detected
+ input format - to ensure a successful encoding session. <b>Note</b>: Converting the input to match
+ an incompatible profile will in most cases result in decreased codec performance.
+ <p>
+ To ensure backward compatibility, the following guarantees are provided by Android:
+ <ul>
+ <li>The default video encoder profile always supports 8-bit YUV 4:2:0 color format ({@link
+ CodecCapabilities#COLOR_FormatYUV420Flexible COLOR_FormatYUV420Flexible} and equivalent
+ {@link CodecCapabilities#colorFormats supported formats}) for both Surface and ByteBuffer modes.
+ <li>The default video encoder profile always supports the default 8-bit RGBA color format in
+ Surface mode even if no such formats are enumerated in the {@link CodecCapabilities#colorFormats
+ supported formats}.
+ </ul>
+ <p class=note>
+ <b>Note</b>: the accepted profile can be queried through the {@link #getOutputFormat output
+ format} of the encoder after {@code configure} to allow applications to set up their
+ codec input to a format supported by the encoder profile.
+ <p>
+ <b>Implication:</b>
+ <ul>
+ <li>Applications that want to encode 4:2:2, 4:4:4, 10+ bit or HDR video input <b>MUST</b> configure
+ a suitable profile for encoders.
+ </ul>
+
  <h4 id=CSD><a name="CSD"></a>Codec-specific Data</h4>
  <p>
  Some formats, notably AAC audio and MPEG4, H.264 and H.265 video formats require the actual data
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index b1b7d40..46db777 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -1136,11 +1136,14 @@
      * may fail if other parameters are not compatible with the desired
      * profile or if the desired profile is not supported, but it may also
      * fail silently (where the encoder ends up using a different, compatible profile.)
+     * <p>
+     * It is recommended that the profile is set for all encoders. For more information, see
+     * the <i>Encoder Profiles</i> section of the {@link MediaCodec} API reference.
      * <p class="note">
      * <strong>Note:</strong> Codecs are free to use all the available
      * coding tools at the specified profile, but may ultimately choose to not do so.
      * <p class="note">
-     * <strong>Note:</strong> When configuring video encoders, profile must be
+     * <strong>Note:</strong> When configuring video encoders, profile (if set) must be
      * set together with {@link #KEY_LEVEL level}.
      *
      * @see MediaCodecInfo.CodecCapabilities#profileLevels
diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml
index 8128d8a..b131a2f 100644
--- a/packages/CompanionDeviceManager/res/values-ko/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml
@@ -31,7 +31,7 @@
     <string name="helper_summary_app_streaming" msgid="2396773196949578425">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> 대신 기기 간에 앱을 스트리밍할 수 있는 권한을 요청하고 있습니다."</string>
     <string name="title_automotive_projection" msgid="3296005598978412847"></string>
     <string name="summary_automotive_projection" msgid="8683801274662496164"></string>
-    <string name="title_computer" msgid="4693714143506569253">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; 앱이 휴대전화에서 이 정보에 액세스하도록 허용"</string>
+    <string name="title_computer" msgid="4693714143506569253">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;이 휴대전화에서 이 정보에 액세스하도록 허용"</string>
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 서비스"</string>
     <string name="helper_summary_computer" msgid="8774832742608187072">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DISPLAY_NAME">%2$s</xliff:g> 대신 휴대전화의 사진, 미디어, 알림에 액세스할 수 있는 권한을 요청하고 있습니다."</string>
diff --git a/packages/CredentialManager/res/values-vi/strings.xml b/packages/CredentialManager/res/values-vi/strings.xml
index 2cbfce8..0e17025 100644
--- a/packages/CredentialManager/res/values-vi/strings.xml
+++ b/packages/CredentialManager/res/values-vi/strings.xml
@@ -61,7 +61,7 @@
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> mật khẩu"</string>
     <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> khoá truy cập"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"<xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g> thông tin xác thực"</string>
-    <string name="passkey_before_subtitle" msgid="2448119456208647444">"Mã xác thực"</string>
+    <string name="passkey_before_subtitle" msgid="2448119456208647444">"Khoá truy cập"</string>
     <string name="another_device" msgid="5147276802037801217">"Thiết bị khác"</string>
     <string name="other_password_manager" msgid="565790221427004141">"Trình quản lý mật khẩu khác"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Đóng trang tính"</string>
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index 2dafbcb..a78509d 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -66,8 +66,9 @@
         )
 
         val originName: String? = when (requestInfo?.type) {
-            RequestInfo.TYPE_CREATE -> requestInfo.createCredentialRequest?.origin
-            RequestInfo.TYPE_GET -> requestInfo.getCredentialRequest?.origin
+            RequestInfo.TYPE_CREATE -> processHttpsOrigin(
+                requestInfo.createCredentialRequest?.origin)
+            RequestInfo.TYPE_GET -> processHttpsOrigin(requestInfo.getCredentialRequest?.origin)
             else -> null
         }
 
@@ -247,6 +248,9 @@
     }
 
     companion object {
+        private const val HTTPS = "https://"
+        private const val FORWARD_SLASH = "/"
+
         fun sendCancellationCode(
             cancelCode: Int,
             requestToken: IBinder?,
@@ -266,5 +270,17 @@
                 CancelUiRequest::class.java
             )
         }
+
+        /** Removes "https://", and the trailing slash if present for an https request. */
+        private fun processHttpsOrigin(origin: String?): String? {
+            var processed = origin
+            if (processed?.startsWith(HTTPS) == true) { // Removes "https://"
+                processed = processed.substring(HTTPS.length)
+                if (processed?.endsWith(FORWARD_SLASH) == true) { // Removes the trailing slash
+                    processed = processed.substring(0, processed.length - 1)
+                }
+            }
+            return processed
+        }
     }
 }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
index cf962d1..bce86c4 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
@@ -118,8 +118,10 @@
         if (entry != null && entry.pendingIntent != null) {
             Log.d(Constants.LOG_TAG, "Launching provider activity")
             uiState = uiState.copy(providerActivityState = ProviderActivityState.PENDING)
+            val entryIntent = entry.fillInIntent
+            entryIntent?.putExtra(Constants.IS_AUTO_SELECTED_KEY, uiState.isAutoSelectFlow)
             val intentSenderRequest = IntentSenderRequest.Builder(entry.pendingIntent)
-                .setFillInIntent(entry.fillInIntent).build()
+                .setFillInIntent(entryIntent).build()
             try {
                 launcher.launch(intentSenderRequest)
             } catch (e: Exception) {
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt
index c6dc594..51ca597 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt
@@ -21,5 +21,6 @@
         const val LOG_TAG = "CredentialSelector"
         const val BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS =
             "androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED"
+        const val IS_AUTO_SELECTED_KEY = "IS_AUTO_SELECTED"
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListPage.kt
index 89bfa0e..030b70a7 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListPage.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListPage.kt
@@ -31,6 +31,8 @@
 /**
  * The full screen template for an App List page.
  *
+ * @param noMoreOptions default false. If true, then do not display more options action button,
+ * including the "Show System" / "Hide System" action.
  * @param header the description header appears before all the applications.
  */
 @Composable
@@ -38,6 +40,7 @@
     title: String,
     listModel: AppListModel<T>,
     showInstantApps: Boolean = false,
+    noMoreOptions: Boolean = false,
     matchAnyUserForAdmin: Boolean = false,
     primaryUserOnly: Boolean = false,
     noItemMessage: String? = null,
@@ -49,9 +52,11 @@
     SearchScaffold(
         title = title,
         actions = {
-            MoreOptionsAction {
-                ShowSystemAction(showSystem.value) { showSystem.value = it }
-                moreOptions()
+            if (!noMoreOptions) {
+                MoreOptionsAction {
+                    ShowSystemAction(showSystem.value) { showSystem.value = it }
+                    moreOptions()
+                }
             }
         },
     ) { bottomPadding, searchQuery ->
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListPageTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListPageTest.kt
index 06003c0..f6f4889 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListPageTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListPageTest.kt
@@ -63,9 +63,7 @@
     fun canShowSystem() {
         val inputState by setContent()
 
-        composeTestRule.onNodeWithContentDescription(
-            context.getString(R.string.abc_action_menu_overflow_description)
-        ).performClick()
+        onMoreOptions().performClick()
         composeTestRule.onNodeWithText(context.getString(R.string.menu_show_system)).performClick()
 
         val state = inputState!!.state
@@ -75,20 +73,32 @@
     @Test
     fun afterShowSystem_displayHideSystem() {
         setContent()
-        composeTestRule.onNodeWithContentDescription(
-            context.getString(R.string.abc_action_menu_overflow_description)
-        ).performClick()
+        onMoreOptions().performClick()
         composeTestRule.onNodeWithText(context.getString(R.string.menu_show_system)).performClick()
 
-        composeTestRule.onNodeWithContentDescription(
-            context.getString(R.string.abc_action_menu_overflow_description)
-        ).performClick()
+        onMoreOptions().performClick()
 
         composeTestRule.onNodeWithText(context.getString(R.string.menu_hide_system))
             .assertIsDisplayed()
     }
 
+    @Test
+    fun noMoreOptions_notDisplayMoreOptions() {
+        setContent(noMoreOptions = true)
+
+        onMoreOptions().assertDoesNotExist()
+    }
+
+    @Test
+    fun noMoreOptions_showSystemIsFalse() {
+        val inputState by setContent(noMoreOptions = true)
+
+        val state = inputState!!.state
+        assertThat(state.showSystem.value).isFalse()
+    }
+
     private fun setContent(
+        noMoreOptions: Boolean = false,
         header: @Composable () -> Unit = {},
     ): State<AppListInput<TestAppRecord>?> {
         val appListState = mutableStateOf<AppListInput<TestAppRecord>?>(null)
@@ -96,6 +106,7 @@
             AppListPage(
                 title = TITLE,
                 listModel = TestAppListModel(),
+                noMoreOptions = noMoreOptions,
                 header = header,
                 appList = { appListState.value = this },
             )
@@ -103,6 +114,11 @@
         return appListState
     }
 
+    private fun onMoreOptions() =
+        composeTestRule.onNodeWithContentDescription(
+            context.getString(R.string.abc_action_menu_overflow_description)
+        )
+
     private companion object {
         const val TITLE = "Title"
     }
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 119bb73..98ad6e3 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -84,7 +84,7 @@
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Ontkoppel"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ontkoppel tans…"</string>
-    <string name="bluetooth_connecting" msgid="5871702668260192755">"Verbind tans…"</string>
+    <string name="bluetooth_connecting" msgid="5871702668260192755">"Verbind tans …"</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"Gekoppel<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="4269046942588193600">"Verbind tans…"</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Gekoppel (geen foon nie)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Sopas"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Hierdie foon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Hierdie tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dokluidspreker"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Eksterne toestel"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Gekoppelde toestel"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Hierdie foon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Kan nie op hierdie toestel speel nie"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Gradeer rekening op om oor te skakel"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 89d68c3..b8b1b69 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ልክ አሁን"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ይህ ስልክ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ይህ ጡባዊ"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"የመትከያ ድምጽ ማውጫ"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"የውጭ መሣሪያ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"የተገናኘ መሣሪያ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ይህ ስልክ"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"በዚህ መሣሪያ ላይ ማጫወት አልተቻለም"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ለመቀየር መለያ ያልቁ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index f7e2b2d..18dc07f 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"للتو"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"هذا الهاتف"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"هذا الجهاز اللوحي"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"مكبّر صوت بقاعدة إرساء"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"جهاز خارجي"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"جهاز متّصل"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"هذا الهاتف"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"لا يمكن تشغيل الوسائط هنا"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"يجب ترقية الحساب للتبديل"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 594ed7b..725a057 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"এই মাত্ৰ"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"এই ফ’নটো"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"এই টেবলেটটো"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ড’ক স্পীকাৰ"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"বাহ্যিক ডিভাইচ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"সংযোগ হৈ থকা ডিভাইচ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"এই ফ’নটো"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"এই ডিভাইচটো প্লে\' কৰিব নোৱাৰি"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"সলনি কৰিবলৈ একাউণ্ট আপগ্ৰে’ড কৰক"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 0b4779f..ec1b8cf 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"İndicə"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Bu telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Bu planşet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dok dinamiki"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Xarici cihaz"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Qoşulmuş cihaz"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Bu telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Bu cihazda oxutmaq olmur"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Keçirmək üçün hesabı güncəllə"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 298835f..91ca8a6 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Upravo"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ovaj telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ovaj tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Zvučnik bazne stanice"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Spoljni uređaj"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Povezani uređaj"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ne možete da pustite na ovom uređaju"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Nadogradite nalog radi prebacivanja"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 666dbb1..aa28a31 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -304,7 +304,7 @@
     <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Пры выбары сеткі Wi-Fi указваць у журнале RSSI для кожнага SSID"</string>
     <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Зніжае расход зараду акумулятара і павышае прадукцыйнасць мабільных сетак"</string>
     <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Калі ўключаны гэты рэжым, MAC-адрас гэтай прылады можа змяняцца падчас кожнага падключэння да сеткі з актыўнай рандамізацыяй MAC-адрасоў."</string>
-    <string name="wifi_metered_label" msgid="8737187690304098638">"Сетка з улікам трафіка"</string>
+    <string name="wifi_metered_label" msgid="8737187690304098638">"Сетка з падлікам трафіка"</string>
     <string name="wifi_unmetered_label" msgid="6174142840934095093">"Сетка без уліку трафіка"</string>
     <string name="select_logd_size_title" msgid="1604578195914595173">"Памеры буфера журнала"</string>
     <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Выберыце памеры сродку вядзення журнала для буфераў журнала"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 9446634..2779689 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Току-що"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Този телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Този таблет"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Високоговорител докинг станция"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Външно устройство"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Свързано устройство"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Този телефон"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Възпроизвеждането не е възможно на това устройство"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Надстройте профила, за да превключите"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index a27c6ff..68283ca 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -86,7 +86,7 @@
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"ডিসকানেক্ট হচ্ছে..."</string>
     <string name="bluetooth_connecting" msgid="5871702668260192755">"কানেক্ট হচ্ছে..."</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"কানেক্ট করা আছে<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_pairing" msgid="4269046942588193600">"যুক্ত করা হচ্ছে..."</string>
+    <string name="bluetooth_pairing" msgid="4269046942588193600">"পেয়ার করা হচ্ছে..."</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"কানেক্ট করা আছে (ফোনের অডিও ছাড়া)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"কানেক্ট করা আছে (মিডিয়ার অডিও ছাড়া)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2893204819854215433">"কানেক্ট করা আছে (ফোনের বা মিডিয়ার অডিও ছাড়া)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"এখনই"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"এই ফোন"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"এই ট্যাবলেট"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ডক স্পিকার"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"এক্সটার্নাল ডিভাইস"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"কানেক্ট থাকা ডিভাইস"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"এই ফোনটি"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"এই ডিভাইসে চালানো যাবে না"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"পাল্টাতে অ্যাকাউন্ট আপগ্রেড করুন"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 345cad1..8e589f6 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Upravo"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ovaj telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ovaj tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Zvučnik priključne stanice"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Vanjski uređaj"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Povezani uređaj"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nije moguće reproducirati na uređaju"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Nadogradite račun da promijenite"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 899bc7d..f22b489b8 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Ara mateix"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Aquest telèfon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Aquesta tauleta"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Base d\'altaveu"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositiu extern"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositiu connectat"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Aquest telèfon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"No es pot reproduir en aquest dispositiu"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Actualitza el compte per canviar"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 1c8fe92..363c22e 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Právě teď"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Tento telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tento tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dok s reproduktorem"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Externí zařízení"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Připojené zařízení"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Tento telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"V zařízení nelze přehrávat"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Účet je třeba upgradovat"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 9253148..1df4dee 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Lige nu"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Denne telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Denne tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dockhøjttaler"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Ekstern enhed"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Forbundet enhed"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Denne telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Kan ikke afspilles på denne enhed"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Opgrader kontoen for at skifte"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 64e9bcf..8f75180 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Μόλις τώρα"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Αυτό το τηλέφωνο"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Αυτό το tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Ηχείο βάσης σύνδεσης"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Εξωτερική συσκευή"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Συνδεδεμένη συσκευή"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Αυτό το τηλέφ."</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Δεν είναι δυνατή η αναπαραγωγή σε αυτήν τη συσκευή"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Αναβαθμίστε τον λογαριασμό για εναλλαγή"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 6779e89..3a50fa3 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"This phone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"This tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dock speaker"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"External device"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Connected device"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Can\'t play on this device"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Upgrade account to switch"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 6779e89..3a50fa3 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"This phone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"This tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dock speaker"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"External device"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Connected device"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Can\'t play on this device"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Upgrade account to switch"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 6779e89..3a50fa3 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"This phone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"This tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dock speaker"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"External device"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Connected device"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Can\'t play on this device"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Upgrade account to switch"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 8946365..4e6cd00 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Recién"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este teléfono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Esta tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Conector de la bocina"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"No se puede reproducir en este dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Actualiza la cuenta para cambiar"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 8268682..6ffed25 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"justo ahora"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este teléfono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Esta tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Altavoz base"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"No se puede reproducir en este dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Actualiza la cuenta para cambiar"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 8e30e3d..434e7d7 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Äsja"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"See telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"See tahvelarvuti"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Doki kõlar"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Väline seade"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Ühendatud seade"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"See telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Selles seadmes ei saa esitada"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Lülitamiseks täiendage kontot"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 7d64cfa..591d3cf 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -99,8 +99,8 @@
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"Ezk. gailuaren bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. Esk- gailuaren bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktibo"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktibo, ezkerreko audifonoa soilik"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktibo, eskuineko audifonoa soilik"</string>
+    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktibo, ezkerrekoa soilik"</string>
+    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktibo, eskuinekoa soilik"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktibo, ezkerreko eta eskuineko audifonoak"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Euskarriaren audioa"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Telefono-deiak"</string>
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Oraintxe"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Telefono hau"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tableta hau"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Oinarri bozgorailuduna"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Kanpoko gailua"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Konektatutako gailua"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Telefono hau"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ezin da erreproduzitu gailu honetan"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Aldatzeko, bertsio-berritu kontua"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 3ba5436..b4e9b35 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -231,9 +231,9 @@
     <string name="adb_wireless_error" msgid="721958772149779856">"خطا"</string>
     <string name="adb_wireless_settings" msgid="2295017847215680229">"اشکال‌زدایی بی‌سیم"</string>
     <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"برای مشاهده و استفاده از دستگاه‌های در دسترس، اشکال‌زدایی بی‌سیم را روشن کنید"</string>
-    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"مرتبط کردن دستگاه با رمزینه پاسخ‌سریع"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"جفت کردن دستگاه با رمزینه پاسخ‌سریع"</string>
     <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"دستگاه‌های جدید را بااستفاده از اسکنر رمزینه پاسخ‌سریع مرتبط کنید"</string>
-    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"مرتبط کردن دستگاه با کد مرتبط‌سازی"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"جفت کردن دستگاه با کد مرتبط‌سازی"</string>
     <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"دستگاه‌های جدید را با استفاده از کد شش رقمی مرتبط کنید"</string>
     <string name="adb_paired_devices_title" msgid="5268997341526217362">"دستگاه‌های مرتبط‌شده"</string>
     <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"درحال‌حاضر متصل"</string>
@@ -242,13 +242,13 @@
     <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"اثرانگشت دستگاه: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
     <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"اتصال ناموفق"</string>
     <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"مطمئن شوید که <xliff:g id="DEVICE_NAME">%1$s</xliff:g> به شبکه درستی متصل شده باشد"</string>
-    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"مرتبط کردن با دستگاه"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"جفت کردن با دستگاه"</string>
     <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"‏کد مرتبط‌سازی Wi‑Fi"</string>
     <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"مرتبط‌سازی ناموفق"</string>
     <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"مطمئن شوید که دستگاه به همان شبکه متصل باشد."</string>
     <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"‏دستگاه را ازطریق Wi‑Fi و با اسکن کردن رمزینه پاسخ‌سریع مرتبط کنید"</string>
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"مرتبط‌سازی دستگاه…"</string>
-    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"مرتبط کردن دستگاه انجام نشد. یا رمزینه پاسخ‌سریع اشتباه بوده است، یا دستگاه به همان شبکه متصل نیست."</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"جفت کردن دستگاه انجام نشد. یا رمزینه پاسخ‌سریع اشتباه بوده است، یا دستگاه به همان شبکه متصل نیست."</string>
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"‏نشانی IP و درگاه"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"اسکن رمزینه پاسخ‌سریع"</string>
     <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"‏دستگاه را ازطریق Wi‑Fi و با اسکن کردن رمزینه پاسخ‌سریع مرتبط کنید"</string>
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"هم‌اکنون"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"این تلفن"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"این رایانه لوحی"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"بلندگوی پایه اتصال"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"دستگاه خارجی"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"دستگاه متصل"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"این تلفن"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"نمی‌توان در این دستگاه پخش کرد"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"برای تغییر، حساب را ارتقا دهید"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index d1bf50a..b3a7560 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Äsken"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Tämä puhelin"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tämä tabletti"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Telinekaiutin"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Ulkoinen laite"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Yhdistetty laite"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Tämä puhelin"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ei voi toistaa tällä laitteella"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Vaihda päivittämällä tili"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 11579af..8d3eae4 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"À l\'instant"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ce téléphone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Cette tablette"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Haut-parleur du socle"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Appareil externe"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Appareil connecté"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ce téléphone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Impossible de faire jouer le contenu sur cet appareil"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Mettez à jour le compte pour passer à la version payante"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index cf444a6..a4e43c7 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"À l\'instant"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ce téléphone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Cette tablette"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Haut-parleur station d\'accueil"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Appareil externe"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Appareil connecté"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ce téléphone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Impossible de lire du contenu sur cet appareil"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Mettez à niveau le compte pour changer"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 89145cb..dbc0ba61 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Agora mesmo"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este teléfono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Esta tableta"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Altofalante da base"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Non se pode reproducir contido neste dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Cambia a conta a un plan superior para facer a modificación"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index fbcc84a..ee44c0a 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"હમણાં જ"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"આ ફોન"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"આ ટૅબ્લેટ"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ડૉક સ્પીકર"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"બહારનું ડિવાઇસ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"કનેક્ટ કરેલું ડિવાઇસ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"આ ફોન"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"આ ડિવાઇસ પર ચલાવી શકતા નથી"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"સ્વિચ કરવા માટે એકાઉન્ટ અપગ્રેડ કરો"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index a123a85..b97837b 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"अभी-अभी"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"यह फ़ोन"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"यह टैबलेट"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"डॉक स्पीकर"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"बाहरी डिवाइस"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"कनेक्ट किया गया डिवाइस"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"यह फ़ोन"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"इस डिवाइस पर मीडिया नहीं चलाया जा सकता"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"प्रीमियम खाते में स्विच करने के लिए, अपना खाता अपग्रेड करें"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 4566cad..6acfb95 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Upravo sad"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ovaj telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ovaj tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Zvučnik priključne stanice"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Vanjski uređaj"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Povezani uređaj"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ne može se reproducirati ovdje"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Nadogradite i prebacite se"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index b9f9d79..14ecad0 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Az imént"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ez a telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ez a táblagép"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dokkhangszóró"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Külső eszköz"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Csatlakoztatott eszköz"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ez a telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nem játszható le ezen az eszközön"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"A váltáshoz frissítse fiókját"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index de002a0..5083165 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Հենց նոր"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Այս հեռախոսը"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Այս պլանշետը"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Դոկ-կայանով բարձրախոս"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Արտաքին սարք"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Միացված սարք"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Այս հեռախոսը"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Հնարավոր չէ նվագարկել այս սարքում"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Փոխելու համար անցեք հաշվի պրեմիում տարբերակին"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index cdc297e..c5e6912 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Baru saja"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ponsel ini"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tablet ini"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Speaker dok"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Perangkat Eksternal"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Perangkat yang terhubung"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ponsel ini"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Tidak dapat memutar di perangkat ini"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Upgrade akun untuk beralih"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 18acafd..5d18930 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Rétt í þessu"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Þessi sími"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Þessi spjaldtölva"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Hátalaradokka"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Ytra tæki"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Tengt tæki"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Þessi sími"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ekki er hægt að spila í þessu tæki"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Uppfærðu reikninginn til að skipta"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 7e84c5a..85d4985 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Adesso"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Questo telefono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Questo tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Base con altoparlante"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo esterno"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo connesso"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Questo telefono"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Impossibile riprodurre su questo dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Esegui l\'upgrade dell\'account per cambiare"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index c772f37..af56031 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"הרגע"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"הטלפון הזה"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"הטאבלט הזה"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"הרמקול של אביזר העגינה"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"מכשיר חיצוני"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"המכשיר המחובר"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"הטלפון הזה"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"לא ניתן להפעיל במכשיר"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"יש לשדרג חשבון כדי לעבור"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index a459abf..076d022 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -551,7 +551,7 @@
     <skip />
     <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
     <skip />
-    <string name="media_transfer_this_phone" msgid="7194341457812151531">"このスマートフォン"</string>
+    <string name="media_transfer_this_phone" msgid="7194341457812151531">"このデバイス"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"このデバイスでは再生できません"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"アカウントを更新して切り替えてください"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"再生不可: ダウンロードしたコンテンツ"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index eba3e9e..147512b 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ახლახან"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ეს ტელეფონი"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ეს ტაბლეტი"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"დინამიკის სამაგრი"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"გარე მოწყობილობა"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"დაკავშირებული მოწყობილობა"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ეს ტელეფონი"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ამ მოწყობილობაზე დაკვრა შეუძლებელია"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"გადასართავად განაახლეთ ანგარიში"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 83388a0..7df9fb3 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -84,7 +84,7 @@
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Ажыратылған"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ажыратылуда…"</string>
-    <string name="bluetooth_connecting" msgid="5871702668260192755">"Жалғауда..."</string>
+    <string name="bluetooth_connecting" msgid="5871702668260192755">"Қосылып жатыр..."</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> жалғанды"</string>
     <string name="bluetooth_pairing" msgid="4269046942588193600">"Жұптасып жатыр..."</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> жалғанды (телефонсыз)"</string>
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Дәл қазір"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Осы телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Осы планшет"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Қондыру динамигі"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Сыртқы құрылғы"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Жалғанған құрылғы"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Осы телефон"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Осы құрылғыда ойнату мүмкін емес."</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Ауысу үшін аккаунтты жаңартыңыз."</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 0e470f5..81d2669 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -99,7 +99,7 @@
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"សកម្ម"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"សកម្មខាងឆ្វេងតែប៉ុណ្ណោះ"</string>
+    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"សកម្ម ខាងឆ្វេងតែប៉ុណ្ណោះ"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"សកម្មខាងស្ដាំតែប៉ុណ្ណោះ"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"សកម្មខាងឆ្វេង និងស្ដាំ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"សំឡេង​មេឌៀ"</string>
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"អម្បាញ់មិញ"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ទូរសព្ទនេះ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ថេប្លេតនេះ"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ឧបករណ៍បំពងសំឡេងដែលមានជើងភ្ជាប់"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ឧបករណ៍ខាងក្រៅ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"​ឧបករណ៍ដែលបាន​ភ្ជាប់"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ទូរសព្ទនេះ"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"មិនអាចចាក់នៅលើ​ឧបករណ៍នេះបានទេ"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ដំឡើងកម្រិតគណនី ដើម្បីប្ដូរ"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index a66f83c..f7f6a2f 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -49,7 +49,7 @@
     <string name="wifi_security_none_owe" msgid="5241745828327404101">"ಯಾವುದೂ ಇಲ್ಲ/Enhanced Open"</string>
     <string name="wifi_security_owe" msgid="3343421403561657809">"Enhanced Open"</string>
     <string name="wifi_security_eap_suiteb" msgid="415842785991698142">"WPA3-ಎಂಟರ್‌ಪ್ರೈಸ್ 192-ಬಿಟ್"</string>
-    <string name="wifi_remembered" msgid="3266709779723179188">"ಉಳಿಸಲಾಗಿದೆ"</string>
+    <string name="wifi_remembered" msgid="3266709779723179188">"ಸೇವ್‌ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="wifi_disconnected" msgid="7054450256284661757">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="wifi_disabled_generic" msgid="2651916945380294607">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP ಕಾನ್ಫಿಗರೇಶನ್ ವಿಫಲತೆ"</string>
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ಇದೀಗ"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ಈ ಫೋನ್"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ಈ ಟ್ಯಾಬ್ಲೆಟ್"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ಡಾಕ್ ಸ್ಪೀಕರ್"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ಬಾಹ್ಯ ಸಾಧನ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"ಕನೆಕ್ಟ್ ಮಾಡಿರುವ ಸಾಧನ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ಈ ಫೋನ್"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ಈ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ಬದಲಾಯಿಸಲು ಖಾತೆಯನ್ನು ಅಪ್‌ಗ್ರೇಡ್ ಮಾಡಿ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 273176c..ffa05cc 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"조금 전"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"이 휴대전화"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"태블릿"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"도크 스피커"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"외부 기기"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"연결된 기기"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"이 휴대전화"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"이 기기에서 재생할 수 없음"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"전환하려면 계정을 업그레이드하세요."</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 3a75a8e..58a930f 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -231,7 +231,7 @@
     <string name="adb_wireless_error" msgid="721958772149779856">"Ката"</string>
     <string name="adb_wireless_settings" msgid="2295017847215680229">"Мүчүлүштүктөрдү Wi-Fi аркылуу аныктоо"</string>
     <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Жеткиликтүү түзмөктөрдү көрүү үчүн мүчүлүштүктөрдү Wi-Fi аркылуу аныктоону күйгүзүңүз"</string>
-    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Түзмөктү QR коду аркылуу жупташтыруу"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Түзмөктү QR код аркылуу жупташтыруу"</string>
     <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"QR кодунун сканерин колдонуп, жаңы түзмөктөрдү жупташтырыңыз"</string>
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Түзмөктү атайын код аркылуу жупташтыруу"</string>
     <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Жаңы түзмөктөрдү алты сандан турган код аркылуу жупташтырасыз"</string>
@@ -246,12 +246,12 @@
     <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi аркылуу байланыштыруу коду"</string>
     <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Туташкан жок"</string>
     <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Түзмөк бир тармакка туташып турушу керек."</string>
-    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR кодун скандап, түзмөктү Wi‑Fi аркылуу жупташтырыңыз"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR кодду скандап, түзмөктү Wi‑Fi аркылуу жупташтырыңыз"</string>
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Түзмөк жупташтырылууда…"</string>
-    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Түзмөк жупташтырылган жок. QR коду туура эмес же түзмөк бир тармакка туташпай турат."</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Түзмөк жупташтырылган жок. QR код туура эмес же түзмөк бир тармакка туташпай турат."</string>
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP дарек жана порт"</string>
-    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR кодун скандоо"</string>
-    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"QR кодун скандап, түзмөктү Wi‑Fi аркылуу жупташтырыңыз"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR кодду скандоо"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"QR кодду скандап, түзмөктү Wi‑Fi аркылуу жупташтырыңыз"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Wi-Fi тармагына туташыңыз"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, мүчүлүштүктөрдү оңдоо, иштеп чыгуу"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Ката жөнүндө кабарлоо"</string>
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Жаңы эле"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ушул телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ушул планшет"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Док бекети үчүн динамик"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Тышкы түзмөк"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Туташкан түзмөк"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ушул телефон"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Бул түзмөктө ойнотууга болбойт"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Премиум аккаунтка которулуу керек"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 25466d4..28fd87e 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ຕອນນີ້"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ໂທລະສັບນີ້"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ແທັບເລັດນີ້"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ແທ່ນວາງລຳໂພງ"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ອຸປະກອນພາຍນອກ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"ອຸປະກອນທີ່ເຊື່ອມຕໍ່"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ໂທລະສັບນີ້"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ຫຼິ້ນຢູ່ອຸປະກອນນີ້ບໍ່ໄດ້"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ອັບເກຣດບັນຊີເພື່ອສະຫຼັບ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index ff9f1c2..8246c6b 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Ką tik"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Šis telefonas"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Šis planšetinis kompiuteris"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Doko garsiakalbis"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Išorinis įrenginys"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Prijungtas įrenginys"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Šis telefonas"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Negalima leisti šiame įrenginyje"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Jei norite perjungti, naujovinkite paskyrą"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 9105153..807df3a 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Tikko"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Šis tālrunis"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Šis planšetdators"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Doka skaļrunis"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Ārēja ierīce"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Pievienotā ierīce"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Šis tālrunis"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nevar atskaņot šajā ierīcē."</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Lai pārslēgtu, jauniniet kontu"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 0005ec5..f7b4c0f 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Пред малку"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Овој телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Овој таблет"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Док со звучник"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Надворешен уред"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Поврзан уред"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Овој телефон"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Не може да се пушти на уредов"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Надградете ја сметката за да се префрлите"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 12d6e52..610f365 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ഇപ്പോൾ"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ഈ ഫോൺ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ഈ ടാബ്‌ലെറ്റ്"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ഡോക്ക് സ്‌പീക്കർ"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ബാഹ്യ ഉപകരണം"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"കണക്‌റ്റ് ചെയ്‌ത ഉപകരണം"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ഈ ഫോൺ"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ഈ ഉപകരണത്തിൽ പ്ലേ ചെയ്യാൻ കഴിയില്ല"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"അക്കൗണ്ട് മാറാൻ അപ്‌ഗ്രേഡ് ചെയ്യുക"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index d2e03f2..040f2c8 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Дөнгөж сая"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Энэ утас"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Энэ таблет"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Суурилуулагчийн чанга яригч"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Гадаад төхөөрөмж"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Холбогдсон төхөөрөмж"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Энэ утас"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Энэ төхөөрөмжид тоглуулах боломжгүй"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Сэлгэхийн тулд бүртгэлийг сайжруулна уу"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 8c2b4ae..932ef6c 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"आत्ताच"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"हा फोन"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"हा टॅबलेट"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"डॉक स्पीकर"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"बाह्य डिव्हाइस"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"कनेक्ट केलेले डिव्हाइस"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"हा फोन"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"या डिव्हाइसवर प्ले करू शकत नाही"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"स्विच करण्यासाठी खाते अपग्रेड करा"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index e991b24..460eb56 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Sebentar tadi"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Telefon ini"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tablet ini"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Pembesar suara dok"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Peranti Luar"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Peranti yang disambungkan"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Telefon ini"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Tidak dapat dimainkan pada peranti ini"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Tingkatkan akaun untuk beralih"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 12bd02e..8458a62 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ယခုလေးတင်"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ဤဖုန်း"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ဤတက်ဘလက်"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"အထိုင် စပီကာ"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ပြင်ပစက်"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"ချိတ်ဆက်ကိရိယာ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ဤဖုန်း"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ဤစက်ပစ္စည်းတွင် ဖွင့်၍မရပါ"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ပြောင်းရန် အကောင့်အဆင့်ကိုမြှင့်ပါ"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index b85dabb..a082be6 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Nå nettopp"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Denne telefonen"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Dette nettbrettet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dokkhøyttaler"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Ekstern enhet"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Tilkoblet enhet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Denne telefonen"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Kan ikke spille på denne enheten"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Oppgrader kontoen for å bytte"</string>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index fccd8bbe..f464f31 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -23,7 +23,7 @@
   <string-array name="wifi_status">
     <item msgid="1596683495752107015"></item>
     <item msgid="3288373008277313483">"स्क्यान गरिँदै..."</item>
-    <item msgid="6050951078202663628">"जडान हुँदै..."</item>
+    <item msgid="6050951078202663628">"कनेक्ट गरिँदै छ..."</item>
     <item msgid="8356618438494652335">"प्रमाणित गर्दै ..."</item>
     <item msgid="2837871868181677206">"IP एड्रेस पत्ता लगाउँदै ..."</item>
     <item msgid="4613015005934755724">"जडान गरिएको"</item>
@@ -37,7 +37,7 @@
   <string-array name="wifi_status_with_ssid">
     <item msgid="5969842512724979061"></item>
     <item msgid="1818677602615822316">"स्क्यान गर्दै..."</item>
-    <item msgid="8339720953594087771">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>सँग जडान हुँदै..."</item>
+    <item msgid="8339720953594087771">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>सँग कनेक्ट गरिँदै छ..."</item>
     <item msgid="3028983857109369308">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>को साथ प्रमाणित गर्दै…"</item>
     <item msgid="4287401332778341890">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>बाट IP एड्रेस प्राप्त गर्दै…"</item>
     <item msgid="1043944043827424501">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> मा कनेक्ट भएको छ छ"</item>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 59a60db..4e345525 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -84,7 +84,7 @@
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"विच्छेदन गरियो"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"जडान हटाइँदै ..."</string>
-    <string name="bluetooth_connecting" msgid="5871702668260192755">"जडान हुँदै..."</string>
+    <string name="bluetooth_connecting" msgid="5871702668260192755">"कनेक्ट गरिँदै छ..."</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> सँग कनेक्ट भएको छ"</string>
     <string name="bluetooth_pairing" msgid="4269046942588193600">"कनेक्ट गरिँदै छ..."</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"जडान गरियो (फोनबाहेेक) <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -99,7 +99,7 @@
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"ब्याट्रीको स्तर: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ब्याट्री, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ब्याट्री"</string>
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"सक्रिय"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"सक्रिय, बायाँ मात्र"</string>
+    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"बायाँ मात्र अन छ"</string>
     <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"सक्रिय, दायाँ मात्र"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"सक्रिय, बायाँ र दायाँ"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"मिडिया अडियो"</string>
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"अहिले भर्खरै"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"यो फोन"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"यो ट्याब्लेट"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"डक स्पिकर"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"बाह्य डिभाइस"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"कनेक्ट गरिएको डिभाइस"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"यो फोन"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"यो डिभाइसमा मिडिया प्ले गर्न मिल्दैन"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"आफूले प्रयोग गर्न चाहेको खाता अपग्रेड गर्नुहोस्"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 02cdba4..1b456b9 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Zojuist"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Deze telefoon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Deze tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dockspeaker"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Extern apparaat"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Verbonden apparaat"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Deze telefoon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Kan niet afspelen op dit apparaat"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Upgrade het account om te schakelen"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 699989b..99bcafe 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -84,9 +84,9 @@
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"ବିଛିନ୍ନ ହେଲା"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"ବିଚ୍ଛିନ୍ନ କରୁଛି…"</string>
-    <string name="bluetooth_connecting" msgid="5871702668260192755">"ସଂଯୋଗ କରାଯାଉଛି…"</string>
+    <string name="bluetooth_connecting" msgid="5871702668260192755">"କନେକ୍ଟ ହେଉଛି…"</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"ସଂଯୁକ୍ତ ହେଲା<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_pairing" msgid="4269046942588193600">"ପେୟାର୍‌ କରୁଛି…"</string>
+    <string name="bluetooth_pairing" msgid="4269046942588193600">"ପେୟାର କରୁଛି…"</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"ସଂଯୁକ୍ତ ହେଲା (ଫୋନ୍ ନୁହେଁ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"ସଂଯୁକ୍ତ ହେଲା (ମିଡିଆ ନୁହେଁ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2893204819854215433">"ସଂଯୁକ୍ତ ହେଲା (ଫୋନ୍ କିମ୍ବା ମେଡିଆ ନୁହେଁ)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -174,7 +174,7 @@
     <string name="launch_defaults_some" msgid="3631650616557252926">"କିଛି ପୂର୍ବ-ନିର୍ଦ୍ଧାରିତ ମାନ ସେଟ୍‌ ହୋଇଛି"</string>
     <string name="launch_defaults_none" msgid="8049374306261262709">"କୌଣସି ଡିଫଲ୍ଟ ସେଟ୍‍ ହୋଇନାହିଁ"</string>
     <string name="tts_settings" msgid="8130616705989351312">"ଟେକ୍ସଟ୍-ଟୁ-ସ୍ପିଚ୍ ସେଟିଂସ"</string>
-    <string name="tts_settings_title" msgid="7602210956640483039">"ଟେକ୍ସଟ୍‍-ଟୁ-ସ୍ପିଚ୍‍ ଆଉଟ୍‍ପୁଟ୍‌"</string>
+    <string name="tts_settings_title" msgid="7602210956640483039">"ଟେକ୍ସଟ-ଟୁ-ସ୍ପିଚ ଆଉଟପୁଟ"</string>
     <string name="tts_default_rate_title" msgid="3964187817364304022">"ସ୍ପିଚ୍‌ ରେଟ୍"</string>
     <string name="tts_default_rate_summary" msgid="3781937042151716987">"ଲେଖା ପଢ଼ିବାର ବେଗ"</string>
     <string name="tts_default_pitch_title" msgid="6988592215554485479">"ପିଚ୍‌"</string>
@@ -250,7 +250,7 @@
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"ଡିଭାଇସ୍ ପେୟାର୍ କରାଯାଉଛି…"</string>
     <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"ଡିଭାଇସରୁ ପେୟାର୍ ହେବାରେ ବିଫଳ ହୋଇଛି। QR କୋଡ୍ ସଠିକ୍ ନଥିଲା ବା ଡିଭାଇସ୍ ସମାନ ନେଟୱାର୍କରେ ସଂଯୋଗ ହୋଇନାହିଁ।"</string>
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP ଠିକଣା ଓ ପୋର୍ଟ"</string>
-    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR କୋଡ୍ ସ୍କାନ୍ କରନ୍ତୁ"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR କୋଡ ସ୍କାନ କରନ୍ତୁ"</string>
     <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"ଏକ QR କୋଡ୍ ସ୍କାନ୍ କରି ୱାଇ-ଫାଇ ମାଧ୍ୟମରେ ଡିଭାଇସ୍ ପେୟାର୍ କରନ୍ତୁ"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"ଦୟାକରି ଏକ ୱାଇ-ଫାଇ ନେଟୱାର୍କରେ ସଂଯୋଗ କରନ୍ତୁ"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ଡିବଗ୍, dev"</string>
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ଏହିକ୍ଷଣି"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ଏହି ଫୋନ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ଏହି ଟାବଲେଟ"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ଡକ ସ୍ପିକର"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ଏକ୍ସଟର୍ନଲ ଡିଭାଇସ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"କନେକ୍ଟ କରାଯାଇଥିବା ଡିଭାଇସ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ଏହି ଫୋନ୍"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ଏହି ଡିଭାଇସରେ ପ୍ଲେ କରାଯାଇପାରିବ ନାହିଁ"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ସ୍ୱିଚ କରିବା ପାଇଁ ଆକାଉଣ୍ଟକୁ ଅପଗ୍ରେଡ କରନ୍ତୁ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 482315f..3e20201 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ਹੁਣੇ ਹੀ"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ਇਹ ਫ਼ੋਨ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ਇਹ ਟੈਬਲੈੱਟ"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ਡੌਕ ਸਪੀਕਰ"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ਬਾਹਰੀ ਡੀਵਾਈਸ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"ਕਨੈਕਟ ਕੀਤਾ ਡੀਵਾਈਸ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ਇਹ ਫ਼ੋਨ"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਨਹੀਂ ਚਲਾਇਆ ਜਾ ਸਕਦਾ"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ਸਵਿੱਚ ਕਰਨ ਲਈ ਖਾਤੇ ਨੂੰ ਅੱਪਗ੍ਰੇਡ ਕਰੋ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 7425744..58a89d9 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -84,7 +84,7 @@
     <string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Rozłączono"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Rozłączanie..."</string>
-    <string name="bluetooth_connecting" msgid="5871702668260192755">"Łączenie..."</string>
+    <string name="bluetooth_connecting" msgid="5871702668260192755">"Łączę..."</string>
     <string name="bluetooth_connected" msgid="8065345572198502293">"Połączono – <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="4269046942588193600">"Paruję…"</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Połączono (bez telefonu) – <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -99,8 +99,8 @@
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</string>
     <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P: bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Urządzenie aktywne"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktywny, tylko lewa strona"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktywny, tylko prawa strona"</string>
+    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktywne, tylko lewa strona"</string>
+    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktywne, tylko prawa strona"</string>
     <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktywny, lewa i prawa strona"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"Dźwięk multimediów"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"Połączenia telefoniczne"</string>
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Przed chwilą"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ten telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ten tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Głośnik ze stacją dokującą"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Urządzenie zewnętrzne"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Połączone urządzenie"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ten telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nie można odtworzyć na tym urządzeniu"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Aby przełączyć, potrzebujesz konta premium"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index e8a3966..678c076 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Agora"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este telefone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Este tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Alto-falante da base"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este telefone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Não é possível reproduzir neste dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Faça upgrade da conta para trocar"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 8b9d33a..847bfb5 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Agora mesmo"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este telemóvel"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Este tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Altifalante estação carregam."</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo associado"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este telemóvel"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Não é possível reproduzir neste dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Atualize a conta para mudar"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index e8a3966..678c076 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Agora"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este telefone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Este tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Alto-falante da base"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este telefone"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Não é possível reproduzir neste dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Faça upgrade da conta para trocar"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 244dc6f..7fa228b 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Chiar acum"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Acest telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Această tabletă"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Difuzorul dispozitivului de andocare"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispozitiv extern"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispozitiv conectat"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Acest telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nu se poate reda pe acest dispozitiv"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Fă upgrade contului pentru a comuta"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 321fe6f..a53b67a 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Только что"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Этот смартфон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Этот планшет"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Колонка с док-станцией"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Внешнее устройство"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Подключенное устройство"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Этот смартфон"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Невозможно воспроизвести на этом устройстве."</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Для переключения требуется премиум-аккаунт"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 400a6e5c..ab5d3ce 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"මේ දැන්"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"මෙම දුරකථනය"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"මෙම ටැබ්ලටය"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ඩොක් ස්පීකරය"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"බාහිර උපාංගය"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"සම්බන්ධ කළ උපාංගය"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"මෙම දුරකථනය"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"මෙම උපාංගය මත ධාවනය කළ නොහැක"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"මාරු වීමට ගිණුම උත්ශ්‍රේණි කරන්න"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 3c2b7ba..daf9492 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -107,7 +107,7 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenos súborov"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Vstupné zariadenie"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Prístup na internet"</string>
-    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Zdieľanie kontaktov a histórie hovorov"</string>
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Zdieľať kontakty a históriu hovorov"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Používané pri zdieľaní kontaktov a histórie hovorov"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Zdieľanie pripojenia na Internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Textové správy"</string>
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Teraz"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Tento telefón"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tento tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Reproduktor doku"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Externé zariadenie"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Pripojené zariadenie"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Tento telefón"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"V tomto zariadení sa nedá prehrávať obsah"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Inovujte účet a prejdite naň"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 86cb46d..7164da6 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Pravkar"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ta telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ta tablični računalnik"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Zvočnik nosilca"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Zunanja naprava"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Povezana naprava"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ta telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ni mogoče predvajati v tej napravi."</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Za preklop je potrebna nadgradnja računa"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index c2cecebb..7fd6ec9 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -455,7 +455,7 @@
     <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"Duhet të zgjasë deri në rreth <xliff:g id="TIME">%1$s</xliff:g> bazuar në përdorimin tënd"</string>
     <string name="power_discharge_by" msgid="4113180890060388350">"Duhet të zgjasë deri në rreth <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only" msgid="92545648425937000">"Duhet të zgjasë deri në rreth <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"Deri në <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by_only_short" msgid="5883041507426914446">"Deri në: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Bateria mund të mbarojë deri në <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"Më pak se <xliff:g id="THRESHOLD">%1$s</xliff:g> e mbetur"</string>
     <string name="power_remaining_less_than_duration" msgid="318215464914990578">"Më pak se <xliff:g id="THRESHOLD">%1$s</xliff:g> e mbetur (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Pikërisht tani"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ky telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ky tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Altoparlanti i stacionit"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Pajisja e jashtme"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Pajisja e lidhur"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ky telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nuk mund të luhet në këtë pajisje"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Përmirëso llogarinë për të ndryshuar"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 041b515a..86675cf 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Управо"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Овај телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Овај таблет"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Звучник базне станице"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Спољни уређај"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Повезани уређај"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Овај телефон"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Не можете да пустите на овом уређају"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Надоградите налог ради пребацивања"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 453f2cf..0d71afd 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Nyss"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Den här telefonen"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Den här surfplattan"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dockningsstationens högtalare"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Extern enhet"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Ansluten enhet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Den här telefonen"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Kan inte spelas på denna enhet"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Uppgradera kontot för att byta"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index d6fdc1e..303131e 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Sasa hivi"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Simu hii"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Kompyuta kibao hii"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Spika ya kituo"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Kifaa cha Nje"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Kifaa kilichounganishwa"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Simu hii"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Huwezi kucheza maudhui kwenye kifaa hiki"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Pata toleo jipya la akaunti ili ubadilishe"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index fa39a71..83aa2af 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"சற்றுமுன்"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"இந்த மொபைல்"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"இந்த டேப்லெட்"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"டாக் ஸ்பீக்கர்"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"வெளிப்புறச் சாதனம்"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"இணைக்கப்பட்டுள்ள சாதனம்"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"இந்த மொபைல்"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"இந்தச் சாதனத்தில் பிளே செய்ய முடியவில்லை"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"மாற்ற, கணக்கை மேம்படுத்துங்கள்"</string>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index db2307d..d250352 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -66,7 +66,7 @@
   <string-array name="bt_hci_snoop_log_filters_entries">
     <item msgid="195768089203590086">"ACLహెడర్‌లను మాత్రమే వదిలివేయండి"</item>
     <item msgid="2776218217644557831">"A2DP మీడియా ప్యాకెట్‌లను ఫిల్టర్ చేయండి"</item>
-    <item msgid="8163235976612675092">"RFCOMM ఛానెల్‌ని ఫిల్టర్ చేయండి"</item>
+    <item msgid="8163235976612675092">"RFCOMM ఛానెల్‌ను ఫిల్టర్ చేయండి"</item>
   </string-array>
   <string-array name="bt_hci_snoop_log_profile_filter_entries">
     <item msgid="3961868665260627524">"డిజేబుల్ చేయండి"</item>
@@ -269,10 +269,10 @@
   <string-array name="app_process_limit_entries">
     <item msgid="794656271086646068">"స్టాండర్డ్ పరిమితి"</item>
     <item msgid="8628438298170567201">"నేపథ్య ప్రాసెస్‌లు లేవు"</item>
-    <item msgid="915752993383950932">"గరిష్టంగా 1 ప్రాసెస్"</item>
-    <item msgid="8554877790859095133">"గరిష్టంగా 2 ప్రాసెస్‌లు"</item>
-    <item msgid="9060830517215174315">"గరిష్టంగా 3 ప్రాసెస్‌లు"</item>
-    <item msgid="6506681373060736204">"గరిష్టంగా 4 ప్రాసెస్‌లు"</item>
+    <item msgid="915752993383950932">"గరిష్ఠంగా 1 ప్రాసెస్"</item>
+    <item msgid="8554877790859095133">"గరిష్ఠంగా 2 ప్రాసెస్‌లు"</item>
+    <item msgid="9060830517215174315">"గరిష్ఠంగా 3 ప్రాసెస్‌లు"</item>
+    <item msgid="6506681373060736204">"గరిష్ఠంగా 4 ప్రాసెస్‌లు"</item>
   </string-array>
   <string-array name="usb_configuration_titles">
     <item msgid="3358668781763928157">"ఛార్జింగ్"</item>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index e8336f0..e7cf933 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ఇప్పుడే"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ఈ ఫోన్"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ఈ టాబ్లెట్"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"డాక్ స్పీకర్"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ఎక్స్‌టర్నల్ పరికరం"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"కనెక్ట్ చేసిన పరికరం"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ఈ ఫోన్"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ఈ పరికరంలో ప్లే చేయడం సాధ్యపడదు"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"మారడానికి ఖాతాను అప్‌గ్రేడ్ చేయండి"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 8335cba..32629c3 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"เมื่อสักครู่"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"โทรศัพท์เครื่องนี้"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"แท็บเล็ตเครื่องนี้"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"แท่นวางลำโพง"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"อุปกรณ์ภายนอก"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"อุปกรณ์ที่เชื่อมต่อ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"โทรศัพท์เครื่องนี้"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"เล่นในอุปกรณ์นี้ไม่ได้"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"อัปเกรดบัญชีเพื่อเปลี่ยน"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index dd729de..e60faf6 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Ngayon lang"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ang teleponong ito"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ang tablet na ito"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Speaker ng dock"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"External na Device"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Nakakonektang device"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ang teleponong ito"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Hindi ma-play sa device na ito"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"I-upgrade ang account para lumipat"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index a2417ed..3ea12ad 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Az önce"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Bu telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Bu tablet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Yuva hoparlörü"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Harici Cihaz"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Bağlı cihaz"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Bu telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Bu cihazda oynatılamıyor"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Geçiş yapmak için hesabı yükseltin"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index b5c31f4..95ece26 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -107,7 +107,7 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Передавання файлів"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Пристрій введення"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Доступ до Інтернету"</string>
-    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Доступ до контактів та історії дзвінків"</string>
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Доступ до контактів і історії викликів"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Використовуйте, щоб надсилати контакти й історію викликів"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Надання доступу до Інтернету"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Текстові повідомлення"</string>
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Щойно"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Цей телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Цей планшет"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Динамік док-станції"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Зовнішній пристрій"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Підключений пристрій"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Цей телефон"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Не можна відтворювати тут"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Потрібний платний обліковий запис"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index fea22aa5..70aa9a3 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"ابھی ابھی"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"یہ فون"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"یہ ٹیبلیٹ"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ڈاک اسپیکر"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"بیرونی آلہ"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"منسلک آلہ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"یہ فون"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"اس آلے پر چلایا نہیں جا سکتا"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"سوئچ کرنے کے لیے اکاؤنٹ اپ گریڈ کریں"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 312a22e..5f42969 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Hozir"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Shu telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Shu planshet"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dok-stansiyali karnay"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Tashqi qurilma"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Ulangan qurilma"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Shu telefon"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Bu qurilmada ijro etilmaydi"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Oʻtish uchun hisobingizni yangilang"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index b16f200..d75f1b2 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Vừa xong"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Điện thoại này"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Máy tính bảng này"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Loa có gắn đế"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Thiết bị bên ngoài"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Thiết bị đã kết nối"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Điện thoại này"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Không phát được trên thiết bị này"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Nâng cấp tài khoản để chuyển đổi"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index d266d14..23b6ff3 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"刚刚"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"这部手机"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"这台平板电脑"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"基座音箱"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"外部设备"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"连接的设备"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"这部手机"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"无法在此设备上播放"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"升级帐号后才能切换"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index be7c044..e6da4bc 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"剛剛"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"此手機"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"此平板電腦"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"插座喇叭"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"外部裝置"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"已連接的裝置"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"這部手機"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"無法在此裝置上播放"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"請升級要切換的帳戶"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 59105e5..e33934c 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"剛剛"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"這支手機"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"這台平板電腦"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"座架喇叭"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"外部裝置"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"已連結的裝置"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"這支手機"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"無法在這部裝置上播放"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"請升級要切換的帳戶"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 87cf1f7..5c7a7b5 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -545,12 +545,9 @@
     <string name="time_unit_just_now" msgid="3006134267292728099">"Khona manje"</string>
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Le foni"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Le thebulethi"</string>
-    <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
-    <skip />
-    <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
-    <skip />
-    <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
-    <skip />
+    <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Isipikha sentuba"</string>
+    <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Idivayisi Yangaphandle"</string>
+    <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Idivayisi exhunyiwe"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Le foni"</string>
     <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ayikwazi ukudlala kule divayisi"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Thuthukisa i-akhawunti ukuze ushintshe"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index dac7f8d..b44c0e0 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -929,7 +929,7 @@
     <!-- UI debug setting: show all ANRs summary [CHAR LIMIT=100] -->
     <string name="show_all_anrs_summary">Display App Not Responding dialog for background apps</string>
 
-    <!-- UI debug setting: show missing channel toasts? [CHAR LIMIT=25] -->
+    <!-- UI debug setting: show missing channel toasts? [CHAR LIMIT=30] -->
     <string name="show_notification_channel_warnings">Show notification channel warnings</string>
     <!-- UI debug setting: show missing channel toasts summary [CHAR LIMIT=50] -->
     <string name="show_notification_channel_warnings_summary">Displays on-screen warning when an app posts a notification without a valid channel</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 8d4aa9a..c967b56 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -688,8 +688,12 @@
                 continue;
             }
             for (int complianceWarningType : complianceWarnings) {
-                if (complianceWarningType != 0) {
-                    return true;
+                switch (complianceWarningType) {
+                    case UsbPortStatus.COMPLIANCE_WARNING_OTHER:
+                    case UsbPortStatus.COMPLIANCE_WARNING_DEBUG_ACCESSORY:
+                        return true;
+                    default:
+                        break;
                 }
             }
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index 3fcb7f3..ffc0479 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -116,10 +116,7 @@
                 && !TextUtils.isEmpty(mPackageName)) {
             RouteListingPreference routeListingPreference =
                     mRouterManager.getRouteListingPreference(mPackageName);
-            if (routeListingPreference != null) {
-                Api34Impl.onRouteListingPreferenceUpdated(null, routeListingPreference,
-                        mPreferenceItemMap);
-            }
+            Api34Impl.onRouteListingPreferenceUpdated(routeListingPreference, mPreferenceItemMap);
         }
         refreshDevices();
     }
@@ -631,7 +628,7 @@
         }
 
         /**
-         * Ignore callback here since we'll also receive {@link onRequestFailed} with reason code.
+         * Ignore callback here since we'll also receive {@link #onRequestFailed} with reason code.
          */
         @Override
         public void onTransferFailed(RoutingSessionInfo session, MediaRoute2Info route) {
@@ -656,9 +653,9 @@
         public void onRouteListingPreferenceUpdated(
                 String packageName,
                 RouteListingPreference routeListingPreference) {
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
-                Api34Impl.onRouteListingPreferenceUpdated(packageName, routeListingPreference,
-                        mPreferenceItemMap);
+            if (TextUtils.equals(mPackageName, packageName)) {
+                Api34Impl.onRouteListingPreferenceUpdated(
+                        routeListingPreference, mPreferenceItemMap);
                 refreshDevices();
             }
         }
@@ -746,7 +743,6 @@
 
         @DoNotInline
         static void onRouteListingPreferenceUpdated(
-                String packageName,
                 RouteListingPreference routeListingPreference,
                 Map<String, RouteListingPreference.Item> preferenceItemMap) {
             preferenceItemMap.clear();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
index 0637e5d..4a913c8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
@@ -455,12 +455,24 @@
     }
 
     @Test
-    public void containsIncompatibleChargers_returnTrue() {
-        setupIncompatibleCharging();
+    public void containsIncompatibleChargers_complianeWarningOther_returnTrue() {
+        setupIncompatibleCharging(UsbPortStatus.COMPLIANCE_WARNING_OTHER);
         assertThat(Utils.containsIncompatibleChargers(mContext, TAG)).isTrue();
     }
 
     @Test
+    public void containsIncompatibleChargers_complianeWarningDebug_returnTrue() {
+        setupIncompatibleCharging(UsbPortStatus.COMPLIANCE_WARNING_DEBUG_ACCESSORY);
+        assertThat(Utils.containsIncompatibleChargers(mContext, TAG)).isTrue();
+    }
+
+    @Test
+    public void containsIncompatibleChargers_unexpectedWarningType_returnFalse() {
+        setupIncompatibleCharging(UsbPortStatus.COMPLIANCE_WARNING_BC_1_2);
+        assertThat(Utils.containsIncompatibleChargers(mContext, TAG)).isFalse();
+    }
+
+    @Test
     public void containsIncompatibleChargers_emptyComplianceWarnings_returnFalse() {
         setupIncompatibleCharging();
         when(mUsbPortStatus.getComplianceWarnings()).thenReturn(new int[1]);
@@ -494,12 +506,17 @@
     }
 
     private void setupIncompatibleCharging() {
+        setupIncompatibleCharging(UsbPortStatus.COMPLIANCE_WARNING_OTHER);
+    }
+
+    private void setupIncompatibleCharging(int complianceWarningType) {
         final List<UsbPort> usbPorts = new ArrayList<>();
         usbPorts.add(mUsbPort);
         when(mUsbManager.getPorts()).thenReturn(usbPorts);
         when(mUsbPort.getStatus()).thenReturn(mUsbPortStatus);
         when(mUsbPort.supportsComplianceWarnings()).thenReturn(true);
         when(mUsbPortStatus.isConnected()).thenReturn(true);
-        when(mUsbPortStatus.getComplianceWarnings()).thenReturn(new int[]{1});
+        when(mUsbPortStatus.getComplianceWarnings())
+                .thenReturn(new int[]{complianceWarningType});
     }
 }
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 aa5f3df..39780f3 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
@@ -73,6 +73,7 @@
 public class InfoMediaManagerTest {
 
     private static final String TEST_PACKAGE_NAME = "com.test.packagename";
+    private static final String TEST_PACKAGE_NAME_2 = "com.test.packagename2";
     private static final String TEST_ID = "test_id";
     private static final String TEST_ID_1 = "test_id_1";
     private static final String TEST_ID_2 = "test_id_2";
@@ -308,7 +309,54 @@
     }
 
     @Test
-    public void onRouteChanged_getAvailableRoutesWithPrefernceListExit_ordersRoutes() {
+    public void onRouteChanged_getAvailableRoutesWithPreferenceListExit_ordersRoutes() {
+        RouteListingPreference routeListingPreference = setUpPreferenceList(TEST_PACKAGE_NAME);
+        setUpSelectedRoutes(TEST_PACKAGE_NAME);
+
+        final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+        final RoutingSessionInfo sessionInfo = mock(RoutingSessionInfo.class);
+        routingSessionInfos.add(sessionInfo);
+
+        when(mRouterManager.getRoutingSessions(TEST_PACKAGE_NAME)).thenReturn(routingSessionInfos);
+        when(sessionInfo.getSelectedRoutes()).thenReturn(ImmutableList.of(TEST_ID));
+
+        setAvailableRoutesList(TEST_PACKAGE_NAME);
+
+        mInfoMediaManager.mRouterManager = mRouterManager;
+        mInfoMediaManager.mMediaRouterCallback.onRouteListingPreferenceUpdated(TEST_PACKAGE_NAME,
+                routeListingPreference);
+        mInfoMediaManager.mMediaRouterCallback.onRoutesUpdated();
+
+        assertThat(mInfoMediaManager.mMediaDevices).hasSize(3);
+        assertThat(mInfoMediaManager.mMediaDevices.get(0).getId()).isEqualTo(TEST_ID);
+        assertThat(mInfoMediaManager.mMediaDevices.get(1).getId()).isEqualTo(TEST_ID_4);
+        assertThat(mInfoMediaManager.mMediaDevices.get(1).isSuggestedDevice()).isTrue();
+        assertThat(mInfoMediaManager.mMediaDevices.get(2).getId()).isEqualTo(TEST_ID_3);
+    }
+
+    @Test
+    public void onRouteChanged_preferenceListUpdateWithDifferentPkg_notOrdersRoutes() {
+        RouteListingPreference routeListingPreference = setUpPreferenceList(TEST_PACKAGE_NAME_2);
+        setUpSelectedRoutes(TEST_PACKAGE_NAME);
+
+        final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+        final RoutingSessionInfo sessionInfo = mock(RoutingSessionInfo.class);
+        routingSessionInfos.add(sessionInfo);
+
+        when(mRouterManager.getRoutingSessions(TEST_PACKAGE_NAME)).thenReturn(routingSessionInfos);
+        when(sessionInfo.getSelectedRoutes()).thenReturn(ImmutableList.of(TEST_ID));
+
+        setAvailableRoutesList(TEST_PACKAGE_NAME);
+        mInfoMediaManager.mRouterManager = mRouterManager;
+        mInfoMediaManager.mMediaRouterCallback.onRouteListingPreferenceUpdated(TEST_PACKAGE_NAME_2,
+                routeListingPreference);
+        mInfoMediaManager.mMediaRouterCallback.onRoutesUpdated();
+
+        assertThat(mInfoMediaManager.mMediaDevices).hasSize(1);
+        assertThat(mInfoMediaManager.mMediaDevices.get(0).getId()).isEqualTo(TEST_ID);
+    }
+
+    private RouteListingPreference setUpPreferenceList(String packageName) {
         ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT",
                 Build.VERSION_CODES.UPSIDE_DOWN_CAKE);
         final List<RouteListingPreference.Item> preferenceItemList = new ArrayList<>();
@@ -324,57 +372,40 @@
         RouteListingPreference routeListingPreference =
                 new RouteListingPreference.Builder().setItems(
                         preferenceItemList).setUseSystemOrdering(false).build();
-        when(mRouterManager.getRouteListingPreference(TEST_PACKAGE_NAME))
+        when(mRouterManager.getRouteListingPreference(packageName))
                 .thenReturn(routeListingPreference);
+        return routeListingPreference;
+    }
 
+    private void setUpSelectedRoutes(String packageName) {
         final List<MediaRoute2Info> selectedRoutes = new ArrayList<>();
         final MediaRoute2Info info = mock(MediaRoute2Info.class);
         when(info.getId()).thenReturn(TEST_ID);
-        when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+        when(info.getClientPackageName()).thenReturn(packageName);
         when(info.isSystemRoute()).thenReturn(true);
         selectedRoutes.add(info);
         when(mRouterManager.getSelectedRoutes(any())).thenReturn(selectedRoutes);
-
-        final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
-        final RoutingSessionInfo sessionInfo = mock(RoutingSessionInfo.class);
-        routingSessionInfos.add(sessionInfo);
-
-        when(mRouterManager.getRoutingSessions(TEST_PACKAGE_NAME)).thenReturn(routingSessionInfos);
-        when(sessionInfo.getSelectedRoutes()).thenReturn(ImmutableList.of(TEST_ID));
-
-        setAvailableRoutesList();
-
-        mInfoMediaManager.mRouterManager = mRouterManager;
-        mInfoMediaManager.mMediaRouterCallback.onRouteListingPreferenceUpdated(TEST_PACKAGE_NAME,
-                routeListingPreference);
-        mInfoMediaManager.mMediaRouterCallback.onRoutesUpdated();
-
-        assertThat(mInfoMediaManager.mMediaDevices).hasSize(3);
-        assertThat(mInfoMediaManager.mMediaDevices.get(0).getId()).isEqualTo(TEST_ID);
-        assertThat(mInfoMediaManager.mMediaDevices.get(1).getId()).isEqualTo(TEST_ID_4);
-        assertThat(mInfoMediaManager.mMediaDevices.get(1).isSuggestedDevice()).isTrue();
-        assertThat(mInfoMediaManager.mMediaDevices.get(2).getId()).isEqualTo(TEST_ID_3);
     }
 
-    private List<MediaRoute2Info> setAvailableRoutesList() {
+    private List<MediaRoute2Info> setAvailableRoutesList(String packageName) {
         final List<MediaRoute2Info> availableRoutes = new ArrayList<>();
         final MediaRoute2Info availableInfo1 = mock(MediaRoute2Info.class);
         when(availableInfo1.getId()).thenReturn(TEST_ID_2);
-        when(availableInfo1.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+        when(availableInfo1.getClientPackageName()).thenReturn(packageName);
         when(availableInfo1.getType()).thenReturn(TYPE_REMOTE_TV);
         availableRoutes.add(availableInfo1);
 
         final MediaRoute2Info availableInfo2 = mock(MediaRoute2Info.class);
         when(availableInfo2.getId()).thenReturn(TEST_ID_3);
-        when(availableInfo2.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+        when(availableInfo2.getClientPackageName()).thenReturn(packageName);
         availableRoutes.add(availableInfo2);
 
         final MediaRoute2Info availableInfo3 = mock(MediaRoute2Info.class);
         when(availableInfo3.getId()).thenReturn(TEST_ID_4);
-        when(availableInfo3.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+        when(availableInfo3.getClientPackageName()).thenReturn(packageName);
         availableRoutes.add(availableInfo3);
 
-        when(mRouterManager.getAvailableRoutes(TEST_PACKAGE_NAME)).thenReturn(
+        when(mRouterManager.getAvailableRoutes(packageName)).thenReturn(
                 availableRoutes);
 
         return availableRoutes;
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index fe90caf..0aa121d 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -913,8 +913,9 @@
                   android:excludeFromRecents="true"
                   android:launchMode="singleInstance"
                   android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
-                  android:visibleToInstantApps="true">
-        </activity>
+                  android:visibleToInstantApps="true"
+                  android:exported="true"
+                  />
 
         <activity android:name=".controls.management.ControlsEditingActivity"
                   android:label="@string/controls_menu_edit"
@@ -947,8 +948,9 @@
                   android:finishOnTaskLaunch="true"
                   android:launchMode="singleInstance"
                   android:configChanges="screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden|orientation"
-                  android:visibleToInstantApps="true">
-        </activity>
+                  android:visibleToInstantApps="true"
+                  android:exported="true"
+                  />
 
         <activity android:name=".wallet.ui.WalletActivity"
                   android:label="@string/wallet_title"
@@ -994,7 +996,6 @@
             android:name=".notetask.shortcut.LaunchNoteTaskActivity"
             android:exported="true"
             android:excludeFromRecents="true"
-            android:resizeableActivity="false"
             android:theme="@android:style/Theme.NoDisplay" >
 
             <intent-filter>
@@ -1010,7 +1011,6 @@
             android:exported="false"
             android:enabled="true"
             android:excludeFromRecents="true"
-            android:resizeableActivity="false"
             android:theme="@android:style/Theme.NoDisplay" />
 
         <activity
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-de/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-de/strings.xml
index fb31e1d..9d9b05a 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-de/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-de/strings.xml
@@ -2,7 +2,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="accessibility_menu_service_name" msgid="730136711554740131">"Menü für Bedienungshilfen"</string>
-    <string name="accessibility_menu_intro" msgid="3164193281544042394">"Über das Menü „Bedienungshilfen“ lässt sich ein großes Menü zur Bedienung deines Geräts auf dem Bildschirm öffnen. Du kannst beispielsweise das Gerät sperren, die Lautstärke und Helligkeit anpassen und Screenshots machen."</string>
+    <string name="accessibility_menu_intro" msgid="3164193281544042394">"Über das Menü für Bedienungshilfen lässt sich ein großes Menü zur Bedienung deines Geräts auf dem Bildschirm öffnen. Du kannst beispielsweise das Gerät sperren, die Lautstärke und Helligkeit anpassen und Screenshots machen."</string>
     <string name="assistant_label" msgid="6796392082252272356">"Assistant"</string>
     <string name="assistant_utterance" msgid="65509599221141377">"Assistant"</string>
     <string name="a11y_settings_label" msgid="3977714687248445050">"Einstellungen für Bedienungshilfen"</string>
@@ -20,9 +20,9 @@
     <string name="brightness_down_label" msgid="7115662941913272072">"Helligkeit verringern"</string>
     <string name="previous_button_content_description" msgid="840869171117765966">"Zum vorherigen Bildschirm"</string>
     <string name="next_button_content_description" msgid="6810058269847364406">"Zum nächsten Bildschirm"</string>
-    <string name="accessibility_menu_description" msgid="4458354794093858297">"Über das Menü „Bedienungshilfen“ lässt sich ein großes Menü zur Bedienung deines Geräts auf dem Bildschirm öffnen. Du kannst beispielsweise das Gerät sperren, die Lautstärke und Helligkeit anpassen und Screenshots machen."</string>
+    <string name="accessibility_menu_description" msgid="4458354794093858297">"Über das Menü für Bedienungshilfen lässt sich ein großes Menü zur Bedienung deines Geräts auf dem Bildschirm öffnen. Du kannst beispielsweise das Gerät sperren, die Lautstärke und Helligkeit anpassen und Screenshots machen."</string>
     <string name="accessibility_menu_summary" msgid="340071398148208130">"Gerät mit großem Menü steuern"</string>
-    <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Menüeinstellungen f. Bedienungshilfen"</string>
+    <string name="accessibility_menu_settings_name" msgid="1716888058785672611">"Einstellungen für das Menü „Bedienungshilfen“"</string>
     <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"Große Schaltflächen"</string>
     <string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"Schaltflächen für das Menü „Bedienungshilfen“ vergrößern"</string>
     <string name="pref_help_title" msgid="6871558837025010641">"Hilfe"</string>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-kk/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-kk/strings.xml
index 9726f20..48c2634 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-kk/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-kk/strings.xml
@@ -11,7 +11,7 @@
     <string name="recent_apps_label" msgid="6583276995616385847">"Соңғы қолданбалар"</string>
     <string name="lockscreen_label" msgid="648347953557887087">"Құлып экраны"</string>
     <string name="quick_settings_label" msgid="2999117381487601865">"Жылдам параметрлер"</string>
-    <string name="notifications_label" msgid="6829741046963013567">"Хабарланды00ADрулар"</string>
+    <string name="notifications_label" msgid="6829741046963013567">"Хабарланды­рулар"</string>
     <string name="screenshot_label" msgid="863978141223970162">"Скриншот"</string>
     <string name="screenshot_utterance" msgid="1430760563401895074">"Скриншот жасау"</string>
     <string name="volume_up_label" msgid="8592766918780362870">"Дыбысын арттыру"</string>
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
index 83e44b6..7e1bfb9 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
@@ -18,6 +18,7 @@
 
 import android.graphics.fonts.Font
 import android.graphics.fonts.FontVariationAxis
+import android.util.Log
 import android.util.LruCache
 import android.util.MathUtils
 import android.util.MathUtils.abs
@@ -114,6 +115,9 @@
         tmpInterpKey.set(start, end, progress)
         val cachedFont = interpCache[tmpInterpKey]
         if (cachedFont != null) {
+            if (DEBUG) {
+                Log.d(LOG_TAG, "[$progress] Interp. cache hit for $tmpInterpKey")
+            }
             return cachedFont
         }
 
@@ -159,6 +163,9 @@
         val axesCachedFont = verFontCache[tmpVarFontKey]
         if (axesCachedFont != null) {
             interpCache.put(InterpKey(start, end, progress), axesCachedFont)
+            if (DEBUG) {
+                Log.d(LOG_TAG, "[$progress] Axis cache hit for $tmpVarFontKey")
+            }
             return axesCachedFont
         }
 
@@ -168,6 +175,9 @@
         val newFont = Font.Builder(start).setFontVariationSettings(newAxes.toTypedArray()).build()
         interpCache.put(InterpKey(start, end, progress), newFont)
         verFontCache.put(VarFontKey(start, newAxes), newFont)
+        if (DEBUG) {
+            Log.d(LOG_TAG, "[$progress] Cache MISS for $tmpInterpKey / $tmpVarFontKey")
+        }
         return newFont
     }
 
@@ -233,6 +243,8 @@
         (v.coerceIn(min, max) / step).toInt() * step
 
     companion object {
+        private const val LOG_TAG = "FontInterpolator"
+        private val DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG)
         private val EMPTY_AXES = arrayOf<FontVariationAxis>()
 
         // Returns true if given two font instance can be interpolated.
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
index 0010894..16ddf0c 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
@@ -26,6 +26,7 @@
 import android.graphics.fonts.FontVariationAxis
 import android.text.Layout
 import android.util.LruCache
+import kotlin.math.roundToInt
 
 private const val DEFAULT_ANIMATION_DURATION: Long = 300
 private const val TYPEFACE_CACHE_MAX_ENTRIES = 5
@@ -63,9 +64,9 @@
             return it
         }
 
-        return TypefaceVariantCache
-            .createVariantTypeface(baseTypeface, fvar)
-            .also { cache.put(fvar, it) }
+        return TypefaceVariantCache.createVariantTypeface(baseTypeface, fvar).also {
+            cache.put(fvar, it)
+        }
     }
 }
 
@@ -74,7 +75,6 @@
  *
  * Currently this class can provide text style animation for text weight and text size. For example
  * the simple view that draws text with animating text size is like as follows:
- *
  * <pre> <code>
  * ```
  *     class SimpleTextAnimation : View {
@@ -97,6 +97,7 @@
  */
 class TextAnimator(
     layout: Layout,
+    numberOfAnimationSteps: Int? = null, // Only do this number of discrete animation steps.
     private val invalidateCallback: () -> Unit,
 ) {
     var typefaceCache: TypefaceVariantCache = TypefaceVariantCacheImpl(layout.paint.typeface)
@@ -112,7 +113,8 @@
         ValueAnimator.ofFloat(1f).apply {
             duration = DEFAULT_ANIMATION_DURATION
             addUpdateListener {
-                textInterpolator.progress = it.animatedValue as Float
+                textInterpolator.progress =
+                    calculateProgress(it.animatedValue as Float, numberOfAnimationSteps)
                 invalidateCallback()
             }
             addListener(
@@ -123,6 +125,17 @@
             )
         }
 
+    private fun calculateProgress(animProgress: Float, numberOfAnimationSteps: Int?): Float {
+        if (numberOfAnimationSteps != null) {
+            // This clamps the progress to the nearest value of "numberOfAnimationSteps"
+            // discrete values between 0 and 1f.
+            return (animProgress * numberOfAnimationSteps).roundToInt() /
+                numberOfAnimationSteps.toFloat()
+        }
+
+        return animProgress
+    }
+
     sealed class PositionedGlyph {
 
         /** Mutable X coordinate of the glyph position relative from drawing offset. */
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
index 89871fa7..2cd587f 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
@@ -56,7 +56,19 @@
     val easeOutDuration: Float = DEFAULT_EASING_DURATION_IN_MILLIS,
     val pixelDensity: Float = 1f,
     val blendMode: BlendMode = DEFAULT_BLEND_MODE,
-    val onAnimationEnd: Runnable? = null
+    val onAnimationEnd: Runnable? = null,
+    /**
+     * Variants in noise. Higher number means more contrast; lower number means less contrast but
+     * make the noise dimmed. You may want to increase the [lumaMatteBlendFactor] to compensate.
+     * Expected range [0, 1].
+     */
+    val lumaMatteBlendFactor: Float = DEFAULT_LUMA_MATTE_BLEND_FACTOR,
+    /**
+     * Offset for the overall brightness in noise. Higher number makes the noise brighter. You may
+     * want to use this if you have made the noise softer using [lumaMatteBlendFactor]. Expected
+     * range [0, 1].
+     */
+    val lumaMatteOverallBrightness: Float = DEFAULT_LUMA_MATTE_OVERALL_BRIGHTNESS
 ) {
     companion object {
         const val DEFAULT_MAX_DURATION_IN_MILLIS = 30_000f // Max 30 sec
@@ -66,6 +78,8 @@
         const val DEFAULT_NOISE_SPEED_Z = 0.3f
         const val DEFAULT_OPACITY = 150 // full opacity is 255.
         const val DEFAULT_COLOR = Color.WHITE
+        const val DEFAULT_LUMA_MATTE_BLEND_FACTOR = 1f
+        const val DEFAULT_LUMA_MATTE_OVERALL_BRIGHTNESS = 0f
         const val DEFAULT_BACKGROUND_COLOR = Color.BLACK
         val DEFAULT_BLEND_MODE = BlendMode.SRC_OVER
     }
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
index d1ba7c4..d3c57c9 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
@@ -37,6 +37,8 @@
             uniform float in_opacity;
             uniform float in_pixelDensity;
             uniform float in_inverseLuma;
+            uniform half in_lumaMatteBlendFactor;
+            uniform half in_lumaMatteOverallBrightness;
             layout(color) uniform vec4 in_color;
             layout(color) uniform vec4 in_backgroundColor;
         """
@@ -48,18 +50,21 @@
                 uv.x *= in_aspectRatio;
 
                 vec3 noiseP = vec3(uv + in_noiseMove.xy, in_noiseMove.z) * in_gridNum;
-                float luma = abs(in_inverseLuma - simplex3d(noiseP)) * in_opacity;
+                // Bring it to [0, 1] range.
+                float luma = (simplex3d(noiseP) * in_inverseLuma) * 0.5 + 0.5;
+                luma = saturate(luma * in_lumaMatteBlendFactor + in_lumaMatteOverallBrightness)
+                        * in_opacity;
                 vec3 mask = maskLuminosity(in_color.rgb, luma);
                 vec3 color = in_backgroundColor.rgb + mask * 0.6;
 
-                // Add dither with triangle distribution to avoid color banding. Ok to dither in the
+                // Add dither with triangle distribution to avoid color banding. Dither in the
                 // shader here as we are in gamma space.
                 float dither = triangleNoise(p * in_pixelDensity) / 255.;
 
                 // The result color should be pre-multiplied, i.e. [R*A, G*A, B*A, A], thus need to
                 // multiply rgb with a to get the correct result.
-                color = (color + dither.rrr) * in_color.a;
-                return vec4(color, in_color.a);
+                color = (color + dither.rrr) * in_opacity;
+                return vec4(color, in_opacity);
             }
         """
 
@@ -70,12 +75,15 @@
                 uv.x *= in_aspectRatio;
 
                 vec3 noiseP = vec3(uv + in_noiseMove.xy, in_noiseMove.z) * in_gridNum;
-                float luma = abs(in_inverseLuma - simplex3d_fractal(noiseP)) * in_opacity;
+                // Bring it to [0, 1] range.
+                float luma = (simplex3d_fractal(noiseP) * in_inverseLuma) * 0.5 + 0.5;
+                luma = saturate(luma * in_lumaMatteBlendFactor + in_lumaMatteOverallBrightness)
+                        * in_opacity;
                 vec3 mask = maskLuminosity(in_color.rgb, luma);
                 vec3 color = in_backgroundColor.rgb + mask * 0.6;
 
                 // Skip dithering.
-                return vec4(color * in_color.a, in_color.a);
+                return vec4(color * in_opacity, in_opacity);
             }
         """
 
@@ -125,6 +133,28 @@
     }
 
     /**
+     * Sets blend and brightness factors of the luma matte.
+     *
+     * @param lumaMatteBlendFactor increases or decreases the amount of variance in noise. Setting
+     *   this a lower number removes variations. I.e. the turbulence noise will look more blended.
+     *   Expected input range is [0, 1]. more dimmed.
+     * @param lumaMatteOverallBrightness adds the overall brightness of the turbulence noise.
+     *   Expected input range is [0, 1].
+     *
+     * Example usage: You may want to apply a small number to [lumaMatteBlendFactor], such as 0.2,
+     * which makes the noise look softer. However it makes the overall noise look dim, so you want
+     * offset something like 0.3 for [lumaMatteOverallBrightness] to bring back its overall
+     * brightness.
+     */
+    fun setLumaMatteFactors(
+        lumaMatteBlendFactor: Float = 1f,
+        lumaMatteOverallBrightness: Float = 0f
+    ) {
+        setFloatUniform("in_lumaMatteBlendFactor", lumaMatteBlendFactor)
+        setFloatUniform("in_lumaMatteOverallBrightness", lumaMatteOverallBrightness)
+    }
+
+    /**
      * Sets whether to inverse the luminosity of the noise.
      *
      * By default noise will be used as a luma matte as is. This means that you will see color in
@@ -132,7 +162,7 @@
      * true.
      */
     fun setInverseNoiseLuminosity(inverse: Boolean) {
-        setFloatUniform("in_inverseLuma", if (inverse) 1f else 0f)
+        setFloatUniform("in_inverseLuma", if (inverse) -1f else 1f)
     }
 
     /** Current noise movements in x, y, and z axes. */
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
index c3e8478..43d6504 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
@@ -215,10 +215,12 @@
         noiseConfig = config
         with(turbulenceNoiseShader) {
             setGridCount(config.gridCount)
-            setColor(ColorUtils.setAlphaComponent(config.color, config.opacity))
+            setColor(config.color)
             setBackgroundColor(config.backgroundColor)
             setSize(config.width, config.height)
             setPixelDensity(config.pixelDensity)
+            setInverseNoiseLuminosity(inverse = false)
+            setLumaMatteFactors(config.lumaMatteBlendFactor, config.lumaMatteOverallBrightness)
         }
         paint.blendMode = config.blendMode
     }
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
index 465b73e..648ef03 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
@@ -74,7 +74,8 @@
     private var onTextAnimatorInitialized: Runnable? = null
 
     @VisibleForTesting var textAnimatorFactory: (Layout, () -> Unit) -> TextAnimator =
-        { layout, invalidateCb -> TextAnimator(layout, invalidateCb) }
+        { layout, invalidateCb ->
+            TextAnimator(layout, NUM_CLOCK_FONT_ANIMATION_STEPS, invalidateCb) }
     @VisibleForTesting var isAnimationEnabled: Boolean = true
     @VisibleForTesting var timeOverrideInMillis: Long? = null
 
@@ -567,6 +568,7 @@
         private const val CHARGE_ANIM_DURATION_PHASE_0: Long = 500
         private const val CHARGE_ANIM_DURATION_PHASE_1: Long = 1000
         private const val COLOR_ANIM_DURATION: Long = 400
+        private const val NUM_CLOCK_FONT_ANIMATION_STEPS = 30
 
         // Constants for the animation
         private val MOVE_INTERPOLATOR = Interpolators.EMPHASIZED
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index 0e20444..8cba2ab 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -48,6 +48,18 @@
 import kotlinx.coroutines.withContext
 
 private val KEY_TIMESTAMP = "appliedTimestamp"
+private val KNOWN_PLUGINS =
+    mapOf<String, List<ClockMetadata>>(
+        "com.android.systemui.falcon.one" to listOf(ClockMetadata("ANALOG_CLOCK_BIGNUM")),
+        "com.android.systemui.falcon.two" to listOf(ClockMetadata("DIGITAL_CLOCK_CALLIGRAPHY")),
+        "com.android.systemui.falcon.three" to listOf(ClockMetadata("DIGITAL_CLOCK_FLEX")),
+        "com.android.systemui.falcon.four" to listOf(ClockMetadata("DIGITAL_CLOCK_GROWTH")),
+        "com.android.systemui.falcon.five" to listOf(ClockMetadata("DIGITAL_CLOCK_HANDWRITTEN")),
+        "com.android.systemui.falcon.six" to listOf(ClockMetadata("DIGITAL_CLOCK_INFLATE")),
+        "com.android.systemui.falcon.seven" to listOf(ClockMetadata("DIGITAL_CLOCK_METRO")),
+        "com.android.systemui.falcon.eight" to listOf(ClockMetadata("DIGITAL_CLOCK_NUMBEROVERLAP")),
+        "com.android.systemui.falcon.nine" to listOf(ClockMetadata("DIGITAL_CLOCK_WEATHER")),
+    )
 
 private fun <TKey, TVal> ConcurrentHashMap<TKey, TVal>.concurrentGetOrPut(
     key: TKey,
@@ -127,8 +139,61 @@
 
     private val pluginListener =
         object : PluginListener<ClockProviderPlugin> {
-            override fun onPluginAttached(manager: PluginLifecycleManager<ClockProviderPlugin>) {
-                manager.loadPlugin()
+            override fun onPluginAttached(
+                manager: PluginLifecycleManager<ClockProviderPlugin>
+            ): Boolean {
+                if (keepAllLoaded) {
+                    // Always load new plugins if requested
+                    return true
+                }
+
+                val knownClocks = KNOWN_PLUGINS.get(manager.getPackage())
+                if (knownClocks == null) {
+                    logBuffer.tryLog(
+                        TAG,
+                        LogLevel.WARNING,
+                        { str1 = manager.getPackage() },
+                        { "Loading unrecognized clock package: $str1" }
+                    )
+                    return true
+                }
+
+                logBuffer.tryLog(
+                    TAG,
+                    LogLevel.INFO,
+                    { str1 = manager.getPackage() },
+                    { "Skipping initial load of known clock package package: $str1" }
+                )
+
+                var isClockListChanged = false
+                for (metadata in knownClocks) {
+                    val id = metadata.clockId
+                    val info =
+                        availableClocks.concurrentGetOrPut(id, ClockInfo(metadata, null, manager)) {
+                            isClockListChanged = true
+                            onConnected(id)
+                        }
+
+                    if (manager != info.manager) {
+                        logBuffer.tryLog(
+                            TAG,
+                            LogLevel.ERROR,
+                            { str1 = id },
+                            { "Clock Id conflict on known attach: $str1 is double registered" }
+                        )
+                        continue
+                    }
+
+                    info.provider = null
+                }
+
+                if (isClockListChanged) {
+                    triggerOnAvailableClocksChanged()
+                }
+                verifyLoadedProviders()
+
+                // Load executed via verifyLoadedProviders
+                return false
             }
 
             override fun onPluginLoaded(
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderClient.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderClient.kt
index cd9fb88..e050604 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderClient.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderClient.kt
@@ -148,11 +148,11 @@
          */
         val isEnabled: Boolean = true,
         /**
-         * If the affordance is disabled, this is a set of instruction messages to be shown to the
-         * user when the disabled affordance is selected. The instructions should help the user
-         * figure out what to do in order to re-neable this affordance.
+         * If the affordance is disabled, this is the explanation to be shown to the user when the
+         * disabled affordance is selected. The instructions should help the user figure out what to
+         * do in order to re-neable this affordance.
          */
-        val enablementInstructions: List<String>? = null,
+        val enablementExplanation: String? = null,
         /**
          * If the affordance is disabled, this is a label for a button shown together with the set
          * of instruction messages when the disabled affordance is selected. The button should help
@@ -163,15 +163,14 @@
          */
         val enablementActionText: String? = null,
         /**
-         * If the affordance is disabled, this is a "component name" of the format
-         * `packageName/action` to be used as an `Intent` for `startActivity` when the action button
-         * (shown together with the set of instruction messages when the disabled affordance is
-         * selected) is clicked by the user. The button should help send the user to a flow that
-         * would help them achieve the instructions and re-enable this affordance.
+         * If the affordance is disabled, this is an [Intent] to be used with `startActivity` when
+         * the action button (shown together with the set of instruction messages when the disabled
+         * affordance is selected) is clicked by the user. The button should help send the user to a
+         * flow that would help them achieve the instructions and re-enable this affordance.
          *
          * If `null`, the button should not be shown.
          */
-        val enablementActionComponentName: String? = null,
+        val enablementActionIntent: Intent? = null,
         /** Optional [Intent] to use to start an activity to configure this affordance. */
         val configureIntent: Intent? = null,
     )
@@ -327,20 +326,20 @@
                                 Contract.LockScreenQuickAffordances.AffordanceTable.Columns
                                     .IS_ENABLED
                             )
-                        val enablementInstructionsColumnIndex =
+                        val enablementExplanationColumnIndex =
                             cursor.getColumnIndex(
                                 Contract.LockScreenQuickAffordances.AffordanceTable.Columns
-                                    .ENABLEMENT_INSTRUCTIONS
+                                    .ENABLEMENT_EXPLANATION
                             )
                         val enablementActionTextColumnIndex =
                             cursor.getColumnIndex(
                                 Contract.LockScreenQuickAffordances.AffordanceTable.Columns
                                     .ENABLEMENT_ACTION_TEXT
                             )
-                        val enablementComponentNameColumnIndex =
+                        val enablementActionIntentColumnIndex =
                             cursor.getColumnIndex(
                                 Contract.LockScreenQuickAffordances.AffordanceTable.Columns
-                                    .ENABLEMENT_COMPONENT_NAME
+                                    .ENABLEMENT_ACTION_INTENT
                             )
                         val configureIntentColumnIndex =
                             cursor.getColumnIndex(
@@ -352,9 +351,9 @@
                                 nameColumnIndex == -1 ||
                                 iconColumnIndex == -1 ||
                                 isEnabledColumnIndex == -1 ||
-                                enablementInstructionsColumnIndex == -1 ||
+                                enablementExplanationColumnIndex == -1 ||
                                 enablementActionTextColumnIndex == -1 ||
-                                enablementComponentNameColumnIndex == -1 ||
+                                enablementActionIntentColumnIndex == -1 ||
                                 configureIntentColumnIndex == -1
                         ) {
                             return@buildList
@@ -368,21 +367,22 @@
                                     name = cursor.getString(nameColumnIndex),
                                     iconResourceId = cursor.getInt(iconColumnIndex),
                                     isEnabled = cursor.getInt(isEnabledColumnIndex) == 1,
-                                    enablementInstructions =
-                                        cursor
-                                            .getString(enablementInstructionsColumnIndex)
-                                            ?.split(
-                                                Contract.LockScreenQuickAffordances.AffordanceTable
-                                                    .ENABLEMENT_INSTRUCTIONS_DELIMITER
-                                            ),
+                                    enablementExplanation =
+                                        cursor.getString(enablementExplanationColumnIndex),
                                     enablementActionText =
                                         cursor.getString(enablementActionTextColumnIndex),
-                                    enablementActionComponentName =
-                                        cursor.getString(enablementComponentNameColumnIndex),
+                                    enablementActionIntent =
+                                        cursor
+                                            .getString(enablementActionIntentColumnIndex)
+                                            ?.toIntent(
+                                                affordanceId = affordanceId,
+                                            ),
                                     configureIntent =
                                         cursor
                                             .getString(configureIntentColumnIndex)
-                                            ?.toIntent(affordanceId = affordanceId),
+                                            ?.toIntent(
+                                                affordanceId = affordanceId,
+                                            ),
                                 )
                             )
                         }
@@ -524,7 +524,7 @@
         affordanceId: String,
     ): Intent? {
         return try {
-            Intent.parseUri(this, 0)
+            Intent.parseUri(this, Intent.URI_INTENT_SCHEME)
         } catch (e: URISyntaxException) {
             Log.w(TAG, "Cannot parse Uri into Intent for affordance with ID \"$affordanceId\"!")
             null
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
index f9e8aaf..b6d5ef3 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
@@ -81,8 +81,6 @@
             const val TABLE_NAME = "affordances"
             val URI: Uri =
                 LOCK_SCREEN_QUICK_AFFORDANCE_BASE_URI.buildUpon().appendPath(TABLE_NAME).build()
-            const val ENABLEMENT_INSTRUCTIONS_DELIMITER = "]["
-            const val COMPONENT_NAME_SEPARATOR = "/"
 
             object Columns {
                 /** String. Unique ID for this affordance. */
@@ -97,22 +95,21 @@
                 /** Integer. `1` if the affordance is enabled or `0` if it disabled. */
                 const val IS_ENABLED = "is_enabled"
                 /**
-                 * String. List of strings, delimited by [ENABLEMENT_INSTRUCTIONS_DELIMITER] to be
-                 * shown to the user if the affordance is disabled and the user selects the
-                 * affordance.
+                 * String. Text to be shown to the user if the affordance is disabled and the user
+                 * selects the affordance.
                  */
-                const val ENABLEMENT_INSTRUCTIONS = "enablement_instructions"
+                const val ENABLEMENT_EXPLANATION = "enablement_explanation"
                 /**
                  * String. Optional label for a button that, when clicked, opens a destination
                  * activity where the user can re-enable the disabled affordance.
                  */
                 const val ENABLEMENT_ACTION_TEXT = "enablement_action_text"
                 /**
-                 * String. Optional package name and activity action string, delimited by
-                 * [COMPONENT_NAME_SEPARATOR] to use with an `Intent` to start an activity that
-                 * opens a destination where the user can re-enable the disabled affordance.
+                 * String. Optional URI-formatted `Intent` (formatted using
+                 * `Intent#toUri(Intent.URI_INTENT_SCHEME)` used to start an activity that opens a
+                 * destination where the user can re-enable the disabled affordance.
                  */
-                const val ENABLEMENT_COMPONENT_NAME = "enablement_action_intent"
+                const val ENABLEMENT_ACTION_INTENT = "enablement_action_intent"
                 /**
                  * Byte array. Optional parcelled `Intent` to use to start an activity that can be
                  * used to configure the affordance.
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
index 3ae328e..537b7a4 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -190,7 +190,9 @@
 data class ClockMetadata(
     val clockId: ClockId,
     val name: String,
-)
+) {
+    constructor(clockId: ClockId) : this(clockId, clockId) {}
+}
 
 /** Render configuration for the full clock. Modifies the way systemUI behaves with this clock. */
 data class ClockConfig(
diff --git a/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/PluginLifecycleManager.java b/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/PluginLifecycleManager.java
index cc6a46f..56c3f93 100644
--- a/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/PluginLifecycleManager.java
+++ b/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/PluginLifecycleManager.java
@@ -16,12 +16,20 @@
 
 package com.android.systemui.plugins;
 
+import android.content.ComponentName;
+
 /**
  * Provides the ability for consumers to control plugin lifecycle.
  *
  * @param <T> is the target plugin type
  */
 public interface PluginLifecycleManager<T extends Plugin> {
+    /** Returns the ComponentName of the target plugin. Maybe be called when not loaded. */
+    ComponentName getComponentName();
+
+    /** Returns the package name of the target plugin. May be called when not loaded. */
+    String getPackage();
+
     /** Returns the currently loaded plugin instance (if plugin is loaded) */
     T getPlugin();
 
diff --git a/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/PluginListener.java b/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/PluginListener.java
index c5f5032..bd0bd89 100644
--- a/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/PluginListener.java
+++ b/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/PluginListener.java
@@ -60,13 +60,18 @@
 
     /**
      * Called when the plugin is first attached to the host application. {@link #onPluginLoaded}
-     * will be automatically called as well when first attached. This may be called multiple times
-     * if multiple plugins are allowed. It may also be called in the future if the plugin package
-     * changes and needs to be reloaded. Each call to {@link #onPluginAttached} will provide a new
-     * or different {@link PluginLifecycleManager}.
+     * will be automatically called as well when first attached if true is returned. This may be
+     * called multiple times if multiple plugins are allowed. It may also be called in the future
+     * if the plugin package changes and needs to be reloaded. Each call to
+     * {@link #onPluginAttached} will provide a new or different {@link PluginLifecycleManager}.
+     *
+     * @return returning true will immediately load the plugin and call onPluginLoaded with the
+     *   created object. false will skip loading, but the listener can load it at any time using the
+     *   provided PluginLifecycleManager. Loading plugins immediately is the default behavior.
      */
-    default void onPluginAttached(PluginLifecycleManager<T> manager) {
+    default boolean onPluginAttached(PluginLifecycleManager<T> manager) {
         // Optional
+        return true;
     }
 
     /**
diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml
index e8c7ef9..4df30dc 100644
--- a/packages/SystemUI/res-keyguard/values-th/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-th/strings.xml
@@ -117,7 +117,7 @@
     <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"ใช้รหัสผ่านแทนเพื่อเพิ่มความปลอดภัย"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ผู้ดูแลระบบล็อกอุปกรณ์"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"มีการล็อกอุปกรณ์ด้วยตัวเอง"</string>
-    <string name="kg_face_not_recognized" msgid="7903950626744419160">"ไม่รู้จัก"</string>
+    <string name="kg_face_not_recognized" msgid="7903950626744419160">"ไม่รู้จักลายนิ้วมือ"</string>
     <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"เปิดการเข้าถึงกล้องในการตั้งค่าเพื่อใช้การปลดล็อกด้วยใบหน้า"</string>
     <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{ป้อน PIN ของซิม คุณพยายามได้อีก # ครั้งก่อนที่จะต้องติดต่อผู้ให้บริการเพื่อปลดล็อกอุปกรณ์}other{ป้อน PIN ของซิม คุณลองได้อีก # ครั้ง}}"</string>
     <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{ตอนนี้ซิมถูกปิดใช้แล้ว ป้อนรหัส PUK เพื่อดำเนินการต่อ คุณพยายามได้อีก # ครั้งก่อนที่ซิมจะใช้งานไม่ได้อย่างถาวร โปรดติดต่อสอบถามรายละเอียดจากผู้ให้บริการ}other{ตอนนี้ซิมถูกปิดใช้แล้ว ป้อนรหัส PUK เพื่อดำเนินการต่อ คุณพยายามได้อีก # ครั้งก่อนที่ซิมจะใช้งานไม่ได้อย่างถาวร โปรดติดต่อสอบถามรายละเอียดจากผู้ให้บริการ}}"</string>
diff --git a/packages/SystemUI/res/drawable/stat_sys_ringer_silent.xml b/packages/SystemUI/res/drawable/stat_sys_ringer_silent.xml
index a8f0cc3..4a9d41f 100644
--- a/packages/SystemUI/res/drawable/stat_sys_ringer_silent.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_ringer_silent.xml
@@ -14,20 +14,6 @@
     limitations under the License.
 -->
 <inset xmlns:android="http://schemas.android.com/apk/res/android"
-        android:insetLeft="3dp"
-        android:insetRight="3dp">
-    <vector android:width="18dp"
-            android:height="18dp"
-            android:viewportWidth="24.0"
-            android:viewportHeight="24.0">
-        <path
-            android:fillColor="#FFFFFFFF"
-            android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4C10,21.1 10.9,22 12,22z"/>
-        <path
-            android:fillColor="#FFFFFFFF"
-            android:pathData="M16,16L2.81,2.81L1.39,4.22l4.85,4.85C6.09,9.68 6,10.33 6,11v6H4v2h12.17l3.61,3.61l1.41,-1.41L16,16zM8,17c0,0 0.01,-6.11 0.01,-6.16L14.17,17H8z"/>
-        <path
-            android:fillColor="#FFFFFFFF"
-            android:pathData="M12,6.5c2.49,0 4,2.02 4,4.5v2.17l2,2V11c0,-3.07 -1.63,-5.64 -4.5,-6.32V4c0,-0.83 -0.67,-1.5 -1.5,-1.5S10.5,3.17 10.5,4v0.68C9.72,4.86 9.05,5.2 8.46,5.63L9.93,7.1C10.51,6.73 11.2,6.5 12,6.5z"/>
-    </vector>
-</inset>
+    android:insetLeft="3dp"
+    android:insetRight="3dp"
+    android:drawable="@drawable/ic_speaker_mute" />
diff --git a/packages/SystemUI/res/layout/auth_biometric_contents.xml b/packages/SystemUI/res/layout/auth_biometric_contents.xml
index 8169189..efc661a 100644
--- a/packages/SystemUI/res/layout/auth_biometric_contents.xml
+++ b/packages/SystemUI/res/layout/auth_biometric_contents.xml
@@ -55,13 +55,7 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center">
 
-        <com.airbnb.lottie.LottieAnimationView
-            android:id="@+id/biometric_icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:contentDescription="@null"
-            android:scaleType="fitXY" />
+        <include layout="@layout/auth_biometric_icon"/>
 
         <com.airbnb.lottie.LottieAnimationView
             android:id="@+id/biometric_icon_overlay"
diff --git a/packages/SystemUI/res/layout/auth_biometric_icon.xml b/packages/SystemUI/res/layout/auth_biometric_icon.xml
new file mode 100644
index 0000000..b2df63d
--- /dev/null
+++ b/packages/SystemUI/res/layout/auth_biometric_icon.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+
+<com.airbnb.lottie.LottieAnimationView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/biometric_icon"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:contentDescription="@null"
+    android:scaleType="fitXY"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 7cf93eb..cd56b8f 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Gesig is gestaaf"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bevestig"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tik op Bevestig om te voltooi"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Ontsluit met gesig."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ontsluit met gesig. Druk om voort te gaan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gesig is herken. Druk om voort te gaan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gesig is herken. Druk die ontsluitikoon om voort te gaan."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kan nie stoor nie. Probeer weer."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kan nie stoor nie."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gebruik minstens 4 karakters"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gebruik minder as 16 karakters"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Bounommer"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Bounommer is na knipbord gekopieer."</string>
     <string name="basic_status" msgid="2315371112182658176">"Maak gesprek oop"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index af07b4a..e754e25f 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"መልክ ተረጋግጧል"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ተረጋግጧል"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ለማጠናቀቅ አረጋግጥን መታ ያድርጉ"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"በመልክ ተከፍቷል።"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"በመልክ ተከፍቷል። ለመቀጠል ይጫኑ።"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"መልክ ተለይቶ ታውቋል። ለመቀጠል ይጫኑ።"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"መልክ ተለይቶ ታውቋል። ለመቀጠል የመክፈቻ አዶውን ይጫኑ።"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ማስቀመጥ አልተቻለም። እንደገና ይሞክሩ።"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ማስቀመጥ አልተቻለም።"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ቢያንስ 4 ቁምፊዎችን ይጠቀሙ"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"ከ16 የሚያንሱ ቁምፊዎችን ይጠቀሙ"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"የግንብ ቁጥር"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"የገንባ ቁጥር ወደ ቅንጥብ ሰሌዳ ተቀድቷል።"</string>
     <string name="basic_status" msgid="2315371112182658176">"ውይይት ይክፈቱ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 6584363..d378aa8 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"تمّت مصادقة الوجه."</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تمّ التأكيد."</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"يمكنك النقر على \"تأكيد\" لإكمال المهمة."</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"تم فتح قفل جهازك عند تقريبه من وجهك."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"تم فتح قفل جهازك عند تقريبه من وجهك. اضغط للمتابعة."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"تم التعرّف على الوجه. اضغط للمتابعة."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"تم التعرّف على الوجه. للمتابعة، اضغط على رمز فتح القفل."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"لا يمكن إجراء الحفظ. يُرجى إعادة المحاولة."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"لا يمكن إجراء الحفظ."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"يجب استخدام 4 أحرف على الأقل."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"يجب أن يحتوي الرمز على أقل من 16 حرفًا."</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"رقم الإصدار"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"تم نسخ رقم الإصدار إلى الحافظة."</string>
     <string name="basic_status" msgid="2315371112182658176">"محادثة مفتوحة"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 1c51918..5f176ae 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"মুখমণ্ডলৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"নিশ্চিত কৰিলে"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"সম্পূৰ্ণ কৰিবলৈ নিশ্চিত কৰক-ত টিপক"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা।"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা হৈছে। অব্যাহত ৰাখিবলৈ টিপক।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। অব্যাহত ৰাখিবলৈ টিপক।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। অব্যাহত ৰাখিবলৈ আনলক কৰক চিহ্নটোত টিপক।"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ছেভ কৰিব নোৱাৰি। পুনৰ চেষ্টা কৰক।"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ছেভ কৰিব নোৱাৰি।"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"অতি কমেও ৪ টা বৰ্ণ ব্যৱহাৰ কৰক"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"১৬ টাতকৈ কম বৰ্ণ ব্যৱহাৰ কৰক"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"বিল্ডৰ নম্বৰ"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"ক্লিপব’ৰ্ডলৈ বিল্ডৰ নম্বৰ প্ৰতিলিপি কৰা হ’ল।"</string>
     <string name="basic_status" msgid="2315371112182658176">"বাৰ্তালাপ খোলক"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 74b4382..fcd433a 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Üz doğrulandı"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Təsdiqləndi"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tamamlamaq üçün \"Təsdiq edin\" seçiminə toxunun"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Üz ilə kiliddən çıxarılıb."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Üz ilə kiliddən çıxarılıb. Davam etmək üçün basın."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Üz tanınıb. Davam etmək üçün basın."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Üz tanınıb. \"Kiliddən çıxar\" ikonasına basıb davam edin."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Yadda saxlamaq mümkün deyil. Yenə cəhd edin."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Yadda saxlamaq mümkün deyil."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Ən azı 4 simvoldan istifadə edin"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Maksimum 16 simvoldan istifadə edin"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Montaj nömrəsi"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Versiya nömrəsi mübadilə buferinə kopyalandı."</string>
     <string name="basic_status" msgid="2315371112182658176">"Açıq söhbət"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 7d87c87..d37c709 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Lice je potvrđeno"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi da biste završili"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Otključano je licem."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Otključano je licem. Pritisnite da biste nastavili."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice je prepoznato. Pritisnite da biste nastavili."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice prepoznato. Pritisnite ikonu otključavanja za nastavak."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Čuvanje nije uspelo. Probajte ponovo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Čuvanje nije uspelo."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Koristite bar 4 znaka"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Koristite manje od 16 znakova"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Broj verzije je kopiran u privremenu memoriju."</string>
     <string name="basic_status" msgid="2315371112182658176">"Otvorite konverzaciju"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 1576fb5..518c5e6 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -142,7 +142,7 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Твар распазнаны"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Пацверджана"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Націсніце \"Пацвердзіць\", каб завяршыць"</string>
-    <!-- no translation found for biometric_dialog_tap_confirm_with_face (3783056044917913453) -->
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
     <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Разблакіравана распазнаваннем твару. Націсніце для працягу."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Твар распазнаны. Націсніце для працягу."</string>
@@ -1004,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не ўдалося захаваць. Паўтарыце спробу."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не ўдалося захаваць."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Скарыстайце не менш як 4 сімвалы"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Скарыстайце менш за 16 сімвалаў"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Нумар зборкі"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Нумар зборкі скапіраваны ў буфер абмену."</string>
     <string name="basic_status" msgid="2315371112182658176">"Адкрытая размова"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index a339744..96646ad 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лицето е удостоверено"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потвърдено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Докоснете „Потвърждаване“ за завършване"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Отключено с лице."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Отключено с лице. Натиснете, за да продължите."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицето бе разпознато. Натиснете, за да продължите."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицето бе разпознато. Продължете чрез иконата за отключване."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не може да се запази. Опитайте отново."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не може да се запази."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Използвайте поне 4 знака"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Използвайте по-малко от 16 знака"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер на компилацията"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Номерът на компилацията е копиран в буферната памет."</string>
     <string name="basic_status" msgid="2315371112182658176">"Отворен разговор"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 5209c18..a53baad 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ফেস যাচাই করা হয়েছে"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"কনফার্ম করা হয়েছে"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"সম্পূর্ণ করতে \'কনফার্ম করুন\' বোতামে ট্যাপ করুন"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"ফেসের সাহায্যে আনলক করা হয়েছে।"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ফেসের সাহায্যে আনলক করা হয়েছে। চালিয়ে যেতে প্রেস করুন।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ফেস শনাক্ত করা হয়েছে। চালিয়ে যেতে প্রেস করুন।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ফেস শনাক্ত করা হয়েছে। চালিয়ে যেতে আনলক আইকন প্রেস করুন।"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"সেভ করা যাচ্ছে না। আবার চেষ্টা করুন।"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"সেভ করা যাচ্ছে না।"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"কমপক্ষে ৪টি অক্ষর ব্যবহার করুন"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"১৬টির চেয়ে কম অক্ষর ব্যবহার করুন"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"বিল্ড নম্বর"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"বিল্ড নম্বর ক্লিপবোর্ডে কপি করা হয়েছে।"</string>
     <string name="basic_status" msgid="2315371112182658176">"খোলা কথোপকথন"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index dfe025d..00790b3 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Lice je provjereno"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi da završite"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Otključano je licem."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Otključano licem. Pritisnite da nastavite."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice prepoznato. Pritisnite da nastavite."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice prepoznato. Pritisnite ikonu za otklj. da nastavite."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nije moguće sačuvati. Pokušajte ponovo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nije moguće sačuvati."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Koristite najmanje 4 znaka"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Koristite manje od 16 znakova"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Broj verzije je kopiran u međumemoriju."</string>
     <string name="basic_status" msgid="2315371112182658176">"Otvoreni razgovor"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index a40073a1..74b557b 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Cara autenticada"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmat"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirma per completar"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"S\'ha desbloquejat amb la cara."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"S\'ha desbloquejat amb la cara. Prem per continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"S\'ha reconegut la cara. Prem per continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"S\'ha reconegut la cara. Prem la icona per continuar."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"No es pot desar. Torna-ho a provar."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"No es pot desar."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utilitza 4 caràcters com a mínim"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utilitza menys de 16 caràcters"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilació"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"El número de compilació s\'ha copiat al porta-retalls."</string>
     <string name="basic_status" msgid="2315371112182658176">"Conversa oberta"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 4271ccf..97bf39f 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Obličej byl ověřen"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrzeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ověření dokončíte klepnutím na Potvrdit"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Odemknuto obličejem."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odemknuto obličejem. Pokračujte stisknutím."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Obličej rozpoznán. Pokračujte stisknutím."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Obličej rozpoznán. Klepněte na ikonu odemknutí."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Uložení se nezdařilo. Zkuste to znovu."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Uložení se nezdařilo."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Heslo musí mít alespoň 4 znaky"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Použijte méně než 16 znaků"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo sestavení"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Číslo sestavení bylo zkopírováno do schránky."</string>
     <string name="basic_status" msgid="2315371112182658176">"Otevřít konverzaci"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 2c3e041..7388fbf 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ansigtet er godkendt"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekræftet"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tryk på Bekræft for at udføre"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Låst op ved hjælp af ansigt."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Låst op ved hjælp af ansigt. Tryk for at fortsætte."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansigt genkendt. Tryk for at fortsætte."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansigt genkendt. Tryk på oplåsningsikonet for at fortsætte."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Der kan ikke gemmes. Prøv igen."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Der kan ikke gemmes."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Angiv mindst 4 tegn"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Angiv højst 16 tegn"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildnummer"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Buildnummeret blev kopieret til udklipsholderen."</string>
     <string name="basic_status" msgid="2315371112182658176">"Åben samtale"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index ee7d4e5..7608509 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Gesicht authentifiziert"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bestätigt"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Zum Abschließen auf \"Bestätigen\" tippen"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Gerät per Gesichtserkennung entsperrt."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Gerät mit dem Gesicht entsperrt. Tippe, um fortzufahren."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gesicht erkannt. Tippe, um fortzufahren."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gesicht erkannt. Tippe zum Fortfahren auf das Symbol „Entsperren“."</string>
@@ -467,7 +468,7 @@
     <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Deine privaten Apps sind über <xliff:g id="VPN_APP">%1$s</xliff:g> mit dem Internet verbunden. Deine Netzwerkaktivitäten, einschließlich E-Mails und Browserdaten, sind für deinen VPN-Anbieter sichtbar."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"VPN-Einstellungen öffnen"</string>
-    <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Dieses Gerät wird von deinen Eltern verwaltet. Sie können unter anderem Informationen über deine genutzten Apps, deinen Standort und deine Gerätenutzungsdauer einsehen und verwalten."</string>
+    <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Dieses Gerät wird von deinen Eltern verwaltet. Sie können unter anderem Informationen über deine genutzten Apps, deinen Standort und deine Bildschirmzeit einsehen und verwalten."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Durch TrustAgent entsperrt"</string>
     <string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Speichern nicht möglich. Versuche es noch einmal."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Speichern nicht möglich."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gib mindestens vier Zeichen ein"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Maximal 16 Zeichen möglich"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build-Nummer"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Build-Nummer in Zwischenablage kopiert."</string>
     <string name="basic_status" msgid="2315371112182658176">"Offene Unterhaltung"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index da73c66..e418754 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Έγινε έλεγχος ταυτότητας προσώπου"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Επιβεβαιώθηκε"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Πατήστε Επιβεβαίωση για ολοκλήρωση"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Ξεκλειδώθηκε με αναγνώριση προσώπου."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ξεκλείδωμα με αναγνώριση προσώπου. Πατήστε για συνέχεια."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Το πρόσωπο αναγνωρίστηκε. Πατήστε για συνέχεια."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Το πρόσωπο αναγνωρ. Πατήστε το εικον. ξεκλειδ. για συνέχεια."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Δεν είναι δυνατή η αποθήκευση. Δοκιμάστε ξανά."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Δεν είναι δυνατή η αποθήκευση."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Χρησιμοποιήστε τουλάχιστον 4 χαρακτήρες"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Χρησιμοποιήστε λιγότερους από 16 χαρακτήρες"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Αριθμός έκδοσης"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Ο αριθμός έκδοσης αντιγράφηκε στο πρόχειρο."</string>
     <string name="basic_status" msgid="2315371112182658176">"Άνοιγμα συνομιλίας"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 2f8e3a4..524864a 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Unlocked by face."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string>
@@ -987,7 +988,7 @@
     <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Available devices for audio output."</string>
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
-    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers &amp; displays"</string>
+    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers and displays"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Suggested devices"</string>
     <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Stop your shared session to move media to another device"</string>
     <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Stop"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Can’t save. Try again."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Can’t save."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use at least four characters"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use fewer than 16 characters"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
     <string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index bcb1a99..d8971ba 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -142,7 +142,7 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Unlocked by face."</string>
+    <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Unlocked by face"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognized. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognized. Press the unlock icon to continue."</string>
@@ -1003,7 +1003,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Can’t save. Try again."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Can’t save."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use at least 4 characters"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use fewer than 16 characters"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
     <string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 2f8e3a4..524864a 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Unlocked by face."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string>
@@ -987,7 +988,7 @@
     <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Available devices for audio output."</string>
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
-    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers &amp; displays"</string>
+    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers and displays"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Suggested devices"</string>
     <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Stop your shared session to move media to another device"</string>
     <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Stop"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Can’t save. Try again."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Can’t save."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use at least four characters"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use fewer than 16 characters"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
     <string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 2f8e3a4..524864a 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Unlocked by face."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string>
@@ -987,7 +988,7 @@
     <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Available devices for audio output."</string>
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
-    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers &amp; displays"</string>
+    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers and displays"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Suggested devices"</string>
     <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Stop your shared session to move media to another device"</string>
     <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Stop"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Can’t save. Try again."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Can’t save."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use at least four characters"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use fewer than 16 characters"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
     <string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index b6c3bc3..368632b 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -142,7 +142,7 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‎‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎Face authenticated‎‏‎‎‏‎"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‎‎‏‏‏‎‎‎‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‏‎‎Confirmed‎‏‎‎‏‎"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‏‏‎‏‏‏‎‎‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‎‎Tap Confirm to complete‎‏‎‎‏‎"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‎‎‎‎‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‏‎Unlocked by face.‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‎‎‏‎‎‏‏‏‏‎‏‎‎‎‏‏‎‎Unlocked by face‎‏‎‎‏‎"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‎‎‎‏‎‏‏‏‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‎‎‏‎‎‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‎Unlocked by face. Press to continue.‎‏‎‎‏‎"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‎‎‎Face recognized. Press to continue.‎‏‎‎‏‎"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‏‏‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‎‎‏‎‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‎Face recognized. Press the unlock icon to continue.‎‏‎‎‏‎"</string>
@@ -1003,7 +1003,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‏‎‏‏‎‎‏‎Can’t save. Try again.‎‏‎‎‏‎"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‎‏‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‎‎‏‏‎Can’t save.‎‏‎‎‏‎"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‏‎‎‏‏‏‎‎‏‎Use at least 4 characters‎‏‎‎‏‎"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‎‏‎‎‎‏‎‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎Use fewer than 16 characters‎‏‎‎‏‎"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‎‎‎‎‎‏‏‏‎‎‎‎‎‎‏‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎Build number‎‏‎‎‏‎"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‎Build number copied to clipboard.‎‏‎‎‏‎"</string>
     <string name="basic_status" msgid="2315371112182658176">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‎‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‎‎‎‎‎Open conversation‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index d43515f..06647b7 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Se autenticó el rostro"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmado"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Presiona Confirmar para completar"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Se desbloqueó con rostro."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueo con rostro. Presiona para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rostro reconocido. Presiona para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rostro reconocido. Presiona el desbloqueo para continuar."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"No se puede guardar. Vuelve a intentarlo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"No se puede guardar."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Usa al menos 4 caracteres"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Usa menos de 16 caracteres"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Se copió el número de compilación en el portapapeles."</string>
     <string name="basic_status" msgid="2315371112182658176">"Conversación abierta"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 0acba5e..c6b8d50 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Cara autenticada"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirmar para completar la acción"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Desbloqueado con la cara."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado con la cara. Pulsa para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Cara reconocida. Pulsa para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Cara reconocida. Pulsa el icono de desbloquear para continuar."</string>
@@ -988,7 +989,7 @@
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volumen"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Altavoces y pantallas"</string>
-    <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Sugerencias de dispositivos"</string>
+    <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivos sugeridos"</string>
     <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Detén tu sesión compartida para transferir el contenido multimedia a otro dispositivo"</string>
     <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Detener"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cómo funciona la emisión"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"No se puede guardar. Inténtalo de nuevo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"No se puede guardar."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Usa 4 caracteres como mínimo"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Usa menos de 16 caracteres"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Número de compilación copiado en el portapapeles."</string>
     <string name="basic_status" msgid="2315371112182658176">"Conversación abierta"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index a51a085..bb9198e 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Nägu on autenditud"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Kinnitatud"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Lõpuleviimiseks puudutage nuppu Kinnita"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Avati näoga."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Avati näoga. Vajutage jätkamiseks."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Nägu tuvastati. Vajutage jätkamiseks."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Nägu tuvastati. Jätkamiseks vajutage avamise ikooni."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ei saa salvestada. Proovige uuesti."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ei saa salvestada."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Kasutage vähemalt 4 tähemärki"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Kasutage vähem kui 16 tähemärki"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Järgunumber"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Järgunumber kopeeriti lõikelauale."</string>
     <string name="basic_status" msgid="2315371112182658176">"Avage vestlus"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index e02f383..a24dfef 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Autentifikatu da aurpegia"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Berretsita"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Amaitzeko, sakatu \"Berretsi\""</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Aurpegiaren bidez desblokeatu da."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Aurpegiaren bidez desblokeatu da. Sakatu aurrera egiteko."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ezagutu da aurpegia. Sakatu aurrera egiteko."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ezagutu da aurpegia. Aurrera egiteko, sakatu desblokeatzeko ikonoa."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ezin da gorde. Saiatu berriro."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ezin da gorde."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Erabili lau karaktere gutxienez"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Erabili 16 karaktere baino gutxiago"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Konpilazio-zenbakia"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Kopiatu da konpilazio-zenbakia arbelean."</string>
     <string name="basic_status" msgid="2315371112182658176">"Elkarrizketa irekia"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 5c9115e..1b02905 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"چهره اصالت‌سنجی شد"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تأیید شد"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"برای تکمیل، روی تأیید ضربه بزنید"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"قفل با چهره باز شد."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"قفلْ با چهره باز شد. برای ادامه، فشار دهید."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"چهره شناسایی شد. برای ادامه، فشار دهید."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"چهره شناسایی شد. برای ادامه، نماد قفل‌گشایی را فشار دهید."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ذخیره نشد. دوباره امتحان کنید."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ذخیره نشد."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"حداقل از ۴ نویسه استفاده کنید"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"از کمتر از ۱۶ نویسه استفاده کنید"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"شماره ساخت"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"شماره ساخت در بریده‌دان کپی شد."</string>
     <string name="basic_status" msgid="2315371112182658176">"باز کردن مکالمه"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 7d4eb4e..91b074d 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Kasvot tunnistettu"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Vahvistettu"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Valitse lopuksi Vahvista"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Avattu kasvojen avulla."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Avattu kasvojen avulla. Jatka painamalla."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Kasvot tunnistettu. Jatka painamalla."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Kasvot tunnistettu. Jatka lukituksen avauskuvakkeella."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Tallennus ei onnistu. Yritä uudelleen."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Tallennus ei onnistu."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Käytä vähintään 4 merkkiä"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Käytä alle 16 merkkiä"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Koontiversion numero"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Koontiversion numero kopioitu leikepöydälle"</string>
     <string name="basic_status" msgid="2315371112182658176">"Avaa keskustelu"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 32b6a59..7d2d92a 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Visage authentifié"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmé"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Touchez Confirmer pour terminer"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Déverrouillé avec le visage."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Déverr. par reconnaissance faciale. Appuyez pour continuer."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Visage reconnu. Appuyez pour continuer."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Visage reconnu. Appuyez sur Déverrouiller pour continuer."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Impossible d\'enregistrer. Réessayez."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Impossible d\'enregistrer."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utilisez au moins 4 caractères"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utilisez moins de 16 caractères"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de version"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Le numéro de version a été copié dans le presse-papiers."</string>
     <string name="basic_status" msgid="2315371112182658176">"Ouvrir la conversation"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 1b0b7c8..496ae69 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Visage authentifié"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmé"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Appuyez sur \"Confirmer\" pour terminer"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Déverrouillé par le visage."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Déverrouillé par visage. Appuyez pour continuer."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Visage reconnu. Appuyez pour continuer."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Visage reconnu. Appuyez sur l\'icône de déverrouillage pour continuer."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Impossible d\'enregistrer. Réessayez."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Impossible d\'enregistrer."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utilisez au moins quatre caractères"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utilisez moins de 16 caractères"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de build"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Numéro de build copié dans le presse-papiers."</string>
     <string name="basic_status" msgid="2315371112182658176">"Conversation ouverte"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 8ab6596..bca8d51 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Autenticouse a cara"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirmar para completar o proceso"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Usouse o desbloqueo facial."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Usouse o desbloqueo facial. Preme para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Recoñeceuse a cara. Preme para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Recoñeceuse a cara. Preme a icona de desbloquear."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Non se puido gardar a información. Téntao de novo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Non se pode gardar a información."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utiliza como mínimo 4 caracteres"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utiliza menos de 16 caracteres"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Copiouse o número de compilación no portapapeis."</string>
     <string name="basic_status" msgid="2315371112182658176">"Conversa aberta"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 32f3c6e..8f86401 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ચહેરાનું પ્રમાણીકરણ થયું"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"પુષ્ટિ કરી"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"પરીક્ષણ પૂર્ણ કરવા કન્ફર્મ કરોને ટૅપ કરો"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"ચહેરા દ્વારા અનલૉક કર્યું."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ચહેરા દ્વારા અનલૉક કર્યું. આગળ વધવા માટે દબાવો."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ચહેરો ઓળખ્યો. આગળ વધવા માટે દબાવો."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ચહેરો ઓળખ્યો. આગળ વધવા \'અનલૉક કરો\' આઇકન દબાવો."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"સાચવી શકતા નથી. ફરી પ્રયાસ કરો."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"સાચવી શકતા નથી."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ઓછામાં ઓછા 4 અક્ષરનો ઉપયોગ કરો"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 કરતાં ઓછા અક્ષરનો ઉપયોગ કરો"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"બિલ્ડ નંબર"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"બિલ્ડ નંબર ક્લિપબૉર્ડ પર કૉપિ કર્યો."</string>
     <string name="basic_status" msgid="2315371112182658176">"વાતચીત ખોલો"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 885a77e..b2d4b88 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"चेहरे की पुष्टि हो गई"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"पुष्टि हो गई"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"\'पुष्टि करें\' पर टैप करके पूरा करें"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"चेहरे से अनलॉक किया गया."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"चेहरे से अनलॉक किया गया. जारी रखने के लिए टैप करें."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"चेहरे की पहचान हो गई. जारी रखने के लिए टैप करें."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"चेहरे की पहचान हो गई. जारी रखने के लिए अनलॉक आइकॉन को टैप करें."</string>
@@ -983,7 +984,7 @@
     <string name="media_output_dialog_pairing_new" msgid="5098212763195577270">"किसी डिवाइस को कनेक्ट करें"</string>
     <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"इस सेशन को कास्ट करने के लिए, कृपया ऐप्लिकेशन खोलें."</string>
     <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"अनजान ऐप्लिकेशन"</string>
-    <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"कास्टिंग करना रोकें"</string>
+    <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"कास्ट करना बंद करें"</string>
     <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"ऑडियो आउटपुट के लिए उपलब्ध डिवाइस."</string>
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"वॉल्यूम"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"सेव नहीं किया जा सका. फिर से कोशिश करें."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"सेव नहीं किया जा सका."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"कम से कम चार वर्ण इस्तेमाल करें"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 वर्ण से कम इस्तेमाल करें"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नंबर को क्लिपबोर्ड पर कॉपी किया गया."</string>
     <string name="basic_status" msgid="2315371112182658176">"ऐसी बातचीत जिसमें इंटरैक्शन डेटा मौजूद नहीं है"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 366785c..54d87f2 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Lice je autentificirano"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi za dovršetak"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Otključano licem."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Otključano pomoću lica. Pritisnite da biste nastavili."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice je prepoznato. Pritisnite da biste nastavili."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice je prepoznato. Pritisnite ikonu otključavanja da biste nastavili."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Spremanje nije uspjelo. Pokušajte ponovo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Spremanje nije uspjelo."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Upotrijebite barem četiri znaka"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Upotrijebite manje od 16 znakova"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj međuverzije"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Broj međuverzije kopiran je u međuspremnik."</string>
     <string name="basic_status" msgid="2315371112182658176">"Otvoreni razgovor"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 5e3f1ec..25b30a7 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Arc hitelesítve"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Megerősítve"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Koppintson a Megerősítés lehetőségre"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Zárolás arccal feloldva."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Zárolás arccal feloldva. Koppintson a folytatáshoz."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Arc felismerve. Koppintson a folytatáshoz."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Arc felismerve. A folytatáshoz koppintson a Feloldásra."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"A mentés nem sikerült. Próbálja újra."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"A mentés nem sikerült."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Legalább négy karaktert használjon"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Legfeljebb 16 karaktert használhat"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildszám"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Buildszám a vágólapra másolva."</string>
     <string name="basic_status" msgid="2315371112182658176">"Beszélgetés megnyitása"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 8dd835a..14326af 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Դեմքը ճանաչվեց"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Հաստատվեց"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ավարտելու համար հպեք «Հաստատել»"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Ապակողպվել է դեմքով։"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ապակողպվել է դեմքով։ Սեղմեք շարունակելու համար։"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Դեմքը ճանաչվեց։ Սեղմեք շարունակելու համար։"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Դեմքը ճանաչվեց։ Սեղմեք ապակողպման պատկերակը։"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Չհաջողվեց պահել։ Նորից փորձեք։"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Չհաջողվեց պահել։"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Օգտագործեք առնվազն 4 նիշ"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Օգտագործեք ոչ ավել քան 16 նիշ"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Կառուցման համարը"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Կառուցման համարը պատճենվեց սեղմատախտակին։"</string>
     <string name="basic_status" msgid="2315371112182658176">"Բաց զրույց"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index cb48312..f402df665 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Wajah diautentikasi"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Dikonfirmasi"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ketuk Konfirmasi untuk menyelesaikan"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Kunci dibuka dengan wajah."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Kunci dibuka dengan wajah. Tekan untuk melanjutkan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Wajah dikenali. Tekan untuk melanjutkan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Wajah dikenali. Tekan ikon buka kunci untuk melanjutkan."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Tidak dapat menyimpan. Coba lagi."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Tidak dapat menyimpan."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gunakan minimal 4 karakter"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gunakan kurang dari 16 karakter"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Nomor build"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Nomor versi disalin ke papan klip."</string>
     <string name="basic_status" msgid="2315371112182658176">"Membuka percakapan"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 3d17d8b..5b75507 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Andlit staðfest"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Staðfest"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ýttu á „Staðfesta“ til að ljúka"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Opnað með andliti."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Opnað með andliti. Ýttu til að halda áfram."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Andlitið var greint. Ýttu til að halda áfram."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Andlitið var greint. Ýttu á opnunartáknið til að halda áfr."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ekki hægt að vista. Reyndu aftur."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ekki hægt að vista."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Notaðu að minnsta kosti 4 stafi"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Notaðu færri en 16 stafi"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Útgáfunúmer smíðar"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Útgáfunúmer smíðar afritað á klippiborð."</string>
     <string name="basic_status" msgid="2315371112182658176">"Opna samtal"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index a2345e5..8937c21 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Volto autenticato"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confermato"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tocca Conferma per completare"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Sbloccato con il volto."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Sbloccato con il volto. Premi per continuare."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Volto riconosciuto. Premi per continuare."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Volto riconosciuto. Premi l\'icona Sblocca e continua."</string>
@@ -912,7 +913,7 @@
     <string name="controls_favorite_see_other_apps" msgid="7709087332255283460">"Mostra altre app"</string>
     <string name="controls_favorite_rearrange_button" msgid="2942788904364641185">"Riordina"</string>
     <string name="controls_favorite_add_controls" msgid="1221420435546694004">"Aggiungi controlli"</string>
-    <string name="controls_favorite_back_to_editing" msgid="184125114090062713">"Torna alle modifiche"</string>
+    <string name="controls_favorite_back_to_editing" msgid="184125114090062713">"Torna alla modifica"</string>
     <string name="controls_favorite_load_error" msgid="5126216176144877419">"Impossibile caricare i controlli. Verifica nell\'app <xliff:g id="APP">%s</xliff:g> che le relative impostazioni non siano cambiate."</string>
     <string name="controls_favorite_load_none" msgid="7687593026725357775">"Controlli compatibili non disponibili"</string>
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Altro"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Impossibile salvare. Riprova."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Impossibile salvare."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Usa almeno 4 caratteri"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Usa meno di 16 caratteri"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero build"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Numero build copiato negli appunti."</string>
     <string name="basic_status" msgid="2315371112182658176">"Apri conversazione"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 45387583..271001d 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"זיהוי הפנים בוצע"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"יש אישור"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"יש להקיש על \'אישור\' לסיום התהליך"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"הנעילה בוטלה באמצעות זיהוי הפנים."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"הנעילה בוטלה באמצעות זיהוי הפנים. יש ללחוץ כדי להמשיך."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"הפנים זוהו. יש ללחוץ כדי להמשיך."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"הפנים זוהו. להמשך יש ללחוץ על סמל ביטול הנעילה."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"לא ניתן לשמור. כדאי לנסות שוב."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"לא ניתן לשמור."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"יש להזין 4 תווים לפחות"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"אפשר להזין עד 16 תווים"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"‏מספר Build"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"‏מספר ה-Build הועתק ללוח."</string>
     <string name="basic_status" msgid="2315371112182658176">"פתיחת שיחה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index c97ed47..88d0c60 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"顔を認証しました"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"確認しました"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"完了するには [確認] をタップしてください"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"顔でロック解除しました。"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"顔でロック解除しました。押して続行してください。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"顔を認識しました。押して続行してください。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"顔を認識しました。ロック解除アイコンを押して続行します。"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"保存できません。もう一度お試しください。"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"保存できません。"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"4 文字以上にしてください"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"使用できる文字数は 16 文字未満です"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"ビルド番号"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"ビルド番号をクリップボードにコピーしました。"</string>
     <string name="basic_status" msgid="2315371112182658176">"空の会話"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index c40107e..e7fd9d3 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"სახის ამოცნობილია"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"დადასტურებული"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"დასასრულებლად შეეხეთ „დადასტურებას“"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"განიბლოკა სახით."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"განიბლოკა სახით. დააჭირეთ გასაგრძელებლად."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ამოცნობილია სახით. დააჭირეთ გასაგრძელებლად."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ამოცნობილია სახით. გასაგრძელებლად დააჭირეთ განბლოკვის ხატულას."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"შენახვა ვერ ხერხდება. ცადეთ ხელახლა."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"შენახვა ვერ ხერხდება."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"გამოიყენეთ მინიმუმ 4 სიმბოლო."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"გამოიყენეთ 16-ზე ნაკლები სიმბოლო"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"ანაწყობის ნომერი"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"ანაწყობის ნომერი დაკოპირებულია გაცვლის ბუფერში."</string>
     <string name="basic_status" msgid="2315371112182658176">"მიმოწერის გახსნა"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 9178d5f..9964f4d 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Бет танылды."</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Расталды"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Аяқтау үшін \"Растау\" түймесін түртіңіз."</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Бетпен ашылды."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Бетпен ашылды. Жалғастыру үшін басыңыз."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Бет танылды. Жалғастыру үшін басыңыз."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Бет танылды. Жалғастыру үшін құлыпты ашу белгішесін басыңыз."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Сақталмайды. Қайталап көріңіз."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Сақталмайды."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Кемінде 4 таңба пайдаланыңыз."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Ең көбі 16 таңба пайдаланыңыз."</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Құрама нөмірі"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Құрама нөмірі буферге көшірілді."</string>
     <string name="basic_status" msgid="2315371112182658176">"Ашық әңгіме"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index cbce5a0..1165ba6 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"បានផ្ទៀងផ្ទាត់​មុខ"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"បានបញ្ជាក់"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ចុច \"បញ្ជាក់\" ដើម្បីបញ្ចប់"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"បានដោះសោដោយប្រើមុខ។"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"បានដោះសោដោយប្រើមុខ។ សូមចុច ដើម្បីបន្ត។"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"បានស្គាល់មុខ។ សូមចុច ដើម្បីបន្ត។"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"បានស្គាល់មុខ។ សូមចុចរូបដោះសោ ដើម្បីបន្ត។"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"មិនអាច​រក្សាទុក​បានទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"មិនអាច​រក្សាទុក​បានទេ។"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ប្រើយ៉ាងហោចណាស់ 4 តួអក្សរ"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"ប្រើតិចជាង 16 តួអក្សរ"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"លេខ​កំណែបង្កើត"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"បានចម្លងលេខ​កំណែបង្កើតទៅឃ្លីបបត។"</string>
     <string name="basic_status" msgid="2315371112182658176">"បើកការសន្ទនា"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 400d2a7..5d8e001 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ಪೂರ್ಣಗೊಳಿಸಲು ದೃಢೀಕರಿಸಿ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"ಮುಖವನ್ನು ಬಳಸಿ ಅನ್‌ಲಾಕ್ ಮಾಡಲಾಗಿದೆ."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ಮುಖವನ್ನು ಬಳಸಿ ಅನ್‌ಲಾಕ್ ಮಾಡಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ಒತ್ತಿ."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ಮುಖ ಗುರುತಿಸಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ಒತ್ತಿ."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ಮುಖ ಗುರುತಿಸಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ಅನ್‌ಲಾಕ್ ಐಕಾನ್ ಅನ್ನು ಒತ್ತಿ."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ಕನಿಷ್ಠ 4 ಅಕ್ಷರಗಳನ್ನು ಬಳಸಿ"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 ಕ್ಕಿಂತ ಕಡಿಮೆ ಅಕ್ಷರಗಳನ್ನು ಬಳಸಿ"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"ಬಿಲ್ಡ್ ಸಂಖ್ಯೆ"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"ಬಿಲ್ಡ್ ಸಂಖ್ಯೆಯನ್ನು ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ನಲ್ಲಿ ನಕಲಿಸಲಾಗಿದೆ."</string>
     <string name="basic_status" msgid="2315371112182658176">"ಸಂಭಾಷಣೆಯನ್ನು ತೆರೆಯಿರಿ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index f699dbf..7329f89 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"얼굴이 인증되었습니다."</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"확인함"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"완료하려면 확인을 탭하세요."</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"얼굴 인식으로 잠금 해제되었습니다."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"얼굴 인식으로 잠금 해제되었습니다. 계속하려면 누르세요."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"얼굴이 인식되었습니다. 계속하려면 누르세요."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"얼굴이 인식되었습니다. 계속하려면 아이콘을 누르세요."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"저장할 수 없습니다. 다시 시도해 주세요."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"저장할 수 없습니다."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"4자 이상 입력하세요."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16자 미만이어야 합니다."</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"빌드 번호"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"빌드 번호가 클립보드에 복사되었습니다."</string>
     <string name="basic_status" msgid="2315371112182658176">"대화 열기"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 402f25d..751c98c 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Жүздүн аныктыгы текшерилди"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Ырасталды"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Бүтүрүү үчүн \"Ырастоо\" баскычын басыңыз"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Түзмөгүңүздү жүзүңүз менен ачтыңыз."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Кулпуну жүзүңүз менен ачтыңыз. Улантуу үчүн басыңыз."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Жүз таанылды. Улантуу үчүн басыңыз."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Жүз таанылды. Улантуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Сакталган жок. Кайталап көрүңүз."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Сакталган жок."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Кеминде 4 символдон турушу керек"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 символдон ашпашы керек"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Курама номери"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Курама номери алмашуу буферине көчүрүлдү."</string>
     <string name="basic_status" msgid="2315371112182658176">"Ачык сүйлөшүү"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 62e649d..e075dba 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ພິສູດຢືນຢັນໃບໜ້າແລ້ວ"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ຢືນຢັນແລ້ວ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ແຕະຢືນຢັນເພື່ອສຳເລັດ"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"ປົດລັອກດ້ວຍໃບໜ້າແລ້ວ."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ປົດລັອກດ້ວຍໜ້າແລ້ວ. ກົດເພື່ອສືບຕໍ່."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດເພື່ອສືບຕໍ່."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດໄອຄອນປົດລັອກເພື່ອສືບຕໍ່."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ບໍ່ສາມາດບັນທຶກໄດ້. ກະລຸນາລອງໃໝ່."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ບໍ່ສາມາດບັນທຶກໄດ້."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ໃຊ້ຢ່າງໜ້ອຍ 4 ຕົວອັກສອນ"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"ໃຊ້ໜ້ອຍກວ່າ 16 ຕົວອັກສອນ"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"ໝາຍເລກສ້າງ"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"ສຳເນົາໝາຍເລກສ້າງໄປໃສ່ຄລິບບອດແລ້ວ."</string>
     <string name="basic_status" msgid="2315371112182658176">"ເປີດການສົນທະນາ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index aa79022..57bb64e 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Veidas autentifikuotas"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Patvirtinta"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Paliesk. „Patvirtinti“, kad užbaigtumėte"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Atrakinta pagal veidą."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Atrakinta pagal veidą. Paspauskite, jei norite tęsti."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Veidas atpažintas. Paspauskite, jei norite tęsti."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Veidas atpažintas. Tęskite paspaudę atrakinimo piktogramą."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nepavyko išsaugoti. Bandykite dar kartą."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nepavyko išsaugoti."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Naudokite bent 4 simbolius"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Naudokite daugiausia 16 simbolių"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijos numeris"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Versijos numeris nukopijuotas į iškarpinę."</string>
     <string name="basic_status" msgid="2315371112182658176">"Atidaryti pokalbį"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index cb5a0e6..78fc7b3 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Seja autentificēta"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Apstiprināts"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Lai pabeigtu, pieskarieties Apstiprināt"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Ierīce atbloķēta pēc sejas."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ierīce atbloķēta ar seju. Nospiediet, lai turpinātu."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Seja atpazīta. Nospiediet, lai turpinātu."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Seja atpazīta. Lai turpinātu, nospiediet atbloķēšanas ikonu."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nevar saglabāt. Mēģiniet vēlreiz."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nevar saglabāt."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Izmantojiet vismaz 4 rakstzīmes"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Izmantojiet mazāk nekā 16 rakstzīmes"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijas numurs"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Versijas numurs ir kopēts starpliktuvē."</string>
     <string name="basic_status" msgid="2315371112182658176">"Atvērt sarunu"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index ec4a6c4..6ddd15c 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лицето е проверено"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потврдено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Допрете „Потврди“ за да се заврши"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Отклучено со лице."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Отклучено со лик. Притиснете за да продолжите."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицето е препознаено. Притиснете за да продолжите."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицето е препознаено. Притиснете ја иконата за отклучување за да продолжите."</string>
@@ -173,12 +174,12 @@
     <string name="fingerprint_re_enroll_dialog_title" msgid="3526033128113925780">"Поставување „Отклучување со отпечаток“"</string>
     <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"За да поставите „Отклучување со отпечаток“ повторно, вашите сегашни слики и модели на отпечаток ќе се избришат.\n\nОткако ќе се избришат, ќе треба повторно да поставите „Отклучување со отпечаток“ за да го користите отпечатокот за отклучување на телефонот или потврда дека сте вие."</string>
     <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"За да поставите „Отклучување со отпечаток“ повторно, вашите сегашните слики и модели на отпечаток ќе бидат избришат.\n\nОткако ќе се избришат, ќе треба повторно да поставите „Отклучување со отпечаток“ за да го користите отпечатокот за да го отклучите телефонот или да потврдите дека сте вие."</string>
-    <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Не можеше да се постави „Отклучување со отпечаток“. Одете во „Поставки“ за да се обидете повторно."</string>
+    <string name="fingerprint_reenroll_failure_dialog_content" msgid="4733768492747300666">"Не можеше да се постави „Отклучување со отпечаток“. Отворете „Поставки“ за да се обидете повторно."</string>
     <string name="face_re_enroll_notification_title" msgid="1850838867718410520">"Поставете „Отклучување со лик“ повторно"</string>
     <string name="face_re_enroll_notification_name" msgid="7384545252206120659">"Отклучување со лик"</string>
     <string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"Поставување „Отклучување со лик“"</string>
     <string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"За да може одново да поставите „Отклучување со лик“, вашиот сегашен модел на лик ќе се избрише.\n\nЗа да го користите ликот за отклучување на телефонот, ќе треба повторно да ја поставите функцијава."</string>
-    <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Не можеше да се постави „Отклучување со лик“. Одете во „Поставки“ за да се обидете повторно."</string>
+    <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Не можеше да се постави „Отклучување со лик“. Отворете „Поставки“ за да се обидете повторно."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Допрете го сензорот за отпечатоци"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Не се препознава ликот. Користете отпечаток."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не може да се зачува. Обидете се повторно."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не може да се зачува."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Употребете најмалку 4 знаци"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Употребете помалку од 16 знаци"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Број на верзија"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Бројот на верзијата е копиран во привремената меморија."</string>
     <string name="basic_status" msgid="2315371112182658176">"Започни разговор"</string>
@@ -1144,7 +1146,7 @@
     <string name="stylus_battery_low" msgid="7134370101603167096">"Слаба батерија на пенкало"</string>
     <string name="video_camera" msgid="7654002575156149298">"Видеокамера"</string>
     <string name="call_from_work_profile_title" msgid="5418253516453177114">"Не може да повикувате од лична апликација"</string>
-    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Вашата организацијата ви дозволува да упатувате повици само од работни апликации"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"Вашата организација ви дозволува да упатувате повици само од работни апликации"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Префрли се на работен профил"</string>
     <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Инсталирајте работна апликација на телефон"</string>
     <string name="call_from_work_profile_close" msgid="5830072964434474143">"Откажи"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 9bc496c..467720a 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"സ്ഥിരീകരിച്ചു"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"പൂർത്തിയാക്കാൻ സ്ഥിരീകരിക്കുക ടാപ്പ് ചെയ്യൂ"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്തിരിക്കുന്നു."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്‌തു. തുടരാൻ അമർത്തുക."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"മുഖം തിരിച്ചറിഞ്ഞു. തുടരാൻ അമർത്തുക."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"മുഖം തിരിച്ചറിഞ്ഞു. തുടരാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"സംരക്ഷിക്കാൻ കഴിയില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"സംരക്ഷിക്കാൻ കഴിയില്ല."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"കുറഞ്ഞത് 4 പ്രതീകങ്ങളെങ്കിലും ഉപയോഗിക്കുക"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16-ൽ കുറവ് പ്രതീകങ്ങൾ ഉപയോഗിക്കുക"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"ബിൽഡ് നമ്പർ"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"ക്ലിപ്പ്ബോർഡിലേക്ക് ബിൽഡ് നമ്പർ പകർത്തി."</string>
     <string name="basic_status" msgid="2315371112182658176">"സംഭാഷണം തുറക്കുക"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 6208833..d17933af 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Царайг баталгаажууллаа"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Баталгаажсан"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Дуусгахын тулд баталгаажуулахыг товших"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Царайгаар түгжээг тайлсан."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Царайгаар түгжээг тайлсан. Үргэлжлүүлэхийн тулд дарна уу."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Царайг таньсан. Үргэлжлүүлэхийн тулд дарна уу."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Царайг таньсан. Үргэлжлүүлэх бол түгжээг тайлах дүрсийг дар."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Хадгалах боломжгүй. Дахин оролдоно уу."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Хадгалах боломжгүй."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Дор хаяж 4 тэмдэгт ашиглана уу."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16-аас цөөн тэмдэгт ашиглана уу"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Хийцийн дугаар"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Хийцийн дугаарыг түр санах ойд хуулсан."</string>
     <string name="basic_status" msgid="2315371112182658176">"Харилцан яриаг нээх"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index eee6bc3..b1825e9 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"चेहरा ऑथेंटिकेशन केलेला आहे"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"निश्चित केले"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"पूर्ण करण्यासाठी खात्री करा वर टॅप करा"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"चेहऱ्याने अनलॉक केले आहे."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"चेहऱ्याने अनलॉक केले आहे. पुढे सुरू ठेवण्यासाठी प्रेस करा."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"चेहरा ओळखला आहे. पुढे सुरू ठेवण्यासाठी प्रेस करा."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"चेहरा ओळखला आहे. पुढे सुरू ठेवण्यासाठी अनलॉक करा आयकन प्रेस करा."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"सेव्ह करू शकत नाही. पुन्हा प्रयत्न करा."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"सेव्ह करू शकत नाही."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"किमान चार वर्ण वापरा"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"१६ पेक्षा कमी वर्ण वापरा"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नंबर क्लिपबोर्डवर कॉपी केला."</string>
     <string name="basic_status" msgid="2315371112182658176">"संभाषण उघडा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index ab68d0a..f12b476 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Wajah disahkan"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Disahkan"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ketik Sahkan untuk menyelesaikan"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Dibuka kunci dengan wajah."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Dibuka kunci dengan wajah. Tekan untuk meneruskan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Wajah dicam. Tekan untuk meneruskan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Wajah dicam. Tekan ikon buka kunci untuk meneruskan."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Tidak dapat disimpan. Cuba lagi."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Tidak dapat disimpan."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gunakan sekurang-kurangnya 4 aksara"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gunakan kurang daripada 16 aksara"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Nombor binaan"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Nombor binaan disalin ke papan keratan."</string>
     <string name="basic_status" msgid="2315371112182658176">"Buka perbualan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index c137069..1d85be1 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"အတည်ပြုပြီးပြီ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"အပြီးသတ်ရန်အတွက် \'အတည်ပြုရန်\' ကို တို့ပါ"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"မျက်နှာဖြင့် ဖွင့်ထားသည်။"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"မျက်နှာဖြင့် ဖွင့်ထားသည်။ ရှေ့ဆက်ရန် နှိပ်ပါ။"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"မျက်နှာ မှတ်မိသည်။ ရှေ့ဆက်ရန် နှိပ်ပါ။"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"မျက်နှာ မှတ်မိသည်။ ရှေ့ဆက်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ။"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"သိမ်း၍မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"သိမ်း၍မရပါ။"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"အနည်းဆုံး အက္ခရာ ၄ လုံး သုံးရန်"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"အက္ခရာ ၁၆ လုံးအောက် သုံးရန်"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"တည်ဆောက်မှုနံပါတ်"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"တည်ဆောက်မှုနံပါတ်ကို ကလစ်ဘုတ်သို့ မိတ္တူကူးပြီးပါပြီ။"</string>
     <string name="basic_status" msgid="2315371112182658176">"စကားဝိုင်းကို ဖွင့်ရန်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index de150fa..2363a68 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ansiktet er autentisert"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekreftet"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Trykk på Bekreft for å fullføre"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Låst opp med ansiktet."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Låst opp med ansiktet. Trykk for å fortsette."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansiktet er gjenkjent. Trykk for å fortsette."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansiktet er gjenkjent. Trykk på lås opp-ikon for å fortsette"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kan ikke lagre. Prøv på nytt."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kan ikke lagre."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Bruk minst 4 tegn"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Bruk færre enn 16 tegn"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Delversjonsnummer"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Delversjonsnummeret er kopiert til utklippstavlen."</string>
     <string name="basic_status" msgid="2315371112182658176">"Åpen samtale"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 9e519b3..2f99cc7 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"अनुहार प्रमाणीकरण गरियो"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"पुष्टि भयो"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"पूरा गर्नका लागि पुष्टि गर्नुहोस् नामक विकल्पमा ट्याप गर्नुहोस्"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"अनुहार प्रयोग गरी अनलक गरियो।"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"अनुहार प्रयोग गरी अनलक गरियो। जारी राख्न थिच्नुहोस्।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"अनुहार पहिचान गरियो। जारी राख्न थिच्नुहोस्।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"अनुहार पहिचान गरियो। जारी राख्न अनलक आइकनमा थिच्नुहोस्।"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"सेभ गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"सेभ गर्न सकिएन।"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"कम्तीमा ४ वटा वर्ण प्रयोग गर्नुहोस्"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"१६ वटाभन्दा कम वर्ण प्रयोग गर्नुहोस्"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नम्बर"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नम्बर कपी गरी क्लिपबोर्डमा सारियो।"</string>
     <string name="basic_status" msgid="2315371112182658176">"वार्तालाप खोल्नुहोस्"</string>
@@ -1144,7 +1146,7 @@
     <string name="stylus_battery_low" msgid="7134370101603167096">"स्टाइलसको ब्याट्री लो छ"</string>
     <string name="video_camera" msgid="7654002575156149298">"भिडियो क्यामेरा"</string>
     <string name="call_from_work_profile_title" msgid="5418253516453177114">"व्यक्तिगत एपमार्फत कल गर्न मिल्दैन"</string>
-    <string name="call_from_work_profile_text" msgid="2856337395968118274">"तपाईंको सङ्गठनले तपाईंलाई कामसम्बन्धी एपहरूमार्फत मात्र कल गर्ने अनुमति दिन्छ"</string>
+    <string name="call_from_work_profile_text" msgid="2856337395968118274">"तपाईंको सङ्गठनले तपाईंलाई कामसम्बन्धी एपहरूमार्फत मात्र कल गर्ने अनुमति दिएको छ"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"कार्य प्रोफाइल प्रयोग गर्नुहोस्"</string>
     <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"कामसम्बन्धी फोन एप इन्स्टल गर्नुहोस्"</string>
     <string name="call_from_work_profile_close" msgid="5830072964434474143">"रद्द गर्नुहोस्"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 4ca6c01..05f7922 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Gezicht geverifieerd"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bevestigd"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tik op Bevestigen om te voltooien"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Ontgrendeld via gezicht."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ontgrendeld via gezicht. Druk om door te gaan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gezicht herkend. Druk om door te gaan."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gezicht herkend. Druk op het ontgrendelicoon."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kan niet opslaan. Probeer het opnieuw."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kan niet opslaan."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gebruik minstens 4 tekens"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gebruik minder dan 16 tekens"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildnummer"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Buildnummer naar klembord gekopieerd."</string>
     <string name="basic_status" msgid="2315371112182658176">"Gesprek openen"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 8281481..7f443de 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ମୁହଁ ପ୍ରାମାଣିକତା ହୋଇଛି"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ସୁନିଶ୍ଚିତ କରାଯାଇଛି"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ସମ୍ପୂର୍ଣ୍ଣ କରିବାକୁ ସୁନିଶ୍ଚିତ କରନ୍ତୁରେ ଟାପ୍ କରନ୍ତୁ"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"ଫେସ ମାଧ୍ୟମରେ ଅନଲକ କରାଯାଇଛି।"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ଫେସ ମାଧ୍ୟମରେ ଅନଲକ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ ଦବାନ୍ତୁ।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ଫେସ ଚିହ୍ନଟ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ ଦବାନ୍ତୁ।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ଫେସ ଚିହ୍ନଟ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ।"</string>
@@ -296,7 +297,7 @@
     <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"<xliff:g id="TIME">%s</xliff:g>ରେ ଅନ୍ ହେବ"</string>
     <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> ପର୍ଯ୍ୟନ୍ତ"</string>
     <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"ଗାଢ଼ା ଥିମ"</string>
-    <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ବ୍ୟାଟେରୀ ସେଭର୍"</string>
+    <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ବେଟେରୀ ସେଭର"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ସନ୍ଧ୍ୟାରେ ଚାଲୁ ହେବ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ସକାଳ ପର୍ଯ୍ୟନ୍ତ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>ରେ ଚାଲୁ ହେବ"</string>
@@ -414,7 +415,7 @@
     <string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"ଆରମ୍ଭ କରନ୍ତୁ"</string>
     <string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"ଆପଣଙ୍କ IT ଆଡମିନଙ୍କ ଦ୍ୱାରା ବ୍ଲକ କରାଯାଇଛି"</string>
     <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ଡିଭାଇସ ନୀତି ଦ୍ୱାରା ସ୍କ୍ରିନ କେପଚରିଂକୁ ଅକ୍ଷମ କରାଯାଇଛି"</string>
-    <string name="clear_all_notifications_text" msgid="348312370303046130">"ସମସ୍ତ ଖାଲି କରନ୍ତୁ"</string>
+    <string name="clear_all_notifications_text" msgid="348312370303046130">"ସବୁ ଖାଲି କରନ୍ତୁ"</string>
     <string name="manage_notifications_text" msgid="6885645344647733116">"ପରିଚାଳନା କରନ୍ତୁ"</string>
     <string name="manage_notifications_history_text" msgid="57055985396576230">"ଇତିହାସ"</string>
     <string name="notification_section_header_incoming" msgid="850925217908095197">"ନୂଆ"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ସେଭ କରାଯାଇପାରିଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ସେଭ କରାଯାଇପାରିଲା ନାହିଁ।"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ଅତିକମରେ 4ଟି କେରେକ୍ଟର ବ୍ୟବହାର କରନ୍ତୁ"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16ଟିରୁ କମ କେରେକ୍ଟର ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"ବିଲ୍ଡ ନମ୍ୱର"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"କ୍ଲିପବୋର୍ଡକୁ କପି କରାଯାଇଥିବା ବିଲ୍ଡ ନମ୍ୱର।"</string>
     <string name="basic_status" msgid="2315371112182658176">"ବାର୍ତ୍ତାଳାପ ଖୋଲନ୍ତୁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index b3d2b2f..f7bb0c9 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ਚਿਹਰਾ ਪ੍ਰਮਾਣੀਕਿਰਤ ਹੋਇਆ"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ਪੁਸ਼ਟੀ ਕੀਤੀ ਗਈ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ਪੂਰਾ ਕਰਨ ਲਈ ਪੁਸ਼ਟੀ ਕਰੋ \'ਤੇ ਟੈਪ ਕਰੋ"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"ਚਿਹਰੇ ਰਾਹੀਂ ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ।"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ਚਿਹਰੇ ਰਾਹੀਂ ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ। ਜਾਰੀ ਰੱਖਣ ਲਈ ਦਬਾਓ।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਹੋਈ। ਜਾਰੀ ਰੱਖਣ ਲਈ ਦਬਾਓ।"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਹੋਈ। ਜਾਰੀ ਰੱਖਣ ਲਈ \'ਅਣਲਾਕ ਕਰੋ\' ਪ੍ਰਤੀਕ ਨੂੰ ਦਬਾਓ।"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ਘੱਟੋ-ਘੱਟ 4 ਅੱਖਰ-ਚਿੰਨ੍ਹ ਵਰਤੋ"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 ਤੋਂ ਘੱਟ ਅੱਖਰ-ਚਿੰਨ੍ਹ ਵਰਤੋ"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"ਬਿਲਡ ਨੰਬਰ"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"ਬਿਲਡ ਨੰਬਰ ਨੂੰ ਕਲਿੱਪਬੋਰਡ \'ਤੇ ਕਾਪੀ ਕੀਤਾ ਗਿਆ।"</string>
     <string name="basic_status" msgid="2315371112182658176">"ਗੱਲਬਾਤ ਖੋਲ੍ਹੋ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 5830ee9..e6af3fc 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Twarz rozpoznana"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potwierdzono"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Aby zakończyć, kliknij Potwierdź"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Odblokowano skanem twarzy."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odblokowano rozpoznawaniem twarzy. Kliknij, aby kontynuować."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Twarz rozpoznana. Kliknij, aby kontynuować."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Twarz rozpoznana. Aby kontynuować, kliknij ikonę odblokowywania."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nie można zapisać. Spróbuj ponownie."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nie można zapisać."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Wpisz co najmniej 4 znaki"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Wpisz mniej niż 16 znaków"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numer kompilacji"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Numer kompilacji został skopiowany do schowka."</string>
     <string name="basic_status" msgid="2315371112182658176">"Otwarta rozmowa"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 16a3d05..b9df661 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Rosto autenticado"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em \"Confirmar\" para concluir"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Desbloqueado pelo rosto."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado pelo rosto. Pressione para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Pressione para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Pressione o ícone para continuar."</string>
@@ -988,7 +989,7 @@
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Alto-falantes e telas"</string>
-    <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivos sugeridos"</string>
+    <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Opções de dispositivos"</string>
     <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Interrompa sua sessão compartilhada para transferir mídia a outro dispositivo"</string>
     <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Parar"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Falha ao salvar. Tente de novo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Falha ao salvar."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use pelo menos 4 caracteres"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use menos de 16 caracteres"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Número da versão copiado para a área de transferência."</string>
     <string name="basic_status" msgid="2315371112182658176">"Conversa aberta"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index dee32a5..9c11d61 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Rosto autenticado"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmado"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em Confirmar para concluir."</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Desbloqueado com o rosto."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado com o rosto. Prima para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Prima para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Prima ícone de desbloqueio para continuar"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Não é possível guardar. Tente novamente."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Não é possível guardar."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use, pelo menos, 4 carateres"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use menos de 16 carateres"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da compilação"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Número da compilação copiado para a área de transferência."</string>
     <string name="basic_status" msgid="2315371112182658176">"Abrir conversa"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 16a3d05..b9df661 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Rosto autenticado"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em \"Confirmar\" para concluir"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Desbloqueado pelo rosto."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado pelo rosto. Pressione para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Pressione para continuar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Pressione o ícone para continuar."</string>
@@ -988,7 +989,7 @@
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Alto-falantes e telas"</string>
-    <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivos sugeridos"</string>
+    <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Opções de dispositivos"</string>
     <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Interrompa sua sessão compartilhada para transferir mídia a outro dispositivo"</string>
     <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Parar"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Falha ao salvar. Tente de novo."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Falha ao salvar."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use pelo menos 4 caracteres"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use menos de 16 caracteres"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Número da versão copiado para a área de transferência."</string>
     <string name="basic_status" msgid="2315371112182658176">"Conversa aberta"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index a388637..9667f43 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Chip autentificat"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmat"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Atinge Confirm pentru a finaliza"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"S-a deblocat folosind fața."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"S-a deblocat cu ajutorul feței. Apasă pentru a continua."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Chipul a fost recunoscut. Apasă pentru a continua."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Chip recunoscut. Apasă pictograma Deblocare ca să continui."</string>
@@ -987,7 +988,7 @@
     <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"Dispozitive disponibile pentru ieșire audio."</string>
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volum"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
-    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Difuzoare și afișaje"</string>
+    <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Difuzoare și ecrane"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispozitive sugerate"</string>
     <string name="media_output_end_session_dialog_summary" msgid="5954520685989877347">"Oprește sesiunea comună ca să muți elementul media pe alt dispozitiv"</string>
     <string name="media_output_end_session_dialog_stop" msgid="208189434474624412">"Oprește"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nu se poate salva. Încearcă din nou."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nu se poate salva."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Folosește minimum 4 caractere."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Folosește maximum 16 caractere"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numărul versiunii"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Numărul versiunii s-a copiat în clipboard."</string>
     <string name="basic_status" msgid="2315371112182658176">"Deschide conversația"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 29ab705..8945e34 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лицо распознано"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Подтверждено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Нажмите \"Подтвердить\""</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Разблокировано сканированием лица."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Разблокировано сканированием лица. Нажмите, чтобы продолжить."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицо распознано. Нажмите, чтобы продолжить."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицо распознано. Нажмите на значок разблокировки."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не удалось сохранить. Повторите попытку."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не удалось сохранить."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Минимальное количество символов – 4"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Максимальное количество символов – 16"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер сборки"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Номер сборки скопирован в буфер обмена."</string>
     <string name="basic_status" msgid="2315371112182658176">"Открытый чат"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index fd63ffc..ef291cba 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"මුහුණ සත්‍යාපන කළා"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"තහවුරු කළා"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"සම්පූර්ණ කිරීමට තහවුරු කරන්න තට්ටු කර."</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"මුහුණ මගින් අගුළු හරින ලදි."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"මුහුණ මගින් අගුලු හරින ලදි. ඉදිරියට යාමට ඔබන්න."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"මුහුණ හඳුනා ගන්නා ලදි. ඉදිරියට යාමට ඔබන්න."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"මුහුණ හඳුනා ගන්නා ලදි. ඉදිරියට යාමට අගුලු හැරීමේ නිරූපකය ඔබන්න."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"සුරැකිය නොහැකිය. නැවත උත්සාහ කරන්න."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"සුරැකිය නොහැකිය."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"අවම වශයෙන් අනුලකුණු 4ක් භාවිතා කරන්න"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"අනුලකුණු 16කට වඩා අඩුවෙන් භාවිතා කරන්න"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"නිමැවුම් අංකය"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"නිමැවුම් අංකය පසුරු පුවරුවට පිටපත් කරන ලදි."</string>
     <string name="basic_status" msgid="2315371112182658176">"සංවාදය විවෘත කරන්න"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 1cc3789..2544505 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Tvár bola overená"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrdené"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Overenie dokončíte klepnutím na Potvrdiť"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Odomknuté tvárou."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odomknuté tvárou. Pokračujte stlačením."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Tvár bola rozpoznaná. Pokračujte stlačením."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Tvár bola rozpoznaná. Pokračujte stlačením ikony odomknutia"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nedá sa uložiť. Skúste to znova."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nedá sa uložiť."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Použite aspoň štyri znaky"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Použite menej než 16 znakov"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo zostavy"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Číslo zostavy bolo skopírované do schránky."</string>
     <string name="basic_status" msgid="2315371112182658176">"Otvorená konverzácia"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 62769ff..9a9676f 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Pristnost obraza je potrjena"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potrjeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Za dokončanje se dotaknite »Potrdite«"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Odklenjeno z obrazom."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odklenjeno z obrazom. Pritisnite za nadaljevanje."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Obraz je prepoznan. Pritisnite za nadaljevanje."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Obraz je prepoznan. Za nadaljevanje pritisnite ikono za odklepanje."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ni mogoče shraniti. Poskusite znova."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ni mogoče shraniti."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Uporabite vsaj 4 znake."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Uporabite manj kot 16 znakov."</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Delovna različica"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Delovna različica je bila kopirana v odložišče."</string>
     <string name="basic_status" msgid="2315371112182658176">"Odprt pogovor"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index a721f6e..d477aa4 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Fytyra u vërtetua"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Konfirmuar"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Trokit \"Konfirmo\" për ta përfunduar"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"U shkyç me fytyrë."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"U shkyç me fytyrë. Shtyp për të vazhduar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Fytyra u njoh. Shtyp për të vazhduar."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Fytyra u njoh. Shtyp ikonën e shkyçjes për të vazhduar."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nuk mund të ruhet. Provo përsëri."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nuk mund të ruhet."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Përdor të paktën 4 karaktere"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Përdor më pak se 16 karaktere"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numri i ndërtimit"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Numri i ndërtimit u kopjua te kujtesa e fragmenteve"</string>
     <string name="basic_status" msgid="2315371112182658176">"Hap bisedën"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 9985ef0..b293e6a 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лице је потврђено"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потврђено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Додирните Потврди да бисте завршили"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Откључано је лицем."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Откључано је лицем. Притисните да бисте наставили."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лице је препознато. Притисните да бисте наставили."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лице препознато. Притисните икону откључавања за наставак."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Чување није успело. Пробајте поново."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Чување није успело."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Користите бар 4 знака"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Користите мање од 16 знакова"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Број верзије"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Број верзије је копиран у привремену меморију."</string>
     <string name="basic_status" msgid="2315371112182658176">"Отворите конверзацију"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 9a08750..00a2e3c 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ansiktet har autentiserats"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekräftat"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Slutför genom att trycka på Bekräfta"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Upplåst med ansiktslås."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Upplåst med ansiktslås. Tryck för att fortsätta."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansiktet har identifierats. Tryck för att fortsätta."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansiktet har identifierats. Tryck på ikonen lås upp."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Det gick inte att spara. Försök igen."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Det gick inte att spara."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Använd minst 4 tecken"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Använd färre än 16 tecken"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Versionsnummer"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Versionsnumret har kopierats till urklipp."</string>
     <string name="basic_status" msgid="2315371112182658176">"Öppen konversation"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index ad4125e..af90c67 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Uso umethibitishwa"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Imethibitishwa"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Gusa Thibitisha ili ukamilishe"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Imefunguka kwa kutumia uso wako."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Imefunguliwa kwa kutumia uso wako. Bonyeza ili uendelee."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Uso umetambuliwa. Bonyeza ili uendelee."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Uso umetambuliwa. Bonyeza aikoni ya kufungua ili uendelee."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Imeshindwa kuhifadhi. Jaribu tena."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Imeshindwa kuhifadhi."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Tumia angalau herufi 4"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Tumia herufi chini ya 16"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Nambari ya muundo"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Nambari ya muundo imewekwa kwenye ubao wa kunakili."</string>
     <string name="basic_status" msgid="2315371112182658176">"Fungua mazungumzo"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 066c8d4..fd33af9 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"முகம் அங்கீகரிக்கப்பட்டது"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"உறுதிப்படுத்தப்பட்டது"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"முடிக்க \'உறுதிப்படுத்துக\' என்பதை தட்டவும்"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"முகம் மூலம் அன்லாக் செய்யப்பட்டது."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"முகம் மூலம் அன்லாக் செய்யப்பட்டது. தொடர அழுத்தவும்."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"முகம் அங்கீகரிக்கப்பட்டது. தொடர அழுத்தவும்."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"முகம் அங்கீகரிக்கப்பட்டது. தொடர அன்லாக் ஐகானை அழுத்தவும்."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"சேமிக்க முடியவில்லை. மீண்டும் முயலவும்."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"சேமிக்க முடியவில்லை."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"குறைந்தது 4 எழுத்துகளைப் பயன்படுத்துங்கள்"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 எழுத்துகளுக்குக் குறைவாகப் பயன்படுத்துங்கள்"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"பதிப்பு எண்"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"பதிப்பு எண் கிளிப்போர்டுக்கு நகலெடுக்கப்பட்டது."</string>
     <string name="basic_status" msgid="2315371112182658176">"திறந்தநிலை உரையாடல்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index dc8c763..63fc9e0 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ముఖం ప్రామాణీకరించబడింది"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"నిర్ధారించబడింది"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"పూర్తి చేయడానికి \"నిర్ధారించు\" నొక్కండి"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"ముఖం ద్వారా అన్‌లాక్ చేయబడింది."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ముఖం ద్వారా అన్‌లాక్ చేయబడింది. కొనసాగించడానికి నొక్కండి."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ముఖం గుర్తించబడింది. కొనసాగించడానికి నొక్కండి."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ముఖం గుర్తించబడింది. కొనసాగడానికి అన్‌లాక్ చిహ్నం నొక్కండి."</string>
@@ -389,7 +390,7 @@
     <string name="guest_notification_session_active" msgid="5567273684713471450">"మీరు గెస్ట్ మోడ్‌లో ఉన్నారు"</string>
     <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"కొత్త యూజర్‌ను జోడించడం వలన గెస్ట్ మోడ్ నుండి వైదొలుగుతుంది. అలాగే ప్రస్తుత గెస్ట్ సెషన్ నుండి అన్ని యాప్‌లతో పాటు మొత్తం డేటా తొలగించబడుతుంది."</string>
     <string name="user_limit_reached_title" msgid="2429229448830346057">"వినియోగదారు పరిమితిని చేరుకున్నారు"</string>
-    <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{ఒక యూజర్‌ను మాత్రమే క్రియేట్ చేయవచ్చు.}other{మీరు గరిష్టంగా # మంది యూజర్‌లను జోడించవచ్చు.}}"</string>
+    <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{ఒక యూజర్‌ను మాత్రమే క్రియేట్ చేయవచ్చు.}other{మీరు గరిష్ఠంగా # మంది యూజర్‌లను జోడించవచ్చు.}}"</string>
     <string name="user_remove_user_title" msgid="9124124694835811874">"యూజర్‌ను తీసివేయాలా?"</string>
     <string name="user_remove_user_message" msgid="6702834122128031833">"ఈ వినియోగదారుకు సంబంధించిన అన్ని యాప్‌లు మరియు డేటా తొలగించబడతాయి."</string>
     <string name="user_remove_user_remove" msgid="8387386066949061256">"తీసివేయండి"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"సేవ్ చేయడం సాధ్యపడదు. మళ్లీ ట్రై చేయండి."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"సేవ్ చేయడం సాధ్యపడదు."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"కనీసం 4 అక్షరాలను ఉపయోగించండి"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 కంటే తక్కువ అక్షరాలను ఉపయోగించండి"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"బిల్డ్ నంబర్"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"బిల్డ్ నంబర్, క్లిప్‌బోర్డ్‌కు కాపీ చేయబడింది."</string>
     <string name="basic_status" msgid="2315371112182658176">"సంభాషణను తెరవండి"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 793a1f7..49f0f2a 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ตรวจสอบสิทธิ์ใบหน้าแล้ว"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ยืนยันแล้ว"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"แตะยืนยันเพื่อดำเนินการให้เสร็จสมบูรณ์"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"ปลดล็อกด้วยใบหน้าแล้ว"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ปลดล็อกด้วยใบหน้าแล้ว กดเพื่อดำเนินการต่อ"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"จดจำใบหน้าได้ กดเพื่อดำเนินการต่อ"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"จดจำใบหน้าได้ กดไอคอนปลดล็อกเพื่อดำเนินการต่อ"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"บันทึกไม่ได้ โปรดลองอีกครั้ง"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"บันทึกไม่ได้"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ใช้อักขระอย่างน้อย 4 ตัว"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"ใช้อักขระไม่เกิน 16 ตัว"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"หมายเลขบิลด์"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"คัดลอกหมายเลขบิลด์ไปยังคลิปบอร์ดแล้ว"</string>
     <string name="basic_status" msgid="2315371112182658176">"เปิดการสนทนา"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 4dd75fe..755c872 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Na-authenticate ang mukha"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Nakumpirma"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"I-tap ang Kumpirmahin para kumpletuhin"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Na-unlock gamit ang mukha."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Na-unlock gamit ang mukha. Pindutin para magpatuloy."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Nakilala ang mukha. Pindutin para magpatuloy."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Nakilala ang mukha. Pindutin ang unlock para magpatuloy."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Hindi ma-save. Subukan ulit."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Hindi ma-save."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gumamit ng hindi bababa sa 4 na character"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gumamit ng mas kaunti sa 16 na character"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero ng build"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Nakopya sa clipboard ang numero ng build."</string>
     <string name="basic_status" msgid="2315371112182658176">"Buksan ang pag-uusap"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 6cec2a6..72c2d43 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Yüz kimliği doğrulandı"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Onaylandı"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tamamlamak için Onayla\'ya dokunun"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Cihazın kilidini yüzünüzle açtınız."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Cihazın kilidini yüzünüzle açtınız. Devam etmek için basın."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Yüzünüz tanındı. Devam etmek için basın."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Yüzünüz tanındı. Kilit açma simgesine basın."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kaydedilemiyor. Tekrar deneyin."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kaydedilemiyor."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"En az 4 karakter kullanın."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"En fazla 16 karakter kullanın"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Derleme numarası"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Derleme numarası panoya kopyalandı."</string>
     <string name="basic_status" msgid="2315371112182658176">"Görüşmeyi aç"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index eb791ae..c1e291d 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Обличчя автентифіковано"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Підтверджено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Щоб завершити, натисніть \"Підтвердити\""</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Розблоковано (фейс-контроль)."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Розблоковано (фейсконтроль). Натисніть, щоб продовжити."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Обличчя розпізнано. Натисніть, щоб продовжити."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Обличчя розпізнано. Натисніть значок розблокування."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не вдалося зберегти. Повторіть спробу."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не вдалося зберегти."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Введіть принаймні 4 символи"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Введіть менше ніж 16 символів"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер складання"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Номер складання скопійовано в буфер обміну."</string>
     <string name="basic_status" msgid="2315371112182658176">"Відкрита розмова"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 8b03b84..46596c3 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"چہرے کی تصدیق ہو گئی"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تصدیق شدہ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"مکمل کرنے کیلئے \'تصدیق کریں\' تھپتھپائیں"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"چہرے سے غیر مقفل کیا گیا۔"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"چہرے سے انلاک کیا گیا۔ جاری رکھنے کے لیے دبائیں۔"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"چہرے کی شناخت ہو گئی۔ جاری رکھنے کے لیے دبائیں۔"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"چہرے کی شناخت ہو گئی۔ جاری رکھنے کیلئے انلاک آئیکن دبائیں۔"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"محفوظ نہیں کیا جا سکا۔ پھر کوشش کریں۔"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"محفوظ نہیں کیا جا سکا۔"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"کم از کم 4 حروف استعمال کریں"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 حروف سے کم استعمال کریں"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"بلڈ نمبر"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"بلڈ نمبر کلپ بورڈ میں کاپی ہو گیا۔"</string>
     <string name="basic_status" msgid="2315371112182658176">"گفتگو کھولیں"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index f703ed5..ab1fe06 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Yuzingiz aniqlandi"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Tasdiqlangan"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tasdiqlash uchun tegining"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Yuz bilan ochildi."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Yuz orqali ochildi. Davom etish uchun bosing."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Yuz aniqlandi. Davom etish uchun bosing."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Yuz aniqlandi. Davom etish uchun ochish belgisini bosing."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Saqlanmadi. Qayta urining."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Saqlanmadi."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Parolga kamida 4 ta belgi kiriting."</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Kiritiladigan belgilar 16 tadan oshmasin"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Nashr raqami"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Nashr raqami vaqtinchalik xotiraga nusxalandi."</string>
     <string name="basic_status" msgid="2315371112182658176">"Suhbatni ochish"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index cc7aa7f..e681b1a 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Đã xác thực khuôn mặt"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Ðã xác nhận"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Nhấn vào Xác nhận để hoàn tất"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Đã mở khoá bằng khuôn mặt."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Đã mở khoá bằng khuôn mặt. Hãy nhấn để tiếp tục."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Đã nhận diện khuôn mặt. Hãy nhấn để tiếp tục."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Đã nhận diện khuôn mặt. Nhấn biểu tượng mở khoá để tiếp tục."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Không lưu được. Hãy thử lại."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Không lưu được."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Sử dụng ít nhất 4 ký tự"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Sử dụng ít hơn 16 ký tự"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Số bản dựng"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Đã sao chép số bản dựng vào bảng nhớ tạm."</string>
     <string name="basic_status" msgid="2315371112182658176">"Mở 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 40b0694..5df113b 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"面孔身份验证成功"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"已确认"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"点按“确认”即可完成"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"已用面孔解锁"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"已通过面孔识别解锁。点按即可继续。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"识别出面孔。点按即可继续。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"识别出面孔。按下解锁图标即可继续。"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"无法保存,请重试。"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"无法保存。"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"必须至少 4 个字符"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"必须少于 16 个字符"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build 号"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"已将 Build 号复制到剪贴板。"</string>
     <string name="basic_status" msgid="2315371112182658176">"开放式对话"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 23c520a..f911d5c 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"面孔已經驗證"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"已確認"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"輕按 [確定] 以完成"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"已使用面孔解鎖。"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"已使用面孔解鎖。按下即可繼續操作。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"已識別面孔。按下即可繼續操作。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"已識別面孔。按解鎖圖示即可繼續。"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"無法儲存,請再試一次。"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"無法儲存。"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"請至少使用 4 個字元"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"請使用少於 16 個字元"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"版本號碼"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"版本號碼已複製到剪貼簿。"</string>
     <string name="basic_status" msgid="2315371112182658176">"開啟對話"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index ec65f9a9..01cd254 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"臉孔驗證成功"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"確認完畢"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"輕觸 [確認] 完成驗證設定"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"裝置已由人臉解鎖。"</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"裝置已透過你的臉解鎖,按下即可繼續操作。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"臉孔辨識完成,按下即可繼續操作。"</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"臉孔辨識完成,按下「解鎖」圖示即可繼續操作。"</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"無法儲存,請再試一次。"</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"無法儲存。"</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"至少要有 4 個半形字元"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"不得超過 16 個半形字元"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"版本號碼"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"已將版本號碼複製到剪貼簿。"</string>
     <string name="basic_status" msgid="2315371112182658176">"開放式對話"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 1ca5c05..3f89ba9 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -142,7 +142,8 @@
     <string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ubuso bufakazelwe ubuqiniso"</string>
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Kuqinisekisiwe"</string>
     <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Thepha okuthi Qinisekisa ukuze uqedele"</string>
-    <string name="biometric_dialog_tap_confirm_with_face" msgid="3783056044917913453">"Kuvulwe ngobuso."</string>
+    <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
+    <skip />
     <string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Vula ngobuso. Cindezela ukuze uqhubeke."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ubuso buyaziwa. Cindezela ukuze uqhubeke."</string>
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ubuso buyaziwa. Cindezela isithonjana sokuvula ukuze uqhubeke."</string>
@@ -1003,7 +1004,8 @@
     <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ayikwazi ukulondoloza. Zama futhi."</string>
     <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ayikwazi ukulondoloza."</string>
     <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Sebenzisa okungenani izinhlamvu ezi-4"</string>
-    <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Sebenzisa isinhlamvu ezimbalwa kuneziyi-16"</string>
+    <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
+    <skip />
     <string name="build_number_clip_data_label" msgid="3623176728412560914">"Yakha inombolo"</string>
     <string name="build_number_copy_toast" msgid="877720921605503046">"Yakha inombolo ekopishelwe kubhodi yokunamathisela."</string>
     <string name="basic_status" msgid="2315371112182658176">"Vula ingxoxo"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index c3651cf..166bd2a 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -902,4 +902,16 @@
     <!-- Time (in ms) to delay the bouncer views from showing when passive auth may be used for
     device entry. -->
     <integer name="primary_bouncer_passive_auth_delay">500</integer>
+
+    <!--
+    The package name of the app store app. If empty, features using this should be gracefully
+    disabled.
+    -->
+    <string name="config_appStorePackageName" translatable="false"></string>
+
+    <!-- Template for a link that leads to an app page in the relevant app store. If empty,
+    features using this should be gracefully disabled. If not empty, it must include a
+    "$packageName" part that will be replaced by the code with the package name of the target app.
+    -->
+    <string name="config_appStoreAppLinkTemplate" translatable="false"></string>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 8d3ba36..4f768cc 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -572,6 +572,7 @@
     <dimen name="qs_brightness_margin_bottom">16dp</dimen>
     <dimen name="qqs_layout_margin_top">16dp</dimen>
     <dimen name="qqs_layout_padding_bottom">24dp</dimen>
+    <item name="qqs_expand_clock_scale" format="float" type="dimen">2.57</item>
 
     <!-- Most of the time it should be the same as notification_side_paddings as it's vertically
          aligned with notifications. The exception is split shade when this value becomes
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 67fdb4c..663efea 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -353,7 +353,7 @@
     <!-- Message shown when a biometric is authenticated, waiting for the user to confirm authentication [CHAR LIMIT=40]-->
     <string name="biometric_dialog_tap_confirm">Tap Confirm to complete</string>
     <!-- Message shown when a biometric has authenticated with a user's face and is waiting for the user to confirm authentication [CHAR LIMIT=60]-->
-    <string name="biometric_dialog_tap_confirm_with_face">Unlocked by face.</string>
+    <string name="biometric_dialog_tap_confirm_with_face">Unlocked by face</string>
     <!-- Message shown when a biometric has authenticated with a user's face and is waiting for the user to confirm authentication [CHAR LIMIT=60]-->
     <string name="biometric_dialog_tap_confirm_with_face_alt_1">Unlocked by face. Press to continue.</string>
     <!-- Message shown when a biometric has authenticated with a user's face and is waiting for the user to confirm authentication [CHAR LIMIT=60]-->
@@ -2724,8 +2724,8 @@
     <string name="media_output_broadcast_last_update_error">Can\u2019t save.</string>
     <!-- The hint message when Broadcast code is less than 4 characters [CHAR LIMIT=60] -->
     <string name="media_output_broadcast_code_hint_no_less_than_min">Use at least 4 characters</string>
-    <!-- The hint message when Broadcast code is more than 16 characters [CHAR LIMIT=60] -->
-    <string name="media_output_broadcast_code_hint_no_more_than_max">Use fewer than 16 characters</string>
+    <!-- The hint message when Broadcast edit is more than 16/254 characters [CHAR LIMIT=60] -->
+    <string name="media_output_broadcast_edit_hint_no_more_than_max">Use fewer than <xliff:g id="length" example="16">%1$d</xliff:g> characters</string>
 
     <!-- Label for clip data when copying the build number off QS [CHAR LIMIT=NONE]-->
     <string name="build_number_clip_data_label">Build number</string>
@@ -3016,52 +3016,54 @@
     -->
     <string name="keyguard_affordance_enablement_dialog_action_template">Open <xliff:g id="appName" example="Wallet">%1$s</xliff:g></string>
 
-    <!--
-    Requirement for the wallet app to be available for the user to use. This is shown as part of a
-    bulleted list of requirements. When all requirements are met, the app can be accessed through a
-    shortcut button on the lock screen. [CHAR LIMIT=NONE].
+    <!---
+    Explains that the wallet app is not available because it is not installed. This is shown as part
+    of a dialog that explains to the user why they cannot select this shortcut for their lock screen
+    right now.
+    [CHAR LIMIT=NONE].
     -->
-    <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1">&#8226; The app is set up</string>
+    <string name="wallet_quick_affordance_unavailable_install_the_app">To add the Wallet app as a shortcut, make sure the app is installed</string>
 
-    <!--
-    Requirement for the wallet app to be available for the user to use. This is shown as part of a
-    bulleted list of requirements. When all requirements are met, the app can be accessed through a
-    shortcut button on the lock screen. [CHAR LIMIT=NONE].
+    <!---
+    Explains that the wallet app is not available because it is not installed. This is shown as part
+    of a dialog that explains to the user why they cannot select this shortcut for their lock screen
+    right now.
+    [CHAR LIMIT=NONE].
     -->
-    <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2">&#8226; At least one card has been added to Wallet</string>
+    <string name="wallet_quick_affordance_unavailable_configure_the_app">To add the Wallet app as a shortcut, make sure at least one card has been added</string>
 
     <!--
     Requirement for the QR code scanner functionality to be available for the user to use. This is
     shown as part of a bulleted list of requirements. When all requirements are met, the piece of
     functionality can be accessed through a shortcut button on the lock screen. [CHAR LIMIT=NONE].
     -->
-    <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction">&#8226; Install a camera app</string>
+    <string name="qr_scanner_quick_affordance_unavailable_explanation">To add the QR code scanner as a shortcut, make sure a camera app is installed</string>
 
     <!--
-    Requirement for the home app to be available for the user to use. This is shown as part of a
-    bulleted list of requirements. When all requirements are met, the app can be accessed through a
-    shortcut button on the lock screen. [CHAR LIMIT=NONE].
+    Explains that the lock screen shortcut for the "home" app is not available because the app isn't
+    installed. This is shown as part of a dialog that explains to the user why they cannot select
+    this shortcut for their lock screen right now. [CHAR LIMIT=NONE].
     -->
-    <string name="keyguard_affordance_enablement_dialog_home_instruction_1">&#8226; The app is set up</string>
+    <string name="home_quick_affordance_unavailable_install_the_app">To add the Home app as a shortcut, make sure the app is installed</string>
 
     <!--
-    Requirement for the home app to be available for the user to use. This is shown as part of a
-    bulleted list of requirements. When all requirements are met, the app can be accessed through a
-    shortcut button on the lock screen. [CHAR LIMIT=NONE].
+    Explains that the lock screen shortcut for the "home" app is not available because the app isn't
+    configured. This is shown as part of a dialog that explains to the user why they cannot select
+    this shortcut for their lock screen right now. [CHAR LIMIT=NONE].
     -->
-    <string name="keyguard_affordance_enablement_dialog_home_instruction_2">&#8226; At least one device is available</string>
+    <string name="home_quick_affordance_unavailable_configure_the_app">&#8226; At least one device is available</string>
 
     <!---
-    Requirement for the notes app to be available for the user to use. This is shown as part of a
-    bulleted list of requirements. When all requirements are met, the app can be accessed through a
-    shortcut button on the lock screen. [CHAR LIMIT=NONE] -->
-    <string name="keyguard_affordance_enablement_dialog_notes_app_instruction">Select a default notes app to use the notetaking shortcut</string>
+    Explains that the notes app is not available. This is shown as part of a dialog that explains to
+    the user why they cannot select this shortcut for their lock screen right now.
+    [CHAR LIMIT=NONE].
+    -->
+    <string name="notes_app_quick_affordance_unavailable_explanation">Select a default notes app to use the notetaking shortcut</string>
 
     <!---
     The action to make the lock screen shortcut for the notes app to be available for the user to
-    use. This is shown as the action button in the dialog listing the requirements. When all
-    requirements are met, the app can be accessed through a shortcut button on the lock screen.
-    [CHAR LIMIT=NONE] -->
+    use. This is shown as the action button in the dialog explaining why the shortcut isn't
+    available. [CHAR LIMIT=NONE] -->
     <string name="keyguard_affordance_enablement_dialog_notes_app_action">Select app</string>
 
     <!--
@@ -3153,4 +3155,11 @@
 
     <!--- Content of toast triggered when the notes app entry point is triggered without setting a default notes app. [CHAR LIMIT=NONE] -->
     <string name="set_default_notes_app_toast_content">Set default notes app in Settings</string>
+
+    <!--
+    Label for a button that, when clicked, sends the user to the app store to install an app.
+
+    [CHAR LIMIT=64].
+    -->
+    <string name="install_app">Install app</string>
 </resources>
diff --git a/packages/SystemUI/res/xml/qs_header.xml b/packages/SystemUI/res/xml/qs_header.xml
index 52a98984..8039c68 100644
--- a/packages/SystemUI/res/xml/qs_header.xml
+++ b/packages/SystemUI/res/xml/qs_header.xml
@@ -43,8 +43,8 @@
             app:layout_constraintBottom_toBottomOf="@id/carrier_group"
         />
         <Transform
-            android:scaleX="2.57"
-            android:scaleY="2.57"
+            android:scaleX="@dimen/qqs_expand_clock_scale"
+            android:scaleY="@dimen/qqs_expand_clock_scale"
             />
     </Constraint>
 
diff --git a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt
index f96d1e3..070a451 100644
--- a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt
+++ b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt
@@ -62,6 +62,15 @@
     private val isRobolectric = if (Build.FINGERPRINT.contains("robolectric")) true else false
 
     override fun apply(base: Statement, description: Description): Statement {
+        if (isRobolectric) {
+            // In robolectric mode, we enable NATIVE graphics and unpack font and icu files.
+            // We need to use reflection, as this library is only needed and therefore
+            //  only available in deviceless mode.
+            val nativeLoaderClassName = "org.robolectric.nativeruntime.DefaultNativeRuntimeLoader"
+            val defaultNativeRuntimeLoader = Class.forName(nativeLoaderClassName)
+            System.setProperty("robolectric.graphicsMode", "NATIVE")
+            defaultNativeRuntimeLoader.getMethod("injectAndLoad").invoke(null)
+        }
         val ruleToApply = if (isRobolectric) roboRule else delegateRule
         return ruleToApply.apply(base, description)
     }
@@ -69,6 +78,7 @@
     protected fun takeScreenshot(
         mode: Mode = Mode.WrapContent,
         viewProvider: (ComponentActivity) -> View,
+        beforeScreenshot: (ComponentActivity) -> Unit = {}
     ): Bitmap {
         activityRule.scenario.onActivity { activity ->
             // Make sure that the activity draws full screen and fits the whole display instead of
@@ -94,6 +104,7 @@
             val content = activity.requireViewById<ViewGroup>(android.R.id.content)
             assertEquals(1, content.childCount)
             contentView = content.getChildAt(0)
+            beforeScreenshot(activity)
         }
 
         return if (isRobolectric) {
@@ -111,9 +122,10 @@
     fun screenshotTest(
         goldenIdentifier: String,
         mode: Mode = Mode.WrapContent,
-        viewProvider: (ComponentActivity) -> View,
+        beforeScreenshot: (ComponentActivity) -> Unit = {},
+        viewProvider: (ComponentActivity) -> View
     ) {
-        val bitmap = takeScreenshot(mode, viewProvider)
+        val bitmap = takeScreenshot(mode, viewProvider, beforeScreenshot)
         screenshotRule.assertBitmapAgainstGolden(
             bitmap,
             goldenIdentifier,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java
index 9a9a242..6b67c09 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java
@@ -79,17 +79,26 @@
 
     /** Alerts listener and plugin that the plugin has been created. */
     public void onCreate() {
-        mListener.onPluginAttached(this);
+        boolean loadPlugin = mListener.onPluginAttached(this);
+        if (!loadPlugin) {
+            if (mPlugin != null) {
+                unloadPlugin();
+            }
+            return;
+        }
+
         if (mPlugin == null) {
             loadPlugin();
-        } else {
-            if (!(mPlugin instanceof PluginFragment)) {
-                // Only call onCreate for plugins that aren't fragments, as fragments
-                // will get the onCreate as part of the fragment lifecycle.
-                mPlugin.onCreate(mAppContext, mPluginContext);
-            }
-            mListener.onPluginLoaded(mPlugin, mPluginContext, this);
+            return;
         }
+
+        mPluginFactory.checkVersion(mPlugin);
+        if (!(mPlugin instanceof PluginFragment)) {
+            // Only call onCreate for plugins that aren't fragments, as fragments
+            // will get the onCreate as part of the fragment lifecycle.
+            mPlugin.onCreate(mAppContext, mPluginContext);
+        }
+        mListener.onPluginLoaded(mPlugin, mPluginContext, this);
     }
 
     /** Alerts listener and plugin that the plugin is being shutdown. */
@@ -118,6 +127,7 @@
             return;
         }
 
+        mPluginFactory.checkVersion(mPlugin);
         if (!(mPlugin instanceof PluginFragment)) {
             // Only call onCreate for plugins that aren't fragments, as fragments
             // will get the onCreate as part of the fragment lifecycle.
@@ -205,12 +215,8 @@
             PluginFactory<T> pluginFactory = new PluginFactory<T>(
                     context, mInstanceFactory, appInfo, componentName, mVersionChecker, pluginClass,
                     () -> getClassLoader(appInfo, mBaseClassLoader));
-            // TODO: Only create the plugin before version check if we need it for
-            // legacy version check.
-            T instance = pluginFactory.createPlugin();
-            pluginFactory.checkVersion(instance);
             return new PluginInstance<T>(
-                    context, listener, componentName, pluginFactory, instance);
+                    context, listener, componentName, pluginFactory, null);
         }
 
         private boolean isPluginPackagePrivileged(String packageName) {
@@ -332,7 +338,9 @@
                 ClassLoader loader = mClassLoaderFactory.get();
                 Class<T> instanceClass = (Class<T>) Class.forName(
                         mComponentName.getClassName(), true, loader);
-                return (T) mInstanceFactory.create(instanceClass);
+                T result = (T) mInstanceFactory.create(instanceClass);
+                Log.v(TAG, "Created plugin: " + result);
+                return result;
             } catch (ClassNotFoundException ex) {
                 Log.e(TAG, "Failed to load plugin", ex);
             } catch (IllegalAccessException ex) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 1721891..83c317f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -3565,7 +3565,6 @@
      */
     private void handleTimeUpdate() {
         Assert.isMainThread();
-        mLogger.d("handleTimeUpdate");
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -3630,9 +3629,9 @@
     private void handleBatteryUpdate(BatteryStatus status) {
         Assert.isMainThread();
         final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
-        mLogger.logHandleBatteryUpdate(batteryUpdateInteresting);
         mBatteryStatus = status;
         if (batteryUpdateInteresting) {
+            mLogger.logHandleBatteryUpdate(mBatteryStatus);
             for (int i = 0; i < mCallbacks.size(); i++) {
                 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
                 if (cb != null) {
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index 4923ab0..b596331 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -30,7 +30,7 @@
 import com.android.keyguard.KeyguardListenModel
 import com.android.keyguard.KeyguardUpdateMonitorCallback
 import com.android.keyguard.TrustGrantFlags
-import com.android.systemui.log.dagger.KeyguardUpdateMonitorLog
+import com.android.settingslib.fuelgauge.BatteryStatus
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.LogLevel
 import com.android.systemui.log.LogLevel.DEBUG
@@ -38,6 +38,7 @@
 import com.android.systemui.log.LogLevel.INFO
 import com.android.systemui.log.LogLevel.VERBOSE
 import com.android.systemui.log.LogLevel.WARNING
+import com.android.systemui.log.dagger.KeyguardUpdateMonitorLog
 import com.google.errorprone.annotations.CompileTimeConstant
 import javax.inject.Inject
 
@@ -683,8 +684,27 @@
         )
     }
 
-    fun logHandleBatteryUpdate(isInteresting: Boolean) {
-        logBuffer.log(TAG, DEBUG, { bool1 = isInteresting }, { "handleBatteryUpdate: $bool1" })
+    fun logHandleBatteryUpdate(batteryStatus: BatteryStatus?) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                bool1 = batteryStatus != null
+                int1 = batteryStatus?.status ?: -1
+                int2 = batteryStatus?.chargingStatus ?: -1
+                long1 = (batteryStatus?.level ?: -1).toLong()
+                long2 = (batteryStatus?.maxChargingWattage ?: -1).toLong()
+                str1 = "${batteryStatus?.plugged ?: -1}"
+            },
+            {
+                "handleBatteryUpdate: isNotNull: $bool1 " +
+                    "BatteryStatus{status= $int1, " +
+                    "level=$long1, " +
+                    "plugged=$str1, " +
+                    "chargingStatus=$int2, " +
+                    "maxChargingWattage= $long2}"
+            }
+        )
     }
 
     fun scheduleWatchdog(@CompileTimeConstant watchdogType: String) {
diff --git a/packages/SystemUI/src/com/android/systemui/DejankUtils.java b/packages/SystemUI/src/com/android/systemui/DejankUtils.java
index 3fce55f..146d12c 100644
--- a/packages/SystemUI/src/com/android/systemui/DejankUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/DejankUtils.java
@@ -29,13 +29,17 @@
 import android.os.RemoteException;
 import android.os.StrictMode;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.view.Choreographer;
+import android.view.View;
+import android.view.ViewRootImpl;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.util.Assert;
 
 import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.Random;
 import java.util.Stack;
 import java.util.function.Supplier;
 
@@ -43,12 +47,14 @@
  * Utility class for methods used to dejank the UI.
  */
 public class DejankUtils {
+    private static final String TRACK_NAME = "DejankUtils";
 
     public static final boolean STRICT_MODE_ENABLED = Build.IS_ENG
             || SystemProperties.getBoolean("persist.sysui.strictmode", false);
     private static final Choreographer sChoreographer = Choreographer.getInstance();
     private static final Handler sHandler = new Handler();
     private static final ArrayList<Runnable> sPendingRunnables = new ArrayList<>();
+    private static final Random sRandom = new Random();
     private static Stack<String> sBlockingIpcs = new Stack<>();
     private static boolean sTemporarilyIgnoreStrictMode;
     private static final HashSet<String> sWhitelistedFrameworkClasses = new HashSet<>();
@@ -254,4 +260,30 @@
     public static void setImmediate(boolean immediate) {
         sImmediate = immediate;
     }
+
+    /**
+     * Calls notifyRendererOfExpensiveFrame on the ViewRootImpl after performing null checks.
+     */
+    public static void notifyRendererOfExpensiveFrame(View view, String reason) {
+        if (view == null) return;
+        notifyRendererOfExpensiveFrame(view.getViewRootImpl(), reason);
+    }
+
+    /**
+     * Calls notifyRendererOfExpensiveFrame on the ViewRootImpl after performing null checks.
+     */
+    public static void notifyRendererOfExpensiveFrame(ViewRootImpl viewRoot, String reason) {
+        if (viewRoot == null) return;
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_APP)) {
+            int cookie = sRandom.nextInt();
+            Trace.asyncTraceForTrackBegin(
+                    Trace.TRACE_TAG_APP,
+                    TRACK_NAME,
+                    "notifyRendererOfExpensiveFrame (" + reason + ")",
+                    cookie);
+            DejankUtils.postAfterTraversal(
+                    () -> Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, TRACK_NAME, cookie));
+        }
+        viewRoot.notifyRendererOfExpensiveFrame();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index c30a214..8af92ce 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -548,6 +548,10 @@
             if (!cancelled) {
                 updateSwipeProgressFromOffset(animView, canBeDismissed);
                 resetSwipeOfView(animView);
+                // Clear the snapped view after success, assuming it's not being swiped now
+                if (animView == mTouchedView && !mIsSwiping) {
+                    mTouchedView = null;
+                }
             }
             onChildSnappedBack(animView, targetLeft);
         });
@@ -813,13 +817,39 @@
         }
     }
 
-    public void resetSwipeState() {
-        View swipedView = getSwipedView();
+    private void resetSwipeState() {
+        resetSwipeStates(/* resetAll= */ false);
+    }
+
+    public void resetTouchState() {
+        resetSwipeStates(/* resetAll= */ true);
+    }
+
+    /** This method resets the swipe state, and if `resetAll` is true, also resets the snap state */
+    private void resetSwipeStates(boolean resetAll) {
+        final View touchedView = mTouchedView;
+        final boolean wasSnapping = mSnappingChild;
+        final boolean wasSwiping = mIsSwiping;
         mTouchedView = null;
         mIsSwiping = false;
-        if (swipedView != null) {
-            snapChildIfNeeded(swipedView, false, 0);
-            onChildSnappedBack(swipedView, 0);
+        // If we were swiping, then we resetting swipe requires resetting everything.
+        resetAll |= wasSwiping;
+        if (resetAll) {
+            mSnappingChild = false;
+        }
+        if (touchedView == null) return;  // No view to reset visually
+        // When snap needs to be reset, first thing is to cancel any translation animation
+        final boolean snapNeedsReset = resetAll && wasSnapping;
+        if (snapNeedsReset) {
+            cancelTranslateAnimation(touchedView);
+        }
+        // actually reset the view to default state
+        if (resetAll) {
+            snapChildIfNeeded(touchedView, false, 0);
+        }
+        // report if a swipe or snap was reset.
+        if (wasSwiping || snapNeedsReset) {
+            onChildSnappedBack(touchedView, 0);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
index 69ce78c..cd8f04d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
@@ -961,6 +961,10 @@
         return Utils.isDeviceCredentialAllowed(mPromptInfo);
     }
 
+    public LottieAnimationView getIconView() {
+        return mIconView;
+    }
+
     @AuthDialog.DialogSize int getSize() {
         return mSize;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 43a3b99..7f70685 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -614,7 +614,11 @@
             return ((AuthBiometricFingerprintView) view).isUdfps();
         }
         if (view instanceof BiometricPromptLayout) {
-            return ((BiometricPromptLayout) view).isUdfps();
+            // this will force the prompt to align itself on the edge of the screen
+            // instead of centering (temporary workaround to prevent small implicit view
+            // from breaking due to the way gravity / margins are set in the legacy
+            // AuthPanelController
+            return true;
         }
 
         return false;
@@ -638,12 +642,12 @@
 
             case Surface.ROTATION_90:
                 mPanelController.setPosition(AuthPanelController.POSITION_RIGHT);
-                setScrollViewGravity(Gravity.BOTTOM | Gravity.RIGHT);
+                setScrollViewGravity(Gravity.CENTER_VERTICAL | Gravity.RIGHT);
                 break;
 
             case Surface.ROTATION_270:
                 mPanelController.setPosition(AuthPanelController.POSITION_LEFT);
-                setScrollViewGravity(Gravity.BOTTOM | Gravity.LEFT);
+                setScrollViewGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
                 break;
 
             case Surface.ROTATION_180:
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java
index acdde34..167067e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java
@@ -114,7 +114,13 @@
     }
 
     private int getTopBound(@Position int position) {
-        return Math.max(mContainerHeight - mContentHeight - mMargin, mMargin);
+        switch (position) {
+            case POSITION_LEFT:
+            case POSITION_RIGHT:
+                return Math.max((mContainerHeight - mContentHeight) / 2, mMargin);
+            default:
+                return Math.max(mContainerHeight - mContentHeight - mMargin, mMargin);
+        }
     }
 
     public void setContainerDimensions(int containerWidth, int containerHeight) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
index baaa96e..d48b9c33 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
@@ -35,6 +35,7 @@
 import android.util.Log
 import android.util.RotationUtils
 import android.view.Display
+import android.view.DisplayInfo
 import android.view.Gravity
 import android.view.LayoutInflater
 import android.view.Surface
@@ -58,6 +59,7 @@
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
+import com.android.systemui.util.boundsOnScreen
 import com.android.systemui.util.concurrency.DelayableExecutor
 import com.android.systemui.util.traceSection
 import java.io.PrintWriter
@@ -129,6 +131,8 @@
         }
     @VisibleForTesting var overlayOffsets: SensorLocationInternal = SensorLocationInternal.DEFAULT
 
+    private val displayInfo = DisplayInfo()
+
     private val overlayViewParams =
         WindowManager.LayoutParams(
                 WindowManager.LayoutParams.WRAP_CONTENT,
@@ -214,6 +218,23 @@
         for (requestSource in requests) {
             pw.println("     $requestSource.name")
         }
+
+        pw.println("overlayView:")
+        pw.println("     width=${overlayView?.width}")
+        pw.println("     height=${overlayView?.height}")
+        pw.println("     boundsOnScreen=${overlayView?.boundsOnScreen}")
+
+        pw.println("displayStateInteractor:")
+        pw.println("     isInRearDisplayMode=${displayStateInteractor?.isInRearDisplayMode?.value}")
+
+        pw.println("sensorProps:")
+        pw.println("     displayId=${displayInfo.uniqueId}")
+        pw.println("     sensorType=${sensorProps?.sensorType}")
+        pw.println("     location=${sensorProps?.getLocation(displayInfo.uniqueId)}")
+
+        pw.println("overlayOffsets=$overlayOffsets")
+        pw.println("isReverseDefaultRotation=$isReverseDefaultRotation")
+        pw.println("currentRotation=${displayInfo.rotation}")
     }
 
     private fun onOrientationChanged(@BiometricOverlayConstants.ShowReason reason: Int) {
@@ -226,6 +247,8 @@
         val view = layoutInflater.inflate(R.layout.sidefps_view, null, false)
         overlayView = view
         val display = context.display!!
+        // b/284098873 `context.display.rotation` may not up-to-date, we use displayInfo.rotation
+        display.getDisplayInfo(displayInfo)
         val offsets =
             sensorProps.getLocation(display.uniqueId).let { location ->
                 if (location == null) {
@@ -239,12 +262,12 @@
         view.rotation =
             display.asSideFpsAnimationRotation(
                 offsets.isYAligned(),
-                getRotationFromDefault(display.rotation)
+                getRotationFromDefault(displayInfo.rotation)
             )
         lottie.setAnimation(
             display.asSideFpsAnimation(
                 offsets.isYAligned(),
-                getRotationFromDefault(display.rotation)
+                getRotationFromDefault(displayInfo.rotation)
             )
         )
         lottie.addLottieOnCompositionLoadedListener {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacy.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacy.java
index a2840fc..056d692 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacy.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacy.java
@@ -103,6 +103,13 @@
     }
 
     @Override
+    void onSensorRectUpdated(RectF bounds) {
+        super.onSensorRectUpdated(bounds);
+        bounds.round(this.mSensorBounds);
+        postInvalidate();
+    }
+
+    @Override
     void onDisplayConfiguring() {
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt
index c935aa2..26b6f2a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/DisplayStateInteractor.kt
@@ -78,6 +78,7 @@
                             sendFoldStateUpdate(isFolded)
                         }
                     }
+
                 sendFoldStateUpdate(false)
                 screenSizeFoldProvider.registerCallback(callback, mainExecutor)
                 awaitClose { screenSizeFoldProvider.unregisterCallback(callback) }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/AuthBiometricFingerprintIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/AuthBiometricFingerprintIconViewBinder.kt
new file mode 100644
index 0000000..bd0907e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/AuthBiometricFingerprintIconViewBinder.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.biometrics.ui.binder
+
+import android.view.DisplayInfo
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import com.airbnb.lottie.LottieAnimationView
+import com.android.systemui.biometrics.AuthBiometricFingerprintView
+import com.android.systemui.biometrics.ui.viewmodel.AuthBiometricFingerprintViewModel
+import com.android.systemui.lifecycle.repeatWhenAttached
+import kotlinx.coroutines.launch
+
+/** Sub-binder for [AuthBiometricFingerprintView.mIconView]. */
+object AuthBiometricFingerprintIconViewBinder {
+
+    /**
+     * Binds a [AuthBiometricFingerprintView.mIconView] to a [AuthBiometricFingerprintViewModel].
+     */
+    @JvmStatic
+    fun bind(view: LottieAnimationView, viewModel: AuthBiometricFingerprintViewModel) {
+        view.repeatWhenAttached {
+            repeatOnLifecycle(Lifecycle.State.STARTED) {
+                val displayInfo = DisplayInfo()
+                view.context.display?.getDisplayInfo(displayInfo)
+                viewModel.setRotation(displayInfo.rotation)
+                viewModel.onConfigurationChanged(view.context.resources.configuration)
+                launch { viewModel.iconAsset.collect { iconAsset -> view.setAnimation(iconAsset) } }
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/AuthBiometricFingerprintViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/AuthBiometricFingerprintViewBinder.kt
index ae0cf37..9c1bcec 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/AuthBiometricFingerprintViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/AuthBiometricFingerprintViewBinder.kt
@@ -17,31 +17,18 @@
 
 package com.android.systemui.biometrics.ui.binder
 
-import android.view.Surface
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.repeatOnLifecycle
 import com.android.systemui.biometrics.AuthBiometricFingerprintView
 import com.android.systemui.biometrics.ui.viewmodel.AuthBiometricFingerprintViewModel
-import com.android.systemui.lifecycle.repeatWhenAttached
-import kotlinx.coroutines.launch
 
 object AuthBiometricFingerprintViewBinder {
 
-    /** Binds a [AuthBiometricFingerprintView] to a [AuthBiometricFingerprintViewModel]. */
+    /**
+     * Binds a [AuthBiometricFingerprintView.mIconView] to a [AuthBiometricFingerprintViewModel].
+     */
     @JvmStatic
     fun bind(view: AuthBiometricFingerprintView, viewModel: AuthBiometricFingerprintViewModel) {
-        view.repeatWhenAttached {
-            repeatOnLifecycle(Lifecycle.State.STARTED) {
-                viewModel.onConfigurationChanged(view.context.resources.configuration)
-                viewModel.setRotation(view.context.display?.orientation ?: Surface.ROTATION_0)
-                launch {
-                    viewModel.iconAsset.collect { iconAsset ->
-                        if (view.isSfps) {
-                            view.updateIconViewAnimation(iconAsset)
-                        }
-                    }
-                }
-            }
+        if (view.isSfps) {
+            AuthBiometricFingerprintIconViewBinder.bind(view.getIconView(), viewModel)
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
index e4c4e9a..1dffa80 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
@@ -19,8 +19,11 @@
 import android.animation.Animator
 import android.animation.AnimatorSet
 import android.animation.ValueAnimator
+import android.view.Surface
 import android.view.View
 import android.view.ViewGroup
+import android.view.WindowInsets
+import android.view.WindowManager
 import android.view.accessibility.AccessibilityManager
 import android.widget.TextView
 import androidx.core.animation.addListener
@@ -52,7 +55,9 @@
         panelViewController: AuthPanelController,
         jankListener: BiometricJankListener,
     ) {
-        val accessibilityManager = view.context.getSystemService(AccessibilityManager::class.java)!!
+        val windowManager = requireNotNull(view.context.getSystemService(WindowManager::class.java))
+        val accessibilityManager =
+            requireNotNull(view.context.getSystemService(AccessibilityManager::class.java))
         fun notifyAccessibilityChanged() {
             Utils.notifyAccessibilityContentChanged(accessibilityManager, view)
         }
@@ -102,15 +107,26 @@
                             when {
                                 size.isSmall -> {
                                     iconHolderView.alpha = 1f
+                                    val bottomInset =
+                                        windowManager.maximumWindowMetrics.windowInsets
+                                            .getInsets(WindowInsets.Type.navigationBars())
+                                            .bottom
                                     iconHolderView.y =
-                                        view.height - iconHolderView.height - iconPadding
+                                        if (view.isLandscape()) {
+                                            (view.height - iconHolderView.height - bottomInset) / 2f
+                                        } else {
+                                            view.height -
+                                                iconHolderView.height -
+                                                iconPadding -
+                                                bottomInset
+                                        }
                                     val newHeight =
-                                        iconHolderView.height + 2 * iconPadding.toInt() -
+                                        iconHolderView.height + (2 * iconPadding.toInt()) -
                                             iconHolderView.paddingTop -
                                             iconHolderView.paddingBottom
                                     panelViewController.updateForContentDimensions(
                                         width,
-                                        newHeight,
+                                        newHeight + bottomInset,
                                         0, /* animateDurationMs */
                                     )
                                 }
@@ -181,6 +197,11 @@
     }
 }
 
+private fun View.isLandscape(): Boolean {
+    val r = context.display.rotation
+    return r == Surface.ROTATION_90 || r == Surface.ROTATION_270
+}
+
 private fun TextView.showTextOrHide(forceHide: Boolean = false) {
     visibility = if (forceHide || text.isBlank()) View.GONE else View.VISIBLE
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfiguration.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfiguration.kt
index d7d17006..c921806 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfiguration.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfiguration.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.controls.controller
 
 interface ControlsTileResourceConfiguration {
+    fun getPackageName(): String?
     fun getTileTitleId(): Int
     fun getTileImageId(): Int
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImpl.kt
index c96d3d4..0249060 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImpl.kt
@@ -20,12 +20,14 @@
 import com.android.systemui.dagger.SysUISingleton
 import javax.inject.Inject
 
-/**
- * Default Instance for ControlsTileResourceConfiguration.
- */
+/** Default Instance for ControlsTileResourceConfiguration. */
 @SysUISingleton
-class ControlsTileResourceConfigurationImpl @Inject constructor()
-    : ControlsTileResourceConfiguration {
+class ControlsTileResourceConfigurationImpl @Inject constructor() :
+    ControlsTileResourceConfiguration {
+    override fun getPackageName(): String? {
+        return null
+    }
+
     override fun getTileTitleId(): Int {
         return R.string.quick_controls_title
     }
@@ -33,4 +35,4 @@
     override fun getTileImageId(): Int {
         return R.drawable.controls_icon
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
index 7509a8a..94e5633 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
@@ -29,9 +29,9 @@
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import dagger.Lazy
-import kotlinx.coroutines.flow.StateFlow
 import java.util.Optional
 import javax.inject.Inject
+import kotlinx.coroutines.flow.StateFlow
 
 /**
  * Pseudo-component to inject into classes outside `com.android.systemui.controls`.
@@ -40,26 +40,26 @@
  * instantiated if `featureEnabled` is true. Can also be queried for the availability of controls.
  */
 @SysUISingleton
-class ControlsComponent @Inject constructor(
-        @ControlsFeatureEnabled private val featureEnabled: Boolean,
-        private val context: Context,
-        private val lazyControlsController: Lazy<ControlsController>,
-        private val lazyControlsUiController: Lazy<ControlsUiController>,
-        private val lazyControlsListingController: Lazy<ControlsListingController>,
-        private val lockPatternUtils: LockPatternUtils,
-        private val keyguardStateController: KeyguardStateController,
-        private val userTracker: UserTracker,
-        controlsSettingsRepository: ControlsSettingsRepository,
-        optionalControlsTileResourceConfiguration: Optional<ControlsTileResourceConfiguration>
+class ControlsComponent
+@Inject
+constructor(
+    @ControlsFeatureEnabled private val featureEnabled: Boolean,
+    private val context: Context,
+    private val lazyControlsController: Lazy<ControlsController>,
+    private val lazyControlsUiController: Lazy<ControlsUiController>,
+    private val lazyControlsListingController: Lazy<ControlsListingController>,
+    private val lockPatternUtils: LockPatternUtils,
+    private val keyguardStateController: KeyguardStateController,
+    private val userTracker: UserTracker,
+    controlsSettingsRepository: ControlsSettingsRepository,
+    optionalControlsTileResourceConfiguration: Optional<ControlsTileResourceConfiguration>
 ) {
 
     val canShowWhileLockedSetting: StateFlow<Boolean> =
-            controlsSettingsRepository.canShowControlsInLockscreen
+        controlsSettingsRepository.canShowControlsInLockscreen
 
     private val controlsTileResourceConfiguration: ControlsTileResourceConfiguration =
-        optionalControlsTileResourceConfiguration.orElse(
-            ControlsTileResourceConfigurationImpl()
-        )
+        optionalControlsTileResourceConfiguration.orElse(ControlsTileResourceConfigurationImpl())
 
     fun getControlsController(): Optional<ControlsController> {
         return if (featureEnabled) Optional.of(lazyControlsController.get()) else Optional.empty()
@@ -77,9 +77,7 @@
         }
     }
 
-    /**
-     * @return true if controls are feature-enabled and the user has the setting enabled
-     */
+    /** @return true if controls are feature-enabled and the user has the setting enabled */
     fun isEnabled() = featureEnabled
 
     /**
@@ -90,8 +88,10 @@
      */
     fun getVisibility(): Visibility {
         if (!isEnabled()) return Visibility.UNAVAILABLE
-        if (lockPatternUtils.getStrongAuthForUser(userTracker.userHandle.identifier)
-                == STRONG_AUTH_REQUIRED_AFTER_BOOT) {
+        if (
+            lockPatternUtils.getStrongAuthForUser(userTracker.userHandle.identifier) ==
+                STRONG_AUTH_REQUIRED_AFTER_BOOT
+        ) {
             return Visibility.AVAILABLE_AFTER_UNLOCK
         }
         if (!canShowWhileLockedSetting.value && !keyguardStateController.isUnlocked()) {
@@ -102,7 +102,13 @@
     }
 
     enum class Visibility {
-        AVAILABLE, AVAILABLE_AFTER_UNLOCK, UNAVAILABLE
+        AVAILABLE,
+        AVAILABLE_AFTER_UNLOCK,
+        UNAVAILABLE
+    }
+
+    fun getPackageName(): String? {
+        return controlsTileResourceConfiguration.getPackageName()
     }
 
     fun getTileTitleId(): Int {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
index 78e132f..4b297a3 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
@@ -33,10 +33,10 @@
 import com.android.systemui.plugins.BcSmartspaceDataPlugin.UI_SURFACE_DREAM
 import com.android.systemui.smartspace.SmartspacePrecondition
 import com.android.systemui.smartspace.SmartspaceTargetFilter
-import com.android.systemui.smartspace.dagger.SmartspaceModule
 import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DREAM_SMARTSPACE_DATA_PLUGIN
 import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DREAM_SMARTSPACE_PRECONDITION
 import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DREAM_SMARTSPACE_TARGET_FILTER
+import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DREAM_WEATHER_SMARTSPACE_DATA_PLUGIN
 import com.android.systemui.smartspace.dagger.SmartspaceViewComponent
 import com.android.systemui.util.concurrency.Execution
 import java.util.Optional
@@ -58,7 +58,7 @@
     @Named(DREAM_SMARTSPACE_TARGET_FILTER)
     private val optionalTargetFilter: Optional<SmartspaceTargetFilter>,
     @Named(DREAM_SMARTSPACE_DATA_PLUGIN) optionalPlugin: Optional<BcSmartspaceDataPlugin>,
-    @Named(SmartspaceModule.WEATHER_SMARTSPACE_DATA_PLUGIN)
+    @Named(DREAM_WEATHER_SMARTSPACE_DATA_PLUGIN)
     optionalWeatherPlugin: Optional<BcSmartspaceDataPlugin>,
 ) {
     companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index e5fa209..1fbbe1c 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -601,7 +601,7 @@
 
     // 1300 - screenshots
     // TODO(b/264916608): Tracking Bug
-    @JvmField val SCREENSHOT_METADATA = unreleasedFlag(1302, "screenshot_metadata", teamfood = true)
+    @JvmField val SCREENSHOT_METADATA = unreleasedFlag(1302, "screenshot_metadata")
 
     // TODO(b/266955521): Tracking bug
     @JvmField val SCREENSHOT_DETECTION = releasedFlag(1303, "screenshot_detection")
@@ -728,6 +728,13 @@
     @JvmField
     val USE_NEW_ACTIVITY_STARTER = releasedFlag(2801, name = "use_new_activity_starter")
 
+    // 2900 - Zero Jank fixes. Naming convention is: zj_<bug number>_<cuj name>
+
+    // TODO:(b/285623104): Tracking bug
+    @JvmField
+    val ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD =
+        releasedFlag(2900, "zj_285570694_lockscreen_transition_from_aod")
+
     // TODO(b/283084712): Tracking Bug
     @JvmField
     val IMPROVED_HUN_ANIMATIONS = unreleasedFlag(283084712, "improved_hun_animations")
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt b/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
index 27a5974..bc07139 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
@@ -20,6 +20,7 @@
 import android.content.ContentProvider
 import android.content.ContentValues
 import android.content.Context
+import android.content.Intent
 import android.content.UriMatcher
 import android.content.pm.PackageManager
 import android.content.pm.ProviderInfo
@@ -282,11 +283,11 @@
                     Contract.LockScreenQuickAffordances.AffordanceTable.Columns.ICON,
                     Contract.LockScreenQuickAffordances.AffordanceTable.Columns.IS_ENABLED,
                     Contract.LockScreenQuickAffordances.AffordanceTable.Columns
-                        .ENABLEMENT_INSTRUCTIONS,
+                        .ENABLEMENT_EXPLANATION,
                     Contract.LockScreenQuickAffordances.AffordanceTable.Columns
                         .ENABLEMENT_ACTION_TEXT,
                     Contract.LockScreenQuickAffordances.AffordanceTable.Columns
-                        .ENABLEMENT_COMPONENT_NAME,
+                        .ENABLEMENT_ACTION_INTENT,
                     Contract.LockScreenQuickAffordances.AffordanceTable.Columns.CONFIGURE_INTENT,
                 )
             )
@@ -298,13 +299,10 @@
                             representation.name,
                             representation.iconResourceId,
                             if (representation.isEnabled) 1 else 0,
-                            representation.instructions?.joinToString(
-                                Contract.LockScreenQuickAffordances.AffordanceTable
-                                    .ENABLEMENT_INSTRUCTIONS_DELIMITER
-                            ),
+                            representation.explanation,
                             representation.actionText,
-                            representation.actionComponentName,
-                            representation.configureIntent?.toUri(0),
+                            representation.actionIntent?.toUri(Intent.URI_INTENT_SCHEME),
+                            representation.configureIntent?.toUri(Intent.URI_INTENT_SCHEME),
                         )
                     )
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 5a8c225..94227bc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -19,6 +19,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
 import static android.view.RemoteAnimationTarget.MODE_OPENING;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
@@ -182,7 +183,8 @@
 
     // Wrap Keyguard going away animation.
     // Note: Also used for wrapping occlude by Dream animation. It works (with some redundancy).
-    public static IRemoteTransition wrap(IRemoteAnimationRunner runner) {
+    public static IRemoteTransition wrap(final KeyguardViewMediator keyguardViewMediator,
+        final IRemoteAnimationRunner runner, final boolean lockscreenLiveWallpaperEnabled) {
         return new IRemoteTransition.Stub() {
 
             private final ArrayMap<SurfaceControl, SurfaceControl> mLeashMap = new ArrayMap<>();
@@ -213,7 +215,9 @@
                         }
                     }
                     initAlphaForAnimationTargets(t, apps);
-                    initAlphaForAnimationTargets(t, wallpapers);
+                    if (lockscreenLiveWallpaperEnabled) {
+                        initAlphaForAnimationTargets(t, wallpapers);
+                    }
                     t.apply();
                     mFinishCallback = finishCallback;
                     runner.onAnimationStart(
@@ -236,6 +240,12 @@
                     SurfaceControl.Transaction candidateT, IBinder currentTransition,
                     IRemoteTransitionFinishedCallback candidateFinishCallback)
                     throws RemoteException {
+                if ((candidateInfo.getFlags() & TRANSIT_FLAG_KEYGUARD_APPEARING) != 0) {
+                    keyguardViewMediator.setPendingLock(true);
+                    keyguardViewMediator.cancelKeyguardExitAnimation();
+                    return;
+                }
+
                 try {
                     synchronized (mLeashMap) {
                         runner.onAnimationCancelled();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index c706363..68e72c5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -19,6 +19,7 @@
 import android.animation.Animator
 import android.animation.AnimatorListenerAdapter
 import android.animation.ValueAnimator
+import android.app.WallpaperManager
 import android.content.Context
 import android.graphics.Matrix
 import android.graphics.Rect
@@ -50,6 +51,7 @@
 import com.android.systemui.statusbar.NotificationShadeWindowController
 import com.android.systemui.statusbar.SysuiStatusBarStateController
 import com.android.systemui.statusbar.phone.BiometricUnlockController
+import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import dagger.Lazy
 import javax.inject.Inject
@@ -148,7 +150,8 @@
     private val biometricUnlockControllerLazy: Lazy<BiometricUnlockController>,
     private val statusBarStateController: SysuiStatusBarStateController,
     private val notificationShadeWindowController: NotificationShadeWindowController,
-    private val powerManager: PowerManager
+    private val powerManager: PowerManager,
+    private val wallpaperManager: WallpaperManager
 ) : KeyguardStateController.Callback, ISysuiUnlockAnimationController.Stub() {
 
     interface KeyguardUnlockAnimationListener {
@@ -171,7 +174,7 @@
         @JvmDefault
         fun onUnlockAnimationStarted(
             playingCannedAnimation: Boolean,
-            fromWakeAndUnlock: Boolean,
+            isWakeAndUnlockNotFromDream: Boolean,
             unlockAnimationStartDelay: Long,
             unlockAnimationDuration: Long
         ) {}
@@ -204,6 +207,12 @@
     var playingCannedUnlockAnimation = false
 
     /**
+     * Whether we reached the swipe gesture threshold to dismiss keyguard, or restore it, once
+     * and should ignore any future changes to the dismiss amount before the animation finishes.
+     */
+    var dismissAmountThresholdsReached = false
+
+    /**
      * Remote callback provided by Launcher that allows us to control the Launcher's unlock
      * animation and smartspace.
      *
@@ -582,10 +591,13 @@
             playCannedUnlockAnimation()
         }
 
+        // Notify if waking from AOD only
+        val isWakeAndUnlockNotFromDream = biometricUnlockControllerLazy.get().isWakeAndUnlock &&
+            biometricUnlockControllerLazy.get().mode != MODE_WAKE_AND_UNLOCK_FROM_DREAM
         listeners.forEach {
             it.onUnlockAnimationStarted(
                 playingCannedUnlockAnimation /* playingCannedAnimation */,
-                biometricUnlockControllerLazy.get().isWakeAndUnlock /* isWakeAndUnlock */,
+                isWakeAndUnlockNotFromDream /* isWakeAndUnlockNotFromDream */,
                 CANNED_UNLOCK_START_DELAY /* unlockStartDelay */,
                 LAUNCHER_ICONS_ANIMATION_DURATION_MS /* unlockAnimationDuration */) }
 
@@ -647,6 +659,7 @@
 
     @VisibleForTesting
     fun unlockToLauncherWithInWindowAnimations() {
+        surfaceBehindAlpha = 1f
         setSurfaceBehindAppearAmount(1f, wallpapers = false)
 
         try {
@@ -686,8 +699,10 @@
                 return@postDelayed
             }
 
-            if (wallpaperTargets != null) {
-              fadeInWallpaper()
+            if ((wallpaperTargets?.isNotEmpty() == true) &&
+                    wallpaperManager.isLockscreenLiveWallpaperEnabled()) {
+                fadeInWallpaper()
+                hideKeyguardViewAfterRemoteAnimation()
             } else {
                 keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
                     false /* cancelled */)
@@ -758,6 +773,10 @@
             return
         }
 
+        if (dismissAmountThresholdsReached) {
+            return
+        }
+
         if (!keyguardStateController.isShowing) {
             return
         }
@@ -789,6 +808,11 @@
             return
         }
 
+        // no-op if we alreaddy reached a threshold.
+        if (dismissAmountThresholdsReached) {
+            return
+        }
+
         // no-op if animation is not requested yet.
         if (!keyguardViewMediator.get().requestedShowSurfaceBehindKeyguard() ||
                 !keyguardViewMediator.get().isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe) {
@@ -803,6 +827,7 @@
                         !keyguardStateController.isFlingingToDismissKeyguardDuringSwipeGesture &&
                         dismissAmount >= DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD)) {
             setSurfaceBehindAppearAmount(1f)
+            dismissAmountThresholdsReached = true
             keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
                     false /* cancelled */)
         }
@@ -937,6 +962,7 @@
         wallpaperTargets = null
 
         playingCannedUnlockAnimation = false
+        dismissAmountThresholdsReached = false
         willUnlockWithInWindowLauncherAnimations = false
         willUnlockWithSmartspaceTransition = false
 
@@ -961,7 +987,7 @@
                 0 /* fadeOutDuration */
             )
         } else {
-            Log.e(TAG, "#hideKeyguardViewAfterRemoteAnimation called when keyguard view is not " +
+            Log.i(TAG, "#hideKeyguardViewAfterRemoteAnimation called when keyguard view is not " +
                     "showing. Ignoring...")
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 3b40d86..6948c8d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -45,6 +45,7 @@
 import android.app.BroadcastOptions;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
+import android.app.WallpaperManager;
 import android.app.WindowConfiguration;
 import android.app.trust.TrustManager;
 import android.content.BroadcastReceiver;
@@ -93,7 +94,6 @@
 import android.view.WindowManagerPolicyConstants;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
-import android.window.IRemoteTransition;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -161,7 +161,6 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Optional;
 import java.util.concurrent.Executor;
 
 /**
@@ -280,6 +279,7 @@
     private AlarmManager mAlarmManager;
     private AudioManager mAudioManager;
     private StatusBarManager mStatusBarManager;
+    private WallpaperManager mWallpaperManager;
     private final IStatusBarService mStatusBarService;
     private final IBinder mStatusBarDisableToken = new Binder();
     private final UserTracker mUserTracker;
@@ -1350,11 +1350,12 @@
             setShowingLocked(false /* showing */, true /* forceCallbacks */);
         }
 
+        boolean isLLwpEnabled = getWallpaperManager().isLockscreenLiveWallpaperEnabled();
         mKeyguardTransitions.register(
-                KeyguardService.wrap(getExitAnimationRunner()),
-                KeyguardService.wrap(getOccludeAnimationRunner()),
-                KeyguardService.wrap(getOccludeByDreamAnimationRunner()),
-                KeyguardService.wrap(getUnoccludeAnimationRunner()));
+                KeyguardService.wrap(this, getExitAnimationRunner(), isLLwpEnabled),
+                KeyguardService.wrap(this, getOccludeAnimationRunner(), isLLwpEnabled),
+                KeyguardService.wrap(this, getOccludeByDreamAnimationRunner(), isLLwpEnabled),
+                KeyguardService.wrap(this, getUnoccludeAnimationRunner(), isLLwpEnabled));
 
         final ContentResolver cr = mContext.getContentResolver();
 
@@ -1400,6 +1401,14 @@
         mWorkLockController = new WorkLockActivityController(mContext, mUserTracker);
     }
 
+    // TODO(b/273443374) remove, temporary util to get a feature flag
+    private WallpaperManager getWallpaperManager() {
+        if (mWallpaperManager == null) {
+            mWallpaperManager = mContext.getSystemService(WallpaperManager.class);
+        }
+        return mWallpaperManager;
+    }
+
     @Override
     public void start() {
         synchronized (this) {
@@ -1902,19 +1911,19 @@
     }
 
     public IRemoteAnimationRunner getExitAnimationRunner() {
-        return mExitAnimationRunner;
+        return validatingRemoteAnimationRunner(mExitAnimationRunner);
     }
 
     public IRemoteAnimationRunner getOccludeAnimationRunner() {
-        return mOccludeAnimationRunner;
+        return validatingRemoteAnimationRunner(mOccludeAnimationRunner);
     }
 
     public IRemoteAnimationRunner getOccludeByDreamAnimationRunner() {
-        return mOccludeByDreamAnimationRunner;
+        return validatingRemoteAnimationRunner(mOccludeByDreamAnimationRunner);
     }
 
     public IRemoteAnimationRunner getUnoccludeAnimationRunner() {
-        return mUnoccludeAnimationRunner;
+        return validatingRemoteAnimationRunner(mUnoccludeAnimationRunner);
     }
 
     public boolean isHiding() {
@@ -1943,7 +1952,8 @@
                 startKeyguardExitAnimation(0, 0);
             }
 
-            mPowerGestureIntercepted = mUpdateMonitor.isSecureCameraLaunchedOverKeyguard();
+            mPowerGestureIntercepted =
+                    isOccluded && mUpdateMonitor.isSecureCameraLaunchedOverKeyguard();
 
             if (mOccluded != isOccluded) {
                 mOccluded = isOccluded;
@@ -2894,6 +2904,7 @@
             // re-locking. We should just end the surface-behind animation without exiting the
             // keyguard. The pending lock will be handled by onFinishedGoingToSleep().
             finishSurfaceBehindRemoteAnimation(true);
+            maybeHandlePendingLock();
         } else {
             Log.d(TAG, "#handleCancelKeyguardExitAnimation: keyguard exit animation cancelled. "
                     + "No pending lock, we should end up unlocked with the app/launcher visible.");
@@ -3249,8 +3260,6 @@
     /**
      * Cancel the keyguard exit animation, usually because we were swiping to unlock but WM starts
      * a new remote animation before finishing the keyguard exit animation.
-     *
-     * This will dismiss the keyguard.
      */
     public void cancelKeyguardExitAnimation() {
         Trace.beginSection("KeyguardViewMediator#cancelKeyguardExitAnimation");
@@ -3423,11 +3432,15 @@
         }
     }
 
-    private void setPendingLock(boolean hasPendingLock) {
+    public void setPendingLock(boolean hasPendingLock) {
         mPendingLock = hasPendingLock;
         Trace.traceCounter(Trace.TRACE_TAG_APP, "pendingLock", mPendingLock ? 1 : 0);
     }
 
+    private boolean isViewRootReady() {
+        return mKeyguardViewControllerLazy.get().getViewRootImpl() != null;
+    }
+
     public void addStateMonitorCallback(IKeyguardStateCallback callback) {
         synchronized (this) {
             mKeyguardStateCallbacks.add(callback);
@@ -3530,4 +3543,27 @@
             mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_OCCLUSION);
         }
     }
+
+    private IRemoteAnimationRunner validatingRemoteAnimationRunner(IRemoteAnimationRunner wrapped) {
+        return new IRemoteAnimationRunner.Stub() {
+            @Override
+            public void onAnimationCancelled() throws RemoteException {
+                wrapped.onAnimationCancelled();
+            }
+
+            @Override
+            public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
+                                         RemoteAnimationTarget[] wallpapers,
+                                         RemoteAnimationTarget[] nonApps,
+                                         IRemoteAnimationFinishedCallback finishedCallback)
+                    throws RemoteException {
+                if (!isViewRootReady()) {
+                    Log.w(TAG, "Skipping remote animation - view root not ready");
+                    return;
+                }
+
+                wrapped.onAnimationStart(transit, apps, wallpapers, nonApps, finishedCallback);
+            }
+        };
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt
index abb63c4..f3fc809 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt
@@ -17,6 +17,7 @@
 
 package com.android.systemui.keyguard.data.quickaffordance
 
+import android.content.ComponentName
 import android.content.Context
 import android.content.Intent
 import androidx.annotation.DrawableRes
@@ -34,6 +35,7 @@
 import com.android.systemui.controls.ui.ControlsUiController
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.Companion.appStoreIntent
 import com.android.systemui.util.kotlin.getOrNull
 import javax.inject.Inject
 import kotlinx.coroutines.channels.awaitClose
@@ -76,18 +78,44 @@
             component.getControlsListingController().getOrNull()?.getCurrentServices()
         val hasFavorites =
             component.getControlsController().getOrNull()?.getFavorites()?.isNotEmpty() == true
-        if (currentServices.isNullOrEmpty() || !hasFavorites) {
-            return KeyguardQuickAffordanceConfig.PickerScreenState.Disabled(
-                instructions =
-                    listOf(
+        val componentPackageName = component.getPackageName()
+        when {
+            currentServices.isNullOrEmpty() && !componentPackageName.isNullOrEmpty() -> {
+                // No home app installed but we know which app we want to install.
+                return disabledPickerState(
+                    explanation =
                         context.getString(
-                            R.string.keyguard_affordance_enablement_dialog_home_instruction_1
+                            R.string.home_quick_affordance_unavailable_install_the_app
                         ),
+                    actionText = context.getString(R.string.install_app),
+                    actionIntent = appStoreIntent(context, componentPackageName),
+                )
+            }
+            currentServices.isNullOrEmpty() && componentPackageName.isNullOrEmpty() -> {
+                // No home app installed and we don't know which app we want to install.
+                return disabledPickerState(
+                    explanation =
                         context.getString(
-                            R.string.keyguard_affordance_enablement_dialog_home_instruction_2
+                            R.string.home_quick_affordance_unavailable_install_the_app
                         ),
-                    ),
-            )
+                )
+            }
+            !hasFavorites -> {
+                // Home app installed but no favorites selected.
+                val activityClass = component.getControlsUiController().get().resolveActivity()
+                return disabledPickerState(
+                    explanation =
+                        context.getString(
+                            R.string.home_quick_affordance_unavailable_configure_the_app
+                        ),
+                    actionText = context.getString(R.string.controls_open_app),
+                    actionIntent =
+                        Intent().apply {
+                            component = ComponentName(context, activityClass)
+                            putExtra(ControlsUiController.EXTRA_ANIMATE, true)
+                        },
+                )
+            }
         }
 
         return KeyguardQuickAffordanceConfig.PickerScreenState.Default()
@@ -172,6 +200,20 @@
         }
     }
 
+    private fun disabledPickerState(
+        explanation: String,
+        actionText: String? = null,
+        actionIntent: Intent? = null,
+    ): KeyguardQuickAffordanceConfig.PickerScreenState.Disabled {
+        check(actionIntent == null || actionText != null)
+
+        return KeyguardQuickAffordanceConfig.PickerScreenState.Disabled(
+            explanation = explanation,
+            actionText = actionText,
+            actionIntent = actionIntent,
+        )
+    }
+
     companion object {
         private const val TAG = "HomeControlsKeyguardQuickAffordanceConfig"
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfig.kt
index 28dc5bd..320d158 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfig.kt
@@ -18,11 +18,13 @@
 package com.android.systemui.keyguard.data.quickaffordance
 
 import android.app.AlertDialog
+import android.content.Context
 import android.content.Intent
+import android.net.Uri
+import com.android.systemui.R
 import com.android.systemui.animation.Expandable
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
-import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
 import kotlinx.coroutines.flow.Flow
 
 /** Defines interface that can act as data source for a single quick affordance model. */
@@ -80,37 +82,35 @@
 
         /**
          * The picker shows the item for selecting this affordance as disabled. Clicking on it will
-         * show the given instructions to the user. If [actionText] and [actionComponentName] are
-         * provided (optional) a button will be shown to open an activity to help the user complete
-         * the steps described in the instructions.
+         * show the given instructions to the user. If [actionText] and [actionIntent] are provided
+         * (optional) a button will be shown to open an activity to help the user complete the steps
+         * described in the instructions.
          */
         data class Disabled(
-            /** List of human-readable instructions for setting up the quick affordance. */
-            val instructions: List<String>,
+            /** Human-readable explanation as to why the quick affordance is current disabled. */
+            val explanation: String,
             /**
              * Optional text to display on a button that the user can click to start a flow to go
              * and set up the quick affordance and make it enabled.
              */
             val actionText: String? = null,
             /**
-             * Optional component name to be able to build an `Intent` that opens an `Activity` for
-             * the user to be able to set up the quick affordance and make it enabled.
-             *
-             * This is either just an action for the `Intent` or a package name and action,
-             * separated by
-             * [Contract.LockScreenQuickAffordances.AffordanceTable.COMPONENT_NAME_SEPARATOR] for
-             * convenience, you can use the [componentName] function.
+             * Optional [Intent] that opens an `Activity` for the user to be able to set up the
+             * quick affordance and make it enabled.
              */
-            val actionComponentName: String? = null,
+            val actionIntent: Intent? = null,
         ) : PickerScreenState() {
             init {
-                check(instructions.isNotEmpty()) { "Instructions must not be empty!" }
+                check(explanation.isNotEmpty()) { "Explanation must not be empty!" }
                 check(
-                    (actionText.isNullOrEmpty() && actionComponentName.isNullOrEmpty()) ||
-                        (!actionText.isNullOrEmpty() && !actionComponentName.isNullOrEmpty())
+                    (actionText.isNullOrEmpty() && actionIntent == null) ||
+                        (!actionText.isNullOrEmpty() && actionIntent != null)
                 ) {
-                    "actionText and actionComponentName must either both be null/empty or both be" +
-                        " non-empty!"
+                    """
+                        actionText and actionIntent must either both be null/empty or both be
+                        non-null and non-empty!
+                    """
+                        .trimIndent()
                 }
             }
         }
@@ -163,17 +163,33 @@
     }
 
     companion object {
-        fun componentName(
-            packageName: String? = null,
-            action: String?,
-        ): String? {
-            return when {
-                action.isNullOrEmpty() -> null
-                !packageName.isNullOrEmpty() ->
-                    "$packageName${Contract.LockScreenQuickAffordances.AffordanceTable
-                        .COMPONENT_NAME_SEPARATOR}$action"
-                else -> action
+
+        /**
+         * Returns an [Intent] that can be used to start an activity that opens the app store app to
+         * a page showing the app with the passed-in [packageName].
+         *
+         * If the feature isn't enabled on this device/variant/configuration, a `null` will be
+         * returned.
+         */
+        fun appStoreIntent(context: Context, packageName: String?): Intent? {
+            if (packageName.isNullOrEmpty()) {
+                return null
+            }
+
+            val appStorePackageName = context.getString(R.string.config_appStorePackageName)
+            val linkTemplate = context.getString(R.string.config_appStoreAppLinkTemplate)
+            if (appStorePackageName.isEmpty() || linkTemplate.isEmpty()) {
+                return null
+            }
+
+            check(linkTemplate.contains(APP_PACKAGE_NAME_PLACEHOLDER))
+
+            return Intent(Intent.ACTION_VIEW).apply {
+                setPackage(appStorePackageName)
+                data = Uri.parse(linkTemplate.replace(APP_PACKAGE_NAME_PLACEHOLDER, packageName))
             }
         }
+
+        private const val APP_PACKAGE_NAME_PLACEHOLDER = "\$packageName"
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfig.kt
index 0d54ab9..20ed549 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfig.kt
@@ -80,16 +80,14 @@
         return when {
             !controller.isAvailableOnDevice ->
                 KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
-            !controller.isAbleToOpenCameraApp ->
+            !controller.isAbleToOpenCameraApp -> {
                 KeyguardQuickAffordanceConfig.PickerScreenState.Disabled(
-                    instructions =
-                        listOf(
-                            context.getString(
-                                R.string
-                                    .keyguard_affordance_enablement_dialog_qr_scanner_instruction
-                            ),
+                    explanation =
+                        context.getString(
+                            R.string.qr_scanner_quick_affordance_unavailable_explanation
                         ),
                 )
+            }
             else -> KeyguardQuickAffordanceConfig.PickerScreenState.Default()
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
index 44e74e7..c019d21 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
@@ -63,7 +63,7 @@
                         val hasCards = response?.walletCards?.isNotEmpty() == true
                         trySendWithFailureLogging(
                             state(
-                                isFeatureEnabled = walletController.isWalletEnabled,
+                                isFeatureEnabled = isWalletAvailable(),
                                 hasCard = hasCards,
                                 tileIcon = walletController.walletClient.tileIcon,
                             ),
@@ -100,19 +100,20 @@
         return when {
             !walletController.walletClient.isWalletServiceAvailable ->
                 KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
-            !walletController.isWalletEnabled || queryCards().isEmpty() -> {
+            !isWalletAvailable() ->
                 KeyguardQuickAffordanceConfig.PickerScreenState.Disabled(
-                    instructions =
-                        listOf(
-                            context.getString(
-                                R.string.keyguard_affordance_enablement_dialog_wallet_instruction_1
-                            ),
-                            context.getString(
-                                R.string.keyguard_affordance_enablement_dialog_wallet_instruction_2
-                            ),
+                    explanation =
+                        context.getString(
+                            R.string.wallet_quick_affordance_unavailable_install_the_app
                         ),
                 )
-            }
+            queryCards().isEmpty() ->
+                KeyguardQuickAffordanceConfig.PickerScreenState.Disabled(
+                    explanation =
+                        context.getString(
+                            R.string.wallet_quick_affordance_unavailable_configure_the_app
+                        ),
+                )
             else -> KeyguardQuickAffordanceConfig.PickerScreenState.Default()
         }
     }
@@ -146,6 +147,9 @@
         }
     }
 
+    private fun isWalletAvailable() =
+        with(walletController.walletClient) { isWalletServiceAvailable && isWalletFeatureAvailable }
+
     private fun state(
         isFeatureEnabled: Boolean,
         hasCard: Boolean,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
index 96c94d7..34f6b4d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
@@ -18,6 +18,7 @@
 package com.android.systemui.keyguard.data.repository
 
 import android.content.Context
+import android.content.Intent
 import android.os.UserHandle
 import android.util.LayoutDirection
 import com.android.systemui.Dumpable
@@ -174,12 +175,23 @@
                     iconResourceId = config.pickerIconResourceId,
                     isEnabled =
                         pickerState is KeyguardQuickAffordanceConfig.PickerScreenState.Default,
-                    instructions = disabledPickerState?.instructions,
+                    explanation = disabledPickerState?.explanation,
                     actionText = disabledPickerState?.actionText,
-                    actionComponentName = disabledPickerState?.actionComponentName,
-                    configureIntent = defaultPickerState?.configureIntent,
+                    actionIntent =
+                        disabledPickerState?.actionIntent?.apply {
+                            addFlags(
+                                Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
+                            )
+                        },
+                    configureIntent =
+                        defaultPickerState?.configureIntent?.apply {
+                            addFlags(
+                                Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
+                            )
+                        },
                 )
             }
+            .sortedBy { it.name }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
index 2275337..ea9c2b2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
@@ -35,6 +35,7 @@
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
+import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
 import com.android.systemui.keyguard.domain.model.KeyguardQuickAffordanceModel
 import com.android.systemui.keyguard.domain.quickaffordance.KeyguardQuickAffordanceRegistry
@@ -77,6 +78,7 @@
     private val logger: KeyguardQuickAffordancesMetricsLogger,
     private val devicePolicyManager: DevicePolicyManager,
     private val dockManager: DockManager,
+    private val biometricSettingsRepository: BiometricSettingsRepository,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
     @Application private val appContext: Context,
 ) {
@@ -107,9 +109,10 @@
             quickAffordanceAlwaysVisible(position),
             keyguardInteractor.isDozing,
             keyguardInteractor.isKeyguardShowing,
-            keyguardInteractor.isQuickSettingsVisible
-        ) { affordance, isDozing, isKeyguardShowing, isQuickSettingsVisible ->
-            if (!isDozing && isKeyguardShowing && !isQuickSettingsVisible) {
+            keyguardInteractor.isQuickSettingsVisible,
+            biometricSettingsRepository.isCurrentUserInLockdown,
+        ) { affordance, isDozing, isKeyguardShowing, isQuickSettingsVisible, isUserInLockdown ->
+            if (!isDozing && isKeyguardShowing && !isQuickSettingsVisible && !isUserInLockdown) {
                 affordance
             } else {
                 KeyguardQuickAffordanceModel.Hidden
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardQuickAffordancePickerRepresentation.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardQuickAffordancePickerRepresentation.kt
index e7e9159..c6320de 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardQuickAffordancePickerRepresentation.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardQuickAffordancePickerRepresentation.kt
@@ -32,8 +32,8 @@
     /** Whether this quick affordance is enabled. */
     val isEnabled: Boolean = true,
 
-    /** If not enabled, the list of user-visible steps to re-enable it. */
-    val instructions: List<String>? = null,
+    /** If not enabled, a user-visible explanation as to why. */
+    val explanation: String? = null,
 
     /**
      * If not enabled, an optional label for a button that takes the user to a destination where
@@ -41,11 +41,8 @@
      */
     val actionText: String? = null,
 
-    /**
-     * If not enabled, an optional component name (package and action) for a button that takes the
-     * user to a destination where they can re-enable it.
-     */
-    val actionComponentName: String? = null,
+    /** Optional [Intent] to use to start an activity to re-enable this affordance. */
+    val actionIntent: Intent? = null,
 
     /** Optional [Intent] to use to start an activity to configure this affordance. */
     val configureIntent: Intent? = null,
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
index c41f82b..8d3c6d5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
@@ -38,8 +38,6 @@
 import com.android.internal.app.chooser.NotSelectableTargetInfo
 import com.android.internal.app.chooser.TargetInfo
 import com.android.systemui.R
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorComponent
 import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorController
 import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorResultHandler
@@ -53,7 +51,6 @@
 class MediaProjectionAppSelectorActivity(
     private val componentFactory: MediaProjectionAppSelectorComponent.Factory,
     private val activityLauncher: AsyncActivityLauncher,
-    private val featureFlags: FeatureFlags,
     /** This is used to override the dependency in a screenshot test */
     @VisibleForTesting
     private val listControllerFactory: ((userHandle: UserHandle) -> ResolverListController)?
@@ -62,9 +59,8 @@
     @Inject
     constructor(
         componentFactory: MediaProjectionAppSelectorComponent.Factory,
-        activityLauncher: AsyncActivityLauncher,
-        featureFlags: FeatureFlags
-    ) : this(componentFactory, activityLauncher, featureFlags, listControllerFactory = null)
+        activityLauncher: AsyncActivityLauncher
+    ) : this(componentFactory, activityLauncher, listControllerFactory = null)
 
     private lateinit var configurationController: ConfigurationController
     private lateinit var controller: MediaProjectionAppSelectorController
@@ -108,11 +104,7 @@
     override fun appliedThemeResId(): Int = R.style.Theme_SystemUI_MediaProjectionAppSelector
 
     override fun createBlockerEmptyStateProvider(): EmptyStateProvider =
-        if (featureFlags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES)) {
-            component.emptyStateProvider
-        } else {
-            object : EmptyStateProvider {}
-        }
+        component.emptyStateProvider
 
     override fun createListController(userHandle: UserHandle): ResolverListController =
         listControllerFactory?.invoke(userHandle) ?: super.createListController(userHandle)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
index 516fbf5..0819d0d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
@@ -76,7 +76,6 @@
 
 import com.android.app.animation.Interpolators;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.graphics.ColorUtils;
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.logging.InstanceId;
 import com.android.internal.widget.CachingIconView;
@@ -249,9 +248,9 @@
     private final FeatureFlags mFeatureFlags;
     private final GlobalSettings mGlobalSettings;
 
-    // TODO(b/281032715): Consider making this as a final variable. For now having a null check
-    //  due to unit test failure. (Perhaps missing some setup)
     private TurbulenceNoiseAnimationConfig mTurbulenceNoiseAnimationConfig;
+    private boolean mWasPlaying = false;
+    private boolean mButtonClicked = false;
 
     private ContentObserver mAnimationScaleObserver = new ContentObserver(null) {
         @Override
@@ -583,6 +582,25 @@
         if (!mMetadataAnimationHandler.isRunning()) {
             mMediaViewController.refreshState();
         }
+
+        // Turbulence noise
+        if (shouldPlayTurbulenceNoise()) {
+            if (mTurbulenceNoiseAnimationConfig == null) {
+                mTurbulenceNoiseAnimationConfig =
+                        createTurbulenceNoiseAnimation();
+            }
+            // Color will be correctly updated in ColorSchemeTransition.
+            mTurbulenceNoiseController.play(
+                    mTurbulenceNoiseAnimationConfig
+            );
+            mMainExecutor.executeDelayed(
+                    mTurbulenceNoiseController::finish,
+                    TURBULENCE_NOISE_PLAY_DURATION
+            );
+        }
+        mButtonClicked = false;
+        mWasPlaying = isPlaying();
+
         Trace.endSection();
     }
 
@@ -1156,21 +1174,14 @@
                     if (!mFalsingManager.isFalseTap(FalsingManager.MODERATE_PENALTY)) {
                         mLogger.logTapAction(button.getId(), mUid, mPackageName, mInstanceId);
                         logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT);
+                        // Used to determine whether to play turbulence noise.
+                        mWasPlaying = isPlaying();
+                        mButtonClicked = true;
+
                         action.run();
+
                         if (mFeatureFlags.isEnabled(Flags.UMO_SURFACE_RIPPLE)) {
                             mMultiRippleController.play(createTouchRippleAnimation(button));
-                            if (mFeatureFlags.isEnabled(Flags.UMO_TURBULENCE_NOISE)) {
-                                if (mTurbulenceNoiseAnimationConfig == null) {
-                                    mTurbulenceNoiseAnimationConfig =
-                                            createTurbulenceNoiseAnimation();
-                                }
-                                // Color will be correctly updated in ColorSchemeTransition.
-                                mTurbulenceNoiseController.play(mTurbulenceNoiseAnimationConfig);
-                                mMainExecutor.executeDelayed(
-                                        mTurbulenceNoiseController::finish,
-                                        TURBULENCE_NOISE_PLAY_DURATION
-                                );
-                            }
                         }
 
                         if (icon instanceof Animatable) {
@@ -1209,26 +1220,31 @@
         );
     }
 
+    private boolean shouldPlayTurbulenceNoise() {
+        return mFeatureFlags.isEnabled(Flags.UMO_TURBULENCE_NOISE) && mButtonClicked && !mWasPlaying
+                && isPlaying();
+    }
+
     private TurbulenceNoiseAnimationConfig createTurbulenceNoiseAnimation() {
         return new TurbulenceNoiseAnimationConfig(
-                TurbulenceNoiseAnimationConfig.DEFAULT_NOISE_GRID_COUNT,
+                /* gridCount= */ 2.14f,
                 TurbulenceNoiseAnimationConfig.DEFAULT_LUMINOSITY_MULTIPLIER,
-                /* noiseMoveSpeedX= */ 0f,
+                /* noiseMoveSpeedX= */ 0.42f,
                 /* noiseMoveSpeedY= */ 0f,
                 TurbulenceNoiseAnimationConfig.DEFAULT_NOISE_SPEED_Z,
                 /* color= */ mColorSchemeTransition.getAccentPrimary().getCurrentColor(),
-                // We want to add (BlendMode.PLUS) the turbulence noise on top of the album art.
-                // Thus, set the background color with alpha 0.
-                /* backgroundColor= */ ColorUtils.setAlphaComponent(Color.BLACK, 0),
-                TurbulenceNoiseAnimationConfig.DEFAULT_OPACITY,
-                /* width= */ mMediaViewHolder.getMultiRippleView().getWidth(),
-                /* height= */ mMediaViewHolder.getMultiRippleView().getHeight(),
+                /* backgroundColor= */ Color.BLACK,
+                /* opacity= */ 51,
+                /* width= */ mMediaViewHolder.getTurbulenceNoiseView().getWidth(),
+                /* height= */ mMediaViewHolder.getTurbulenceNoiseView().getHeight(),
                 TurbulenceNoiseAnimationConfig.DEFAULT_MAX_DURATION_IN_MILLIS,
-                /* easeInDuration= */ 2500f,
-                /* easeOutDuration= */ 2500f,
-                this.getContext().getResources().getDisplayMetrics().density,
-                BlendMode.PLUS,
-                /* onAnimationEnd= */ null
+                /* easeInDuration= */ 1350f,
+                /* easeOutDuration= */ 1350f,
+                getContext().getResources().getDisplayMetrics().density,
+                BlendMode.SCREEN,
+                /* onAnimationEnd= */ null,
+                /* lumaMatteBlendFactor= */ 0.26f,
+                /* lumaMatteOverallBrightness= */ 0.09f
         );
     }
     private void clearButton(final ImageButton button) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java
index abf0932..b4578e9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java
@@ -41,6 +41,7 @@
 import androidx.annotation.NonNull;
 import androidx.core.graphics.drawable.IconCompat;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.media.BluetoothMediaDevice;
 import com.android.settingslib.media.MediaDevice;
 import com.android.settingslib.qrcode.QrCodeGenerator;
@@ -58,6 +59,17 @@
 public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog {
     private static final String TAG = "MediaOutputBroadcastDialog";
 
+    static final int METADATA_BROADCAST_NAME = 0;
+    static final int METADATA_BROADCAST_CODE = 1;
+
+    private static final int MAX_BROADCAST_INFO_UPDATE = 3;
+    @VisibleForTesting
+    static final int BROADCAST_CODE_MAX_LENGTH = 16;
+    @VisibleForTesting
+    static final int BROADCAST_CODE_MIN_LENGTH = 4;
+    @VisibleForTesting
+    static final int BROADCAST_NAME_MAX_LENGTH = 254;
+
     private ViewStub mBroadcastInfoArea;
     private ImageView mBroadcastQrCodeView;
     private ImageView mBroadcastNotify;
@@ -67,14 +79,16 @@
     private ImageView mBroadcastCodeEye;
     private Boolean mIsPasswordHide = true;
     private ImageView mBroadcastCodeEdit;
-    private AlertDialog mAlertDialog;
+    @VisibleForTesting
+    AlertDialog mAlertDialog;
     private TextView mBroadcastErrorMessage;
     private int mRetryCount = 0;
     private String mCurrentBroadcastName;
     private String mCurrentBroadcastCode;
     private boolean mIsStopbyUpdateBroadcastCode = false;
+    private boolean mIsLeBroadcastAssistantCallbackRegistered;
 
-    private TextWatcher mTextWatcher = new TextWatcher() {
+    private TextWatcher mBroadcastCodeTextWatcher = new TextWatcher() {
         @Override
         public void beforeTextChanged(CharSequence s, int start, int count, int after) {
             // Do nothing
@@ -102,7 +116,9 @@
                         R.string.media_output_broadcast_code_hint_no_less_than_min);
             } else if (breakBroadcastCodeRuleTextLengthMoreThanMax) {
                 mBroadcastErrorMessage.setText(
-                        R.string.media_output_broadcast_code_hint_no_more_than_max);
+                        mContext.getResources().getString(
+                                R.string.media_output_broadcast_edit_hint_no_more_than_max,
+                                BROADCAST_CODE_MAX_LENGTH));
             }
 
             mBroadcastErrorMessage.setVisibility(breakRule ? View.VISIBLE : View.INVISIBLE);
@@ -113,7 +129,40 @@
         }
     };
 
-    private boolean mIsLeBroadcastAssistantCallbackRegistered;
+    private TextWatcher mBroadcastNameTextWatcher = new TextWatcher() {
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+            // Do nothing
+        }
+
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+            // Do nothing
+        }
+
+        @Override
+        public void afterTextChanged(Editable s) {
+            if (mAlertDialog == null || mBroadcastErrorMessage == null) {
+                return;
+            }
+            boolean breakBroadcastNameRuleTextLengthMoreThanMax =
+                    s.length() > BROADCAST_NAME_MAX_LENGTH;
+            boolean breakRule = breakBroadcastNameRuleTextLengthMoreThanMax || (s.length() == 0);
+
+            if (breakBroadcastNameRuleTextLengthMoreThanMax) {
+                mBroadcastErrorMessage.setText(
+                        mContext.getResources().getString(
+                                R.string.media_output_broadcast_edit_hint_no_more_than_max,
+                                BROADCAST_NAME_MAX_LENGTH));
+            }
+            mBroadcastErrorMessage.setVisibility(
+                    breakBroadcastNameRuleTextLengthMoreThanMax ? View.VISIBLE : View.INVISIBLE);
+            Button positiveBtn = mAlertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
+            if (positiveBtn != null) {
+                positiveBtn.setEnabled(breakRule ? false : true);
+            }
+        }
+    };
 
     private BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
             new BluetoothLeBroadcastAssistant.Callback() {
@@ -186,13 +235,6 @@
                 }
             };
 
-    static final int METADATA_BROADCAST_NAME = 0;
-    static final int METADATA_BROADCAST_CODE = 1;
-
-    private static final int MAX_BROADCAST_INFO_UPDATE = 3;
-    private static final int BROADCAST_CODE_MAX_LENGTH = 16;
-    private static final int BROADCAST_CODE_MIN_LENGTH = 4;
-
     MediaOutputBroadcastDialog(Context context, boolean aboveStatusbar,
             BroadcastSender broadcastSender, MediaOutputController mediaOutputController) {
         super(context, broadcastSender, mediaOutputController);
@@ -391,13 +433,12 @@
                 R.layout.media_output_broadcast_update_dialog, null);
         final EditText editText = layout.requireViewById(R.id.broadcast_edit_text);
         editText.setText(editString);
-        if (isBroadcastCode) {
-            editText.addTextChangedListener(mTextWatcher);
-        }
+        editText.addTextChangedListener(
+                isBroadcastCode ? mBroadcastCodeTextWatcher : mBroadcastNameTextWatcher);
         mBroadcastErrorMessage = layout.requireViewById(R.id.broadcast_error_message);
         mAlertDialog = new Builder(mContext)
                 .setTitle(isBroadcastCode ? R.string.media_output_broadcast_code
-                    : R.string.media_output_broadcast_name)
+                        : R.string.media_output_broadcast_name)
                 .setView(layout)
                 .setNegativeButton(android.R.string.cancel, null)
                 .setPositiveButton(R.string.media_output_broadcast_dialog_save,
@@ -420,7 +461,8 @@
         return mMediaOutputController.getBroadcastMetadata();
     }
 
-    private void updateBroadcastInfo(boolean isBroadcastCode, String updatedString) {
+    @VisibleForTesting
+    void updateBroadcastInfo(boolean isBroadcastCode, String updatedString) {
         Button positiveBtn = mAlertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
         if (positiveBtn != null) {
             positiveBtn.setEnabled(false);
@@ -523,16 +565,33 @@
     }
 
     private void handleUpdateFailedUi() {
-        final Button positiveBtn = mAlertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
-        mBroadcastErrorMessage.setVisibility(View.VISIBLE);
+        if (mAlertDialog == null) {
+            Log.d(TAG, "handleUpdateFailedUi: mAlertDialog is null");
+            return;
+        }
+        int errorMessageStringId = -1;
+        boolean enablePositiveBtn = false;
         if (mRetryCount < MAX_BROADCAST_INFO_UPDATE) {
-            if (positiveBtn != null) {
-                positiveBtn.setEnabled(true);
-            }
-            mBroadcastErrorMessage.setText(R.string.media_output_broadcast_update_error);
+            enablePositiveBtn = true;
+            errorMessageStringId = R.string.media_output_broadcast_update_error;
         } else {
             mRetryCount = 0;
-            mBroadcastErrorMessage.setText(R.string.media_output_broadcast_last_update_error);
+            errorMessageStringId = R.string.media_output_broadcast_last_update_error;
         }
+
+        // update UI
+        final Button positiveBtn = mAlertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
+        if (positiveBtn != null && enablePositiveBtn) {
+            positiveBtn.setEnabled(true);
+        }
+        if (mBroadcastErrorMessage != null) {
+            mBroadcastErrorMessage.setVisibility(View.VISIBLE);
+            mBroadcastErrorMessage.setText(errorMessageStringId);
+        }
+    }
+
+    @VisibleForTesting
+    int getRetryCount() {
+        return mRetryCount;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorController.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorController.kt
index 1d8fe72..e61650f 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorController.kt
@@ -18,9 +18,9 @@
 
 import android.content.ComponentName
 import android.os.UserHandle
-import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.mediaprojection.appselector.data.RecentTask
 import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider
+import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.cancel
@@ -32,7 +32,7 @@
 constructor(
     private val recentTaskListProvider: RecentTaskListProvider,
     private val view: MediaProjectionAppSelectorView,
-    private val flags: FeatureFlags,
+    private val devicePolicyResolver: ScreenCaptureDevicePolicyResolver,
     @HostUserHandle private val hostUserHandle: UserHandle,
     @MediaProjectionAppSelector private val scope: CoroutineScope,
     @MediaProjectionAppSelector private val appSelectorComponentName: ComponentName,
@@ -54,11 +54,13 @@
         scope.cancel()
     }
 
-    /**
-     * Removes all recent tasks that are different from the profile of the host app to avoid any
-     * cross-profile sharing
-     */
-    private fun List<RecentTask>.filterDevicePolicyRestrictedTasks(): List<RecentTask> = this
+    /** Removes all recent tasks that should be blocked according to the policy */
+    private fun List<RecentTask>.filterDevicePolicyRestrictedTasks(): List<RecentTask> = filter {
+        devicePolicyResolver.isScreenCaptureAllowed(
+            targetAppUserHandle = UserHandle.of(it.userId),
+            hostAppUserHandle = hostUserHandle
+        )
+    }
 
     private fun List<RecentTask>.filterAppSelector(): List<RecentTask> = filter {
         // Only take tasks that is not the app selector
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolver.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolver.kt
index 6bd33e7..b11a244 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolver.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolver.kt
@@ -47,7 +47,7 @@
             return false
         }
 
-        if (!hostAppUserHandle.isWorkProfile() && personalProfileScreenCaptureDisabled) {
+        if (personalProfileScreenCaptureDisabled) {
             // Disable screen capturing as personal apps should not capture the screen
             return false
         }
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index b0fb349..682335e 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -76,7 +76,6 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.Display;
-import android.view.DisplayCutout;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.InsetsFrameProvider;
@@ -1730,9 +1729,6 @@
             tappableElementProvider.setInsetsSize(Insets.NONE);
         }
 
-        final DisplayCutout cutout = userContext.getDisplay().getCutout();
-        final int safeInsetsLeft = cutout != null ? cutout.getSafeInsetLeft() : 0;
-        final int safeInsetsRight = cutout != null ? cutout.getSafeInsetRight() : 0;
         final int gestureHeight = userContext.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.navigation_bar_gesture_height);
         final boolean handlingGesture = mEdgeBackGestureHandler.isHandlingGestures();
@@ -1742,19 +1738,23 @@
             mandatoryGestureProvider.setInsetsSize(Insets.of(0, 0, 0, gestureHeight));
         }
         final int gestureInsetsLeft = handlingGesture
-                ? mEdgeBackGestureHandler.getEdgeWidthLeft() + safeInsetsLeft : 0;
+                ? mEdgeBackGestureHandler.getEdgeWidthLeft() : 0;
         final int gestureInsetsRight = handlingGesture
-                ? mEdgeBackGestureHandler.getEdgeWidthRight() + safeInsetsRight : 0;
+                ? mEdgeBackGestureHandler.getEdgeWidthRight() : 0;
         return new InsetsFrameProvider[] {
                 navBarProvider,
                 tappableElementProvider,
                 mandatoryGestureProvider,
                 new InsetsFrameProvider(mInsetsSourceOwner, 0, WindowInsets.Type.systemGestures())
                         .setSource(InsetsFrameProvider.SOURCE_DISPLAY)
-                        .setInsetsSize(Insets.of(gestureInsetsLeft, 0, 0, 0)),
+                        .setInsetsSize(Insets.of(gestureInsetsLeft, 0, 0, 0))
+                        .setMinimalInsetsSizeInDisplayCutoutSafe(
+                                Insets.of(gestureInsetsLeft, 0, 0, 0)),
                 new InsetsFrameProvider(mInsetsSourceOwner, 1, WindowInsets.Type.systemGestures())
                         .setSource(InsetsFrameProvider.SOURCE_DISPLAY)
                         .setInsetsSize(Insets.of(0, 0, gestureInsetsRight, 0))
+                        .setMinimalInsetsSizeInDisplayCutoutSafe(
+                                Insets.of(0, 0, gestureInsetsRight, 0))
         };
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
index c804df8..a256b59 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
@@ -157,17 +157,17 @@
 
         arrowPaint.color = Utils.getColorAttrDefaultColor(context,
                 if (isDeviceInNightTheme) {
-                    com.android.internal.R.attr.colorAccentPrimary
+                    com.android.internal.R.attr.materialColorOnSecondaryContainer
                 } else {
-                    com.android.internal.R.attr.textColorPrimary
+                    com.android.internal.R.attr.materialColorOnSecondaryFixed
                 }
         )
 
         arrowBackgroundPaint.color = Utils.getColorAttrDefaultColor(context,
                 if (isDeviceInNightTheme) {
-                    com.android.internal.R.attr.materialColorOnSecondary
+                    com.android.internal.R.attr.materialColorSecondaryContainer
                 } else {
-                    com.android.internal.R.attr.colorAccentSecondary
+                    com.android.internal.R.attr.materialColorSecondaryFixedDim
                 }
         )
     }
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index 25272ae..ccfbaf1 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -215,7 +215,7 @@
                     debugLog { "onShowNoteTask - opened as app bubble: $info" }
                 }
                 is NoteTaskLaunchMode.Activity -> {
-                    if (activityManager.isInForeground(info.packageName)) {
+                    if (info.isKeyguardLocked && activityManager.isInForeground(info.packageName)) {
                         // Force note task into background by calling home.
                         val intent = createHomeIntent()
                         context.startActivityAsUser(intent, user)
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt
index fae325c..4420002 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt
@@ -25,12 +25,14 @@
  * An entry point represents where the note task has ben called from. In rare cases, it may
  * represent a "re-entry" (i.e., [APP_CLIPS]).
  */
-enum class
-NoteTaskEntryPoint {
+enum class NoteTaskEntryPoint {
 
     /** @see [LaunchNoteTaskActivity] */
     WIDGET_PICKER_SHORTCUT,
 
+    /** @see [LaunchNoteTaskActivity] */
+    WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE,
+
     /** @see [NoteTaskQuickAffordanceConfig] */
     QUICK_AFFORDANCE,
 
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt
index 48a5933..a79057e 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt
@@ -22,6 +22,8 @@
 import com.android.systemui.notetask.NoteTaskEntryPoint.QUICK_AFFORDANCE
 import com.android.systemui.notetask.NoteTaskEntryPoint.TAIL_BUTTON
 import com.android.systemui.notetask.NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT
+import com.android.systemui.notetask.NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent
 import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
 import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT
 import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
@@ -41,40 +43,45 @@
     /** Logs a [NoteTaskInfo] as an **open** [NoteTaskUiEvent], including package name and uid. */
     fun logNoteTaskOpened(info: NoteTaskInfo) {
         val event =
-            when (info.entryPoint) {
-                TAIL_BUTTON -> {
-                    if (info.isKeyguardLocked) {
-                        NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED
-                    } else {
-                        NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
+                when (info.entryPoint) {
+                    TAIL_BUTTON -> {
+                        if (info.isKeyguardLocked) {
+                            NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+                        } else {
+                            NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
+                        }
                     }
+
+                    WIDGET_PICKER_SHORTCUT,
+                    WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE -> NOTE_OPENED_VIA_SHORTCUT
+
+                    QUICK_AFFORDANCE -> NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
+                    APP_CLIPS,
+                    KEYBOARD_SHORTCUT,
+                    null -> return
                 }
-                WIDGET_PICKER_SHORTCUT -> NOTE_OPENED_VIA_SHORTCUT
-                QUICK_AFFORDANCE -> NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
-                APP_CLIPS -> return
-                KEYBOARD_SHORTCUT -> return
-                null -> return
-            }
         uiEventLogger.log(event, info.uid, info.packageName)
     }
 
     /** Logs a [NoteTaskInfo] as a **closed** [NoteTaskUiEvent], including package name and uid. */
     fun logNoteTaskClosed(info: NoteTaskInfo) {
         val event =
-            when (info.entryPoint) {
-                TAIL_BUTTON -> {
-                    if (info.isKeyguardLocked) {
-                        NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED
-                    } else {
-                        NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON
+                when (info.entryPoint) {
+                    TAIL_BUTTON -> {
+                        if (info.isKeyguardLocked) {
+                            NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+                        } else {
+                            NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON
+                        }
                     }
+
+                    WIDGET_PICKER_SHORTCUT,
+                    WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE,
+                    QUICK_AFFORDANCE,
+                    APP_CLIPS,
+                    KEYBOARD_SHORTCUT,
+                    null -> return
                 }
-                WIDGET_PICKER_SHORTCUT -> return
-                QUICK_AFFORDANCE -> return
-                APP_CLIPS -> return
-                KEYBOARD_SHORTCUT -> return
-                null -> return
-            }
         uiEventLogger.log(event, info.uid, info.packageName)
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt
index a758347..269eb87 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt
@@ -16,6 +16,7 @@
 package com.android.systemui.notetask
 
 import android.os.UserHandle
+import com.android.systemui.notetask.NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE
 
 /** Contextual information required to launch a Note Task by [NoteTaskController]. */
 data class NoteTaskInfo(
@@ -27,7 +28,7 @@
 ) {
 
     val launchMode: NoteTaskLaunchMode =
-        if (isKeyguardLocked) {
+        if (isKeyguardLocked || entryPoint == WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE) {
             NoteTaskLaunchMode.Activity
         } else {
             NoteTaskLaunchMode.AppBubble
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskRoleManagerExt.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskRoleManagerExt.kt
index 441b9f5..754c365 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskRoleManagerExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskRoleManagerExt.kt
@@ -51,7 +51,8 @@
         val icon = Icon.createWithResource(context, R.drawable.ic_note_task_shortcut_widget)
 
         return ShortcutInfo.Builder(context, NoteTaskController.SHORTCUT_ID)
-            .setIntent(LaunchNoteTaskActivity.newIntent(context = context))
+            .setIntent(LaunchNoteTaskActivity.createIntent(context))
+            .setActivity(LaunchNoteTaskActivity.createComponent(context))
             .setShortLabel(context.getString(R.string.note_task_button_label))
             .setLongLived(true)
             .setIcon(icon)
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
index 0ce20cd..f02d362 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
@@ -19,6 +19,7 @@
 import android.app.role.OnRoleHoldersChangedListener
 import android.app.role.RoleManager
 import android.content.Context
+import android.content.Intent
 import android.hardware.input.InputSettings
 import android.os.Build
 import android.os.UserHandle
@@ -42,7 +43,6 @@
 import com.android.systemui.notetask.NoteTaskEnabledKey
 import com.android.systemui.notetask.NoteTaskEntryPoint.QUICK_AFFORDANCE
 import com.android.systemui.notetask.NoteTaskInfoResolver
-import com.android.systemui.shared.customization.data.content.CustomizationProviderContract.LockScreenQuickAffordances.AffordanceTable.COMPONENT_NAME_SEPARATOR
 import com.android.systemui.stylus.StylusManager
 import dagger.Lazy
 import java.util.concurrent.Executor
@@ -122,16 +122,18 @@
             isEnabled && isDefaultNotesAppSet -> PickerScreenState.Default()
             isEnabled -> {
                 PickerScreenState.Disabled(
-                    listOf(
+                    explanation =
                         context.getString(
-                            R.string.keyguard_affordance_enablement_dialog_notes_app_instruction
-                        )
-                    ),
-                    context.getString(
-                        R.string.keyguard_affordance_enablement_dialog_notes_app_action
-                    ),
-                    "${context.packageName}$COMPONENT_NAME_SEPARATOR" +
-                        "$ACTION_MANAGE_NOTES_ROLE_FROM_QUICK_AFFORDANCE",
+                            R.string.notes_app_quick_affordance_unavailable_explanation
+                        ),
+                    actionText =
+                        context.getString(
+                            R.string.keyguard_affordance_enablement_dialog_notes_app_action
+                        ),
+                    actionIntent =
+                        Intent(ACTION_MANAGE_NOTES_ROLE_FROM_QUICK_AFFORDANCE).apply {
+                            setPackage(context.packageName)
+                        },
                 )
             }
             else -> PickerScreenState.UnavailableOnDevice
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
index 8ca13b9..7ef149d 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.notetask.shortcut
 
+import android.content.ComponentName
 import android.content.Context
 import android.content.Intent
 import android.os.Bundle
@@ -72,7 +73,13 @@
                 controller.startNoteTaskProxyActivityForUser(mainUser)
             }
         } else {
-            controller.showNoteTask(entryPoint = NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT)
+            val entryPoint =
+                if (isInMultiWindowMode) {
+                    NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE
+                } else {
+                    NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT
+                }
+            controller.showNoteTask(entryPoint)
         }
         finish()
     }
@@ -80,11 +87,14 @@
     companion object {
 
         /** Creates a new [Intent] set to start [LaunchNoteTaskActivity]. */
-        fun newIntent(context: Context): Intent {
-            return Intent(context, LaunchNoteTaskActivity::class.java).apply {
+        fun createIntent(context: Context): Intent =
+            Intent(context, LaunchNoteTaskActivity::class.java).apply {
                 // Intent's action must be set in shortcuts, or an exception will be thrown.
                 action = Intent.ACTION_CREATE_NOTE
             }
-        }
+
+        /** Creates a new [ComponentName] for [LaunchNoteTaskActivity]. */
+        fun createComponent(context: Context): ComponentName =
+            ComponentName(context, LaunchNoteTaskActivity::class.java)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
index 18be0aa..8d3b745 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
@@ -775,9 +775,13 @@
                 NotificationChannel channel,
                 int modificationType) {
             if (channel.isConversation()) {
-                updateWidgets(mAppWidgetManager.getAppWidgetIds(
-                        new ComponentName(mContext, PeopleSpaceWidgetProvider.class)
-                ));
+                mBgExecutor.execute(() -> {
+                    if (mUserManager.isUserUnlocked(user)) {
+                        updateWidgets(mAppWidgetManager.getAppWidgetIds(
+                                new ComponentName(mContext, PeopleSpaceWidgetProvider.class)
+                        ));
+                    }
+                });
             }
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 897b0e7..5d02830 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -65,14 +65,12 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.settings.DisplayTracker;
 
-import dagger.Lazy;
-
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.inject.Inject;
 
-
+import dagger.Lazy;
 
 public class CustomTile extends QSTileImpl<State> implements TileChangeListener {
     public static final String PREFIX = "custom(";
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSPipelineModule.kt
index a066242..d7ae575 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSPipelineModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSPipelineModule.kt
@@ -20,6 +20,8 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.LogBufferFactory
+import com.android.systemui.qs.pipeline.data.repository.InstalledTilesComponentRepository
+import com.android.systemui.qs.pipeline.data.repository.InstalledTilesComponentRepositoryImpl
 import com.android.systemui.qs.pipeline.data.repository.TileSpecRepository
 import com.android.systemui.qs.pipeline.data.repository.TileSpecSettingsRepository
 import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor
@@ -45,6 +47,11 @@
     ): CurrentTilesInteractor
 
     @Binds
+    abstract fun provideInstalledTilesPackageRepository(
+        impl: InstalledTilesComponentRepositoryImpl
+    ): InstalledTilesComponentRepository
+
+    @Binds
     @IntoMap
     @ClassKey(PrototypeCoreStartable::class)
     abstract fun providePrototypeCoreStartable(startable: PrototypeCoreStartable): CoreStartable
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepository.kt
new file mode 100644
index 0000000..498f403
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepository.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.pipeline.data.repository
+
+import android.Manifest.permission.BIND_QUICK_SETTINGS_TILE
+import android.annotation.WorkerThread
+import android.content.BroadcastReceiver
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.ResolveInfoFlags
+import android.os.UserHandle
+import android.service.quicksettings.TileService
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.util.kotlin.isComponentActuallyEnabled
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
+
+interface InstalledTilesComponentRepository {
+
+    fun getInstalledTilesComponents(userId: Int): Flow<Set<ComponentName>>
+}
+
+@SysUISingleton
+class InstalledTilesComponentRepositoryImpl
+@Inject
+constructor(
+    @Application private val applicationContext: Context,
+    private val packageManager: PackageManager,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+) : InstalledTilesComponentRepository {
+
+    override fun getInstalledTilesComponents(userId: Int): Flow<Set<ComponentName>> =
+        conflatedCallbackFlow {
+                val receiver =
+                    object : BroadcastReceiver() {
+                        override fun onReceive(context: Context?, intent: Intent?) {
+                            trySend(Unit)
+                        }
+                    }
+                applicationContext.registerReceiverAsUser(
+                    receiver,
+                    UserHandle.of(userId),
+                    INTENT_FILTER,
+                    /* broadcastPermission = */ null,
+                    /* scheduler = */ null
+                )
+
+                awaitClose { applicationContext.unregisterReceiver(receiver) }
+            }
+            .onStart { emit(Unit) }
+            .map { reloadComponents(userId) }
+            .distinctUntilChanged()
+            .flowOn(backgroundDispatcher)
+
+    @WorkerThread
+    private fun reloadComponents(userId: Int): Set<ComponentName> {
+        return packageManager
+            .queryIntentServicesAsUser(INTENT, FLAGS, userId)
+            .mapNotNull { it.serviceInfo }
+            .filter { it.permission == BIND_QUICK_SETTINGS_TILE }
+            .filter { packageManager.isComponentActuallyEnabled(it) }
+            .mapTo(mutableSetOf()) { it.componentName }
+    }
+
+    companion object {
+        private val INTENT_FILTER =
+            IntentFilter().apply {
+                addAction(Intent.ACTION_PACKAGE_ADDED)
+                addAction(Intent.ACTION_PACKAGE_CHANGED)
+                addAction(Intent.ACTION_PACKAGE_REMOVED)
+                addAction(Intent.ACTION_PACKAGE_REPLACED)
+                addDataScheme("package")
+            }
+        private val INTENT = Intent(TileService.ACTION_QS_TILE)
+        private val FLAGS =
+            ResolveInfoFlags.of(
+                (PackageManager.GET_SERVICES or
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE or
+                        PackageManager.MATCH_DIRECT_BOOT_UNAWARE)
+                    .toLong()
+            )
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt
index 3b2362f..a162d11 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt
@@ -42,6 +42,8 @@
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.sync.Mutex
+import kotlinx.coroutines.sync.withLock
 import kotlinx.coroutines.withContext
 
 /** Repository that tracks the current tiles. */
@@ -104,6 +106,8 @@
     @Background private val backgroundDispatcher: CoroutineDispatcher,
 ) : TileSpecRepository {
 
+    private val mutex = Mutex()
+
     private val retailModeTiles by lazy {
         resources
             .getString(R.string.quick_settings_tiles_retail_mode)
@@ -145,37 +149,40 @@
             .flowOn(backgroundDispatcher)
     }
 
-    override suspend fun addTile(userId: Int, tile: TileSpec, position: Int) {
-        if (tile == TileSpec.Invalid) {
-            return
-        }
-        val tilesList = loadTiles(userId).toMutableList()
-        if (tile !in tilesList) {
-            if (position < 0 || position >= tilesList.size) {
-                tilesList.add(tile)
-            } else {
-                tilesList.add(position, tile)
+    override suspend fun addTile(userId: Int, tile: TileSpec, position: Int) =
+        mutex.withLock {
+            if (tile == TileSpec.Invalid) {
+                return
             }
-            storeTiles(userId, tilesList)
+            val tilesList = loadTiles(userId).toMutableList()
+            if (tile !in tilesList) {
+                if (position < 0 || position >= tilesList.size) {
+                    tilesList.add(tile)
+                } else {
+                    tilesList.add(position, tile)
+                }
+                storeTiles(userId, tilesList)
+            }
         }
-    }
 
-    override suspend fun removeTiles(userId: Int, tiles: Collection<TileSpec>) {
-        if (tiles.all { it == TileSpec.Invalid }) {
-            return
+    override suspend fun removeTiles(userId: Int, tiles: Collection<TileSpec>) =
+        mutex.withLock {
+            if (tiles.all { it == TileSpec.Invalid }) {
+                return
+            }
+            val tilesList = loadTiles(userId).toMutableList()
+            if (tilesList.removeAll(tiles)) {
+                storeTiles(userId, tilesList.toList())
+            }
         }
-        val tilesList = loadTiles(userId).toMutableList()
-        if (tilesList.removeAll(tiles)) {
-            storeTiles(userId, tilesList.toList())
-        }
-    }
 
-    override suspend fun setTiles(userId: Int, tiles: List<TileSpec>) {
-        val filtered = tiles.filter { it != TileSpec.Invalid }
-        if (filtered.isNotEmpty()) {
-            storeTiles(userId, filtered)
+    override suspend fun setTiles(userId: Int, tiles: List<TileSpec>) =
+        mutex.withLock {
+            val filtered = tiles.filter { it != TileSpec.Invalid }
+            if (filtered.isNotEmpty()) {
+                storeTiles(userId, filtered)
+            }
         }
-    }
 
     private suspend fun loadTiles(@UserIdInt forUser: Int): List<TileSpec> {
         return withContext(backgroundDispatcher) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt
index c579f5c..ff881f7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt
@@ -36,6 +36,7 @@
 import com.android.systemui.qs.external.TileLifecycleManager
 import com.android.systemui.qs.external.TileServiceKey
 import com.android.systemui.qs.pipeline.data.repository.CustomTileAddedRepository
+import com.android.systemui.qs.pipeline.data.repository.InstalledTilesComponentRepository
 import com.android.systemui.qs.pipeline.data.repository.TileSpecRepository
 import com.android.systemui.qs.pipeline.domain.model.TileModel
 import com.android.systemui.qs.pipeline.shared.TileSpec
@@ -52,6 +53,8 @@
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOn
@@ -117,11 +120,13 @@
  * * Platform tiles will be kept between users, with a call to [QSTile.userSwitch]
  * * [CustomTile]s will only be destroyed if the user changes.
  */
+@OptIn(ExperimentalCoroutinesApi::class)
 @SysUISingleton
 class CurrentTilesInteractorImpl
 @Inject
 constructor(
     private val tileSpecRepository: TileSpecRepository,
+    private val installedTilesComponentRepository: InstalledTilesComponentRepository,
     private val userRepository: UserRepository,
     private val customTileStatePersister: CustomTileStatePersister,
     private val tileFactory: QSFactory,
@@ -141,7 +146,7 @@
     override val currentTiles: StateFlow<List<TileModel>> = _currentSpecsAndTiles.asStateFlow()
 
     // This variable should only be accessed inside the collect of `startTileCollection`.
-    private val specsToTiles = mutableMapOf<TileSpec, QSTile>()
+    private val specsToTiles = mutableMapOf<TileSpec, TileOrNotInstalled>()
 
     private val currentUser = MutableStateFlow(userTracker.userId)
     override val userId = currentUser.asStateFlow()
@@ -149,6 +154,20 @@
     private val _userContext = MutableStateFlow(userTracker.userContext)
     override val userContext = _userContext.asStateFlow()
 
+    private val userAndTiles =
+        currentUser
+            .flatMapLatest { userId ->
+                tileSpecRepository.tilesSpecs(userId).map { UserAndTiles(userId, it) }
+            }
+            .distinctUntilChanged()
+            .pairwise(UserAndTiles(-1, emptyList()))
+            .flowOn(backgroundDispatcher)
+
+    private val installedPackagesWithTiles =
+        currentUser.flatMapLatest {
+            installedTilesComponentRepository.getInstalledTilesComponents(it)
+        }
+
     init {
         if (featureFlags.isEnabled(Flags.QS_PIPELINE_NEW_HOST)) {
             startTileCollection()
@@ -158,68 +177,98 @@
     @OptIn(ExperimentalCoroutinesApi::class)
     private fun startTileCollection() {
         scope.launch {
-            userRepository.selectedUserInfo
-                .flatMapLatest { user ->
+            launch {
+                userRepository.selectedUserInfo.collect { user ->
                     currentUser.value = user.id
                     _userContext.value = userTracker.userContext
-                    tileSpecRepository.tilesSpecs(user.id).map { user.id to it }
                 }
-                .distinctUntilChanged()
-                .pairwise(-1 to emptyList())
-                .flowOn(backgroundDispatcher)
-                .collect { (old, new) ->
-                    val newTileList = new.second
-                    val userChanged = old.first != new.first
-                    val newUser = new.first
+            }
 
-                    // Destroy all tiles that are not in the new set
-                    specsToTiles
-                        .filter { it.key !in newTileList }
-                        .forEach { entry ->
-                            logger.logTileDestroyed(
-                                entry.key,
-                                if (userChanged) {
-                                    QSPipelineLogger.TileDestroyedReason
-                                        .TILE_NOT_PRESENT_IN_NEW_USER
-                                } else {
-                                    QSPipelineLogger.TileDestroyedReason.TILE_REMOVED
-                                }
-                            )
-                            entry.value.destroy()
-                        }
-                    // MutableMap will keep the insertion order
-                    val newTileMap = mutableMapOf<TileSpec, QSTile>()
+            launch(backgroundDispatcher) {
+                userAndTiles
+                    .combine(installedPackagesWithTiles) { usersAndTiles, packages ->
+                        Data(
+                            usersAndTiles.previousValue,
+                            usersAndTiles.newValue,
+                            packages,
+                        )
+                    }
+                    .collectLatest {
+                        val newTileList = it.newData.tiles
+                        val userChanged = it.oldData.userId != it.newData.userId
+                        val newUser = it.newData.userId
+                        val components = it.installedComponents
 
-                    newTileList.forEach { tileSpec ->
-                        if (tileSpec !in newTileMap) {
-                            val newTile =
-                                if (tileSpec in specsToTiles) {
-                                    processExistingTile(
-                                        tileSpec,
-                                        specsToTiles.getValue(tileSpec),
-                                        userChanged,
-                                        newUser
-                                    )
-                                        ?: createTile(tileSpec)
+                        // Destroy all tiles that are not in the new set
+                        specsToTiles
+                            .filter {
+                                it.key !in newTileList && it.value is TileOrNotInstalled.Tile
+                            }
+                            .forEach { entry ->
+                                logger.logTileDestroyed(
+                                    entry.key,
+                                    if (userChanged) {
+                                        QSPipelineLogger.TileDestroyedReason
+                                            .TILE_NOT_PRESENT_IN_NEW_USER
+                                    } else {
+                                        QSPipelineLogger.TileDestroyedReason.TILE_REMOVED
+                                    }
+                                )
+                                (entry.value as TileOrNotInstalled.Tile).tile.destroy()
+                            }
+                        // MutableMap will keep the insertion order
+                        val newTileMap = mutableMapOf<TileSpec, TileOrNotInstalled>()
+
+                        newTileList.forEach { tileSpec ->
+                            if (tileSpec !in newTileMap) {
+                                if (
+                                    tileSpec is TileSpec.CustomTileSpec &&
+                                        tileSpec.componentName !in components
+                                ) {
+                                    newTileMap[tileSpec] = TileOrNotInstalled.NotInstalled
                                 } else {
-                                    createTile(tileSpec)
+                                    // Create tile here will never try to create a CustomTile that
+                                    // is not installed
+                                    val newTile =
+                                        if (tileSpec in specsToTiles) {
+                                            processExistingTile(
+                                                tileSpec,
+                                                specsToTiles.getValue(tileSpec),
+                                                userChanged,
+                                                newUser
+                                            )
+                                                ?: createTile(tileSpec)
+                                        } else {
+                                            createTile(tileSpec)
+                                        }
+                                    if (newTile != null) {
+                                        newTileMap[tileSpec] = TileOrNotInstalled.Tile(newTile)
+                                    }
                                 }
-                            if (newTile != null) {
-                                newTileMap[tileSpec] = newTile
                             }
                         }
-                    }
 
-                    val resolvedSpecs = newTileMap.keys.toList()
-                    specsToTiles.clear()
-                    specsToTiles.putAll(newTileMap)
-                    _currentSpecsAndTiles.value = newTileMap.map { TileModel(it.key, it.value) }
-                    if (resolvedSpecs != newTileList) {
-                        // There were some tiles that couldn't be created. Change the value in the
-                        // repository
-                        launch { tileSpecRepository.setTiles(currentUser.value, resolvedSpecs) }
+                        val resolvedSpecs = newTileMap.keys.toList()
+                        specsToTiles.clear()
+                        specsToTiles.putAll(newTileMap)
+                        _currentSpecsAndTiles.value =
+                            newTileMap
+                                .filter { it.value is TileOrNotInstalled.Tile }
+                                .map {
+                                    TileModel(it.key, (it.value as TileOrNotInstalled.Tile).tile)
+                                }
+                        logger.logTilesNotInstalled(
+                            newTileMap.filter { it.value is TileOrNotInstalled.NotInstalled }.keys,
+                            newUser
+                        )
+                        if (resolvedSpecs != newTileList) {
+                            // There were some tiles that couldn't be created. Change the value in
+                            // the
+                            // repository
+                            launch { tileSpecRepository.setTiles(currentUser.value, resolvedSpecs) }
+                        }
                     }
-                }
+            }
         }
     }
 
@@ -301,42 +350,66 @@
 
     private fun processExistingTile(
         tileSpec: TileSpec,
-        qsTile: QSTile,
+        tileOrNotInstalled: TileOrNotInstalled,
         userChanged: Boolean,
         user: Int,
     ): QSTile? {
-        return when {
-            !qsTile.isAvailable -> {
-                logger.logTileDestroyed(
-                    tileSpec,
-                    QSPipelineLogger.TileDestroyedReason.EXISTING_TILE_NOT_AVAILABLE
-                )
-                qsTile.destroy()
-                null
-            }
-            // Tile is in the current list of tiles and available.
-            // We have a handful of different cases
-            qsTile !is CustomTile -> {
-                // The tile is not a custom tile. Make sure they are reset to the correct user
-                if (userChanged) {
-                    qsTile.userSwitch(user)
-                    logger.logTileUserChanged(tileSpec, user)
+        return when (tileOrNotInstalled) {
+            is TileOrNotInstalled.NotInstalled -> null
+            is TileOrNotInstalled.Tile -> {
+                val qsTile = tileOrNotInstalled.tile
+                when {
+                    !qsTile.isAvailable -> {
+                        logger.logTileDestroyed(
+                            tileSpec,
+                            QSPipelineLogger.TileDestroyedReason.EXISTING_TILE_NOT_AVAILABLE
+                        )
+                        qsTile.destroy()
+                        null
+                    }
+                    // Tile is in the current list of tiles and available.
+                    // We have a handful of different cases
+                    qsTile !is CustomTile -> {
+                        // The tile is not a custom tile. Make sure they are reset to the correct
+                        // user
+                        if (userChanged) {
+                            qsTile.userSwitch(user)
+                            logger.logTileUserChanged(tileSpec, user)
+                        }
+                        qsTile
+                    }
+                    qsTile.user == user -> {
+                        // The tile is a custom tile for the same user, just return it
+                        qsTile
+                    }
+                    else -> {
+                        // The tile is a custom tile and the user has changed. Destroy it
+                        qsTile.destroy()
+                        logger.logTileDestroyed(
+                            tileSpec,
+                            QSPipelineLogger.TileDestroyedReason.CUSTOM_TILE_USER_CHANGED
+                        )
+                        null
+                    }
                 }
-                qsTile
-            }
-            qsTile.user == user -> {
-                // The tile is a custom tile for the same user, just return it
-                qsTile
-            }
-            else -> {
-                // The tile is a custom tile and the user has changed. Destroy it
-                qsTile.destroy()
-                logger.logTileDestroyed(
-                    tileSpec,
-                    QSPipelineLogger.TileDestroyedReason.CUSTOM_TILE_USER_CHANGED
-                )
-                null
             }
         }
     }
+
+    private sealed interface TileOrNotInstalled {
+        object NotInstalled : TileOrNotInstalled
+
+        @JvmInline value class Tile(val tile: QSTile) : TileOrNotInstalled
+    }
+
+    private data class UserAndTiles(
+        val userId: Int,
+        val tiles: List<TileSpec>,
+    )
+
+    private data class Data(
+        val oldData: UserAndTiles,
+        val newData: UserAndTiles,
+        val installedComponents: Set<ComponentName>,
+    )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt
index ff7d206..8318ec9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt
@@ -124,6 +124,18 @@
         tileListLogBuffer.log(TILE_LIST_TAG, LogLevel.DEBUG, {}, { "Using retail tiles" })
     }
 
+    fun logTilesNotInstalled(tiles: Collection<TileSpec>, user: Int) {
+        tileListLogBuffer.log(
+            TILE_LIST_TAG,
+            LogLevel.DEBUG,
+            {
+                str1 = tiles.toString()
+                int1 = user
+            },
+            { "Tiles kept for not installed packages for user $int1: $str1" }
+        )
+    }
+
     /** Reasons for destroying an existing tile. */
     enum class TileDestroyedReason(val readable: String) {
         TILE_REMOVED("Tile removed from  current set"),
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index e1ac0fd..2c4555a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -427,6 +427,7 @@
                 Log.e(TAG, "stopRecording called, but there was an error when ending"
                         + "recording");
                 exception.printStackTrace();
+                createErrorNotification();
             } catch (Throwable throwable) {
                 // Something unexpected happen, SystemUI will crash but let's delete
                 // the temporary files anyway
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index 3227ef4..bd1b7ca 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -137,7 +137,12 @@
                 // Since Quick Share target recommendation does not rely on image URL, it is
                 // queried and surfaced before image compress/export. Action intent would not be
                 // used, because it does not contain image URL.
-                queryQuickShareAction(image, mParams.owner);
+                Notification.Action quickShare =
+                        queryQuickShareAction(mScreenshotId, image, mParams.owner, null);
+                if (quickShare != null) {
+                    mQuickShareData.quickShareAction = quickShare;
+                    mParams.mQuickShareActionsReadyListener.onActionsReady(mQuickShareData);
+                }
             }
 
             // Call synchronously here since already on a background thread.
@@ -176,9 +181,10 @@
                     smartActionsEnabled);
             mImageData.deleteAction = createDeleteAction(mContext, mContext.getResources(), uri,
                     smartActionsEnabled);
-            mImageData.quickShareAction = createQuickShareAction(mContext,
-                    mQuickShareData.quickShareAction, uri);
-            mImageData.subject = getSubjectString();
+            mImageData.quickShareAction = createQuickShareAction(
+                    mQuickShareData.quickShareAction, mScreenshotId, uri, mImageTime, image,
+                    mParams.owner);
+            mImageData.subject = getSubjectString(mImageTime);
 
             mParams.mActionsReadyListener.onActionsReady(mImageData);
             if (DEBUG_CALLBACK) {
@@ -251,7 +257,7 @@
                     new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
                     new ClipData.Item(uri));
             sharingIntent.setClipData(clipdata);
-            sharingIntent.putExtra(Intent.EXTRA_SUBJECT, getSubjectString());
+            sharingIntent.putExtra(Intent.EXTRA_SUBJECT, getSubjectString(mImageTime));
             sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                     .addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
 
@@ -417,60 +423,73 @@
     }
 
     /**
-     * Populate image uri into intent of Quick Share action.
+     * Wrap the quickshare intent and populate the fillin intent with the URI
      */
     @VisibleForTesting
-    private Notification.Action createQuickShareAction(Context context, Notification.Action action,
-            Uri uri) {
-        if (action == null) {
+    Notification.Action createQuickShareAction(
+            Notification.Action quickShare, String screenshotId, Uri uri, long imageTime,
+            Bitmap image, UserHandle user) {
+        if (quickShare == null) {
             return null;
+        } else if (quickShare.actionIntent.isImmutable()) {
+            Notification.Action quickShareWithUri =
+                    queryQuickShareAction(screenshotId, image, user, uri);
+            if (quickShareWithUri == null
+                    || !quickShareWithUri.title.toString().contentEquals(quickShare.title)) {
+                return null;
+            }
+            quickShare = quickShareWithUri;
         }
-        // Populate image URI into Quick Share chip intent
-        Intent sharingIntent = action.actionIntent.getIntent();
-        sharingIntent.setType("image/png");
-        sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
-        String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
-        String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
-        sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
-        // Include URI in ClipData also, so that grantPermission picks it up.
-        // We don't use setData here because some apps interpret this as "to:".
-        ClipData clipdata = new ClipData(new ClipDescription("content",
-                new String[]{"image/png"}),
-                new ClipData.Item(uri));
-        sharingIntent.setClipData(clipdata);
-        sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        PendingIntent updatedPendingIntent = PendingIntent.getActivity(
-                context, 0, sharingIntent,
-                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
 
-        // Proxy smart actions through {@link SmartActionsReceiver} for logging smart actions.
-        Bundle extras = action.getExtras();
+        Intent wrappedIntent = new Intent(mContext, SmartActionsReceiver.class)
+                .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, quickShare.actionIntent)
+                .putExtra(ScreenshotController.EXTRA_ACTION_INTENT_FILLIN,
+                        createFillInIntent(uri, imageTime))
+                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        Bundle extras = quickShare.getExtras();
         String actionType = extras.getString(
                 ScreenshotNotificationSmartActionsProvider.ACTION_TYPE,
                 ScreenshotNotificationSmartActionsProvider.DEFAULT_ACTION_TYPE);
-        Intent intent = new Intent(context, SmartActionsReceiver.class)
-                .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, updatedPendingIntent)
-                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
         // We only query for quick share actions when smart actions are enabled, so we can assert
         // that it's true here.
-        addIntentExtras(mScreenshotId, intent, actionType, true /* smartActionsEnabled */);
-        PendingIntent broadcastIntent = PendingIntent.getBroadcast(context,
-                mRandom.nextInt(),
-                intent,
-                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
-        return new Notification.Action.Builder(action.getIcon(), action.title,
-                broadcastIntent).setContextual(true).addExtras(extras).build();
+        addIntentExtras(screenshotId, wrappedIntent, actionType, true /* smartActionsEnabled */);
+        PendingIntent broadcastIntent =
+                PendingIntent.getBroadcast(mContext, mRandom.nextInt(), wrappedIntent,
+                        PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+        return new Notification.Action.Builder(quickShare.getIcon(), quickShare.title,
+                broadcastIntent)
+                .setContextual(true)
+                .addExtras(extras)
+                .build();
+    }
+
+    private Intent createFillInIntent(Uri uri, long imageTime) {
+        Intent fillIn = new Intent();
+        fillIn.setType("image/png");
+        fillIn.putExtra(Intent.EXTRA_STREAM, uri);
+        fillIn.putExtra(Intent.EXTRA_SUBJECT, getSubjectString(imageTime));
+        // Include URI in ClipData also, so that grantPermission picks it up.
+        // We don't use setData here because some apps interpret this as "to:".
+        ClipData clipData = new ClipData(
+                new ClipDescription("content", new String[]{"image/png"}),
+                new ClipData.Item(uri));
+        fillIn.setClipData(clipData);
+        fillIn.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        return fillIn;
     }
 
     /**
      * Query and surface Quick Share chip if it is available. Action intent would not be used,
      * because it does not contain image URL which would be populated in {@link
-     * #createQuickShareAction(Context, Notification.Action, Uri)}
+     * #createQuickShareAction(Notification.Action, String, Uri, long, Bitmap, UserHandle)}
      */
-    private void queryQuickShareAction(Bitmap image, UserHandle user) {
+
+    @VisibleForTesting
+    Notification.Action queryQuickShareAction(
+            String screenshotId, Bitmap image, UserHandle user, Uri uri) {
         CompletableFuture<List<Notification.Action>> quickShareActionsFuture =
                 mScreenshotSmartActions.getSmartActionsFuture(
-                        mScreenshotId, null, image, mSmartActionsProvider,
+                        screenshotId, uri, image, mSmartActionsProvider,
                         ScreenshotSmartActionType.QUICK_SHARE_ACTION,
                         true /* smartActionsEnabled */, user);
         int timeoutMs = DeviceConfig.getInt(
@@ -479,17 +498,17 @@
                 500);
         List<Notification.Action> quickShareActions =
                 mScreenshotSmartActions.getSmartActions(
-                        mScreenshotId, quickShareActionsFuture, timeoutMs,
+                        screenshotId, quickShareActionsFuture, timeoutMs,
                         mSmartActionsProvider,
                         ScreenshotSmartActionType.QUICK_SHARE_ACTION);
         if (!quickShareActions.isEmpty()) {
-            mQuickShareData.quickShareAction = quickShareActions.get(0);
-            mParams.mQuickShareActionsReadyListener.onActionsReady(mQuickShareData);
+            return quickShareActions.get(0);
         }
+        return null;
     }
 
-    private String getSubjectString() {
-        String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
+    private static String getSubjectString(long imageTime) {
+        String subjectDate = DateFormat.getDateTimeInstance().format(new Date(imageTime));
         return String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 77a65b2..b59106e 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -246,6 +246,7 @@
     static final String EXTRA_SMART_ACTIONS_ENABLED = "android:smart_actions_enabled";
     static final String EXTRA_OVERRIDE_TRANSITION = "android:screenshot_override_transition";
     static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent";
+    static final String EXTRA_ACTION_INTENT_FILLIN = "android:screenshot_action_intent_fillin";
 
     static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";
     static final String EXTRA_CANCEL_NOTIFICATION = "android:screenshot_cancel_notification";
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java
index 68b46d2..ca713fe 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSmartActions.java
@@ -30,7 +30,6 @@
 import android.os.UserHandle;
 import android.util.Log;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 
@@ -61,7 +60,6 @@
                 screenshotNotificationSmartActionsProviderProvider;
     }
 
-    @VisibleForTesting
     CompletableFuture<List<Notification.Action>> getSmartActionsFuture(
             String screenshotId, Uri screenshotUri, Bitmap image,
             ScreenshotNotificationSmartActionsProvider smartActionsProvider,
@@ -83,7 +81,7 @@
         if (image.getConfig() != Bitmap.Config.HARDWARE) {
             if (DEBUG_ACTIONS) {
                 Log.d(TAG, String.format("Bitmap expected: Hardware, Bitmap found: %s. "
-                                + "Returning empty list.", image.getConfig()));
+                        + "Returning empty list.", image.getConfig()));
             }
             return CompletableFuture.completedFuture(Collections.emptyList());
         }
@@ -112,7 +110,6 @@
         return smartActionsFuture;
     }
 
-    @VisibleForTesting
     List<Notification.Action> getSmartActions(String screenshotId,
             CompletableFuture<List<Notification.Action>> smartActionsFuture, int timeoutMs,
             ScreenshotNotificationSmartActionsProvider smartActionsProvider,
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java
index 45af187..9761f59 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java
@@ -18,6 +18,7 @@
 
 import static com.android.systemui.screenshot.LogConfig.DEBUG_ACTIONS;
 import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_INTENT;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_INTENT_FILLIN;
 import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_TYPE;
 import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ID;
 
@@ -46,7 +47,9 @@
 
     @Override
     public void onReceive(Context context, Intent intent) {
-        PendingIntent pendingIntent = intent.getParcelableExtra(EXTRA_ACTION_INTENT);
+        PendingIntent pendingIntent =
+                intent.getParcelableExtra(EXTRA_ACTION_INTENT, PendingIntent.class);
+        Intent fillIn = intent.getParcelableExtra(EXTRA_ACTION_INTENT_FILLIN, Intent.class);
         String actionType = intent.getStringExtra(EXTRA_ACTION_TYPE);
         if (DEBUG_ACTIONS) {
             Log.d(TAG, "Executing smart action [" + actionType + "]:" + pendingIntent.getIntent());
@@ -54,7 +57,7 @@
         ActivityOptions opts = ActivityOptions.makeBasic();
 
         try {
-            pendingIntent.send(context, 0, null, null, null, null, opts.toBundle());
+            pendingIntent.send(context, 0, fillIn, null, null, null, opts.toBundle());
         } catch (PendingIntent.CanceledException e) {
             Log.e(TAG, "Pending intent canceled", e);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 047fea1..17a8870 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -222,6 +222,8 @@
 import com.android.systemui.util.time.SystemClock;
 import com.android.wm.shell.animation.FlingAnimationUtils;
 
+import kotlin.Unit;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -232,7 +234,6 @@
 import javax.inject.Inject;
 import javax.inject.Provider;
 
-import kotlin.Unit;
 import kotlinx.coroutines.CoroutineDispatcher;
 
 @CentralSurfacesComponent.CentralSurfacesScope
@@ -934,10 +935,11 @@
                     @Override
                     public void onUnlockAnimationStarted(
                             boolean playingCannedAnimation,
-                            boolean isWakeAndUnlock,
+                            boolean isWakeAndUnlockNotFromDream,
                             long startDelay,
                             long unlockAnimationDuration) {
-                        unlockAnimationStarted(playingCannedAnimation, isWakeAndUnlock, startDelay);
+                        unlockAnimationStarted(playingCannedAnimation, isWakeAndUnlockNotFromDream,
+                                startDelay);
                     }
                 });
         mAlternateBouncerInteractor = alternateBouncerInteractor;
@@ -952,7 +954,7 @@
 
     private void unlockAnimationStarted(
             boolean playingCannedAnimation,
-            boolean isWakeAndUnlock,
+            boolean isWakeAndUnlockNotFromDream,
             long unlockAnimationStartDelay) {
         // Disable blurs while we're unlocking so that panel expansion does not
         // cause blurring. This will eventually be re-enabled by the panel view on
@@ -960,7 +962,7 @@
         // unlock gesture, and we don't want that to cause blurring either.
         mDepthController.setBlursDisabledForUnlock(mTracking);
 
-        if (playingCannedAnimation && !isWakeAndUnlock) {
+        if (playingCannedAnimation && !isWakeAndUnlockNotFromDream) {
             // Hide the panel so it's not in the way or the surface behind the
             // keyguard, which will be appearing. If we're wake and unlocking, the
             // lock screen is hidden instantly so should not be flung away.
@@ -2010,6 +2012,8 @@
         }
         updateExpansionAndVisibility();
         mNotificationStackScrollLayoutController.setPanelFlinging(false);
+        // expandImmediate should be always reset at the end of animation
+        mQsController.setExpandImmediate(false);
     }
 
     private boolean isInContentBounds(float x, float y) {
@@ -3450,6 +3454,7 @@
     @VisibleForTesting
     void notifyExpandingStarted() {
         if (!mExpanding) {
+            DejankUtils.notifyRendererOfExpensiveFrame(mView, "notifyExpandingStarted");
             mExpanding = true;
             mIsExpandingOrCollapsing = true;
             mQsController.onExpandingStarted(mQsController.getFullyExpanded());
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index c42c2f4..6480164 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -63,6 +63,7 @@
 import com.android.internal.policy.SystemBarUtils;
 import com.android.keyguard.FaceAuthApiRequestReason;
 import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.DejankUtils;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.classifier.Classifier;
@@ -958,6 +959,7 @@
         // TODO (b/265193930): remove dependency on NPVC
         mPanelViewControllerLazy.get().cancelHeightAnimator();
         // end
+        DejankUtils.notifyRendererOfExpensiveFrame(mPanelView, "onExpansionStarted");
 
         // Reset scroll position and apply that position to the expanded height.
         float height = mExpansionHeight;
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
index f080d3d..3af75ce 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
@@ -34,6 +34,7 @@
 import android.widget.TextView
 import androidx.annotation.VisibleForTesting
 import androidx.constraintlayout.motion.widget.MotionLayout
+import androidx.core.view.doOnLayout
 import com.android.app.animation.Interpolators
 import com.android.settingslib.Utils
 import com.android.systemui.Dumpable
@@ -220,6 +221,7 @@
             override fun demoCommands() = listOf(DemoMode.COMMAND_CLOCK)
             override fun dispatchDemoCommand(command: String, args: Bundle) =
                 clock.dispatchDemoCommand(command, args)
+
             override fun onDemoModeStarted() = clock.onDemoModeStarted()
             override fun onDemoModeFinished() = clock.onDemoModeFinished()
         }
@@ -259,6 +261,7 @@
                     resources.getDimensionPixelSize(R.dimen.large_screen_shade_header_min_height)
                 lastInsets?.let { updateConstraintsForInsets(header, it) }
                 updateResources()
+                updateCarrierGroupPadding()
             }
         }
 
@@ -291,6 +294,7 @@
         privacyIconsController.chipVisibilityListener = chipVisibilityListener
         updateVisibility()
         updateTransition()
+        updateCarrierGroupPadding()
 
         header.setOnApplyWindowInsetsListener(insetListener)
 
@@ -298,8 +302,6 @@
             val newPivot = if (v.isLayoutRtl) v.width.toFloat() else 0f
             v.pivotX = newPivot
             v.pivotY = v.height.toFloat() / 2
-
-            mShadeCarrierGroup.setPaddingRelative((v.width * v.scaleX).toInt(), 0, 0, 0)
         }
         clock.setOnClickListener { launchClockActivity() }
 
@@ -359,6 +361,14 @@
             .load(context, resources.getXml(R.xml.large_screen_shade_header))
     }
 
+    private fun updateCarrierGroupPadding() {
+        clock.doOnLayout {
+            val maxClockWidth =
+                (clock.width * resources.getFloat(R.dimen.qqs_expand_clock_scale)).toInt()
+            mShadeCarrierGroup.setPaddingRelative(maxClockWidth, 0, 0, 0)
+        }
+    }
+
     private fun updateConstraintsForInsets(view: MotionLayout, insets: WindowInsets) {
         val cutout = insets.displayCutout.also { this.cutout = it }
 
diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt b/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
index 641131e..03be88f 100644
--- a/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
@@ -34,6 +34,11 @@
         const val DREAM_SMARTSPACE_DATA_PLUGIN = "dreams_smartspace_data_plugin"
 
         /**
+         * The BcSmartspaceDataPlugin for the standalone weather on dream.
+         */
+        const val DREAM_WEATHER_SMARTSPACE_DATA_PLUGIN = "dream_weather_smartspace_data_plugin"
+
+        /**
          * The dream smartspace target filter.
          */
         const val DREAM_SMARTSPACE_TARGET_FILTER = "dream_smartspace_target_filter"
@@ -62,6 +67,10 @@
     @Named(DREAM_SMARTSPACE_DATA_PLUGIN)
     abstract fun optionalDreamsBcSmartspaceDataPlugin(): BcSmartspaceDataPlugin?
 
+    @BindsOptionalOf
+    @Named(DREAM_WEATHER_SMARTSPACE_DATA_PLUGIN)
+    abstract fun optionalDreamWeatherSmartspaceDataPlugin(): BcSmartspaceDataPlugin?
+
     @Binds
     @Named(DREAM_SMARTSPACE_PRECONDITION)
     abstract fun bindSmartspacePrecondition(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
index b6970ae..39d213d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
@@ -83,7 +83,8 @@
             return
         }
         if (lastAppliedBlur == 0 && radius != 0) {
-            Trace.asyncTraceForTrackBegin(TRACE_TAG_APP, TRACK_NAME, EARLY_WAKEUP_SLICE_NAME, 0)
+            Trace.asyncTraceForTrackBegin(
+                    TRACE_TAG_APP, TRACK_NAME, "eEarlyWakeup (prepareBlur)", 0)
             earlyWakeupEnabled = true
             createTransaction().use {
                 it.setEarlyWakeupStart()
@@ -110,7 +111,7 @@
                     Trace.asyncTraceForTrackBegin(
                         TRACE_TAG_APP,
                         TRACK_NAME,
-                        EARLY_WAKEUP_SLICE_NAME,
+                        "eEarlyWakeup (applyBlur)",
                         0
                     )
                     it.setEarlyWakeupStart()
@@ -159,6 +160,5 @@
 
     companion object {
         const val TRACK_NAME = "BlurUtils"
-        const val EARLY_WAKEUP_SLICE_NAME = "eEarlyWakeup"
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
index 0a18f2d..56ea703 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
@@ -188,7 +188,9 @@
         if (animationState.value == ANIMATING_OUT) {
             coroutineScope.launch {
                 withTimeout(DISAPPEAR_ANIMATION_DURATION) {
-                    animationState.first { it == SHOWING_PERSISTENT_DOT || it == ANIMATION_QUEUED }
+                    animationState.first {
+                        it == SHOWING_PERSISTENT_DOT || it == IDLE || it == ANIMATION_QUEUED
+                    }
                     notifyHidePersistentDot()
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
index 23b5241..314566e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
@@ -633,12 +633,17 @@
         mFSIUpdateCandidates.removeAll(toRemoveForFSI)
     }
 
-    /** When an action is pressed on a notification, end HeadsUp lifetime extension. */
+    /**
+     * When an action is pressed on a notification, make sure we don't lifetime-extend it in the
+     * future by informing the HeadsUpManager, and make sure we don't keep lifetime-extending it if
+     * we already are.
+     *
+     * @see HeadsUpManager.setUserActionMayIndirectlyRemove
+     * @see HeadsUpManager.canRemoveImmediately
+     */
     private val mActionPressListener = Consumer<NotificationEntry> { entry ->
-        if (mNotifsExtendingLifetime.contains(entry)) {
-            val removeInMillis = mHeadsUpManager.getEarliestRemovalTime(entry.key)
-            mExecutor.executeDelayed({ endNotifLifetimeExtensionIfExtended(entry) }, removeInMillis)
-        }
+        mHeadsUpManager.setUserActionMayIndirectlyRemove(entry)
+        mExecutor.execute { endNotifLifetimeExtensionIfExtended(entry) }
     }
 
     private val mLifetimeExtender = object : NotifLifetimeExtender {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index bfb6fb0..9f397fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -556,6 +556,11 @@
     }
 
     public void onNotificationUpdated() {
+        if (mIsSummaryWithChildren) {
+            Trace.beginSection("ExpNotRow#onNotifUpdated (summary)");
+        } else {
+            Trace.beginSection("ExpNotRow#onNotifUpdated (leaf)");
+        }
         for (NotificationContentView l : mLayouts) {
             l.onNotificationUpdated(mEntry);
         }
@@ -591,6 +596,7 @@
             mUpdateSelfBackgroundOnUpdate = false;
             updateBackgroundColorsOfSelf();
         }
+        Trace.endSection();
     }
 
     private void updateBackgroundColorsOfSelf() {
@@ -2588,6 +2594,7 @@
         mIsSummaryWithChildren = mChildrenContainer != null
                 && mChildrenContainer.getNotificationChildCount() > 0;
         if (mIsSummaryWithChildren) {
+            Trace.beginSection("ExpNotRow#onChildCountChanged (summary)");
             NotificationViewWrapper wrapper = mChildrenContainer.getNotificationViewWrapper();
             if (wrapper == null || wrapper.getNotificationHeader() == null) {
                 mChildrenContainer.recreateNotificationHeader(mExpandClickListener,
@@ -2599,6 +2606,9 @@
         updateChildrenAppearance();
         updateChildrenVisibility();
         applyChildrenRoundness();
+        if (mIsSummaryWithChildren) {
+            Trace.endSection();
+        }
     }
 
     protected void expandNotification() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java
index 77fd051..3e10f2a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java
@@ -22,6 +22,7 @@
 import android.app.Notification;
 import android.content.Context;
 import android.content.res.Resources;
+import android.os.Trace;
 import android.service.notification.StatusBarNotification;
 import android.util.TypedValue;
 import android.view.LayoutInflater;
@@ -57,6 +58,7 @@
     }
 
     private HybridNotificationView inflateHybridView(View contentView, ViewGroup parent) {
+        Trace.beginSection("HybridGroupManager#inflateHybridView");
         LayoutInflater inflater = LayoutInflater.from(mContext);
         int layout = contentView instanceof ConversationLayout
                 ? R.layout.hybrid_conversation_notification
@@ -64,6 +66,7 @@
         HybridNotificationView hybrid = (HybridNotificationView)
                 inflater.inflate(layout, parent, false);
         parent.addView(hybrid);
+        Trace.endSection();
         return hybrid;
     }
 
@@ -90,12 +93,18 @@
     public HybridNotificationView bindFromNotification(HybridNotificationView reusableView,
             View contentView, StatusBarNotification notification,
             ViewGroup parent) {
+        boolean isNewView = false;
         if (reusableView == null) {
+            Trace.beginSection("HybridGroupManager#bindFromNotification");
             reusableView = inflateHybridView(contentView, parent);
+            isNewView = true;
         }
         CharSequence titleText = resolveTitle(notification.getNotification());
         CharSequence contentText = resolveText(notification.getNotification());
         reusableView.bind(titleText, contentText, contentView);
+        if (isNewView) {
+            Trace.endSection();
+        }
         return reusableView;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 451d837..124df8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -26,6 +26,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.RemoteException;
+import android.os.Trace;
 import android.service.notification.StatusBarNotification;
 import android.util.ArrayMap;
 import android.util.AttributeSet;
@@ -1193,6 +1194,7 @@
 
     private void updateSingleLineView() {
         if (mIsChildInGroup) {
+            Trace.beginSection("NotifContentView#updateSingleLineView");
             boolean isNewView = mSingleLineView == null;
             mSingleLineView = mHybridGroupManager.bindFromNotification(
                     mSingleLineView, mContractedChild, mNotificationEntry.getSbn(), this);
@@ -1200,6 +1202,7 @@
                 updateViewVisibility(mVisibleType, VISIBLE_TYPE_SINGLELINE,
                         mSingleLineView, mSingleLineView);
             }
+            Trace.endSection();
         } else if (mSingleLineView != null) {
             removeView(mSingleLineView);
             mSingleLineView = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index d18757d..f8e374d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -379,6 +379,7 @@
     }
 
     public void recreateNotificationHeader(OnClickListener listener, boolean isConversation) {
+        Trace.beginSection("NotifChildCont#recreateHeader");
         mHeaderClickListener = listener;
         mIsConversation = isConversation;
         StatusBarNotification notification = mContainingNotification.getEntry().getSbn();
@@ -406,6 +407,7 @@
         recreateLowPriorityHeader(builder, isConversation);
         updateHeaderVisibility(false /* animate */);
         updateChildrenAppearance();
+        Trace.endSection();
     }
 
     /**
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 b81cb2b..f7c6594 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
@@ -4079,6 +4079,7 @@
                 if (!mIsExpansionChanging) {
                     cancelActiveSwipe();
                 }
+                finalizeClearAllAnimation();
             }
             updateNotificationAnimationStates();
             updateChronometers();
@@ -4174,20 +4175,30 @@
         runAnimationFinishedRunnables();
         clearTransient();
         clearHeadsUpDisappearRunning();
+        finalizeClearAllAnimation();
+    }
 
+    private void finalizeClearAllAnimation() {
         if (mAmbientState.isClearAllInProgress()) {
             setClearAllInProgress(false);
             if (mShadeNeedsToClose) {
                 mShadeNeedsToClose = false;
-                postDelayed(
-                        () -> {
-                            mShadeController.animateCollapseShade(CommandQueue.FLAG_EXCLUDE_NONE);
-                        },
-                        DELAY_BEFORE_SHADE_CLOSE /* delayMillis */);
+                if (mIsExpanded) {
+                    collapseShadeDelayed();
+                }
             }
         }
     }
 
+    private void collapseShadeDelayed() {
+        postDelayed(
+                () -> {
+                    mShadeController.animateCollapseShade(
+                            CommandQueue.FLAG_EXCLUDE_NONE);
+                },
+                DELAY_BEFORE_SHADE_CLOSE /* delayMillis */);
+    }
+
     private void clearHeadsUpDisappearRunning() {
         for (int i = 0; i < getChildCount(); i++) {
             View view = getChildAt(i);
@@ -4395,6 +4406,7 @@
         boolean nowHiddenAtAll = mAmbientState.isHiddenAtAll();
         if (nowFullyHidden != wasFullyHidden) {
             updateVisibility();
+            mSwipeHelper.resetTouchState();
         }
         if (!wasHiddenAtAll && nowHiddenAtAll) {
             resetExposedMenuView(true /* animate */, true /* animate */);
@@ -4535,6 +4547,7 @@
         mFooterView.setFooterLabelVisible(mHasFilteredOutSeenNotifications);
     }
 
+    @VisibleForTesting
     public void setClearAllInProgress(boolean clearAllInProgress) {
         mClearAllInProgress = clearAllInProgress;
         mAmbientState.setClearAllInProgress(clearAllInProgress);
@@ -4688,6 +4701,7 @@
         if (v instanceof ExpandableNotificationRow && !mController.isShowingEmptyShadeView()) {
             mController.updateShowEmptyShadeView();
             updateFooter();
+            mController.updateImportantForAccessibility();
         }
 
         updateSpeedBumpIndex();
@@ -4699,6 +4713,7 @@
         if (v instanceof ExpandableNotificationRow && mController.isShowingEmptyShadeView()) {
             mController.updateShowEmptyShadeView();
             updateFooter();
+            mController.updateImportantForAccessibility();
         }
 
         updateSpeedBumpIndex();
@@ -4711,6 +4726,7 @@
         if (v instanceof ExpandableNotificationRow && mController.isShowingEmptyShadeView()) {
             mController.updateShowEmptyShadeView();
             updateFooter();
+            mController.updateImportantForAccessibility();
         }
 
         updateSpeedBumpIndex();
@@ -5151,7 +5167,8 @@
         mHeadsUpAppearanceController = headsUpAppearanceController;
     }
 
-    private boolean isVisible(View child) {
+    @VisibleForTesting
+    public boolean isVisible(View child) {
         boolean hasClipBounds = child.getClipBounds(mTmpRect);
         return child.getVisibility() == View.VISIBLE
                 && (!hasClipBounds || mTmpRect.height() > 0);
@@ -5850,7 +5867,7 @@
     }
 
     private void cancelActiveSwipe() {
-        mSwipeHelper.resetSwipeState();
+        mSwipeHelper.resetTouchState();
         updateContinuousShadowDrawing();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 7b046d6..9272c37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -327,6 +327,7 @@
                     mView.updateSensitiveness(mStatusBarStateController.goingToFullShade(),
                             mLockscreenUserManager.isAnyProfilePublicMode());
                     mView.onStatePostChange(mStatusBarStateController.fromShadeLocked());
+                    updateImportantForAccessibility();
                 }
             };
 
@@ -1205,6 +1206,7 @@
         if (mView.getVisibility() == View.VISIBLE) {
             // Synchronize EmptyShadeView visibility with the parent container.
             updateShowEmptyShadeView();
+            updateImportantForAccessibility();
         }
     }
 
@@ -1232,6 +1234,22 @@
     }
 
     /**
+     * Update the importantForAccessibility of NotificationStackScrollLayout.
+     * <p>
+     * We want the NSSL to be unimportant for accessibility when there's no
+     * notifications in it while the device is on lock screen, to avoid unlablel NSSL view.
+     * Otherwise, we want it to be important for accessibility to enable accessibility
+     * auto-scrolling in NSSL.
+     */
+    public void updateImportantForAccessibility() {
+        if (getVisibleNotificationCount() == 0 && mView.onKeyguard()) {
+            mView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+        } else {
+            mView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+        }
+    }
+
+    /**
      * @return true if {@link StatusBarStateController} is in transition to the KEYGUARD
      * and false otherwise.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 0402d4f..1cd0f08 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -2836,7 +2836,11 @@
     }
 
     private void updateDozingState() {
-        Trace.traceCounter(Trace.TRACE_TAG_APP, "dozing", mDozing ? 1 : 0);
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_APP)) {
+            Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, "Dozing", 0);
+            Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, "Dozing", String.valueOf(mDozing),
+                    0);
+        }
         Trace.beginSection("CentralSurfaces#updateDozingState");
 
         boolean keyguardVisible = mKeyguardStateController.isVisible();
@@ -3190,6 +3194,10 @@
 
         @Override
         public void onStartedWakingUp() {
+            // Between onStartedWakingUp() and onFinishedWakingUp(), the system is changing the
+            // display power mode. To avoid jank, animations should NOT run during these power
+            // mode transitions, which means that whenever possible, animations should
+            // start running during the onFinishedWakingUp() callback instead of this callback.
             String tag = "CentralSurfaces#onStartedWakingUp";
             DejankUtils.startDetectingBlockingIpcs(tag);
             mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> {
@@ -3234,26 +3242,41 @@
 
                 updateVisibleToUser();
                 updateIsKeyguard();
-                mDozeServiceHost.stopDozing();
-                // This is intentionally below the stopDozing call above, since it avoids that we're
-                // unnecessarily animating the wakeUp transition. Animations should only be enabled
-                // once we fully woke up.
-                updateRevealEffect(true /* wakingUp */);
-                updateNotificationPanelTouchState();
-                mStatusBarTouchableRegionManager.updateTouchableRegion();
-
-                // If we are waking up during the screen off animation, we should undo making the
-                // expanded visible (we did that so the LightRevealScrim would be visible).
-                if (mScreenOffAnimationController.shouldHideLightRevealScrimOnWakeUp()) {
-                    mShadeController.makeExpandedInvisible();
+                if (!mFeatureFlags.isEnabled(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD)) {
+                    startLockscreenTransitionFromAod();
                 }
-
             });
             DejankUtils.stopDetectingBlockingIpcs(tag);
         }
 
+        /**
+         * Private helper for starting the LOCKSCREEN_TRANSITION_FROM_AOD animation - only necessary
+         * so we can start it from either onFinishedWakingUp() or onFinishedWakingUp() depending
+         * on a flag value.
+         */
+        private void startLockscreenTransitionFromAod() {
+            // stopDozing() starts the LOCKSCREEN_TRANSITION_FROM_AOD animation.
+            mDozeServiceHost.stopDozing();
+            // This is intentionally below the stopDozing call above, since it avoids that we're
+            // unnecessarily animating the wakeUp transition. Animations should only be enabled
+            // once we fully woke up.
+            updateRevealEffect(true /* wakingUp */);
+            updateNotificationPanelTouchState();
+            mStatusBarTouchableRegionManager.updateTouchableRegion();
+
+            // If we are waking up during the screen off animation, we should undo making the
+            // expanded visible (we did that so the LightRevealScrim would be visible).
+            if (mScreenOffAnimationController.shouldHideLightRevealScrimOnWakeUp()) {
+                mShadeController.makeExpandedInvisible();
+            }
+        }
+
         @Override
         public void onFinishedWakingUp() {
+            if (mFeatureFlags.isEnabled(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD)) {
+                mNotificationShadeWindowController.batchApplyWindowLayoutParams(
+                        this::startLockscreenTransitionFromAod);
+            }
             mWakeUpCoordinator.setFullyAwake(true);
             mWakeUpCoordinator.setWakingUp(false, false);
             if (mKeyguardStateController.isOccluded()
@@ -3677,7 +3700,10 @@
     private void onShadeVisibilityChanged(boolean visible) {
         if (mVisible != visible) {
             mVisible = visible;
-            if (!visible) {
+            if (visible) {
+                DejankUtils.notifyRendererOfExpensiveFrame(
+                        mNotificationShadeWindowView, "onShadeVisibilityChanged");
+            } else {
                 mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */,
                         true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index ed8050a..92a7854 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -393,6 +393,31 @@
         }
     }
 
+    /**
+     * Notes that the user took an action on an entry that might indirectly cause the system or the
+     * app to remove the notification.
+     *
+     * @param entry the entry that might be indirectly removed by the user's action
+     *
+     * @see com.android.systemui.statusbar.notification.collection.coordinator.HeadsUpCoordinator#mActionPressListener
+     * @see #canRemoveImmediately(String)
+     */
+    public void setUserActionMayIndirectlyRemove(@NonNull NotificationEntry entry) {
+        HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.getKey());
+        if (headsUpEntry != null) {
+            headsUpEntry.userActionMayIndirectlyRemove = true;
+        }
+    }
+
+    @Override
+    public boolean canRemoveImmediately(@NonNull String key) {
+        HeadsUpEntry headsUpEntry = getHeadsUpEntry(key);
+        if (headsUpEntry != null && headsUpEntry.userActionMayIndirectlyRemove) {
+            return true;
+        }
+        return super.canRemoveImmediately(key);
+    }
+
     @NonNull
     @Override
     protected HeadsUpEntry createAlertEntry() {
@@ -421,6 +446,8 @@
      */
     protected class HeadsUpEntry extends AlertEntry {
         public boolean remoteInputActive;
+        public boolean userActionMayIndirectlyRemove;
+
         protected boolean expanded;
         protected boolean wasUnpinned;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index d585163..02b7e91 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -21,7 +21,6 @@
 import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_STANDARD;
 
 import android.app.ActivityManager;
-import android.app.Notification;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.ColorStateList;
@@ -47,7 +46,6 @@
 import android.view.View;
 import android.view.ViewAnimationUtils;
 import android.view.ViewGroup;
-import android.view.ViewGroupOverlay;
 import android.view.ViewRootImpl;
 import android.view.WindowInsets;
 import android.view.WindowInsetsAnimation;
@@ -58,6 +56,7 @@
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.EditText;
+import android.widget.FrameLayout;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -436,25 +435,23 @@
             if (animate && parent != null && mIsFocusAnimationFlagActive) {
 
                 ViewGroup grandParent = (ViewGroup) parent.getParent();
-                ViewGroupOverlay overlay = parent.getOverlay();
                 View actionsContainer = getActionsContainerLayout();
                 int actionsContainerHeight =
                         actionsContainer != null ? actionsContainer.getHeight() : 0;
 
-                // After adding this RemoteInputView to the overlay of the parent (and thus removing
-                // it from the parent itself), the parent will shrink in height. This causes the
-                // overlay to be moved. To correct the position of the overlay we need to offset it.
-                int overlayOffsetY = actionsContainerHeight - getHeight();
-                overlay.add(this);
+                // When defocusing, the notification needs to shrink. Therefore, we need to free
+                // up the space that was needed for the RemoteInputView. This is done by setting
+                // a negative top margin of the height difference of the RemoteInputView and its
+                // sibling (the actions_container_layout containing the Reply button etc.)
+                final int heightToShrink = actionsContainerHeight - getHeight();
+                setTopMargin(heightToShrink);
                 if (grandParent != null) grandParent.setClipChildren(false);
 
-                Animator animator = getDefocusAnimator(actionsContainer, overlayOffsetY);
-                View self = this;
+                final Animator animator = getDefocusAnimator(actionsContainer);
                 animator.addListener(new AnimatorListenerAdapter() {
                     @Override
                     public void onAnimationEnd(Animator animation) {
-                        overlay.remove(self);
-                        parent.addView(self);
+                        setTopMargin(0);
                         if (grandParent != null) grandParent.setClipChildren(true);
                         setVisibility(GONE);
                         if (mWrapper != null) {
@@ -499,6 +496,13 @@
         }
     }
 
+    private void setTopMargin(int topMargin) {
+        if (!(getLayoutParams() instanceof FrameLayout.LayoutParams)) return;
+        final FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) getLayoutParams();
+        layoutParams.topMargin = topMargin;
+        setLayoutParams(layoutParams);
+    }
+
     @VisibleForTesting
     protected void setViewRootImpl(ViewRootImpl viewRoot) {
         mTestableViewRootImpl = viewRoot;
@@ -674,12 +678,12 @@
             mProgressBar.setVisibility(INVISIBLE);
             mResetting = true;
             mSending = false;
+            mController.removeSpinning(mEntry.getKey(), mToken);
             onDefocus(true /* animate */, false /* logClose */, () -> {
                 mEntry.remoteInputTextWhenReset = SpannedString.valueOf(mEditText.getText());
                 mEditText.getText().clear();
                 mEditText.setEnabled(isAggregatedVisible());
                 mSendButton.setVisibility(VISIBLE);
-                mController.removeSpinning(mEntry.getKey(), mToken);
                 updateSendButton();
                 setAttachment(null);
                 mResetting = false;
@@ -874,7 +878,7 @@
 
         ValueAnimator scaleAnimator = ValueAnimator.ofFloat(FOCUS_ANIMATION_MIN_SCALE, 1f);
         scaleAnimator.addUpdateListener(valueAnimator -> {
-            setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue(), 0);
+            setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue());
         });
         scaleAnimator.setDuration(FOCUS_ANIMATION_TOTAL_DURATION);
         scaleAnimator.setInterpolator(InterpolatorsAndroidX.FAST_OUT_SLOW_IN);
@@ -901,9 +905,8 @@
      * Creates an animator for the defocus animation.
      *
      * @param fadeInView View that will be faded in during the defocus animation.
-     * @param offsetY    The RemoteInputView will be offset by offsetY during the animation
      */
-    private Animator getDefocusAnimator(@Nullable View fadeInView, int offsetY) {
+    private Animator getDefocusAnimator(@Nullable View fadeInView) {
         final AnimatorSet animatorSet = new AnimatorSet();
 
         final Animator alphaAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 1f, 0f);
@@ -913,14 +916,14 @@
 
         ValueAnimator scaleAnimator = ValueAnimator.ofFloat(1f, FOCUS_ANIMATION_MIN_SCALE);
         scaleAnimator.addUpdateListener(valueAnimator -> {
-            setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue(), offsetY);
+            setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue());
         });
         scaleAnimator.setDuration(FOCUS_ANIMATION_TOTAL_DURATION);
         scaleAnimator.setInterpolator(InterpolatorsAndroidX.FAST_OUT_SLOW_IN);
         scaleAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation, boolean isReverse) {
-                setFocusAnimationScaleY(1f /* scaleY */, 0 /* verticalOffset */);
+                setFocusAnimationScaleY(1f /* scaleY */);
             }
         });
 
@@ -942,9 +945,8 @@
      * Sets affected view properties for a vertical scale animation
      *
      * @param scaleY         desired vertical view scale
-     * @param verticalOffset vertical offset to apply to the RemoteInputView during the animation
      */
-    private void setFocusAnimationScaleY(float scaleY, int verticalOffset) {
+    private void setFocusAnimationScaleY(float scaleY) {
         int verticalBoundOffset = (int) ((1f - scaleY) * 0.5f * mContentView.getHeight());
         Rect contentBackgroundBounds = new Rect(0, verticalBoundOffset, mContentView.getWidth(),
                 mContentView.getHeight() - verticalBoundOffset);
@@ -955,7 +957,7 @@
         } else {
             mContentBackgroundBounds = contentBackgroundBounds;
         }
-        setTranslationY(verticalBoundOffset + verticalOffset);
+        setTranslationY(verticalBoundOffset);
     }
 
     /** Handler for button click on send action in IME. */
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldHapticsPlayer.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldHapticsPlayer.kt
index 8214822..1e73cb3 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldHapticsPlayer.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldHapticsPlayer.kt
@@ -1,6 +1,7 @@
 package com.android.systemui.unfold
 
 import android.os.SystemProperties
+import android.os.VibrationAttributes
 import android.os.VibrationEffect
 import android.os.Vibrator
 import com.android.systemui.dagger.qualifiers.Main
@@ -22,6 +23,8 @@
 ) : TransitionProgressListener {
 
     private var isFirstAnimationAfterUnfold = false
+    private val touchVibrationAttributes =
+            VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK)
 
     init {
         if (vibrator != null) {
@@ -71,7 +74,7 @@
     }
 
     private fun playHaptics() {
-        vibrator?.vibrate(effect)
+        vibrator?.vibrate(effect, touchVibrationAttributes)
     }
 
     private val hapticsScale: Float
diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt b/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt
index 7236e0f..59f2cdb 100644
--- a/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt
@@ -224,7 +224,7 @@
                     }
             sectionView.removeAllViewsInLayout()
 
-            for (viewModel in section) {
+            section.onEachIndexed { index, viewModel ->
                 val view =
                     layoutInflater.inflate(
                         R.layout.user_switcher_fullscreen_popup_item,
@@ -237,6 +237,13 @@
                     view.resources.getString(viewModel.textResourceId)
                 view.setOnClickListener { viewModel.onClicked() }
                 sectionView.addView(view)
+                // Ensure that the first item in the first section gets accessibility focus.
+                // Request for focus with a delay when view is inflated an added to the listview.
+                if (index == 0 && position == 0) {
+                    view.postDelayed({
+                        view.requestAccessibilityFocus()
+                    }, 200)
+                }
             }
             return sectionView
         }
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/PackageManagerExt.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/PackageManagerExt.kt
new file mode 100644
index 0000000..891ee0c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/PackageManagerExt.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.kotlin
+
+import android.annotation.WorkerThread
+import android.content.pm.ComponentInfo
+import android.content.pm.PackageManager
+import com.android.systemui.util.Assert
+
+@WorkerThread
+fun PackageManager.isComponentActuallyEnabled(componentInfo: ComponentInfo): Boolean {
+    Assert.isNotMainThread()
+    return when (getComponentEnabledSetting(componentInfo.componentName)) {
+        PackageManager.COMPONENT_ENABLED_STATE_ENABLED -> true
+        PackageManager.COMPONENT_ENABLED_STATE_DISABLED -> false
+        PackageManager.COMPONENT_ENABLED_STATE_DEFAULT -> componentInfo.isEnabled
+        else -> false
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index b24a692..9362220 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -390,8 +390,6 @@
     public void init(int windowType, Callback callback) {
         initDialog(mActivityManager.getLockTaskModeState());
 
-        mAccessibility.init();
-
         mController.addCallback(mControllerCallbackH, mHandler);
         mController.getState();
 
@@ -677,6 +675,7 @@
         initRingerH();
         initSettingsH(lockTaskModeState);
         initODICaptionsH();
+        mAccessibility.init();
     }
 
     private boolean isWindowGravityLeft() {
@@ -2006,14 +2005,14 @@
                 if (row.anim == null) {
                     row.anim = ObjectAnimator.ofInt(row.slider, "progress", progress, newProgress);
                     row.anim.setInterpolator(new DecelerateInterpolator());
+                    row.anim.addListener(
+                        getJankListener(row.view, TYPE_UPDATE, UPDATE_ANIMATION_DURATION));
                 } else {
                     row.anim.cancel();
                     row.anim.setIntValues(progress, newProgress);
                 }
                 row.animTargetProgress = newProgress;
                 row.anim.setDuration(UPDATE_ANIMATION_DURATION);
-                row.anim.addListener(
-                        getJankListener(row.view, TYPE_UPDATE, UPDATE_ANIMATION_DURATION));
                 row.anim.start();
             } else {
                 // update slider directly to clamped value
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt
index 14ad3ac..263d375 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt
@@ -26,18 +26,17 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.google.common.truth.Truth.assertThat
+import kotlin.math.ceil
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentCaptor
-import org.mockito.Mockito.`when`
 import org.mockito.Mockito.eq
 import org.mockito.Mockito.inOrder
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.never
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
-
-import kotlin.math.ceil
+import org.mockito.Mockito.`when`
 
 @RunWith(AndroidTestingRunner::class)
 @SmallTest
@@ -56,15 +55,13 @@
         val paint = mock(TextPaint::class.java)
         `when`(textInterpolator.targetPaint).thenReturn(paint)
 
-        val textAnimator = TextAnimator(layout, {}).apply {
-            this.textInterpolator = textInterpolator
-            this.animator = valueAnimator
-        }
+        val textAnimator =
+            TextAnimator(layout, null, {}).apply {
+                this.textInterpolator = textInterpolator
+                this.animator = valueAnimator
+            }
 
-        textAnimator.setTextStyle(
-                weight = 400,
-                animate = true
-        )
+        textAnimator.setTextStyle(weight = 400, animate = true)
 
         // If animation is requested, the base state should be rebased and the target state should
         // be updated.
@@ -88,15 +85,13 @@
         val paint = mock(TextPaint::class.java)
         `when`(textInterpolator.targetPaint).thenReturn(paint)
 
-        val textAnimator = TextAnimator(layout, {}).apply {
-            this.textInterpolator = textInterpolator
-            this.animator = valueAnimator
-        }
+        val textAnimator =
+            TextAnimator(layout, null, {}).apply {
+                this.textInterpolator = textInterpolator
+                this.animator = valueAnimator
+            }
 
-        textAnimator.setTextStyle(
-                weight = 400,
-                animate = false
-        )
+        textAnimator.setTextStyle(weight = 400, animate = false)
 
         // If animation is not requested, the progress should be 1 which is end of animation and the
         // base state is rebased to target state by calling rebase.
@@ -118,15 +113,16 @@
         `when`(textInterpolator.targetPaint).thenReturn(paint)
         val animationEndCallback = mock(Runnable::class.java)
 
-        val textAnimator = TextAnimator(layout, {}).apply {
-            this.textInterpolator = textInterpolator
-            this.animator = valueAnimator
-        }
+        val textAnimator =
+            TextAnimator(layout, null, {}).apply {
+                this.textInterpolator = textInterpolator
+                this.animator = valueAnimator
+            }
 
         textAnimator.setTextStyle(
-                weight = 400,
-                animate = true,
-                onAnimationEnd = animationEndCallback
+            weight = 400,
+            animate = true,
+            onAnimationEnd = animationEndCallback
         )
 
         // Verify animationEnd callback has been added.
@@ -144,34 +140,27 @@
         val layout = makeLayout("Hello, World", PAINT)
         val valueAnimator = mock(ValueAnimator::class.java)
         val textInterpolator = mock(TextInterpolator::class.java)
-        val paint = TextPaint().apply {
-            typeface = Typeface.createFromFile("/system/fonts/Roboto-Regular.ttf")
-        }
+        val paint =
+            TextPaint().apply {
+                typeface = Typeface.createFromFile("/system/fonts/Roboto-Regular.ttf")
+            }
         `when`(textInterpolator.targetPaint).thenReturn(paint)
 
-        val textAnimator = TextAnimator(layout, {}).apply {
-            this.textInterpolator = textInterpolator
-            this.animator = valueAnimator
-        }
+        val textAnimator =
+            TextAnimator(layout, null, {}).apply {
+                this.textInterpolator = textInterpolator
+                this.animator = valueAnimator
+            }
 
-        textAnimator.setTextStyle(
-                weight = 400,
-                animate = true
-        )
+        textAnimator.setTextStyle(weight = 400, animate = true)
 
         val prevTypeface = paint.typeface
 
-        textAnimator.setTextStyle(
-                weight = 700,
-                animate = true
-        )
+        textAnimator.setTextStyle(weight = 700, animate = true)
 
         assertThat(paint.typeface).isNotSameInstanceAs(prevTypeface)
 
-        textAnimator.setTextStyle(
-                weight = 400,
-                animate = true
-        )
+        textAnimator.setTextStyle(weight = 400, animate = true)
 
         assertThat(paint.typeface).isSameInstanceAs(prevTypeface)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImplTest.kt
index 7fb088e..bd4e8da 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImplTest.kt
@@ -20,6 +20,7 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
 import org.junit.Assert.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -27,16 +28,20 @@
 @RunWith(AndroidTestingRunner::class)
 @SmallTest
 class ControlsTileResourceConfigurationImplTest : SysuiTestCase() {
+
+    @Test
+    fun getPackageName() {
+        assertThat(ControlsTileResourceConfigurationImpl().getPackageName()).isNull()
+    }
+
     @Test
     fun getTileImageId() {
         val instance = ControlsTileResourceConfigurationImpl()
-        assertEquals(instance.getTileImageId(),
-            R.drawable.controls_icon)
+        assertEquals(instance.getTileImageId(), R.drawable.controls_icon)
     }
     @Test
     fun getTileTitleId() {
         val instance = ControlsTileResourceConfigurationImpl()
-        assertEquals(instance.getTileTitleId(),
-            R.string.quick_controls_title)
+        assertEquals(instance.getTileTitleId(), R.string.quick_controls_title)
     }
-}
\ No newline at end of file
+}
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
index 9144b13..0b27bc9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
@@ -22,10 +22,10 @@
 import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED
 import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.controls.settings.FakeControlsSettingsRepository
 import com.android.systemui.controls.controller.ControlsController
 import com.android.systemui.controls.controller.ControlsTileResourceConfiguration
 import com.android.systemui.controls.management.ControlsListingController
+import com.android.systemui.controls.settings.FakeControlsSettingsRepository
 import com.android.systemui.controls.ui.ControlsUiController
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -40,32 +40,25 @@
 import org.mockito.Answers
 import org.mockito.Mock
 import org.mockito.Mockito
+import org.mockito.Mockito.any
 import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.`when`
-import org.mockito.Mockito.any
 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
-    @Mock
-    private lateinit var keyguardStateController: KeyguardStateController
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private lateinit var userTracker: UserTracker
-    @Mock
-    private lateinit var lockPatternUtils: LockPatternUtils
+    @Mock private lateinit var controller: ControlsController
+    @Mock private lateinit var uiController: ControlsUiController
+    @Mock private lateinit var listingController: ControlsListingController
+    @Mock private lateinit var keyguardStateController: KeyguardStateController
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var userTracker: UserTracker
+    @Mock private lateinit var lockPatternUtils: LockPatternUtils
     @Mock
     private lateinit var optionalControlsTileResourceConfiguration:
-            Optional<ControlsTileResourceConfiguration>
-    @Mock
-    private lateinit var controlsTileResourceConfiguration: ControlsTileResourceConfiguration
+        Optional<ControlsTileResourceConfiguration>
+    @Mock private lateinit var controlsTileResourceConfiguration: ControlsTileResourceConfiguration
 
     private lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
 
@@ -123,8 +116,7 @@
 
     @Test
     fun testFeatureEnabledAndCannotShowOnLockScreenVisibility() {
-        `when`(lockPatternUtils.getStrongAuthForUser(anyInt()))
-            .thenReturn(STRONG_AUTH_NOT_REQUIRED)
+        `when`(lockPatternUtils.getStrongAuthForUser(anyInt())).thenReturn(STRONG_AUTH_NOT_REQUIRED)
         `when`(keyguardStateController.isUnlocked()).thenReturn(false)
         controlsSettingsRepository.setCanShowControlsInLockscreen(false)
         val component = setupComponent(true)
@@ -134,8 +126,7 @@
 
     @Test
     fun testFeatureEnabledAndCanShowOnLockScreenVisibility() {
-        `when`(lockPatternUtils.getStrongAuthForUser(anyInt()))
-            .thenReturn(STRONG_AUTH_NOT_REQUIRED)
+        `when`(lockPatternUtils.getStrongAuthForUser(anyInt())).thenReturn(STRONG_AUTH_NOT_REQUIRED)
         `when`(keyguardStateController.isUnlocked()).thenReturn(false)
         controlsSettingsRepository.setCanShowControlsInLockscreen(true)
         val component = setupComponent(true)
@@ -146,8 +137,7 @@
     @Test
     fun testFeatureEnabledAndCanShowWhileUnlockedVisibility() {
         controlsSettingsRepository.setCanShowControlsInLockscreen(false)
-        `when`(lockPatternUtils.getStrongAuthForUser(anyInt()))
-            .thenReturn(STRONG_AUTH_NOT_REQUIRED)
+        `when`(lockPatternUtils.getStrongAuthForUser(anyInt())).thenReturn(STRONG_AUTH_NOT_REQUIRED)
         `when`(keyguardStateController.isUnlocked()).thenReturn(true)
         val component = setupComponent(true)
 
@@ -158,8 +148,7 @@
     fun testGetTileImageId() {
         val tileImageId = 0
 
-        `when`(controlsTileResourceConfiguration.getTileImageId())
-            .thenReturn(tileImageId)
+        `when`(controlsTileResourceConfiguration.getTileImageId()).thenReturn(tileImageId)
         val component = setupComponent(true)
         assertEquals(component.getTileImageId(), tileImageId)
     }
@@ -168,12 +157,19 @@
     fun testGetTileTitleId() {
         val tileTitleId = 0
 
-        `when`(controlsTileResourceConfiguration.getTileTitleId())
-            .thenReturn(tileTitleId)
+        `when`(controlsTileResourceConfiguration.getTileTitleId()).thenReturn(tileTitleId)
         val component = setupComponent(true)
         assertEquals(component.getTileTitleId(), tileTitleId)
     }
 
+    @Test
+    fun getPackageName() {
+        val packageName = "packageName"
+        `when`(controlsTileResourceConfiguration.getPackageName()).thenReturn(packageName)
+        val component = setupComponent(true)
+        assertEquals(component.getPackageName(), packageName)
+    }
+
     private fun setupComponent(enabled: Boolean): ControlsComponent {
         return ControlsComponent(
             enabled,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
index 8ee7d3e..cdc99af3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
@@ -42,6 +42,7 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
+import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
@@ -98,6 +99,7 @@
     @Mock private lateinit var logger: KeyguardQuickAffordancesMetricsLogger
 
     private lateinit var dockManager: DockManagerFake
+    private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
 
     private lateinit var underTest: CustomizationProvider
     private lateinit var testScope: TestScope
@@ -111,6 +113,7 @@
         whenever(backgroundHandler.looper).thenReturn(TestableLooper.get(this).looper)
 
         dockManager = DockManagerFake()
+        biometricSettingsRepository = FakeBiometricSettingsRepository()
 
         underTest = CustomizationProvider()
         val testDispatcher = UnconfinedTestDispatcher()
@@ -197,6 +200,7 @@
                 logger = logger,
                 devicePolicyManager = devicePolicyManager,
                 dockManager = dockManager,
+                biometricSettingsRepository = biometricSettingsRepository,
                 backgroundDispatcher = testDispatcher,
                 appContext = mContext,
             )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
index 477e076..2230841 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
@@ -1,6 +1,7 @@
 package com.android.systemui.keyguard
 
 import android.app.ActivityManager
+import android.app.WallpaperManager
 import android.app.WindowConfiguration
 import android.graphics.Point
 import android.graphics.Rect
@@ -21,6 +22,7 @@
 import com.android.systemui.statusbar.SysuiStatusBarStateController
 import com.android.systemui.statusbar.phone.BiometricUnlockController
 import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.argThat
 import com.android.systemui.util.mockito.whenever
 import junit.framework.Assert.assertEquals
@@ -32,6 +34,7 @@
 import org.junit.runner.RunWith
 import org.mockito.Mock
 import org.mockito.Mockito.atLeastOnce
+import org.mockito.Mockito.eq
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.never
 import org.mockito.Mockito.times
@@ -64,6 +67,8 @@
     private lateinit var notificationShadeWindowController: NotificationShadeWindowController
     @Mock
     private lateinit var powerManager: PowerManager
+    @Mock
+    private lateinit var wallpaperManager: WallpaperManager
 
     @Mock
     private lateinit var launcherUnlockAnimationController: ILauncherUnlockAnimationController.Stub
@@ -94,13 +99,14 @@
         keyguardUnlockAnimationController = KeyguardUnlockAnimationController(
             context, keyguardStateController, { keyguardViewMediator }, keyguardViewController,
             featureFlags, { biometricUnlockController }, statusBarStateController,
-            notificationShadeWindowController, powerManager
+            notificationShadeWindowController, powerManager, wallpaperManager
         )
         keyguardUnlockAnimationController.setLauncherUnlockController(
             launcherUnlockAnimationController)
 
         whenever(keyguardViewController.viewRootImpl).thenReturn(mock(ViewRootImpl::class.java))
         whenever(powerManager.isInteractive).thenReturn(true)
+        whenever(wallpaperManager.isLockscreenLiveWallpaperEnabled).thenReturn(false)
 
         // All of these fields are final, so we can't mock them, but are needed so that the surface
         // appear amount setter doesn't short circuit.
@@ -173,6 +179,46 @@
             false /* cancelled */)
     }
 
+    @Test
+    fun onWakeAndUnlock_notifiesListenerWithTrue() {
+        whenever(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
+        whenever(biometricUnlockController.mode).thenReturn(
+            BiometricUnlockController.MODE_WAKE_AND_UNLOCK)
+
+        val listener = mock(
+            KeyguardUnlockAnimationController.KeyguardUnlockAnimationListener::class.java)
+        keyguardUnlockAnimationController.addKeyguardUnlockAnimationListener(listener)
+
+        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
+            remoteAnimationTargets,
+            wallpaperTargets,
+            0 /* startTime */,
+            false /* requestedShowSurfaceBehindKeyguard */
+        )
+
+        verify(listener).onUnlockAnimationStarted(any(), eq(true), any(), any())
+    }
+
+    @Test
+    fun onWakeAndUnlockFromDream_notifiesListenerWithFalse() {
+        whenever(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
+        whenever(biometricUnlockController.mode).thenReturn(
+            BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM)
+
+        val listener = mock(
+            KeyguardUnlockAnimationController.KeyguardUnlockAnimationListener::class.java)
+        keyguardUnlockAnimationController.addKeyguardUnlockAnimationListener(listener)
+
+        keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
+            remoteAnimationTargets,
+            wallpaperTargets,
+            0 /* startTime */,
+            false /* requestedShowSurfaceBehindKeyguard */
+        )
+
+        verify(listener).onUnlockAnimationStarted(any(), eq(false), any(), any())
+    }
+
     /**
      * If we requested that the surface behind be made visible, and we're not flinging away the
      * keyguard, it means that we're swiping to unlock and want the surface visible so it can follow
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt
index f8cb408..1815ea9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt
@@ -17,6 +17,7 @@
 
 package com.android.systemui.keyguard.data.quickaffordance
 
+import android.app.Activity
 import androidx.test.filters.SmallTest
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
@@ -24,6 +25,7 @@
 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.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
@@ -75,6 +77,7 @@
     @Mock private lateinit var component: ControlsComponent
     @Mock private lateinit var controlsController: ControlsController
     @Mock private lateinit var controlsListingController: ControlsListingController
+    @Mock private lateinit var controlsUiController: ControlsUiController
     @Mock private lateinit var controlsServiceInfo: ControlsServiceInfo
     @Captor
     private lateinit var callbackCaptor:
@@ -98,6 +101,8 @@
         whenever(component.getControlsController()).thenReturn(Optional.of(controlsController))
         whenever(component.getControlsListingController())
             .thenReturn(Optional.of(controlsListingController))
+        whenever(controlsUiController.resolveActivity()).thenReturn(FakeActivity::class.java)
+        whenever(component.getControlsUiController()).thenReturn(Optional.of(controlsUiController))
         if (hasPanels) {
             whenever(controlsServiceInfo.panelActivity).thenReturn(mock())
         }
@@ -178,4 +183,6 @@
             )
         job.cancel()
     }
+
+    private class FakeActivity : Activity()
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfigTest.kt
new file mode 100644
index 0000000..7941a23
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfigTest.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.data.quickaffordance
+
+import android.content.Intent
+import android.net.Uri
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@SmallTest
+@RunWith(JUnit4::class)
+class KeyguardQuickAffordanceConfigTest : SysuiTestCase() {
+
+    @Test
+    fun appStoreIntent() {
+        overrideResource(R.string.config_appStorePackageName, "app.store.package.name")
+        overrideResource(R.string.config_appStoreAppLinkTemplate, "prefix?id=\$packageName")
+        val packageName = "com.app.package.name"
+
+        val intent = KeyguardQuickAffordanceConfig.appStoreIntent(context, packageName)
+
+        assertThat(intent).isNotNull()
+        assertThat(intent?.`package`).isEqualTo("app.store.package.name")
+        assertThat(intent?.action).isEqualTo(Intent.ACTION_VIEW)
+        assertThat(intent?.data).isEqualTo(Uri.parse("prefix?id=$packageName"))
+    }
+
+    @Test
+    fun appStoreIntent_packageNameNotConfigured_returnNull() {
+        overrideResource(R.string.config_appStorePackageName, "")
+        overrideResource(R.string.config_appStoreAppLinkTemplate, "prefix?id=\$packageName")
+        val packageName = "com.app.package.name"
+
+        val intent = KeyguardQuickAffordanceConfig.appStoreIntent(context, packageName)
+
+        assertThat(intent).isNull()
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun appStoreIntent_packageNameMisconfigured_throwsIllegalStateException() {
+        overrideResource(R.string.config_appStorePackageName, "app.store.package.name")
+        overrideResource(
+            R.string.config_appStoreAppLinkTemplate,
+            "prefix?id=\$misconfiguredPackageName"
+        )
+        val packageName = "com.app.package.name"
+
+        KeyguardQuickAffordanceConfig.appStoreIntent(context, packageName)
+    }
+
+    @Test
+    fun appStoreIntent_linkTemplateNotConfigured_returnNull() {
+        overrideResource(R.string.config_appStorePackageName, "app.store.package.name")
+        overrideResource(R.string.config_appStoreAppLinkTemplate, "")
+        val packageName = "com.app.package.name"
+
+        val intent = KeyguardQuickAffordanceConfig.appStoreIntent(context, packageName)
+
+        assertThat(intent).isNull()
+    }
+
+    @Test
+    fun appStoreIntent_appPackageNameNull_returnNull() {
+        overrideResource(R.string.config_appStorePackageName, "app.store.package.name")
+        overrideResource(R.string.config_appStoreAppLinkTemplate, "prefix?id=\$packageName")
+
+        val intent = KeyguardQuickAffordanceConfig.appStoreIntent(context, null)
+
+        assertThat(intent).isNull()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt
index 26c0ea4..7510373 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt
@@ -53,7 +53,7 @@
         MockitoAnnotations.initMocks(this)
         whenever(controller.intent).thenReturn(INTENT_1)
 
-        underTest = QrCodeScannerKeyguardQuickAffordanceConfig(mock(), controller)
+        underTest = QrCodeScannerKeyguardQuickAffordanceConfig(context, controller)
     }
 
     @Test
@@ -77,22 +77,21 @@
     }
 
     @Test
-    fun affordance_scannerActivityChanged_deliversModelWithUpdatedIntent() =
-        runBlockingTest {
-            whenever(controller.isEnabledForLockScreenButton).thenReturn(true)
-            var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
-            val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
-            val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>()
-            verify(controller).addCallback(callbackCaptor.capture())
+    fun affordance_scannerActivityChanged_deliversModelWithUpdatedIntent() = runBlockingTest {
+        whenever(controller.isEnabledForLockScreenButton).thenReturn(true)
+        var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
+        val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
+        val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>()
+        verify(controller).addCallback(callbackCaptor.capture())
 
-            whenever(controller.intent).thenReturn(INTENT_2)
-            callbackCaptor.value.onQRCodeScannerActivityChanged()
+        whenever(controller.intent).thenReturn(INTENT_2)
+        callbackCaptor.value.onQRCodeScannerActivityChanged()
 
-            assertVisibleState(latest)
+        assertVisibleState(latest)
 
-            job.cancel()
-            verify(controller).removeCallback(callbackCaptor.value)
-        }
+        job.cancel()
+        verify(controller).removeCallback(callbackCaptor.value)
+    }
 
     @Test
     fun affordance_scannerPreferenceChanged_deliversVisibleModel() = runBlockingTest {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
index 111b8e8..d36e778 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
@@ -92,8 +92,8 @@
     }
 
     @Test
-    fun affordance_walletNotEnabled_modelIsNone() = runBlockingTest {
-        setUpState(isWalletEnabled = false)
+    fun affordance_walletFeatureNotEnabled_modelIsNone() = runBlockingTest {
+        setUpState(isWalletFeatureAvailable = false)
         var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
 
         val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
@@ -165,7 +165,7 @@
     @Test
     fun getPickerScreenState_disabledWhenTheFeatureIsNotEnabled() = runTest {
         setUpState(
-            isWalletEnabled = false,
+            isWalletFeatureAvailable = false,
         )
 
         assertThat(underTest.getPickerScreenState())
@@ -183,16 +183,15 @@
     }
 
     private fun setUpState(
-        isWalletEnabled: Boolean = true,
+        isWalletFeatureAvailable: Boolean = true,
         isWalletServiceAvailable: Boolean = true,
         isWalletQuerySuccessful: Boolean = true,
         hasSelectedCard: Boolean = true,
     ) {
-        whenever(walletController.isWalletEnabled).thenReturn(isWalletEnabled)
-
         val walletClient: QuickAccessWalletClient = mock()
         whenever(walletClient.tileIcon).thenReturn(ICON)
         whenever(walletClient.isWalletServiceAvailable).thenReturn(isWalletServiceAvailable)
+        whenever(walletClient.isWalletFeatureAvailable).thenReturn(isWalletFeatureAvailable)
 
         whenever(walletController.walletClient).thenReturn(walletClient)
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
index fb21847..2c90d53 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
@@ -38,6 +38,7 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
+import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
@@ -239,6 +240,7 @@
     @JvmField @Parameter(4) var startActivity: Boolean = false
     private lateinit var homeControls: FakeKeyguardQuickAffordanceConfig
     private lateinit var dockManager: DockManagerFake
+    private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
     private lateinit var userTracker: UserTracker
 
     @Before
@@ -250,6 +252,7 @@
         homeControls =
             FakeKeyguardQuickAffordanceConfig(BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS)
         dockManager = DockManagerFake()
+        biometricSettingsRepository = FakeBiometricSettingsRepository()
         val quickAccessWallet =
             FakeKeyguardQuickAffordanceConfig(
                 BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET
@@ -339,6 +342,7 @@
                 logger = logger,
                 devicePolicyManager = devicePolicyManager,
                 dockManager = dockManager,
+                biometricSettingsRepository = biometricSettingsRepository,
                 backgroundDispatcher = testDispatcher,
                 appContext = mContext,
             )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
index 1d5971c..7cab680 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
@@ -40,6 +40,7 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
+import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
@@ -97,6 +98,7 @@
     private lateinit var qrCodeScanner: FakeKeyguardQuickAffordanceConfig
     private lateinit var featureFlags: FakeFeatureFlags
     private lateinit var dockManager: DockManagerFake
+    private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
 
     @Before
     fun setUp() {
@@ -119,6 +121,7 @@
         testScope = TestScope(testDispatcher)
 
         dockManager = DockManagerFake()
+        biometricSettingsRepository = FakeBiometricSettingsRepository()
 
         val localUserSelectionManager =
             KeyguardQuickAffordanceLocalUserSelectionManager(
@@ -201,6 +204,7 @@
                 logger = logger,
                 devicePolicyManager = devicePolicyManager,
                 dockManager = dockManager,
+                biometricSettingsRepository = biometricSettingsRepository,
                 backgroundDispatcher = testDispatcher,
                 appContext = context,
             )
@@ -314,6 +318,24 @@
         }
 
     @Test
+    fun quickAffordance_hiddenWhenUserIsInLockdownMode() =
+        testScope.runTest {
+            biometricSettingsRepository.setIsUserInLockdown(true)
+            quickAccessWallet.setState(
+                KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+                    icon = ICON,
+                )
+            )
+
+            val collectedValue by
+                collectLastValue(
+                    underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END)
+                )
+
+            assertThat(collectedValue).isEqualTo(KeyguardQuickAffordanceModel.Hidden)
+        }
+
+    @Test
     fun quickAffordance_bottomStartAffordanceHiddenWhileDozing() =
         testScope.runTest {
             repository.setIsDozing(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
index 8a36dbc..73fe380 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
@@ -39,6 +39,7 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
+import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
@@ -110,6 +111,7 @@
     private lateinit var quickAccessWalletAffordanceConfig: FakeKeyguardQuickAffordanceConfig
     private lateinit var qrCodeScannerAffordanceConfig: FakeKeyguardQuickAffordanceConfig
     private lateinit var dockManager: DockManagerFake
+    private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
 
     @Before
     fun setUp() {
@@ -126,6 +128,7 @@
         qrCodeScannerAffordanceConfig =
             FakeKeyguardQuickAffordanceConfig(BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER)
         dockManager = DockManagerFake()
+        biometricSettingsRepository = FakeBiometricSettingsRepository()
         registry =
             FakeKeyguardQuickAffordanceRegistry(
                 mapOf(
@@ -240,6 +243,7 @@
                         logger = logger,
                         devicePolicyManager = devicePolicyManager,
                         dockManager = dockManager,
+                        biometricSettingsRepository = biometricSettingsRepository,
                         backgroundDispatcher = testDispatcher,
                         appContext = mContext,
                     ),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
index 7b673bc..f6075ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
@@ -2420,7 +2420,6 @@
 
     @Test
     fun playTurbulenceNoise_finishesAfterDuration() {
-        fakeFeatureFlag.set(Flags.UMO_SURFACE_RIPPLE, true)
         fakeFeatureFlag.set(Flags.UMO_TURBULENCE_NOISE, true)
 
         val semanticActions =
@@ -2452,6 +2451,29 @@
     }
 
     @Test
+    fun playTurbulenceNoise_whenPlaybackStateIsNotPlaying_doesNotPlayTurbulence() {
+        fakeFeatureFlag.set(Flags.UMO_TURBULENCE_NOISE, true)
+
+        val semanticActions =
+            MediaButton(
+                custom0 =
+                    MediaAction(
+                        icon = null,
+                        action = {},
+                        contentDescription = "custom0",
+                        background = null
+                    ),
+            )
+        val data = mediaData.copy(semanticActions = semanticActions)
+        player.attachPlayer(viewHolder)
+        player.bindPlayer(data, KEY)
+
+        viewHolder.action0.callOnClick()
+
+        assertThat(turbulenceNoiseView.visibility).isEqualTo(View.INVISIBLE)
+    }
+
+    @Test
     fun outputSwitcher_hasCustomIntent_openOverLockscreen() {
         // When the device for a media player has an intent that opens over lockscreen
         val pendingIntent = mock(PendingIntent::class.java)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java
index 705b485..9dba9b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.media.dialog;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.mock;
@@ -33,6 +35,10 @@
 import android.os.PowerExemptionManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.TextView;
 
 import androidx.test.filters.SmallTest;
 
@@ -44,6 +50,7 @@
 import com.android.settingslib.media.BluetoothMediaDevice;
 import com.android.settingslib.media.LocalMediaManager;
 import com.android.settingslib.media.MediaDevice;
+import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.broadcast.BroadcastSender;
@@ -53,11 +60,14 @@
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
 
+import com.google.common.base.Strings;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
@@ -68,6 +78,9 @@
 public class MediaOutputBroadcastDialogTest extends SysuiTestCase {
 
     private static final String TEST_PACKAGE = "test_package";
+    private static final String BROADCAST_NAME_TEST = "Broadcast_name_test";
+    private static final String BROADCAST_CODE_TEST = "112233";
+    private static final String BROADCAST_CODE_UPDATE_TEST = "11223344";
 
     // Mock
     private final MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class);
@@ -106,6 +119,9 @@
         when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
         when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(null);
         when(mLocalBluetoothProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(null);
+        when(mLocalBluetoothLeBroadcast.getProgramInfo()).thenReturn(BROADCAST_NAME_TEST);
+        when(mLocalBluetoothLeBroadcast.getBroadcastCode()).thenReturn(
+                BROADCAST_CODE_TEST.getBytes(StandardCharsets.UTF_8));
 
         mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
                 mMediaSessionManager, mLocalBluetoothManager, mStarter,
@@ -194,4 +210,152 @@
 
         verify(mLocalBluetoothLeBroadcastAssistant, times(1)).addSource(any(), any(), anyBoolean());
     }
+
+    @Test
+    public void handleLeBroadcastMetadataChanged_checkBroadcastName() {
+        when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
+                mLocalBluetoothLeBroadcast);
+        final TextView broadcastName = mMediaOutputBroadcastDialog.mDialogView
+                .requireViewById(R.id.broadcast_name_summary);
+
+        mMediaOutputBroadcastDialog.handleLeBroadcastMetadataChanged();
+
+        assertThat(broadcastName.getText().toString()).isEqualTo(BROADCAST_NAME_TEST);
+    }
+
+    @Test
+    public void handleLeBroadcastMetadataChanged_checkBroadcastCode() {
+        when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
+                mLocalBluetoothLeBroadcast);
+
+        final TextView broadcastCode = mMediaOutputBroadcastDialog.mDialogView
+                .requireViewById(R.id.broadcast_code_summary);
+
+        mMediaOutputBroadcastDialog.handleLeBroadcastMetadataChanged();
+
+        assertThat(broadcastCode.getText().toString()).isEqualTo(BROADCAST_CODE_TEST);
+    }
+
+    @Test
+    public void updateBroadcastInfo_stopBroadcastFailed_handleFailedUi() {
+        ImageView broadcastCodeEdit = mMediaOutputBroadcastDialog.mDialogView
+                .requireViewById(R.id.broadcast_code_edit);
+        TextView broadcastCode = mMediaOutputBroadcastDialog.mDialogView.requireViewById(
+                R.id.broadcast_code_summary);
+        broadcastCode.setText(BROADCAST_CODE_UPDATE_TEST);
+        when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(null);
+        broadcastCodeEdit.callOnClick();
+
+        mMediaOutputBroadcastDialog.updateBroadcastInfo(true, BROADCAST_CODE_UPDATE_TEST);
+        assertThat(mMediaOutputBroadcastDialog.getRetryCount()).isEqualTo(1);
+
+        mMediaOutputBroadcastDialog.updateBroadcastInfo(true, BROADCAST_CODE_UPDATE_TEST);
+        assertThat(mMediaOutputBroadcastDialog.getRetryCount()).isEqualTo(2);
+
+        // It will be the MAX Retry Count = 3
+        mMediaOutputBroadcastDialog.updateBroadcastInfo(true, BROADCAST_CODE_UPDATE_TEST);
+        assertThat(mMediaOutputBroadcastDialog.getRetryCount()).isEqualTo(0);
+    }
+
+    @Test
+    public void afterTextChanged_nameLengthMoreThanMax_showErrorMessage() {
+        ImageView broadcastNameEdit = mMediaOutputBroadcastDialog.mDialogView
+                .requireViewById(R.id.broadcast_name_edit);
+        TextView broadcastName = mMediaOutputBroadcastDialog.mDialogView.requireViewById(
+                R.id.broadcast_name_summary);
+        broadcastName.setText(BROADCAST_NAME_TEST);
+        when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
+                mLocalBluetoothLeBroadcast);
+        broadcastNameEdit.callOnClick();
+        EditText editText = mMediaOutputBroadcastDialog.mAlertDialog.findViewById(
+                R.id.broadcast_edit_text);
+        TextView broadcastErrorMessage = mMediaOutputBroadcastDialog.mAlertDialog.findViewById(
+                R.id.broadcast_error_message);
+        assertThat(broadcastErrorMessage.getVisibility()).isEqualTo(View.INVISIBLE);
+
+        // input the invalid text
+        String moreThanMax = Strings.repeat("a",
+                MediaOutputBroadcastDialog.BROADCAST_NAME_MAX_LENGTH + 3);
+        editText.setText(moreThanMax);
+
+        assertThat(broadcastErrorMessage.getVisibility()).isEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void afterTextChanged_enterValidNameAfterLengthMoreThanMax_noErrorMessage() {
+        ImageView broadcastNameEdit = mMediaOutputBroadcastDialog.mDialogView
+                .requireViewById(R.id.broadcast_name_edit);
+        TextView broadcastName = mMediaOutputBroadcastDialog.mDialogView.requireViewById(
+                R.id.broadcast_name_summary);
+        broadcastName.setText(BROADCAST_NAME_TEST);
+        when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
+                mLocalBluetoothLeBroadcast);
+        broadcastNameEdit.callOnClick();
+        EditText editText = mMediaOutputBroadcastDialog.mAlertDialog.findViewById(
+                R.id.broadcast_edit_text);
+        TextView broadcastErrorMessage = mMediaOutputBroadcastDialog.mAlertDialog.findViewById(
+                R.id.broadcast_error_message);
+        assertThat(broadcastErrorMessage.getVisibility()).isEqualTo(View.INVISIBLE);
+
+        // input the invalid text
+        String testString = Strings.repeat("a",
+                MediaOutputBroadcastDialog.BROADCAST_NAME_MAX_LENGTH + 2);
+        editText.setText(testString);
+        assertThat(broadcastErrorMessage.getVisibility()).isEqualTo(View.VISIBLE);
+
+        // input the valid text
+        testString = Strings.repeat("b",
+                MediaOutputBroadcastDialog.BROADCAST_NAME_MAX_LENGTH - 100);
+        editText.setText(testString);
+
+        assertThat(broadcastErrorMessage.getVisibility()).isEqualTo(View.INVISIBLE);
+    }
+
+    @Test
+    public void afterTextChanged_codeLengthMoreThanMax_showErrorMessage() {
+        ImageView broadcastCodeEdit = mMediaOutputBroadcastDialog.mDialogView
+                .requireViewById(R.id.broadcast_code_edit);
+        TextView broadcastCode = mMediaOutputBroadcastDialog.mDialogView.requireViewById(
+                R.id.broadcast_code_summary);
+        broadcastCode.setText(BROADCAST_CODE_UPDATE_TEST);
+        when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
+                mLocalBluetoothLeBroadcast);
+        broadcastCodeEdit.callOnClick();
+        EditText editText = mMediaOutputBroadcastDialog.mAlertDialog.findViewById(
+                R.id.broadcast_edit_text);
+        TextView broadcastErrorMessage = mMediaOutputBroadcastDialog.mAlertDialog.findViewById(
+                R.id.broadcast_error_message);
+        assertThat(broadcastErrorMessage.getVisibility()).isEqualTo(View.INVISIBLE);
+
+        // input the invalid text
+        String moreThanMax = Strings.repeat("a",
+                MediaOutputBroadcastDialog.BROADCAST_CODE_MAX_LENGTH + 1);
+        editText.setText(moreThanMax);
+
+        assertThat(broadcastErrorMessage.getVisibility()).isEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void afterTextChanged_codeLengthLessThanMin_showErrorMessage() {
+        ImageView broadcastCodeEdit = mMediaOutputBroadcastDialog.mDialogView
+                .requireViewById(R.id.broadcast_code_edit);
+        TextView broadcastCode = mMediaOutputBroadcastDialog.mDialogView.requireViewById(
+                R.id.broadcast_code_summary);
+        broadcastCode.setText(BROADCAST_CODE_UPDATE_TEST);
+        when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
+                mLocalBluetoothLeBroadcast);
+        broadcastCodeEdit.callOnClick();
+        EditText editText = mMediaOutputBroadcastDialog.mAlertDialog.findViewById(
+                R.id.broadcast_edit_text);
+        TextView broadcastErrorMessage = mMediaOutputBroadcastDialog.mAlertDialog.findViewById(
+                R.id.broadcast_error_message);
+        assertThat(broadcastErrorMessage.getVisibility()).isEqualTo(View.INVISIBLE);
+
+        // input the invalid text
+        String moreThanMax = Strings.repeat("a",
+                MediaOutputBroadcastDialog.BROADCAST_CODE_MIN_LENGTH - 1);
+        editText.setText(moreThanMax);
+
+        assertThat(broadcastErrorMessage.getVisibility()).isEqualTo(View.VISIBLE);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt
index f1bbd84..f25cd24 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorControllerTest.kt
@@ -5,14 +5,15 @@
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.mediaprojection.appselector.data.RecentTask
 import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider
+import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver
+import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mockito.verify
@@ -27,23 +28,28 @@
     private val callerPackageName = "com.test.caller"
     private val callerComponentName = ComponentName(callerPackageName, "Caller")
 
-    private val hostUserHandle = UserHandle.of(123)
-    private val otherUserHandle = UserHandle.of(456)
+    private val personalUserHandle = UserHandle.of(123)
+    private val workUserHandle = UserHandle.of(456)
 
     private val view: MediaProjectionAppSelectorView = mock()
-    private val featureFlags: FeatureFlags = mock()
+    private val policyResolver: ScreenCaptureDevicePolicyResolver = mock()
 
     private val controller =
         MediaProjectionAppSelectorController(
             taskListProvider,
             view,
-            featureFlags,
-            hostUserHandle,
+            policyResolver,
+            personalUserHandle,
             scope,
             appSelectorComponentName,
             callerPackageName
         )
 
+    @Before
+    fun setup() {
+        givenCaptureAllowed(isAllow = true)
+    }
+
     @Test
     fun initNoRecentTasks_bindsEmptyList() {
         taskListProvider.tasks = emptyList()
@@ -132,73 +138,57 @@
     }
 
     @Test
-    fun initRecentTasksWithAppSelectorTasks_enterprisePoliciesDisabled_bindsAllTasks() {
-        givenEnterprisePoliciesFeatureFlag(enabled = false)
-
+    fun initRecentTasksWithAppSelectorTasks_withEnterprisePolicies_bindsAllTasks() {
         val tasks =
             listOf(
-                createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
-                createRecentTask(taskId = 2, userId = otherUserHandle.identifier),
-                createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
-                createRecentTask(taskId = 4, userId = otherUserHandle.identifier),
-                createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
+                createRecentTask(taskId = 1, userId = personalUserHandle.identifier),
+                createRecentTask(taskId = 2, userId = workUserHandle.identifier),
+                createRecentTask(taskId = 3, userId = personalUserHandle.identifier),
+                createRecentTask(taskId = 4, userId = workUserHandle.identifier),
+                createRecentTask(taskId = 5, userId = personalUserHandle.identifier),
             )
         taskListProvider.tasks = tasks
 
         controller.init()
 
-        // TODO (b/263950746): Cross-profile filtering is removed for now. This should be brought
-        // back with the future fix
         verify(view)
             .bind(
                 listOf(
-                    createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
-                    createRecentTask(taskId = 2, userId = otherUserHandle.identifier),
-                    createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
-                    createRecentTask(taskId = 4, userId = otherUserHandle.identifier),
-                    createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
+                    createRecentTask(taskId = 1, userId = personalUserHandle.identifier),
+                    createRecentTask(taskId = 2, userId = workUserHandle.identifier),
+                    createRecentTask(taskId = 3, userId = personalUserHandle.identifier),
+                    createRecentTask(taskId = 4, userId = workUserHandle.identifier),
+                    createRecentTask(taskId = 5, userId = personalUserHandle.identifier),
                 )
             )
     }
 
     @Test
-    fun initRecentTasksWithAppSelectorTasks_enterprisePoliciesEnabled_bindsAllTasks() {
-        givenEnterprisePoliciesFeatureFlag(enabled = true)
-
+    fun initRecentTasksWithAppSelectorTasks_withEnterprisePolicies_blocksAllTasks() {
         val tasks =
             listOf(
-                createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
-                createRecentTask(taskId = 2, userId = otherUserHandle.identifier),
-                createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
-                createRecentTask(taskId = 4, userId = otherUserHandle.identifier),
-                createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
+                createRecentTask(taskId = 1, userId = personalUserHandle.identifier),
+                createRecentTask(taskId = 2, userId = workUserHandle.identifier),
+                createRecentTask(taskId = 3, userId = personalUserHandle.identifier),
+                createRecentTask(taskId = 4, userId = workUserHandle.identifier),
+                createRecentTask(taskId = 5, userId = personalUserHandle.identifier),
             )
         taskListProvider.tasks = tasks
 
+        givenCaptureAllowed(isAllow = false)
         controller.init()
 
-        // TODO(b/233348916) should filter depending on the policies
-        verify(view)
-            .bind(
-                listOf(
-                    createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
-                    createRecentTask(taskId = 2, userId = otherUserHandle.identifier),
-                    createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
-                    createRecentTask(taskId = 4, userId = otherUserHandle.identifier),
-                    createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
-                )
-            )
+        verify(view).bind(emptyList())
     }
 
-    private fun givenEnterprisePoliciesFeatureFlag(enabled: Boolean) {
-        whenever(featureFlags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES))
-            .thenReturn(enabled)
+    private fun givenCaptureAllowed(isAllow: Boolean) {
+        whenever(policyResolver.isScreenCaptureAllowed(any(), any())).thenReturn(isAllow)
     }
 
     private fun createRecentTask(
         taskId: Int,
         topActivityComponent: ComponentName? = null,
-        userId: Int = hostUserHandle.identifier
+        userId: Int = personalUserHandle.identifier
     ): RecentTask {
         return RecentTask(
             taskId = taskId,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolverTest.kt
index e8b6f9b..c63efa1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolverTest.kt
@@ -406,28 +406,6 @@
                             isHostInWorkProfile = true,
                             isTargetInWorkProfile = true,
                             personalScreenCaptureDisabled = true,
-                            workScreenCaptureDisabled = false,
-                            disallowShareIntoManagedProfile = false
-                        ),
-                    expectedScreenCaptureAllowed = true,
-                ),
-                IsScreenCaptureAllowedTestCase(
-                    given =
-                        Preconditions(
-                            isHostInWorkProfile = true,
-                            isTargetInWorkProfile = true,
-                            personalScreenCaptureDisabled = true,
-                            workScreenCaptureDisabled = false,
-                            disallowShareIntoManagedProfile = true
-                        ),
-                    expectedScreenCaptureAllowed = true,
-                ),
-                IsScreenCaptureAllowedTestCase(
-                    given =
-                        Preconditions(
-                            isHostInWorkProfile = true,
-                            isTargetInWorkProfile = true,
-                            personalScreenCaptureDisabled = true,
                             workScreenCaptureDisabled = true,
                             disallowShareIntoManagedProfile = false
                         ),
@@ -626,26 +604,6 @@
                         Preconditions(
                             isHostInWorkProfile = true,
                             personalScreenCaptureDisabled = true,
-                            workScreenCaptureDisabled = false,
-                            disallowShareIntoManagedProfile = false
-                        ),
-                    expectedScreenCaptureCompletelyDisabled = false,
-                ),
-                IsScreenCaptureCompletelyDisabledTestCase(
-                    given =
-                        Preconditions(
-                            isHostInWorkProfile = true,
-                            personalScreenCaptureDisabled = true,
-                            workScreenCaptureDisabled = false,
-                            disallowShareIntoManagedProfile = true
-                        ),
-                    expectedScreenCaptureCompletelyDisabled = false,
-                ),
-                IsScreenCaptureCompletelyDisabledTestCase(
-                    given =
-                        Preconditions(
-                            isHostInWorkProfile = true,
-                            personalScreenCaptureDisabled = true,
                             workScreenCaptureDisabled = true,
                             disallowShareIntoManagedProfile = false
                         ),
@@ -686,7 +644,8 @@
                 "personal screen capture disabled = ${given.personalScreenCaptureDisabled}, " +
                 "work screen capture disabled = ${given.workScreenCaptureDisabled}, " +
                 "disallow share into managed profile = ${given.disallowShareIntoManagedProfile}, " +
-                "expected screen capture completely disabled = $expectedScreenCaptureCompletelyDisabled"
+                "expected screen capture completely disabled = " +
+                "$expectedScreenCaptureCompletelyDisabled"
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
index e99f8b6..0954f6f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -72,6 +72,7 @@
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
+import org.mockito.Mockito.atLeastOnce
 import org.mockito.Mockito.doNothing
 import org.mockito.Mockito.never
 import org.mockito.Mockito.spy
@@ -227,31 +228,7 @@
 
     // region showNoteTask
     @Test
-    fun showNoteTask_keyguardIsLocked_shouldStartActivityAndLogUiEvent() {
-        val expectedInfo = NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = true)
-        whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
-        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
-
-        createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
-
-        val intentCaptor = argumentCaptor<Intent>()
-        val userCaptor = argumentCaptor<UserHandle>()
-        verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
-        assertThat(intentCaptor.value).run {
-            hasAction(ACTION_CREATE_NOTE)
-            hasPackage(NOTE_TASK_PACKAGE_NAME)
-            hasFlags(FLAG_ACTIVITY_NEW_TASK)
-            hasFlags(FLAG_ACTIVITY_MULTIPLE_TASK)
-            hasFlags(FLAG_ACTIVITY_NEW_DOCUMENT)
-            extras().bool(EXTRA_USE_STYLUS_MODE).isTrue()
-        }
-        assertThat(userCaptor.value).isEqualTo(userTracker.userHandle)
-        verify(eventLogger).logNoteTaskOpened(expectedInfo)
-        verifyZeroInteractions(bubbles)
-    }
-
-    @Test
-    fun showNoteTaskWithUser_keyguardIsLocked_shouldStartActivityWithExpectedUserAndLogUiEvent() {
+    fun showNoteTaskAsUser_keyguardIsLocked_shouldStartActivityWithExpectedUserAndLogUiEvent() {
         val user10 = UserHandle.of(/* userId= */ 10)
         val expectedInfo =
             NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = true, user = user10)
@@ -278,6 +255,30 @@
     }
 
     @Test
+    fun showNoteTask_keyguardIsLocked_notesIsClosed_shouldStartActivityAndLogUiEvent() {
+        val expectedInfo = NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = true)
+        whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
+        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
+
+        createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
+
+        val intentCaptor = argumentCaptor<Intent>()
+        val userCaptor = argumentCaptor<UserHandle>()
+        verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
+        assertThat(intentCaptor.value).run {
+            hasAction(ACTION_CREATE_NOTE)
+            hasPackage(NOTE_TASK_PACKAGE_NAME)
+            hasFlags(FLAG_ACTIVITY_NEW_TASK)
+            hasFlags(FLAG_ACTIVITY_MULTIPLE_TASK)
+            hasFlags(FLAG_ACTIVITY_NEW_DOCUMENT)
+            extras().bool(EXTRA_USE_STYLUS_MODE).isTrue()
+        }
+        assertThat(userCaptor.value).isEqualTo(userTracker.userHandle)
+        verify(eventLogger).logNoteTaskOpened(expectedInfo)
+        verifyZeroInteractions(bubbles)
+    }
+
+    @Test
     fun showNoteTask_keyguardIsLocked_noteIsOpen_shouldCloseActivityAndLogUiEvent() {
         val expectedInfo = NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = true)
         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
@@ -301,7 +302,7 @@
     }
 
     @Test
-    fun showNoteTask_keyguardIsUnlocked_shouldStartBubblesWithoutLoggingUiEvent() {
+    fun showNoteTask_keyguardIsUnlocked_noteIsClosed_shouldStartBubblesWithoutLoggingUiEvent() {
         val expectedInfo = NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = false)
         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
@@ -309,7 +310,23 @@
         createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
 
         // Context package name used to create bubble icon from drawable resource id
-        verify(context).packageName
+        verify(context, atLeastOnce()).packageName
+        verifyNoteTaskOpenInBubbleInUser(userTracker.userHandle)
+        verifyZeroInteractions(eventLogger)
+    }
+
+    @Test
+    fun showNoteTask_keyguardIsUnlocked_noteIsOpen_shouldStartBubblesWithoutLoggingUiEvent() {
+        val expectedInfo = NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = false)
+        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
+        whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
+        whenever(activityManager.getRunningTasks(anyInt()))
+            .thenReturn(listOf(NOTE_RUNNING_TASK_INFO))
+
+        createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
+
+        // Context package name used to create bubble icon from drawable resource id
+        verify(context, atLeastOnce()).packageName
         verifyNoteTaskOpenInBubbleInUser(userTracker.userHandle)
         verifyZeroInteractions(eventLogger)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
index 3435450..24f39d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
@@ -16,37 +16,47 @@
 package com.android.systemui.notetask
 
 import android.os.UserHandle
-import android.test.suitebuilder.annotation.SmallTest
-import androidx.test.runner.AndroidJUnit4
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.notetask.NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
 
 /** atest SystemUITests:NoteTaskInfoTest */
 @SmallTest
-@RunWith(AndroidJUnit4::class)
+@RunWith(AndroidTestingRunner::class)
 internal class NoteTaskInfoTest : SysuiTestCase() {
 
-    private fun createNoteTaskInfo(): NoteTaskInfo =
-        NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID, UserHandle.of(0))
-
     @Test
     fun launchMode_keyguardLocked_launchModeActivity() {
-        val underTest = createNoteTaskInfo().copy(isKeyguardLocked = true)
+        val underTest = DEFAULT_INFO.copy(isKeyguardLocked = true)
 
         assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.Activity)
     }
 
     @Test
-    fun launchMode_keyguardUnlocked_launchModeActivity() {
-        val underTest = createNoteTaskInfo().copy(isKeyguardLocked = false)
+    fun launchMode_multiWindowMode_launchModeActivity() {
+        val underTest = DEFAULT_INFO.copy(entryPoint = WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE)
+
+        assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.Activity)
+    }
+
+    @Test
+    fun launchMode_keyguardUnlocked_launchModeAppBubble() {
+        val underTest = DEFAULT_INFO.copy(isKeyguardLocked = false)
 
         assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.AppBubble)
     }
 
     private companion object {
-        const val NOTES_PACKAGE_NAME = "com.android.note.app"
-        const val NOTES_UID = 123456
+
+        val DEFAULT_INFO =
+            NoteTaskInfo(
+                packageName = "com.android.note.app",
+                uid = 123456,
+                user = UserHandle.of(0),
+            )
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt
index 4526580..58c762e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt
@@ -40,7 +40,6 @@
 import com.android.systemui.notetask.NoteTaskController
 import com.android.systemui.notetask.NoteTaskEntryPoint
 import com.android.systemui.notetask.NoteTaskInfoResolver
-import com.android.systemui.shared.customization.data.content.CustomizationProviderContract.LockScreenQuickAffordances.AffordanceTable.COMPONENT_NAME_SEPARATOR
 import com.android.systemui.stylus.StylusManager
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.any
@@ -283,7 +282,7 @@
     }
 
     @Test
-    fun getPickerScreenState_nodefaultNoteAppSet_shouldReturnDisable() = runTest {
+    fun getPickerScreenState_noDefaultNoteAppSet_shouldReturnDisabled() = runTest {
         val underTest = createUnderTest(isEnabled = true)
         whenever(
                 roleManager.getRoleHoldersAsUser(
@@ -293,16 +292,16 @@
             )
             .thenReturn(emptyList())
 
-        assertThat(underTest.getPickerScreenState())
-            .isEqualTo(
-                KeyguardQuickAffordanceConfig.PickerScreenState.Disabled(
-                    listOf("Select a default notes app to use the notetaking shortcut"),
-                    actionText = "Select app",
-                    actionComponentName =
-                        "${context.packageName}$COMPONENT_NAME_SEPARATOR" +
-                            "$ACTION_MANAGE_NOTES_ROLE_FROM_QUICK_AFFORDANCE"
-                )
-            )
+        val pickerScreenState = underTest.getPickerScreenState()
+        assertThat(pickerScreenState is KeyguardQuickAffordanceConfig.PickerScreenState.Disabled)
+            .isTrue()
+        val disabled = pickerScreenState as KeyguardQuickAffordanceConfig.PickerScreenState.Disabled
+        assertThat(disabled.explanation)
+            .isEqualTo("Select a default notes app to use the notetaking shortcut")
+        assertThat(disabled.actionText).isEqualTo("Select app")
+        assertThat(disabled.actionIntent?.action)
+            .isEqualTo(ACTION_MANAGE_NOTES_ROLE_FROM_QUICK_AFFORDANCE)
+        assertThat(disabled.actionIntent?.`package`).isEqualTo(context.packageName)
     }
     // endregion
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
index e0f27de1..e669d06 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
@@ -481,6 +481,8 @@
         int[] widgetIdsArray = {1};
         when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
 
+        when(mUserManager.isUserUnlocked(any())).thenReturn(true);
+
         NotificationChannel channel =
                 new NotificationChannel(TEST_CHANNEL_ID, TEST_CHANNEL_NAME, IMPORTANCE_DEFAULT);
         channel.setConversationId(TEST_PARENT_CHANNEL_ID, TEST_CONVERSATION_ID);
@@ -489,8 +491,25 @@
                 UserHandle.getUserHandleForUid(0), channel, IMPORTANCE_HIGH);
         mClock.advanceTime(MIN_LINGER_DURATION);
 
-        verify(mAppWidgetManager, times(1)).updateAppWidget(anyInt(),
-                any());
+        verify(mAppWidgetManager, times(1)).updateAppWidget(anyInt(), any());
+    }
+
+    @Test
+    public void testOnNotificationChannelModified_userLocked() {
+        int[] widgetIdsArray = {1};
+        when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+        when(mUserManager.isUserUnlocked(any())).thenReturn(false);
+
+        NotificationChannel channel =
+                new NotificationChannel(TEST_CHANNEL_ID, TEST_CHANNEL_NAME, IMPORTANCE_DEFAULT);
+        channel.setConversationId(TEST_PARENT_CHANNEL_ID, TEST_CONVERSATION_ID);
+
+        mNoMan.issueChannelModification(TEST_PACKAGE_A,
+                UserHandle.getUserHandleForUid(0), channel, IMPORTANCE_HIGH);
+        mClock.advanceTime(MIN_LINGER_DURATION);
+
+        verify(mAppWidgetManager, never()).updateAppWidget(anyInt(), any());
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepositoryImplTest.kt
new file mode 100644
index 0000000..18f3837
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepositoryImplTest.kt
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.pipeline.data.repository
+
+import android.Manifest.permission.BIND_QUICK_SETTINGS_TILE
+import android.content.BroadcastReceiver
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.ResolveInfoFlags
+import android.content.pm.ResolveInfo
+import android.content.pm.ServiceInfo
+import android.os.UserHandle
+import android.service.quicksettings.TileService
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argThat
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.nullable
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@OptIn(ExperimentalCoroutinesApi::class)
+class InstalledTilesComponentRepositoryImplTest : SysuiTestCase() {
+    private val testDispatcher = StandardTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
+
+    @Mock private lateinit var context: Context
+    @Mock private lateinit var packageManager: PackageManager
+    @Captor private lateinit var receiverCaptor: ArgumentCaptor<BroadcastReceiver>
+
+    private lateinit var underTest: InstalledTilesComponentRepositoryImpl
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        // Use the default value set in the ServiceInfo
+        whenever(packageManager.getComponentEnabledSetting(any()))
+            .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)
+
+        // Return empty by default
+        whenever(packageManager.queryIntentServicesAsUser(any(), any<ResolveInfoFlags>(), anyInt()))
+            .thenReturn(emptyList())
+
+        underTest =
+            InstalledTilesComponentRepositoryImpl(
+                context,
+                packageManager,
+                testDispatcher,
+            )
+    }
+
+    @Test
+    fun registersAndUnregistersBroadcastReceiver() =
+        testScope.runTest {
+            val user = 10
+            val job = launch { underTest.getInstalledTilesComponents(user).collect {} }
+            runCurrent()
+
+            verify(context)
+                .registerReceiverAsUser(
+                    capture(receiverCaptor),
+                    eq(UserHandle.of(user)),
+                    any(),
+                    nullable(),
+                    nullable(),
+                )
+
+            verify(context, never()).unregisterReceiver(receiverCaptor.value)
+
+            job.cancel()
+            runCurrent()
+            verify(context).unregisterReceiver(receiverCaptor.value)
+        }
+
+    @Test
+    fun intentFilterForCorrectActionsAndScheme() =
+        testScope.runTest {
+            val filterCaptor = argumentCaptor<IntentFilter>()
+
+            backgroundScope.launch { underTest.getInstalledTilesComponents(0).collect {} }
+            runCurrent()
+
+            verify(context)
+                .registerReceiverAsUser(
+                    any(),
+                    any(),
+                    capture(filterCaptor),
+                    nullable(),
+                    nullable(),
+                )
+
+            with(filterCaptor.value) {
+                assertThat(matchAction(Intent.ACTION_PACKAGE_CHANGED)).isTrue()
+                assertThat(matchAction(Intent.ACTION_PACKAGE_ADDED)).isTrue()
+                assertThat(matchAction(Intent.ACTION_PACKAGE_REMOVED)).isTrue()
+                assertThat(matchAction(Intent.ACTION_PACKAGE_REPLACED)).isTrue()
+                assertThat(countActions()).isEqualTo(4)
+
+                assertThat(hasDataScheme("package")).isTrue()
+                assertThat(countDataSchemes()).isEqualTo(1)
+            }
+        }
+
+    @Test
+    fun componentsLoadedOnStart() =
+        testScope.runTest {
+            val userId = 0
+            val resolveInfo =
+                ResolveInfo(TEST_COMPONENT, hasPermission = true, defaultEnabled = true)
+            whenever(
+                    packageManager.queryIntentServicesAsUser(
+                        matchIntent(),
+                        matchFlags(),
+                        eq(userId)
+                    )
+                )
+                .thenReturn(listOf(resolveInfo))
+
+            val componentNames by collectLastValue(underTest.getInstalledTilesComponents(userId))
+
+            assertThat(componentNames).containsExactly(TEST_COMPONENT)
+        }
+
+    @Test
+    fun componentAdded_foundAfterBroadcast() =
+        testScope.runTest {
+            val userId = 0
+            val resolveInfo =
+                ResolveInfo(TEST_COMPONENT, hasPermission = true, defaultEnabled = true)
+
+            val componentNames by collectLastValue(underTest.getInstalledTilesComponents(userId))
+            assertThat(componentNames).isEmpty()
+
+            whenever(
+                    packageManager.queryIntentServicesAsUser(
+                        matchIntent(),
+                        matchFlags(),
+                        eq(userId)
+                    )
+                )
+                .thenReturn(listOf(resolveInfo))
+            getRegisteredReceiver().onReceive(context, Intent(Intent.ACTION_PACKAGE_ADDED))
+
+            assertThat(componentNames).containsExactly(TEST_COMPONENT)
+        }
+
+    @Test
+    fun componentWithoutPermission_notValid() =
+        testScope.runTest {
+            val userId = 0
+            val resolveInfo =
+                ResolveInfo(TEST_COMPONENT, hasPermission = false, defaultEnabled = true)
+            whenever(
+                    packageManager.queryIntentServicesAsUser(
+                        matchIntent(),
+                        matchFlags(),
+                        eq(userId)
+                    )
+                )
+                .thenReturn(listOf(resolveInfo))
+
+            val componentNames by collectLastValue(underTest.getInstalledTilesComponents(userId))
+            assertThat(componentNames).isEmpty()
+        }
+
+    @Test
+    fun componentNotEnabled_notValid() =
+        testScope.runTest {
+            val userId = 0
+            val resolveInfo =
+                ResolveInfo(TEST_COMPONENT, hasPermission = true, defaultEnabled = false)
+            whenever(
+                    packageManager.queryIntentServicesAsUser(
+                        matchIntent(),
+                        matchFlags(),
+                        eq(userId)
+                    )
+                )
+                .thenReturn(listOf(resolveInfo))
+
+            val componentNames by collectLastValue(underTest.getInstalledTilesComponents(userId))
+            assertThat(componentNames).isEmpty()
+        }
+
+    private fun getRegisteredReceiver(): BroadcastReceiver {
+        verify(context)
+            .registerReceiverAsUser(
+                capture(receiverCaptor),
+                any(),
+                any(),
+                nullable(),
+                nullable(),
+            )
+
+        return receiverCaptor.value
+    }
+
+    companion object {
+        private val INTENT = Intent(TileService.ACTION_QS_TILE)
+        private val FLAGS =
+            ResolveInfoFlags.of(
+                (PackageManager.MATCH_DIRECT_BOOT_AWARE or
+                        PackageManager.MATCH_DIRECT_BOOT_UNAWARE or
+                        PackageManager.GET_SERVICES)
+                    .toLong()
+            )
+        private val PERMISSION = BIND_QUICK_SETTINGS_TILE
+
+        private val TEST_COMPONENT = ComponentName("pkg", "cls")
+
+        private fun matchFlags() =
+            argThat<ResolveInfoFlags> { flags -> flags?.value == FLAGS.value }
+        private fun matchIntent() = argThat<Intent> { intent -> intent.action == INTENT.action }
+
+        private fun ResolveInfo(
+            componentName: ComponentName,
+            hasPermission: Boolean,
+            defaultEnabled: Boolean
+        ): ResolveInfo {
+            val applicationInfo = ApplicationInfo().apply { enabled = true }
+            val serviceInfo =
+                ServiceInfo().apply {
+                    packageName = componentName.packageName
+                    name = componentName.className
+                    if (hasPermission) {
+                        permission = PERMISSION
+                    }
+                    enabled = defaultEnabled
+                    this.applicationInfo = applicationInfo
+                }
+            val resolveInfo = ResolveInfo()
+            resolveInfo.serviceInfo = serviceInfo
+            return resolveInfo
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt
index 426ff67..e7ad489 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt
@@ -38,6 +38,7 @@
 import com.android.systemui.qs.external.TileServiceKey
 import com.android.systemui.qs.pipeline.data.repository.CustomTileAddedRepository
 import com.android.systemui.qs.pipeline.data.repository.FakeCustomTileAddedRepository
+import com.android.systemui.qs.pipeline.data.repository.FakeInstalledTilesComponentRepository
 import com.android.systemui.qs.pipeline.data.repository.FakeTileSpecRepository
 import com.android.systemui.qs.pipeline.data.repository.TileSpecRepository
 import com.android.systemui.qs.pipeline.domain.model.TileModel
@@ -73,6 +74,7 @@
 
     private val tileSpecRepository: TileSpecRepository = FakeTileSpecRepository()
     private val userRepository = FakeUserRepository()
+    private val installedTilesPackageRepository = FakeInstalledTilesComponentRepository()
     private val tileFactory = FakeQSFactory(::tileCreator)
     private val customTileAddedRepository: CustomTileAddedRepository =
         FakeCustomTileAddedRepository()
@@ -100,11 +102,13 @@
         featureFlags.set(Flags.QS_PIPELINE_NEW_HOST, true)
 
         userRepository.setUserInfos(listOf(USER_INFO_0, USER_INFO_1))
+
         setUserTracker(0)
 
         underTest =
             CurrentTilesInteractorImpl(
                 tileSpecRepository = tileSpecRepository,
+                installedTilesComponentRepository = installedTilesPackageRepository,
                 userRepository = userRepository,
                 customTileStatePersister = customTileStatePersister,
                 tileFactory = tileFactory,
@@ -609,6 +613,40 @@
             assertThat((tileA as FakeQSTile).callbacks).containsExactly(callback)
         }
 
+    @Test
+    fun packageNotInstalled_customTileNotVisible() =
+        testScope.runTest(USER_INFO_0) {
+            installedTilesPackageRepository.setInstalledPackagesForUser(USER_INFO_0.id, emptySet())
+
+            val tiles by collectLastValue(underTest.currentTiles)
+
+            val specs = listOf(TileSpec.create("a"), CUSTOM_TILE_SPEC)
+            tileSpecRepository.setTiles(USER_INFO_0.id, specs)
+
+            assertThat(tiles!!.size).isEqualTo(1)
+            assertThat(tiles!![0].spec).isEqualTo(specs[0])
+        }
+
+    @Test
+    fun packageInstalledLater_customTileAdded() =
+        testScope.runTest(USER_INFO_0) {
+            installedTilesPackageRepository.setInstalledPackagesForUser(USER_INFO_0.id, emptySet())
+
+            val tiles by collectLastValue(underTest.currentTiles)
+            val specs = listOf(TileSpec.create("a"), CUSTOM_TILE_SPEC, TileSpec.create("b"))
+            tileSpecRepository.setTiles(USER_INFO_0.id, specs)
+
+            assertThat(tiles!!.size).isEqualTo(2)
+
+            installedTilesPackageRepository.setInstalledPackagesForUser(
+                USER_INFO_0.id,
+                setOf(TEST_COMPONENT)
+            )
+
+            assertThat(tiles!!.size).isEqualTo(3)
+            assertThat(tiles!![1].spec).isEqualTo(CUSTOM_TILE_SPEC)
+        }
+
     private fun QSTile.State.fillIn(state: Int, label: CharSequence, secondaryLabel: CharSequence) {
         this.state = state
         this.label = label
@@ -654,6 +692,7 @@
 
     private suspend fun switchUser(user: UserInfo) {
         setUserTracker(user.id)
+        installedTilesPackageRepository.setInstalledPackagesForUser(user.id, setOf(TEST_COMPONENT))
         userRepository.setSelectedUserInfo(user)
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
index 3def6ba..8744aa3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
@@ -204,6 +204,17 @@
     }
 
     @Test
+    public void testOnSystemRequestedStop_recorderEndThrowsRuntimeException_showsErrorNotification()
+            throws IOException {
+        doReturn(true).when(mController).isRecording();
+        doThrow(new RuntimeException()).when(mScreenMediaRecorder).end();
+
+        mRecordingService.onStopped();
+
+        verify(mRecordingService).createErrorNotification();
+    }
+
+    @Test
     public void testOnSystemRequestedStop_recorderEndThrowsOOMError_releasesRecording()
             throws IOException {
         doReturn(true).when(mController).isRecording();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/SaveImageInBackgroundTaskTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/SaveImageInBackgroundTaskTest.kt
new file mode 100644
index 0000000..fbb77cd
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/SaveImageInBackgroundTaskTest.kt
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot
+
+import android.app.Notification
+import android.app.PendingIntent
+import android.content.ComponentName
+import android.content.Intent
+import android.graphics.Bitmap
+import android.graphics.drawable.Icon
+import android.net.Uri
+import android.os.UserHandle
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.screenshot.ScreenshotController.SaveImageInBackgroundData
+import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import java.util.concurrent.CompletableFuture
+import java.util.function.Supplier
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Before
+import org.junit.Test
+
+@SmallTest
+class SaveImageInBackgroundTaskTest : SysuiTestCase() {
+    private val imageExporter = mock<ImageExporter>()
+    private val smartActions = mock<ScreenshotSmartActions>()
+    private val smartActionsProvider = mock<ScreenshotNotificationSmartActionsProvider>()
+    private val saveImageData = SaveImageInBackgroundData()
+    private val sharedTransitionSupplier =
+        mock<Supplier<ScreenshotController.SavedImageData.ActionTransition>>()
+    private val testScreenshotId: String = "testScreenshotId"
+    private val testBitmap = mock<Bitmap>()
+    private val testUser = UserHandle.getUserHandleForUid(0)
+    private val testIcon = mock<Icon>()
+    private val testImageTime = 1234.toLong()
+    private val flags = FakeFeatureFlags()
+
+    private val smartActionsUriFuture = mock<CompletableFuture<List<Notification.Action>>>()
+    private val smartActionsFuture = mock<CompletableFuture<List<Notification.Action>>>()
+
+    private val testUri: Uri = Uri.parse("testUri")
+    private val intent =
+        Intent(Intent.ACTION_SEND)
+            .setComponent(
+                ComponentName.unflattenFromString(
+                    "com.google.android.test/com.google.android.test.TestActivity"
+                )
+            )
+    private val immutablePendingIntent =
+        PendingIntent.getBroadcast(
+            mContext,
+            0,
+            intent,
+            PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
+        )
+    private val mutablePendingIntent =
+        PendingIntent.getBroadcast(
+            mContext,
+            0,
+            intent,
+            PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_MUTABLE
+        )
+
+    private val saveImageTask =
+        SaveImageInBackgroundTask(
+            mContext,
+            flags,
+            imageExporter,
+            smartActions,
+            saveImageData,
+            sharedTransitionSupplier,
+            smartActionsProvider,
+        )
+
+    @Before
+    fun setup() {
+        whenever(
+                smartActions.getSmartActionsFuture(
+                    eq(testScreenshotId),
+                    any(Uri::class.java),
+                    eq(testBitmap),
+                    eq(smartActionsProvider),
+                    any(ScreenshotSmartActionType::class.java),
+                    any(Boolean::class.java),
+                    eq(testUser)
+                )
+            )
+            .thenReturn(smartActionsUriFuture)
+        whenever(
+                smartActions.getSmartActionsFuture(
+                    eq(testScreenshotId),
+                    eq(null),
+                    eq(testBitmap),
+                    eq(smartActionsProvider),
+                    any(ScreenshotSmartActionType::class.java),
+                    any(Boolean::class.java),
+                    eq(testUser)
+                )
+            )
+            .thenReturn(smartActionsFuture)
+    }
+
+    @Test
+    fun testQueryQuickShare_noAction() {
+        whenever(
+                smartActions.getSmartActions(
+                    eq(testScreenshotId),
+                    eq(smartActionsFuture),
+                    any(Int::class.java),
+                    eq(smartActionsProvider),
+                    eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION)
+                )
+            )
+            .thenReturn(ArrayList<Notification.Action>())
+
+        val quickShareAction =
+            saveImageTask.queryQuickShareAction(testScreenshotId, testBitmap, testUser, testUri)
+
+        assertNull(quickShareAction)
+    }
+
+    @Test
+    fun testQueryQuickShare_withActions() {
+        val actions = ArrayList<Notification.Action>()
+        actions.add(constructAction("Action One", mutablePendingIntent))
+        actions.add(constructAction("Action Two", mutablePendingIntent))
+        whenever(
+                smartActions.getSmartActions(
+                    eq(testScreenshotId),
+                    eq(smartActionsUriFuture),
+                    any(Int::class.java),
+                    eq(smartActionsProvider),
+                    eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION)
+                )
+            )
+            .thenReturn(actions)
+
+        val quickShareAction =
+            saveImageTask.queryQuickShareAction(testScreenshotId, testBitmap, testUser, testUri)!!
+
+        assertEquals("Action One", quickShareAction.title)
+        assertEquals(mutablePendingIntent, quickShareAction.actionIntent)
+    }
+
+    @Test
+    fun testCreateQuickShareAction_originalWasNull_returnsNull() {
+        val quickShareAction =
+            saveImageTask.createQuickShareAction(
+                null,
+                testScreenshotId,
+                testUri,
+                testImageTime,
+                testBitmap,
+                testUser
+            )
+
+        assertNull(quickShareAction)
+    }
+
+    @Test
+    fun testCreateQuickShareAction_immutableIntentDifferentAction_returnsNull() {
+        val actions = ArrayList<Notification.Action>()
+        actions.add(constructAction("New Test Action", immutablePendingIntent))
+        whenever(
+                smartActions.getSmartActions(
+                    eq(testScreenshotId),
+                    eq(smartActionsUriFuture),
+                    any(Int::class.java),
+                    eq(smartActionsProvider),
+                    eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION)
+                )
+            )
+            .thenReturn(actions)
+        val origAction = constructAction("Old Test Action", immutablePendingIntent)
+
+        val quickShareAction =
+            saveImageTask.createQuickShareAction(
+                origAction,
+                testScreenshotId,
+                testUri,
+                testImageTime,
+                testBitmap,
+                testUser,
+            )
+
+        assertNull(quickShareAction)
+    }
+
+    @Test
+    fun testCreateQuickShareAction_mutableIntent_returnsSafeIntent() {
+        val actions = ArrayList<Notification.Action>()
+        val action = constructAction("Action One", mutablePendingIntent)
+        actions.add(action)
+        whenever(
+                smartActions.getSmartActions(
+                    eq(testScreenshotId),
+                    eq(smartActionsUriFuture),
+                    any(Int::class.java),
+                    eq(smartActionsProvider),
+                    eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION)
+                )
+            )
+            .thenReturn(actions)
+
+        val quickShareAction =
+            saveImageTask.createQuickShareAction(
+                constructAction("Test Action", mutablePendingIntent),
+                testScreenshotId,
+                testUri,
+                testImageTime,
+                testBitmap,
+                testUser
+            )
+        val quickSharePendingIntent =
+            quickShareAction.actionIntent.intent.extras!!.getParcelable(
+                ScreenshotController.EXTRA_ACTION_INTENT,
+                PendingIntent::class.java
+            )
+
+        assertEquals("Test Action", quickShareAction.title)
+        assertEquals(mutablePendingIntent, quickSharePendingIntent)
+    }
+
+    @Test
+    fun testCreateQuickShareAction_immutableIntent_returnsSafeIntent() {
+        val actions = ArrayList<Notification.Action>()
+        val action = constructAction("Test Action", immutablePendingIntent)
+        actions.add(action)
+        whenever(
+                smartActions.getSmartActions(
+                    eq(testScreenshotId),
+                    eq(smartActionsUriFuture),
+                    any(Int::class.java),
+                    eq(smartActionsProvider),
+                    eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION)
+                )
+            )
+            .thenReturn(actions)
+
+        val quickShareAction =
+            saveImageTask.createQuickShareAction(
+                constructAction("Test Action", immutablePendingIntent),
+                testScreenshotId,
+                testUri,
+                testImageTime,
+                testBitmap,
+                testUser,
+            )!!
+
+        assertEquals("Test Action", quickShareAction.title)
+        assertEquals(
+            immutablePendingIntent,
+            quickShareAction.actionIntent.intent.extras!!.getParcelable(
+                ScreenshotController.EXTRA_ACTION_INTENT,
+                PendingIntent::class.java
+            )
+        )
+    }
+
+    private fun constructAction(title: String, intent: PendingIntent): Notification.Action {
+        return Notification.Action.Builder(testIcon, title, intent).build()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index a5a9de5..8f2ee91 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -1097,6 +1097,13 @@
     }
 
     @Test
+    public void onShadeFlingEnd_mExpandImmediateShouldBeReset() {
+        mNotificationPanelViewController.onFlingEnd(false);
+
+        verify(mQsController).setExpandImmediate(false);
+    }
+
+    @Test
     public void inUnlockedSplitShade_transitioningMaxTransitionDistance_makesShadeFullyExpanded() {
         mStatusBarStateController.setState(SHADE);
         enableSplitShade(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
index 20da8a6..2da2e92 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
@@ -78,6 +78,7 @@
 import org.mockito.Mockito
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.reset
+import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when` as whenever
 import org.mockito.junit.MockitoJUnit
@@ -387,7 +388,7 @@
         whenever(clock.isLayoutRtl).thenReturn(false)
 
         val captor = ArgumentCaptor.forClass(View.OnLayoutChangeListener::class.java)
-        verify(clock).addOnLayoutChangeListener(capture(captor))
+        verify(clock, times(2)).addOnLayoutChangeListener(capture(captor))
 
         captor.value.onLayoutChange(clock, 0, 1, 2, 3, 4, 5, 6, 7)
         verify(clock).pivotX = 0f
@@ -400,7 +401,7 @@
         whenever(clock.isLayoutRtl).thenReturn(true)
 
         val captor = ArgumentCaptor.forClass(View.OnLayoutChangeListener::class.java)
-        verify(clock).addOnLayoutChangeListener(capture(captor))
+        verify(clock, times(2)).addOnLayoutChangeListener(capture(captor))
 
         captor.value.onLayoutChange(clock, 0, 1, 2, 3, 4, 5, 6, 7)
         verify(clock).pivotX = width.toFloat()
@@ -793,7 +794,7 @@
     @Test
     fun clockPivotYInCenter() {
         val captor = ArgumentCaptor.forClass(View.OnLayoutChangeListener::class.java)
-        verify(clock).addOnLayoutChangeListener(capture(captor))
+        verify(clock, times(2)).addOnLayoutChangeListener(capture(captor))
         var height = 100
         val width = 50
 
@@ -825,16 +826,17 @@
     }
 
     @Test
-    fun carrierLeftPaddingIsSetWhenClockLayoutChanges() {
-        val width = 200
-        whenever(clock.width).thenReturn(width)
-        whenever(clock.scaleX).thenReturn(2.57f) // 2.57 comes from qs_header.xml
+    fun carrierStartPaddingIsSetOnClockLayout() {
+        val clockWidth = 200
+        val maxClockScale = context.resources.getFloat(R.dimen.qqs_expand_clock_scale)
+        val expectedStartPadding = (clockWidth * maxClockScale).toInt()
+        whenever(clock.width).thenReturn(clockWidth)
+
         val captor = ArgumentCaptor.forClass(View.OnLayoutChangeListener::class.java)
+        verify(clock, times(2)).addOnLayoutChangeListener(capture(captor))
+        captor.allValues.forEach { clock.executeLayoutChange(0, 0, clockWidth, 0, it) }
 
-        verify(clock).addOnLayoutChangeListener(capture(captor))
-        captor.value.onLayoutChange(clock, 0, 0, width, 0, 0, 0, 0, 0)
-
-        verify(carrierGroup).setPaddingRelative(514, 0, 0, 0)
+        verify(carrierGroup).setPaddingRelative(expectedStartPadding, 0, 0, 0)
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
index eef4470..04c93cb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
@@ -298,6 +298,54 @@
     }
 
     @Test
+    fun unknownPluginAttached_clockAndListUnchanged_loadRequested() {
+        val mockPluginLifecycle = mock<PluginLifecycleManager<ClockProviderPlugin>>()
+        whenever(mockPluginLifecycle.getPackage()).thenReturn("some.other.package")
+
+        var changeCallCount = 0
+        var listChangeCallCount = 0
+        registry.registerClockChangeListener(object : ClockRegistry.ClockChangeListener {
+            override fun onCurrentClockChanged() { changeCallCount++ }
+            override fun onAvailableClocksChanged() { listChangeCallCount++ }
+        })
+
+        assertEquals(true, pluginListener.onPluginAttached(mockPluginLifecycle))
+        scheduler.runCurrent()
+        assertEquals(0, changeCallCount)
+        assertEquals(0, listChangeCallCount)
+    }
+
+    @Test
+    fun knownPluginAttached_clockAndListChanged_notLoaded() {
+        val mockPluginLifecycle1 = mock<PluginLifecycleManager<ClockProviderPlugin>>()
+        whenever(mockPluginLifecycle1.getPackage()).thenReturn("com.android.systemui.falcon.one")
+        val mockPluginLifecycle2 = mock<PluginLifecycleManager<ClockProviderPlugin>>()
+        whenever(mockPluginLifecycle2.getPackage()).thenReturn("com.android.systemui.falcon.two")
+
+        var changeCallCount = 0
+        var listChangeCallCount = 0
+        registry.registerClockChangeListener(object : ClockRegistry.ClockChangeListener {
+            override fun onCurrentClockChanged() { changeCallCount++ }
+            override fun onAvailableClocksChanged() { listChangeCallCount++ }
+        })
+
+        registry.applySettings(ClockSettings("DIGITAL_CLOCK_CALLIGRAPHY", null))
+        scheduler.runCurrent()
+        assertEquals(1, changeCallCount)
+        assertEquals(0, listChangeCallCount)
+
+        assertEquals(false, pluginListener.onPluginAttached(mockPluginLifecycle1))
+        scheduler.runCurrent()
+        assertEquals(1, changeCallCount)
+        assertEquals(1, listChangeCallCount)
+
+        assertEquals(false, pluginListener.onPluginAttached(mockPluginLifecycle2))
+        scheduler.runCurrent()
+        assertEquals(1, changeCallCount)
+        assertEquals(2, listChangeCallCount)
+    }
+
+    @Test
     fun pluginAddRemove_concurrentModification() {
         val mockPluginLifecycle1 = mock<PluginLifecycleManager<ClockProviderPlugin>>()
         val mockPluginLifecycle2 = mock<PluginLifecycleManager<ClockProviderPlugin>>()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
index d5e904c..88d853e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
@@ -122,6 +122,7 @@
         mPluginInstanceFactory.create(
                 mContext, mAppInfo, wrongVersionTestPluginComponentName,
                 TestPlugin.class, mPluginListener);
+        mPluginInstance.onCreate();
     }
 
     @Test
@@ -135,11 +136,12 @@
 
     @Test
     public void testOnDestroy() {
+        mPluginInstance.onCreate();
         mPluginInstance.onDestroy();
         assertEquals(1, mPluginListener.mDetachedCount);
         assertEquals(1, mPluginListener.mUnloadCount);
         assertNull(mPluginInstance.getPlugin());
-        assertInstances(0, -1); // Destroyed but never created
+        assertInstances(0, 0); // Destroyed but never created
     }
 
     @Test
@@ -161,6 +163,16 @@
         assertInstances(0, 0);
     }
 
+    @Test
+    public void testOnAttach_SkipLoad() {
+        mPluginListener.mAttachReturn = false;
+        mPluginInstance.onCreate();
+        assertEquals(1, mPluginListener.mAttachedCount);
+        assertEquals(0, mPluginListener.mLoadCount);
+        assertEquals(null, mPluginInstance.getPlugin());
+        assertInstances(0, 0);
+    }
+
     // This target class doesn't matter, it just needs to have a Requires to hit the flow where
     // the mock version info is called.
     @ProvidesInterface(action = TestPlugin.ACTION, version = TestPlugin.VERSION)
@@ -220,15 +232,17 @@
     }
 
     public class FakeListener implements PluginListener<TestPlugin> {
+        public boolean mAttachReturn = true;
         public int mAttachedCount = 0;
         public int mDetachedCount = 0;
         public int mLoadCount = 0;
         public int mUnloadCount = 0;
 
         @Override
-        public void onPluginAttached(PluginLifecycleManager<TestPlugin> manager) {
+        public boolean onPluginAttached(PluginLifecycleManager<TestPlugin> manager) {
             mAttachedCount++;
             assertEquals(PluginInstanceTest.this.mPluginInstance, manager);
+            return mAttachReturn;
         }
 
         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
index 39ed553..914301f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
@@ -60,9 +60,13 @@
 class SystemStatusAnimationSchedulerImplTest : SysuiTestCase() {
 
     @Mock private lateinit var systemEventCoordinator: SystemEventCoordinator
+
     @Mock private lateinit var statusBarWindowController: StatusBarWindowController
+
     @Mock private lateinit var statusBarContentInsetProvider: StatusBarContentInsetsProvider
+
     @Mock private lateinit var dumpManager: DumpManager
+
     @Mock private lateinit var listener: SystemStatusAnimationCallback
 
     private lateinit var systemClock: FakeSystemClock
@@ -380,6 +384,32 @@
     }
 
     @Test
+    fun testPrivacyDot_isRemovedDuringChipDisappearAnimation() = runTest {
+        // Instantiate class under test with TestScope from runTest
+        initializeSystemStatusAnimationScheduler(testScope = this)
+
+        // create and schedule high priority event
+        createAndScheduleFakePrivacyEvent()
+
+        // fast forward to ANIMATING_OUT state
+        fastForwardAnimationToState(ANIMATING_OUT)
+        assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+        verify(listener, times(1)).onSystemStatusAnimationTransitionToPersistentDot(any())
+
+        // remove persistent dot
+        systemStatusAnimationScheduler.removePersistentDot()
+        testScheduler.runCurrent()
+
+        // skip disappear animation
+        animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
+        testScheduler.runCurrent()
+
+        // verify that animationState changes to IDLE and onHidePersistentDot callback is invoked
+        assertEquals(IDLE, systemStatusAnimationScheduler.getAnimationState())
+        verify(listener, times(1)).onHidePersistentDot()
+    }
+
+    @Test
     fun testPrivacyEvent_forceVisibleIsUpdated_whenRescheduledDuringQueuedState() = runTest {
         // Instantiate class under test with TestScope from runTest
         initializeSystemStatusAnimationScheduler(testScope = this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
index 283efe2..257cc5b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
@@ -221,16 +221,35 @@
     }
 
     @Test
-    fun hunExtensionCancelledWhenHunActionPressed() {
+    fun actionPressCancelsExistingLifetimeExtension() {
         whenever(headsUpManager.isSticky(anyString())).thenReturn(true)
         addHUN(entry)
+
         whenever(headsUpManager.canRemoveImmediately(anyString())).thenReturn(false)
         whenever(headsUpManager.getEarliestRemovalTime(anyString())).thenReturn(1000L)
-        assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, 0))
+        assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, /* reason = */ 0))
+
         actionPressListener.accept(entry)
-        executor.advanceClockToLast()
         executor.runAllReady()
-        verify(headsUpManager, times(1)).removeNotification(eq(entry.key), eq(true))
+        verify(endLifetimeExtension, times(1)).onEndLifetimeExtension(notifLifetimeExtender, entry)
+
+        collectionListener.onEntryRemoved(entry, /* reason = */ 0)
+        verify(headsUpManager, times(1)).removeNotification(eq(entry.key), any())
+    }
+
+    @Test
+    fun actionPressPreventsFutureLifetimeExtension() {
+        whenever(headsUpManager.isSticky(anyString())).thenReturn(true)
+        addHUN(entry)
+
+        actionPressListener.accept(entry)
+        verify(headsUpManager, times(1)).setUserActionMayIndirectlyRemove(entry)
+
+        whenever(headsUpManager.canRemoveImmediately(anyString())).thenReturn(true)
+        assertFalse(notifLifetimeExtender.maybeExtendLifetime(entry, 0))
+
+        collectionListener.onEntryRemoved(entry, /* reason = */ 0)
+        verify(headsUpManager, times(1)).removeNotification(eq(entry.key), any())
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 6a0e3c6..02666e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -35,6 +35,7 @@
 import android.content.res.Resources;
 import android.metrics.LogMaker;
 import android.testing.AndroidTestingRunner;
+import android.view.View;
 
 import androidx.test.filters.SmallTest;
 
@@ -430,6 +431,84 @@
         verify(mNotificationStackScrollLayout).setStatusBarState(KEYGUARD);
     }
 
+    @Test
+    public void updateImportantForAccessibility_noChild_onKeyGuard_notImportantForA11y() {
+        // GIVEN: Controller is attached, active notifications is empty,
+        // and mNotificationStackScrollLayout.onKeyguard() is true
+        initController(/* viewIsAttached= */ true);
+        when(mNotificationStackScrollLayout.onKeyguard()).thenReturn(true);
+        mController.getNotifStackController().setNotifStats(NotifStats.getEmpty());
+
+        // WHEN: call updateImportantForAccessibility
+        mController.updateImportantForAccessibility();
+
+        // THEN: mNotificationStackScrollLayout should not be important for A11y
+        verify(mNotificationStackScrollLayout)
+                .setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+    }
+
+    @Test
+    public void updateImportantForAccessibility_hasChild_onKeyGuard_importantForA11y() {
+        // GIVEN: Controller is attached, active notifications is not empty,
+        // and mNotificationStackScrollLayout.onKeyguard() is true
+        initController(/* viewIsAttached= */ true);
+        when(mNotificationStackScrollLayout.onKeyguard()).thenReturn(true);
+        mController.getNotifStackController().setNotifStats(
+                new NotifStats(
+                        /* numActiveNotifs = */ 1,
+                        /* hasNonClearableAlertingNotifs = */ false,
+                        /* hasClearableAlertingNotifs = */ false,
+                        /* hasNonClearableSilentNotifs = */ false,
+                        /* hasClearableSilentNotifs = */ false)
+        );
+
+        // WHEN: call updateImportantForAccessibility
+        mController.updateImportantForAccessibility();
+
+        // THEN: mNotificationStackScrollLayout should be important for A11y
+        verify(mNotificationStackScrollLayout)
+                .setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+    }
+
+    @Test
+    public void updateImportantForAccessibility_hasChild_notOnKeyGuard_importantForA11y() {
+        // GIVEN: Controller is attached, active notifications is not empty,
+        // and mNotificationStackScrollLayout.onKeyguard() is false
+        initController(/* viewIsAttached= */ true);
+        when(mNotificationStackScrollLayout.onKeyguard()).thenReturn(false);
+        mController.getNotifStackController().setNotifStats(
+                new NotifStats(
+                        /* numActiveNotifs = */ 1,
+                        /* hasNonClearableAlertingNotifs = */ false,
+                        /* hasClearableAlertingNotifs = */ false,
+                        /* hasNonClearableSilentNotifs = */ false,
+                        /* hasClearableSilentNotifs = */ false)
+        );
+
+        // WHEN: call updateImportantForAccessibility
+        mController.updateImportantForAccessibility();
+
+        // THEN: mNotificationStackScrollLayout should be important for A11y
+        verify(mNotificationStackScrollLayout)
+                .setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+    }
+
+    @Test
+    public void updateImportantForAccessibility_noChild_notOnKeyGuard_importantForA11y() {
+        // GIVEN: Controller is attached, active notifications is empty,
+        // and mNotificationStackScrollLayout.onKeyguard() is false
+        initController(/* viewIsAttached= */ true);
+        when(mNotificationStackScrollLayout.onKeyguard()).thenReturn(false);
+        mController.getNotifStackController().setNotifStats(NotifStats.getEmpty());
+
+        // WHEN: call updateImportantForAccessibility
+        mController.updateImportantForAccessibility();
+
+        // THEN: mNotificationStackScrollLayout should be important for A11y
+        verify(mNotificationStackScrollLayout)
+                .setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+    }
+
     private LogMaker logMatcher(int category, int type) {
         return argThat(new LogMatcher(category, type));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index a4ee349..85b1ec1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -41,6 +41,7 @@
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
@@ -575,10 +576,7 @@
         mStackScroller.inflateFooterView();
 
         // add notification
-        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
-        NotificationEntry entry = mock(NotificationEntry.class);
-        when(row.getEntry()).thenReturn(entry);
-        when(entry.isClearable()).thenReturn(true);
+        ExpandableNotificationRow row = createClearableRow();
         mStackScroller.addContainerView(row);
 
         mStackScroller.onUpdateRowStates();
@@ -648,6 +646,50 @@
     }
 
     @Test
+    public void testClearNotifications_clearAllInProgress() {
+        ExpandableNotificationRow row = createClearableRow();
+        when(row.getEntry().hasFinishedInitialization()).thenReturn(true);
+        doReturn(true).when(mStackScroller).isVisible(row);
+        mStackScroller.addContainerView(row);
+
+        mStackScroller.clearNotifications(ROWS_ALL, false);
+
+        assertClearAllInProgress(true);
+        verify(mNotificationRoundnessManager).setClearAllInProgress(true);
+    }
+
+    @Test
+    public void testOnChildAnimationFinished_resetsClearAllInProgress() {
+        mStackScroller.setClearAllInProgress(true);
+
+        mStackScroller.onChildAnimationFinished();
+
+        assertClearAllInProgress(false);
+        verify(mNotificationRoundnessManager).setClearAllInProgress(false);
+    }
+
+    @Test
+    public void testShadeCollapsed_resetsClearAllInProgress() {
+        mStackScroller.setClearAllInProgress(true);
+
+        mStackScroller.setIsExpanded(false);
+
+        assertClearAllInProgress(false);
+        verify(mNotificationRoundnessManager).setClearAllInProgress(false);
+    }
+
+    @Test
+    public void testShadeExpanded_doesntChangeClearAllInProgress() {
+        mStackScroller.setClearAllInProgress(true);
+        clearInvocations(mNotificationRoundnessManager);
+
+        mStackScroller.setIsExpanded(true);
+
+        assertClearAllInProgress(true);
+        verify(mNotificationRoundnessManager, never()).setClearAllInProgress(anyBoolean());
+    }
+
+    @Test
     public void testAddNotificationUpdatesSpeedBumpIndex() {
         // initial state calculated == 0
         assertEquals(0, mStackScroller.getSpeedBumpIndex());
@@ -794,7 +836,7 @@
     }
 
     @Test
-    public void onShadeClosesWithAnimationWillResetSwipeState() {
+    public void onShadeClosesWithAnimationWillResetTouchState() {
         // GIVEN shade is expanded
         mStackScroller.setIsExpanded(true);
         clearInvocations(mNotificationSwipeHelper);
@@ -804,12 +846,12 @@
         mStackScroller.setIsExpanded(false);
         mStackScroller.onExpansionStopped();
 
-        // VERIFY swipe is reset
-        verify(mNotificationSwipeHelper).resetSwipeState();
+        // VERIFY touch is reset
+        verify(mNotificationSwipeHelper).resetTouchState();
     }
 
     @Test
-    public void onShadeClosesWithoutAnimationWillResetSwipeState() {
+    public void onShadeClosesWithoutAnimationWillResetTouchState() {
         // GIVEN shade is expanded
         mStackScroller.setIsExpanded(true);
         clearInvocations(mNotificationSwipeHelper);
@@ -817,8 +859,8 @@
         // WHEN closing the shade without the animation
         mStackScroller.setIsExpanded(false);
 
-        // VERIFY swipe is reset
-        verify(mNotificationSwipeHelper).resetSwipeState();
+        // VERIFY touch is reset
+        verify(mNotificationSwipeHelper).resetTouchState();
     }
 
     @Test
@@ -896,6 +938,21 @@
         mStackScroller.setStatusBarState(state);
     }
 
+    private ExpandableNotificationRow createClearableRow() {
+        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+        NotificationEntry entry = mock(NotificationEntry.class);
+        when(row.canViewBeCleared()).thenReturn(true);
+        when(row.getEntry()).thenReturn(entry);
+        when(entry.isClearable()).thenReturn(true);
+
+        return row;
+    }
+
+    private void assertClearAllInProgress(boolean expected) {
+        assertEquals(expected, mStackScroller.getClearAllInProgress());
+        assertEquals(expected, mAmbientState.isClearAllInProgress());
+    }
+
     private static void mockBoundsOnScreen(View view, Rect bounds) {
         doAnswer(invocation -> {
             Rect out = invocation.getArgument(0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index fd9f6a7..8062272 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -350,6 +350,7 @@
         // For the Shade to animate during the Back gesture, we must enable the animation flag.
         mFeatureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, true);
         mFeatureFlags.set(Flags.LIGHT_REVEAL_MIGRATION, true);
+        mFeatureFlags.set(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD, true);
 
         IThermalService thermalService = mock(IThermalService.class);
         mPowerManager = new PowerManager(mContext, mPowerManagerService, thermalService,
@@ -1103,8 +1104,10 @@
         clearInvocations(mNotificationPanelViewController);
 
         mCentralSurfaces.mWakefulnessObserver.onStartedWakingUp();
-        verify(mDozeServiceHost).stopDozing();
+        verify(mDozeServiceHost, never()).stopDozing();
         verify(mNotificationPanelViewController).expand(eq(false));
+        mCentralSurfaces.mWakefulnessObserver.onFinishedWakingUp();
+        verify(mDozeServiceHost).stopDozing();
     }
 
     @Test
@@ -1118,6 +1121,8 @@
         mCentralSurfaces.setBouncerShowing(true);
         mCentralSurfaces.mWakefulnessObserver.onStartedWakingUp();
         verify(mNotificationPanelViewController, never()).expand(anyBoolean());
+        mCentralSurfaces.mWakefulnessObserver.onFinishedWakingUp();
+        verify(mDozeServiceHost).stopDozing();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
index 487d26d..a797e03 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
@@ -20,7 +20,6 @@
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertNotSame;
 import static junit.framework.Assert.assertTrue;
 
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -346,4 +345,17 @@
         assertEquals(HeadsUpManager.NotificationPeekEvent.NOTIFICATION_PEEK.getId(),
                 mUiEventLoggerFake.eventId(0));
     }
+
+    @Test
+    public void testSetUserActionMayIndirectlyRemove() {
+        NotificationEntry notifEntry = new NotificationEntryBuilder()
+                .setSbn(createNewNotification(/* id= */ 0))
+                .build();
+
+        mHeadsUpManager.showNotification(notifEntry);
+        assertFalse(mHeadsUpManager.canRemoveImmediately(notifEntry.getKey()));
+
+        mHeadsUpManager.setUserActionMayIndirectlyRemove(notifEntry);
+        assertTrue(mHeadsUpManager.canRemoveImmediately(notifEntry.getKey()));
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt
index 3dec45b..b9c7e61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldHapticsPlayerTest.kt
@@ -15,6 +15,7 @@
  */
 package com.android.systemui.unfold
 
+import android.os.VibrationAttributes
 import android.os.VibrationEffect
 import android.os.Vibrator
 import android.testing.AndroidTestingRunner
@@ -53,7 +54,7 @@
         progressProvider.onTransitionProgress(0.5f)
         progressProvider.onTransitionFinishing()
 
-        verify(vibrator).vibrate(any<VibrationEffect>())
+        verify(vibrator).vibrate(any<VibrationEffect>(), any<VibrationAttributes>())
     }
 
     @Test
@@ -64,7 +65,7 @@
         progressProvider.onTransitionProgress(0.99f)
         progressProvider.onTransitionFinishing()
 
-        verify(vibrator, never()).vibrate(any<VibrationEffect>())
+        verify(vibrator, never()).vibrate(any<VibrationEffect>(), any<VibrationAttributes>())
     }
 
     @Test
@@ -84,7 +85,7 @@
         progressProvider.onTransitionFinished()
         testFoldProvider.onFoldUpdate(isFolded = true)
 
-        verify(vibrator, never()).vibrate(any<VibrationEffect>())
+        verify(vibrator, never()).vibrate(any<VibrationEffect>(), any<VibrationAttributes>())
     }
 
     @Test
@@ -112,6 +113,6 @@
         progressProvider.onTransitionFinishing()
         progressProvider.onTransitionFinished()
 
-        verify(vibrator).vibrate(any<VibrationEffect>())
+        verify(vibrator).vibrate(any<VibrationEffect>(), any<VibrationAttributes>())
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/PackageManagerExtComponentEnabledTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/PackageManagerExtComponentEnabledTest.kt
new file mode 100644
index 0000000..2013bb0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/PackageManagerExtComponentEnabledTest.kt
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.kotlin
+
+import android.content.ComponentName
+import android.content.pm.ComponentInfo
+import android.content.pm.PackageManager
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.junit.runners.Parameterized.Parameters
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(Parameterized::class)
+internal class PackageManagerExtComponentEnabledTest(private val testCase: TestCase) :
+    SysuiTestCase() {
+
+    @Mock private lateinit var packageManager: PackageManager
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+    }
+
+    @Test
+    fun testComponentActuallyEnabled() {
+        whenever(packageManager.getComponentEnabledSetting(TEST_COMPONENT))
+            .thenReturn(testCase.componentEnabledSetting)
+        val componentInfo =
+            mock<ComponentInfo>() {
+                whenever(isEnabled).thenReturn(testCase.componentIsEnabled)
+                whenever(componentName).thenReturn(TEST_COMPONENT)
+            }
+
+        assertThat(packageManager.isComponentActuallyEnabled(componentInfo))
+            .isEqualTo(testCase.expected)
+    }
+
+    internal data class TestCase(
+        @PackageManager.EnabledState val componentEnabledSetting: Int,
+        val componentIsEnabled: Boolean,
+        val expected: Boolean,
+    ) {
+        override fun toString(): String {
+            return "WHEN(" +
+                "componentIsEnabled = $componentIsEnabled, " +
+                "componentEnabledSetting = ${enabledStateToString()}) then " +
+                "EXPECTED = $expected"
+        }
+
+        private fun enabledStateToString() =
+            when (componentEnabledSetting) {
+                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT -> "STATE_DEFAULT"
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED -> "STATE_DISABLED"
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED -> {
+                    "STATE_DISABLED_UNTIL_USED"
+                }
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER -> "STATE_DISABLED_USER"
+                PackageManager.COMPONENT_ENABLED_STATE_ENABLED -> "STATE_ENABLED"
+                else -> "INVALID STATE"
+            }
+    }
+
+    companion object {
+        @Parameters(name = "{0}") @JvmStatic fun data(): Collection<TestCase> = testData
+
+        private val testDataComponentIsEnabled =
+            listOf(
+                TestCase(
+                    componentEnabledSetting = PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+                    componentIsEnabled = true,
+                    expected = true,
+                ),
+                TestCase(
+                    componentEnabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER,
+                    componentIsEnabled = true,
+                    expected = false,
+                ),
+                TestCase(
+                    componentEnabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                    componentIsEnabled = true,
+                    expected = false,
+                ),
+                TestCase(
+                    componentEnabledSetting =
+                        PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED,
+                    componentIsEnabled = true,
+                    expected = false,
+                ),
+                TestCase(
+                    componentEnabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
+                    componentIsEnabled = true,
+                    expected = true,
+                ),
+            )
+
+        private val testDataComponentIsDisabled =
+            listOf(
+                TestCase(
+                    componentEnabledSetting = PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+                    componentIsEnabled = false,
+                    expected = true,
+                ),
+                TestCase(
+                    componentEnabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER,
+                    componentIsEnabled = false,
+                    expected = false,
+                ),
+                TestCase(
+                    componentEnabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                    componentIsEnabled = false,
+                    expected = false,
+                ),
+                TestCase(
+                    componentEnabledSetting =
+                        PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED,
+                    componentIsEnabled = false,
+                    expected = false,
+                ),
+                TestCase(
+                    componentEnabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
+                    componentIsEnabled = false,
+                    expected = false,
+                ),
+            )
+
+        private val testData = testDataComponentIsDisabled + testDataComponentIsEnabled
+
+        private val TEST_COMPONENT = ComponentName("pkg", "cls")
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/repository/FakeInstalledTilesComponentRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/repository/FakeInstalledTilesComponentRepository.kt
new file mode 100644
index 0000000..ff6b7d0
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/repository/FakeInstalledTilesComponentRepository.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.pipeline.data.repository
+
+import android.content.ComponentName
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+class FakeInstalledTilesComponentRepository : InstalledTilesComponentRepository {
+
+    private val installedComponentsPerUser =
+        mutableMapOf<Int, MutableStateFlow<Set<ComponentName>>>()
+
+    override fun getInstalledTilesComponents(userId: Int): Flow<Set<ComponentName>> {
+        return getFlow(userId).asStateFlow()
+    }
+
+    fun setInstalledPackagesForUser(userId: Int, components: Set<ComponentName>) {
+        getFlow(userId).value = components
+    }
+
+    private fun getFlow(userId: Int): MutableStateFlow<Set<ComponentName>> =
+        installedComponentsPerUser.getOrPut(userId) { MutableStateFlow(emptySet()) }
+}
diff --git a/services/autofill/java/com/android/server/autofill/LogFieldClassificationScoreOnResultListener.java b/services/autofill/java/com/android/server/autofill/LogFieldClassificationScoreOnResultListener.java
new file mode 100644
index 0000000..b4aca15
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/LogFieldClassificationScoreOnResultListener.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.autofill;
+
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.RemoteCallback;
+import android.service.autofill.FieldClassification;
+import android.service.autofill.FillEventHistory.Event.NoSaveReason;
+import android.util.Slog;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager.AutofillCommitReason;
+
+import java.util.ArrayList;
+
+class LogFieldClassificationScoreOnResultListener implements
+        RemoteCallback.OnResultListener {
+
+    private static final String TAG = "LogFieldClassificationScoreOnResultListener";
+
+    private Session mSession;
+    private final @NoSaveReason int mSaveDialogNotShowReason;
+    private final @AutofillCommitReason int mCommitReason;
+    private final int mViewsSize;
+    private final AutofillId[] mAutofillIds;
+    private final String[] mUserValues;
+    private final String[] mCategoryIds;
+    private final ArrayList<AutofillId> mDetectedFieldIds;
+    private final ArrayList<FieldClassification> mDetectedFieldClassifications;
+    LogFieldClassificationScoreOnResultListener(Session session,
+            int saveDialogNotShowReason,
+            int commitReason, int viewsSize, AutofillId[] autofillIds, String[] userValues,
+            String[] categoryIds, ArrayList<AutofillId> detectedFieldIds,
+            ArrayList<FieldClassification> detectedFieldClassifications) {
+        this.mSession = session;
+        this.mSaveDialogNotShowReason = saveDialogNotShowReason;
+        this.mCommitReason = commitReason;
+        this.mViewsSize = viewsSize;
+        this.mAutofillIds = autofillIds;
+        this.mUserValues = userValues;
+        this.mCategoryIds = categoryIds;
+        this.mDetectedFieldIds = detectedFieldIds;
+        this.mDetectedFieldClassifications = detectedFieldClassifications;
+    }
+
+    public void onResult(@Nullable Bundle result) {
+        // Create a local copy to safe guard race condition
+        Session session = mSession;
+        if (session == null) {
+            Slog.wtf(TAG, "session is null when calling onResult()");
+            return;
+        }
+        session.handleLogFieldClassificationScore(
+                result,
+                mSaveDialogNotShowReason,
+                mCommitReason,
+                mViewsSize,
+                mAutofillIds,
+                mUserValues,
+                mCategoryIds,
+                mDetectedFieldIds,
+                mDetectedFieldClassifications);
+        mSession = null;
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 563e431..0c3f866 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -3063,78 +3063,93 @@
         }
 
         // Then use the results, asynchronously
-        final RemoteCallback callback = new RemoteCallback((result) -> {
-            if (result == null) {
-                if (sDebug) Slog.d(TAG, "setFieldClassificationScore(): no results");
-                logContextCommitted(null, null, saveDialogNotShowReason, commitReason);
-                return;
-            }
-            final Scores scores = result.getParcelable(EXTRA_SCORES, android.service.autofill.AutofillFieldClassificationService.Scores.class);
-            if (scores == null) {
-                Slog.w(TAG, "No field classification score on " + result);
-                return;
-            }
-            int i = 0, j = 0;
-            try {
-                // Iteract over all autofill fields first
-                for (i = 0; i < viewsSize; i++) {
-                    final AutofillId autofillId = autofillIds[i];
-
-                    // Search the best scores for each category (as some categories could have
-                    // multiple user values
-                    ArrayMap<String, Float> scoresByField = null;
-                    for (j = 0; j < userValues.length; j++) {
-                        final String categoryId = categoryIds[j];
-                        final float score = scores.scores[i][j];
-                        if (score > 0) {
-                            if (scoresByField == null) {
-                                scoresByField = new ArrayMap<>(userValues.length);
-                            }
-                            final Float currentScore = scoresByField.get(categoryId);
-                            if (currentScore != null && currentScore > score) {
-                                if (sVerbose) {
-                                    Slog.v(TAG, "skipping score " + score
-                                            + " because it's less than " + currentScore);
-                                }
-                                continue;
-                            }
-                            if (sVerbose) {
-                                Slog.v(TAG, "adding score " + score + " at index " + j + " and id "
-                                        + autofillId);
-                            }
-                            scoresByField.put(categoryId, score);
-                        } else if (sVerbose) {
-                            Slog.v(TAG, "skipping score 0 at index " + j + " and id " + autofillId);
-                        }
-                    }
-                    if (scoresByField == null) {
-                        if (sVerbose) Slog.v(TAG, "no score for autofillId=" + autofillId);
-                        continue;
-                    }
-
-                    // Then create the matches for that autofill id
-                    final ArrayList<Match> matches = new ArrayList<>(scoresByField.size());
-                    for (j = 0; j < scoresByField.size(); j++) {
-                        final String fieldId = scoresByField.keyAt(j);
-                        final float score = scoresByField.valueAt(j);
-                        matches.add(new Match(fieldId, score));
-                    }
-                    detectedFieldIds.add(autofillId);
-                    detectedFieldClassifications.add(new FieldClassification(matches));
-                } // for i
-            } catch (ArrayIndexOutOfBoundsException e) {
-                wtf(e, "Error accessing FC score at [%d, %d] (%s): %s", i, j, scores, e);
-                return;
-            }
-
-            logContextCommitted(detectedFieldIds, detectedFieldClassifications,
-                    saveDialogNotShowReason, commitReason);
-        });
+        final RemoteCallback callback = new RemoteCallback(
+                new LogFieldClassificationScoreOnResultListener(
+                        this,
+                        saveDialogNotShowReason,
+                        commitReason,
+                        viewsSize,
+                        autofillIds,
+                        userValues,
+                        categoryIds,
+                        detectedFieldIds,
+                        detectedFieldClassifications));
 
         fcStrategy.calculateScores(callback, currentValues, userValues, categoryIds,
                 defaultAlgorithm, defaultArgs, algorithms, args);
     }
 
+    void handleLogFieldClassificationScore(@Nullable Bundle result, int saveDialogNotShowReason,
+            int commitReason, int viewsSize, AutofillId[] autofillIds, String[] userValues,
+            String[] categoryIds, ArrayList<AutofillId> detectedFieldIds,
+            ArrayList<FieldClassification> detectedFieldClassifications) {
+        if (result == null) {
+            if (sDebug) Slog.d(TAG, "setFieldClassificationScore(): no results");
+            logContextCommitted(null, null, saveDialogNotShowReason, commitReason);
+            return;
+        }
+        final Scores scores = result.getParcelable(EXTRA_SCORES,
+                android.service.autofill.AutofillFieldClassificationService.Scores.class);
+        if (scores == null) {
+            Slog.w(TAG, "No field classification score on " + result);
+            return;
+        }
+        int i = 0, j = 0;
+        try {
+            // Iteract over all autofill fields first
+            for (i = 0; i < viewsSize; i++) {
+                final AutofillId autofillId = autofillIds[i];
+
+                // Search the best scores for each category (as some categories could have
+                // multiple user values
+                ArrayMap<String, Float> scoresByField = null;
+                for (j = 0; j < userValues.length; j++) {
+                    final String categoryId = categoryIds[j];
+                    final float score = scores.scores[i][j];
+                    if (score > 0) {
+                        if (scoresByField == null) {
+                            scoresByField = new ArrayMap<>(userValues.length);
+                        }
+                        final Float currentScore = scoresByField.get(categoryId);
+                        if (currentScore != null && currentScore > score) {
+                            if (sVerbose) {
+                                Slog.v(TAG, "skipping score " + score
+                                        + " because it's less than " + currentScore);
+                            }
+                            continue;
+                        }
+                        if (sVerbose) {
+                            Slog.v(TAG, "adding score " + score + " at index " + j + " and id "
+                                    + autofillId);
+                        }
+                        scoresByField.put(categoryId, score);
+                    } else if (sVerbose) {
+                        Slog.v(TAG, "skipping score 0 at index " + j + " and id " + autofillId);
+                    }
+                }
+                if (scoresByField == null) {
+                    if (sVerbose) Slog.v(TAG, "no score for autofillId=" + autofillId);
+                    continue;
+                }
+
+                // Then create the matches for that autofill id
+                final ArrayList<Match> matches = new ArrayList<>(scoresByField.size());
+                for (j = 0; j < scoresByField.size(); j++) {
+                    final String fieldId = scoresByField.keyAt(j);
+                    final float score = scoresByField.valueAt(j);
+                    matches.add(new Match(fieldId, score));
+                }
+                detectedFieldIds.add(autofillId);
+                detectedFieldClassifications.add(new FieldClassification(matches));
+            } // for i
+        } catch (ArrayIndexOutOfBoundsException e) {
+            wtf(e, "Error accessing FC score at [%d, %d] (%s): %s", i, j, scores, e);
+            return;
+        }
+        logContextCommitted(detectedFieldIds, detectedFieldClassifications,
+                saveDialogNotShowReason, commitReason);
+    }
+
     /**
      * Generates a {@link android.service.autofill.FillEventHistory.Event#TYPE_SAVE_SHOWN}
      * when necessary.
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index 6b55d7e..cd2f844 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -987,8 +987,12 @@
                     "Virtual device doesn't have a virtual display with ID " + displayId);
         }
 
-        releaseOwnedVirtualDisplayResources(virtualDisplayWrapper);
-
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            releaseOwnedVirtualDisplayResources(virtualDisplayWrapper);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/WallpaperUpdateReceiver.java b/services/core/java/com/android/server/WallpaperUpdateReceiver.java
index 2812233..9917892 100644
--- a/services/core/java/com/android/server/WallpaperUpdateReceiver.java
+++ b/services/core/java/com/android/server/WallpaperUpdateReceiver.java
@@ -88,7 +88,7 @@
         } else {
             //live wallpaper
             ComponentName currCN = info.getComponent();
-            ComponentName defaultCN = WallpaperManager.getCmfDefaultWallpaperComponent(context);
+            ComponentName defaultCN = WallpaperManager.getDefaultWallpaperComponent(context);
             if (!currCN.equals(defaultCN)) {
                 return true;
             }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 6db8ea7..fc84e13 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -70,6 +70,7 @@
 import static android.os.PowerExemptionManager.REASON_OPT_OUT_REQUESTED;
 import static android.os.PowerExemptionManager.REASON_OP_ACTIVATE_PLATFORM_VPN;
 import static android.os.PowerExemptionManager.REASON_OP_ACTIVATE_VPN;
+import static android.os.PowerExemptionManager.REASON_OTHER;
 import static android.os.PowerExemptionManager.REASON_PACKAGE_INSTALLER;
 import static android.os.PowerExemptionManager.REASON_PROC_STATE_PERSISTENT;
 import static android.os.PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI;
@@ -85,7 +86,6 @@
 import static android.os.PowerExemptionManager.REASON_SYSTEM_UID;
 import static android.os.PowerExemptionManager.REASON_TEMP_ALLOWED_WHILE_IN_USE;
 import static android.os.PowerExemptionManager.REASON_UID_VISIBLE;
-import static android.os.PowerExemptionManager.REASON_UNKNOWN;
 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
 import static android.os.PowerExemptionManager.getReasonCodeFromProcState;
 import static android.os.PowerExemptionManager.reasonCodeToString;
@@ -621,7 +621,8 @@
                     try {
                         final ServiceRecord.StartItem si = r.pendingStarts.get(0);
                         startServiceInnerLocked(this, si.intent, r, false, true, si.callingId,
-                                si.mCallingProcessName, r.startRequested, si.mCallingPackageName);
+                                si.mCallingProcessName, si.mCallingProcessState,
+                                r.startRequested, si.mCallingPackageName);
                     } catch (TransactionTooLargeException e) {
                         // Ignore, nobody upstack cares.
                     }
@@ -977,10 +978,22 @@
             fgRequired = false;
         }
 
+        final ProcessRecord callingApp;
+        synchronized (mAm.mPidsSelfLocked) {
+            callingApp = mAm.mPidsSelfLocked.get(callingPid);
+        }
+        final String callingProcessName = callingApp != null
+                ? callingApp.processName : callingPackage;
+        final int callingProcessState =
+                callingApp != null && callingApp.getThread() != null && !callingApp.isKilled()
+                ? callingApp.mState.getCurProcState() : ActivityManager.PROCESS_STATE_UNKNOWN;
+        r.updateProcessStateOnRequest();
+
         // The package could be frozen (meaning it's doing surgery), defer the actual
         // start until the package is unfrozen.
         if (deferServiceBringupIfFrozenLocked(r, service, callingPackage, callingFeatureId,
-                callingUid, callingPid, fgRequired, callerFg, userId,
+                callingUid, callingPid, callingProcessName,
+                callingProcessState, fgRequired, callerFg, userId,
                 backgroundStartPrivileges, false, null)) {
             return null;
         }
@@ -1001,7 +1014,7 @@
         // what realResult contains.
         final ComponentName realResult =
                 startServiceInnerLocked(r, service, callingUid, callingPid,
-                        getCallingProcessNameLocked(callingUid, callingPid, callingPackage),
+                        callingProcessName, callingProcessState,
                         fgRequired, callerFg,
                         backgroundStartPrivileges, callingPackage);
         if (res.aliasComponent != null
@@ -1013,17 +1026,9 @@
         }
     }
 
-    private String getCallingProcessNameLocked(int callingUid, int callingPid,
-            String callingPackage) {
-        synchronized (mAm.mPidsSelfLocked) {
-            final ProcessRecord callingApp = mAm.mPidsSelfLocked.get(callingPid);
-            return callingApp != null ? callingApp.processName : callingPackage;
-        }
-    }
-
     private ComponentName startServiceInnerLocked(ServiceRecord r, Intent service,
-            int callingUid, int callingPid, String callingProcessName, boolean fgRequired,
-            boolean callerFg,
+            int callingUid, int callingPid, String callingProcessName,
+            int callingProcessState, boolean fgRequired, boolean callerFg,
             BackgroundStartPrivileges backgroundStartPrivileges, String callingPackage)
             throws TransactionTooLargeException {
         NeededUriGrants neededGrants = mAm.mUgmInternal.checkGrantUriPermissionFromIntent(
@@ -1037,7 +1042,8 @@
         r.delayedStop = false;
         r.fgRequired = fgRequired;
         r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
-                service, neededGrants, callingUid, callingProcessName, callingPackage));
+                service, neededGrants, callingUid, callingProcessName, callingPackage,
+                callingProcessState));
 
         // We want to allow scheduling user-initiated jobs when the app is running a
         // foreground service that was started in the same conditions that allows for scheduling
@@ -1140,7 +1146,8 @@
             r.allowBgActivityStartsOnServiceStart(backgroundStartPrivileges);
         }
         ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting,
-                callingUid, callingProcessName, wasStartRequested, callingPackage);
+                callingUid, callingProcessName, callingProcessState,
+                wasStartRequested, callingPackage);
         return cmp;
     }
 
@@ -1244,7 +1251,8 @@
     @GuardedBy("mAm")
     private boolean deferServiceBringupIfFrozenLocked(ServiceRecord s, Intent serviceIntent,
             String callingPackage, @Nullable String callingFeatureId,
-            int callingUid, int callingPid, boolean fgRequired, boolean callerFg, int userId,
+            int callingUid, int callingPid, String callingProcessName,
+            int callingProcessState, boolean fgRequired, boolean callerFg, int userId,
             BackgroundStartPrivileges backgroundStartPrivileges,
             boolean isBinding, IServiceConnection connection) {
         final PackageManagerInternal pm = mAm.getPackageManagerInternal();
@@ -1258,8 +1266,6 @@
             curPendingBringups = new ArrayList<>();
             mPendingBringups.put(s, curPendingBringups);
         }
-        final String callingProcessName = getCallingProcessNameLocked(
-                callingUid, callingPid, callingPackage);
         curPendingBringups.add(new Runnable() {
             @Override
             public void run() {
@@ -1291,7 +1297,7 @@
                     } else { // Starting a service
                         try {
                             startServiceInnerLocked(s, serviceIntent, callingUid, callingPid,
-                                    callingProcessName, fgRequired, callerFg,
+                                    callingProcessName, callingProcessState, fgRequired, callerFg,
                                     backgroundStartPrivileges, callingPackage);
                         } catch (TransactionTooLargeException e) {
                             /* ignore - local call */
@@ -1338,7 +1344,8 @@
 
     ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
             boolean callerFg, boolean addToStarting, int callingUid, String callingProcessName,
-            boolean wasStartRequested, String callingPackage) throws TransactionTooLargeException {
+            int callingProcessState, boolean wasStartRequested, String callingPackage)
+            throws TransactionTooLargeException {
         synchronized (mAm.mProcessStats.mLock) {
             final ServiceState stracker = r.getTracker();
             if (stracker != null) {
@@ -1381,7 +1388,9 @@
                 getShortServiceNameForStats(r),
                 packageState,
                 packageName,
-                callingPackage);
+                callingPackage,
+                callingProcessState,
+                r.mProcessStateOnRequest);
 
         if (r.startRequested && addToStarting) {
             boolean first = smap.mStartingBackground.size() == 0;
@@ -2156,9 +2165,7 @@
                         }
                     }
 
-                    final boolean fgsTypeChangingFromShortFgs = r.isForeground && isOldTypeShortFgs;
-
-                    if (fgsTypeChangingFromShortFgs) {
+                    if (r.isForeground && isOldTypeShortFgs) {
 
                         // If we get here, that means startForeground(SHORT_SERVICE) is called again
                         // on a SHORT_SERVICE FGS.
@@ -2211,9 +2218,7 @@
                                 // "if (r.mAllowStartForeground == REASON_DENIED...)" block below.
                             }
                         }
-                    }
-
-                    if (!fgsTypeChangingFromShortFgs && r.mStartForegroundCount == 0) {
+                    } else if (r.mStartForegroundCount == 0) {
                         /*
                         If the service was started with startService(), not
                         startForegroundService(), and if startForeground() isn't called within
@@ -2244,7 +2249,7 @@
                                 r.mLoggedInfoAllowStartForeground = false;
                             }
                         }
-                    } else if (!fgsTypeChangingFromShortFgs && r.mStartForegroundCount >= 1) {
+                    } else if (r.mStartForegroundCount >= 1) {
                         // We get here if startForeground() is called multiple times
                         // on the same service after it's created, regardless of whether
                         // stopForeground() has been called or not.
@@ -3615,11 +3620,22 @@
             return 0;
         }
 
+        final ProcessRecord callingApp;
+        synchronized (mAm.mPidsSelfLocked) {
+            callingApp = mAm.mPidsSelfLocked.get(callingPid);
+        }
+        final String callingProcessName = callingApp != null
+                ? callingApp.processName : callingPackage;
+        final int callingProcessState =
+                callingApp != null && callingApp.getThread() != null && !callingApp.isKilled()
+                ? callingApp.mState.getCurProcState() : ActivityManager.PROCESS_STATE_UNKNOWN;
+        s.updateProcessStateOnRequest();
+
         // The package could be frozen (meaning it's doing surgery), defer the actual
         // binding until the package is unfrozen.
         boolean packageFrozen = deferServiceBringupIfFrozenLocked(s, service, callingPackage, null,
-                callingUid, callingPid, false, callerFg, userId, BackgroundStartPrivileges.NONE,
-                true, connection);
+                callingUid, callingPid, callingProcessName, callingProcessState,
+                false, callerFg, userId, BackgroundStartPrivileges.NONE, true, connection);
 
         // If permissions need a review before any of the app components can run,
         // we schedule binding to the service but do not start its process, then
@@ -3760,7 +3776,9 @@
                     getShortServiceNameForStats(s),
                     packageState,
                     s.packageName,
-                    callerApp.info.packageName);
+                    callerApp.info.packageName,
+                    callerApp.mState.getCurProcState(),
+                    s.mProcessStateOnRequest);
 
             if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
                     + ": received=" + b.intent.received
@@ -5359,7 +5377,7 @@
         // be called.
         if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
             r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
-                    null, null, 0, null, null));
+                    null, null, 0, null, null, ActivityManager.PROCESS_STATE_UNKNOWN));
         }
 
         sendServiceArgsLocked(r, execInFg, true);
@@ -6355,7 +6373,8 @@
                     stopServiceLocked(sr, true);
                 } else {
                     sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
-                            sr.getLastStartId(), baseIntent, null, 0, null, null));
+                            sr.getLastStartId(), baseIntent, null, 0, null, null,
+                            ActivityManager.PROCESS_STATE_UNKNOWN));
                     if (sr.app != null && sr.app.getThread() != null) {
                         // We always run in the foreground, since this is called as
                         // part of the "remove task" UI operation.
@@ -7428,33 +7447,30 @@
             boolean isStartService) {
         // Check DeviceConfig flag.
         if (!mAm.mConstants.mFlagBackgroundFgsStartRestrictionEnabled) {
+            if (!r.mAllowWhileInUsePermissionInFgs) {
+                // BGFGS start restrictions are disabled. We're allowing while-in-use permissions.
+                // Note REASON_OTHER since there's no other suitable reason.
+                r.mAllowWhileInUsePermissionInFgsReason = REASON_OTHER;
+            }
             r.mAllowWhileInUsePermissionInFgs = true;
         }
 
-        final @ReasonCode int allowWhileInUse;
-
-        // Either (or both) mAllowWhileInUsePermissionInFgs or mAllowStartForeground is
-        // newly allowed?
-        boolean newlyAllowed = false;
         if (!r.mAllowWhileInUsePermissionInFgs
                 || (r.mAllowStartForeground == REASON_DENIED)) {
-            allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked(
-                    callingPackage, callingPid, callingUid, r.app, backgroundStartPrivileges,
-                    isBindService);
+            @ReasonCode final int allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked(
+                    callingPackage, callingPid, callingUid, r.app, backgroundStartPrivileges);
             // We store them to compare the old and new while-in-use logics to each other.
             // (They're not used for any other purposes.)
             if (!r.mAllowWhileInUsePermissionInFgs) {
                 r.mAllowWhileInUsePermissionInFgs = (allowWhileInUse != REASON_DENIED);
+                r.mAllowWhileInUsePermissionInFgsReason = allowWhileInUse;
             }
             if (r.mAllowStartForeground == REASON_DENIED) {
                 r.mAllowStartForeground = shouldAllowFgsStartForegroundWithBindingCheckLocked(
                         allowWhileInUse, callingPackage, callingPid, callingUid, intent, r,
                         backgroundStartPrivileges, isBindService);
             }
-        } else {
-            allowWhileInUse = REASON_UNKNOWN;
         }
-        r.mAllowWhileInUsePermissionInFgsReason = allowWhileInUse;
     }
 
     /**
@@ -7476,7 +7492,7 @@
         }
         final @ReasonCode int allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked(
                 callingPackage, callingPid, callingUid, null /* targetProcess */,
-                BackgroundStartPrivileges.NONE, false);
+                BackgroundStartPrivileges.NONE);
         @ReasonCode int allowStartFgs = shouldAllowFgsStartForegroundNoBindingCheckLocked(
                 allowWhileInUse, callingPid, callingUid, callingPackage, null /* targetService */,
                 BackgroundStartPrivileges.NONE);
@@ -7500,19 +7516,15 @@
      */
     private @ReasonCode int shouldAllowFgsWhileInUsePermissionLocked(String callingPackage,
             int callingPid, int callingUid, @Nullable ProcessRecord targetProcess,
-            BackgroundStartPrivileges backgroundStartPrivileges, boolean isBindService) {
+            BackgroundStartPrivileges backgroundStartPrivileges) {
         int ret = REASON_DENIED;
 
-        final boolean forStartForeground = !isBindService;
-
-        if (forStartForeground) {
-            final int uidState = mAm.getUidStateLocked(callingUid);
-            if (ret == REASON_DENIED) {
-                // Allow FGS while-in-use if the caller's process state is PROCESS_STATE_PERSISTENT,
-                // PROCESS_STATE_PERSISTENT_UI or PROCESS_STATE_TOP.
-                if (uidState <= PROCESS_STATE_TOP) {
-                    ret = getReasonCodeFromProcState(uidState);
-                }
+        final int uidState = mAm.getUidStateLocked(callingUid);
+        if (ret == REASON_DENIED) {
+            // Allow FGS while-in-use if the caller's process state is PROCESS_STATE_PERSISTENT,
+            // PROCESS_STATE_PERSISTENT_UI or PROCESS_STATE_TOP.
+            if (uidState <= PROCESS_STATE_TOP) {
+                ret = getReasonCodeFromProcState(uidState);
             }
         }
 
@@ -7733,7 +7745,7 @@
                                         shouldAllowFgsWhileInUsePermissionLocked(
                                                 clientPackageName,
                                                 clientPid, clientUid, null /* targetProcess */,
-                                                BackgroundStartPrivileges.NONE, false);
+                                                BackgroundStartPrivileges.NONE);
                                 final @ReasonCode int allowStartFgs =
                                         shouldAllowFgsStartForegroundNoBindingCheckLocked(
                                                 allowWhileInUse2,
@@ -8162,7 +8174,7 @@
             String callingPackage) {
         return shouldAllowFgsWhileInUsePermissionLocked(callingPackage, callingPid, callingUid,
                 /* targetProcess */ null,
-                BackgroundStartPrivileges.NONE, false)
+                BackgroundStartPrivileges.NONE)
                 != REASON_DENIED;
     }
 
@@ -8170,7 +8182,7 @@
             String callingPackage, @Nullable ProcessRecord targetProcess,
             @NonNull BackgroundStartPrivileges backgroundStartPrivileges) {
         return shouldAllowFgsWhileInUsePermissionLocked(callingPackage, callingPid, callingUid,
-                targetProcess, backgroundStartPrivileges, false) != REASON_DENIED;
+                targetProcess, backgroundStartPrivileges) != REASON_DENIED;
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5c1dad9..824299b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1176,20 +1176,24 @@
         public Intent intent;
         public boolean deferUntilActive;
         public int originalCallingUid;
+        /** The snapshot process state of the app who sent this broadcast */
+        public int originalCallingAppProcessState;
 
         public static StickyBroadcast create(Intent intent, boolean deferUntilActive,
-                int originalCallingUid) {
+                int originalCallingUid, int originalCallingAppProcessState) {
             final StickyBroadcast b = new StickyBroadcast();
             b.intent = intent;
             b.deferUntilActive = deferUntilActive;
             b.originalCallingUid = originalCallingUid;
+            b.originalCallingAppProcessState = originalCallingAppProcessState;
             return b;
         }
 
         @Override
         public String toString() {
             return "{intent=" + intent + ", defer=" + deferUntilActive + ", originalCallingUid="
-                    + originalCallingUid + "}";
+                    + originalCallingUid + ", originalCallingAppProcessState="
+                    + originalCallingAppProcessState + "}";
         }
     }
 
@@ -1616,6 +1620,8 @@
     static final int SERVICE_SHORT_FGS_PROCSTATE_TIMEOUT_MSG = 77;
     static final int SERVICE_SHORT_FGS_ANR_TIMEOUT_MSG = 78;
     static final int UPDATE_CACHED_APP_HIGH_WATERMARK = 79;
+    static final int ADD_UID_TO_OBSERVER_MSG = 80;
+    static final int REMOVE_UID_FROM_OBSERVER_MSG = 81;
 
     static final int FIRST_BROADCAST_QUEUE_MSG = 200;
 
@@ -1774,6 +1780,12 @@
                 case PUSH_TEMP_ALLOWLIST_UI_MSG: {
                     pushTempAllowlist();
                 } break;
+                case ADD_UID_TO_OBSERVER_MSG: {
+                    mUidObserverController.addUidToObserverImpl((IBinder) msg.obj, msg.arg1);
+                } break;
+                case REMOVE_UID_FROM_OBSERVER_MSG: {
+                    mUidObserverController.removeUidFromObserverImpl((IBinder) msg.obj, msg.arg1);
+                } break;
             }
         }
     }
@@ -13785,7 +13797,8 @@
                         if (action.startsWith("android.intent.action.USER_")
                                 || action.startsWith("android.intent.action.PACKAGE_")
                                 || action.startsWith("android.intent.action.UID_")
-                                || action.startsWith("android.intent.action.EXTERNAL_")) {
+                                || action.startsWith("android.intent.action.EXTERNAL_")
+                                || action.startsWith("android.bluetooth.")) {
                             if (DEBUG_BROADCAST) {
                                 Slog.wtf(TAG,
                                         "System internals registering for " + filter.toLongString()
@@ -14033,7 +14046,8 @@
                             receivers, null, null, 0, null, null, false, true, true, -1,
                             originalStickyCallingUid, BackgroundStartPrivileges.NONE,
                             false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */,
-                            null /* filterExtrasForReceiver */);
+                            null /* filterExtrasForReceiver */,
+                            broadcast.originalCallingAppProcessState);
                     queue.enqueueBroadcastLocked(r);
                 }
             }
@@ -14848,6 +14862,7 @@
             }
         }
 
+        final int callerAppProcessState = getRealProcessStateLocked(callerApp, realCallingPid);
         // Add to the sticky list if requested.
         if (sticky) {
             if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
@@ -14910,12 +14925,13 @@
                 if (intent.filterEquals(list.get(i).intent)) {
                     // This sticky already exists, replace it.
                     list.set(i, StickyBroadcast.create(new Intent(intent), deferUntilActive,
-                            callingUid));
+                            callingUid, callerAppProcessState));
                     break;
                 }
             }
             if (i >= stickiesCount) {
-                list.add(StickyBroadcast.create(new Intent(intent), deferUntilActive, callingUid));
+                list.add(StickyBroadcast.create(new Intent(intent), deferUntilActive, callingUid,
+                        callerAppProcessState));
             }
         }
 
@@ -14998,7 +15014,8 @@
                     requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
                     registeredReceivers, resultToApp, resultTo, resultCode, resultData,
                     resultExtras, ordered, sticky, false, userId,
-                    backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver);
+                    backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver,
+                    callerAppProcessState);
             if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
             queue.enqueueBroadcastLocked(r);
             registeredReceivers = null;
@@ -15092,7 +15109,8 @@
                     requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
                     receivers, resultToApp, resultTo, resultCode, resultData, resultExtras,
                     ordered, sticky, false, userId,
-                    backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver);
+                    backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver,
+                    callerAppProcessState);
 
             if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r);
             queue.enqueueBroadcastLocked(r);
@@ -15109,6 +15127,19 @@
         return ActivityManager.BROADCAST_SUCCESS;
     }
 
+    @GuardedBy("this")
+    private int getRealProcessStateLocked(ProcessRecord app, int pid) {
+        if (app == null) {
+            synchronized (mPidsSelfLocked) {
+                app = mPidsSelfLocked.get(pid);
+            }
+        }
+        if (app != null && app.getThread() != null && !app.isKilled()) {
+            return app.mState.getCurProcState();
+        }
+        return PROCESS_STATE_NONEXISTENT;
+    }
+
     @VisibleForTesting
     ArrayList<StickyBroadcast> getStickyBroadcasts(String action, int userId) {
         final ArrayMap<String, ArrayList<StickyBroadcast>> stickyBroadcasts =
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
index 0b5b1cb..a80ad59 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -25,6 +25,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UptimeMillisLong;
+import android.app.BroadcastOptions;
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
 import android.os.SystemClock;
@@ -105,6 +106,12 @@
     long lastCpuDelayTime;
 
     /**
+     * Snapshotted value of {@link ProcessStateRecord#getCurProcState()} before
+     * dispatching the current broadcast to the receiver in this process.
+     */
+    int lastProcessState;
+
+    /**
      * Ordered collection of broadcasts that are waiting to be dispatched to
      * this process, as a pair of {@link BroadcastRecord} and the index into
      * {@link BroadcastRecord#receivers} that represents the receiver.
@@ -257,7 +264,10 @@
             deferredStatesApplyConsumer.accept(record, recordIndex);
         }
 
-        if (record.isReplacePending()) {
+        // Ignore FLAG_RECEIVER_REPLACE_PENDING if the sender specified the policy using the
+        // BroadcastOptions delivery group APIs.
+        if (record.isReplacePending()
+                && record.getDeliveryGroupPolicy() == BroadcastOptions.DELIVERY_GROUP_POLICY_ALL) {
             final BroadcastRecord replacedBroadcastRecord = replaceBroadcast(record, recordIndex);
             if (replacedBroadcastRecord != null) {
                 return replacedBroadcastRecord;
diff --git a/services/core/java/com/android/server/am/BroadcastQueueImpl.java b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
index f6004d7..f13dc89 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
@@ -269,7 +269,10 @@
                                 Activity.RESULT_CANCELED, null, null,
                                 false, false, oldRecord.shareIdentity, oldRecord.userId,
                                 oldRecord.callingUid, r.callingUid, r.callerPackage,
-                                SystemClock.uptimeMillis() - oldRecord.enqueueTime, 0);
+                                SystemClock.uptimeMillis() - oldRecord.enqueueTime, 0, 0,
+                                oldRecord.resultToApp != null
+                                        ? oldRecord.resultToApp.mState.getCurProcState()
+                                        : ActivityManager.PROCESS_STATE_UNKNOWN);
                     } catch (RemoteException e) {
                         Slog.w(TAG, "Failure ["
                                 + mQueueName + "] sending broadcast result of "
@@ -339,7 +342,7 @@
     private BroadcastRecord replaceBroadcastLocked(ArrayList<BroadcastRecord> queue,
             BroadcastRecord r, String typeForLogging) {
         final Intent intent = r.intent;
-        for (int i = queue.size() - 1; i > 0; i--) {
+        for (int i = queue.size() - 1; i >= 0; i--) {
             final BroadcastRecord old = queue.get(i);
             if (old.userId == r.userId && intent.filterEquals(old.intent)) {
                 if (DEBUG_BROADCAST) {
@@ -367,6 +370,7 @@
         }
 
         r.curApp = app;
+        r.curAppLastProcessState = app.mState.getCurProcState();
         final ProcessReceiverRecord prr = app.mReceivers;
         prr.addCurReceiver(r);
         app.mState.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
@@ -418,6 +422,7 @@
                 if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                         "Process cur broadcast " + r + ": NOT STARTED!");
                 r.curApp = null;
+                r.curAppLastProcessState = ActivityManager.PROCESS_STATE_UNKNOWN;
                 prr.removeCurReceiver(r);
             }
         }
@@ -617,7 +622,11 @@
                     r.curApp.info.packageName,
                     r.callerPackage,
                     r.calculateTypeForLogging(),
-                    r.getDeliveryGroupPolicy());
+                    r.getDeliveryGroupPolicy(),
+                    r.intent.getFlags(),
+                    BroadcastRecord.getReceiverPriority(curReceiver),
+                    r.callerProcState,
+                    r.curAppLastProcessState);
         }
         if (state == BroadcastRecord.IDLE) {
             Slog.w(TAG_BROADCAST, "finishReceiver [" + mQueueName + "] called but state is IDLE");
@@ -679,6 +688,7 @@
         r.curFilter = null;
         r.curReceiver = null;
         r.curApp = null;
+        r.curAppLastProcessState = ActivityManager.PROCESS_STATE_UNKNOWN;
         r.curFilteredExtras = null;
         r.mWasReceiverAppStopped = false;
         mPendingBroadcast = null;
@@ -748,7 +758,8 @@
             Intent intent, int resultCode, String data, Bundle extras,
             boolean ordered, boolean sticky, boolean shareIdentity, int sendingUser,
             int receiverUid, int callingUid, String callingPackage,
-            long dispatchDelay, long receiveDelay) throws RemoteException {
+            long dispatchDelay, long receiveDelay, int priority,
+            int receiverProcessState) throws RemoteException {
         // If the broadcaster opted-in to sharing their identity, then expose package visibility for
         // the receiver.
         if (shareIdentity) {
@@ -798,7 +809,8 @@
                     dispatchDelay, receiveDelay, 0 /* finish_delay */,
                     SERVICE_REQUEST_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL,
                     app != null ? app.info.packageName : null, callingPackage,
-                    r.calculateTypeForLogging(), r.getDeliveryGroupPolicy());
+                    r.calculateTypeForLogging(), r.getDeliveryGroupPolicy(), r.intent.getFlags(),
+                    priority, r.callerProcState, receiverProcessState);
         }
     }
 
@@ -845,6 +857,7 @@
                 // things that directly call the IActivityManager API, which
                 // are already core system stuff so don't matter for this.
                 r.curApp = filter.receiverList.app;
+                r.curAppLastProcessState = r.curApp.mState.getCurProcState();
                 filter.receiverList.app.mReceivers.addCurReceiver(r);
                 mService.enqueueOomAdjTargetLocked(r.curApp);
                 mService.updateOomAdjPendingTargetsLocked(
@@ -879,7 +892,10 @@
                         r.resultExtras, r.ordered, r.initialSticky, r.shareIdentity, r.userId,
                         filter.receiverList.uid, r.callingUid, r.callerPackage,
                         r.dispatchTime - r.enqueueTime,
-                        r.receiverTime - r.dispatchTime);
+                        r.receiverTime - r.dispatchTime, filter.getPriority(),
+                        filter.receiverList.app != null
+                                ? filter.receiverList.app.mState.getCurProcState()
+                                : ActivityManager.PROCESS_STATE_UNKNOWN);
                 // parallel broadcasts are fire-and-forget, not bookended by a call to
                 // finishReceiverLocked(), so we manage their activity-start token here
                 if (filter.receiverList.app != null
@@ -1170,7 +1186,10 @@
                                     r.resultData, r.resultExtras, false, false, r.shareIdentity,
                                     r.userId, r.callingUid, r.callingUid, r.callerPackage,
                                     r.dispatchTime - r.enqueueTime,
-                                    now - r.dispatchTime);
+                                    now - r.dispatchTime, 0,
+                                    r.resultToApp != null
+                                            ? r.resultToApp.mState.getCurProcState()
+                                            : ActivityManager.PROCESS_STATE_UNKNOWN);
                             logBootCompletedBroadcastCompletionLatencyIfPossible(r);
                             // Set this to null so that the reference
                             // (local and remote) isn't kept in the mBroadcastHistory.
@@ -1476,6 +1495,7 @@
                         r.intent.getAction(), r.getHostingRecordTriggerType()),
                 isActivityCapable ? ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE : ZYGOTE_POLICY_FLAG_EMPTY,
                 (r.intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false);
+        r.curAppLastProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
         if (r.curApp == null) {
             // Ah, this recipient is unavailable.  Finish it if necessary,
             // and mark the broadcast record as ready for the next.
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index cbc7540..397eef4 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -719,11 +719,12 @@
     private void skipAndCancelReplacedBroadcasts(ArraySet<BroadcastRecord> replacedBroadcasts) {
         for (int i = 0; i < replacedBroadcasts.size(); ++i) {
             final BroadcastRecord r = replacedBroadcasts.valueAt(i);
-            r.resultCode = Activity.RESULT_CANCELED;
-            r.resultData = null;
-            r.resultExtras = null;
-            scheduleResultTo(r);
-            notifyFinishBroadcast(r);
+            // Skip all the receivers in the replaced broadcast
+            for (int rcvrIdx = 0; rcvrIdx < r.receivers.size(); ++rcvrIdx) {
+                if (!isDeliveryStateTerminal(r.getDeliveryState(rcvrIdx))) {
+                    mBroadcastConsumerSkipAndCanceled.accept(r, rcvrIdx);
+                }
+            }
         }
     }
 
@@ -1001,6 +1002,7 @@
                     mService.mPackageManagerInt.grantImplicitAccess(r.userId, r.intent,
                             UserHandle.getAppId(app.uid), r.callingUid, true);
                 }
+                queue.lastProcessState = app.mState.getCurProcState();
                 if (receiver instanceof BroadcastFilter) {
                     notifyScheduleRegisteredReceiver(app, r, (BroadcastFilter) receiver);
                     thread.scheduleRegisteredReceiver(
@@ -1913,12 +1915,16 @@
                 ? BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__RUNTIME
                 : BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST;
         final int type;
+        final int receiverProcessState;
         if (queue == null) {
             type = BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_UNKNOWN;
+            receiverProcessState = ActivityManager.PROCESS_STATE_UNKNOWN;
         } else if (queue.getActiveViaColdStart()) {
             type = BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD;
+            receiverProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
         } else {
             type = BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM;
+            receiverProcessState = queue.lastProcessState;
         }
         // With the new per-process queues, there's no delay between being
         // "dispatched" and "scheduled", so we report no "receive delay"
@@ -1932,7 +1938,9 @@
             FrameworkStatsLog.write(BROADCAST_DELIVERY_EVENT_REPORTED, uid, senderUid, actionName,
                     receiverType, type, dispatchDelay, receiveDelay, finishDelay, packageState,
                     app != null ? app.info.packageName : null, r.callerPackage,
-                    r.calculateTypeForLogging(), r.getDeliveryGroupPolicy());
+                    r.calculateTypeForLogging(), r.getDeliveryGroupPolicy(), r.intent.getFlags(),
+                    BroadcastRecord.getReceiverPriority(receiver), r.callerProcState,
+                    receiverProcessState);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index cfdb133..198adcb 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -44,6 +44,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UptimeMillisLong;
+import android.app.ActivityManager.ProcessState;
 import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
 import android.app.BackgroundStartPrivileges;
@@ -93,6 +94,7 @@
     final @Nullable String callerFeatureId; // which feature in the package sent this
     final int callingPid;   // the pid of who sent this
     final int callingUid;   // the uid of who sent this
+    final @ProcessState int callerProcState; // Procstate of the caller process at enqueue time.
 
     final int originalStickyCallingUid;
             // if this is a sticky broadcast, the Uid of the original sender
@@ -268,6 +270,8 @@
     BroadcastFilter curFilter;  // the registered receiver currently running.
     Bundle curFilteredExtras;   // the bundle that has been filtered by the package visibility rules
 
+    int curAppLastProcessState; // The last process state of the current receiver before receiving
+
     boolean mIsReceiverAppRunning; // Was the receiver's app already running.
 
     boolean mWasReceiverAppStopped; // Was the receiver app stopped prior to starting
@@ -429,13 +433,14 @@
             boolean initialSticky, int userId,
             @NonNull BackgroundStartPrivileges backgroundStartPrivileges,
             boolean timeoutExempt,
-            @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) {
+            @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver,
+            int callerAppProcessState) {
         this(queue, intent, callerApp, callerPackage, callerFeatureId, callingPid,
                 callingUid, callerInstantApp, resolvedType, requiredPermissions,
                 excludedPermissions, excludedPackages, appOp, options, receivers, resultToApp,
                 resultTo, resultCode, resultData, resultExtras, serialized, sticky,
                 initialSticky, userId, -1, backgroundStartPrivileges, timeoutExempt,
-                filterExtrasForReceiver);
+                filterExtrasForReceiver, callerAppProcessState);
     }
 
     BroadcastRecord(BroadcastQueue _queue,
@@ -450,7 +455,8 @@
             boolean _initialSticky, int _userId, int originalStickyCallingUid,
             @NonNull BackgroundStartPrivileges backgroundStartPrivileges,
             boolean timeoutExempt,
-            @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) {
+            @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver,
+            int callerAppProcessState) {
         if (_intent == null) {
             throw new NullPointerException("Can't construct with a null intent");
         }
@@ -462,6 +468,7 @@
         callerFeatureId = _callerFeatureId;
         callingPid = _callingPid;
         callingUid = _callingUid;
+        callerProcState = callerAppProcessState;
         callerInstantApp = _callerInstantApp;
         callerInstrumented = isCallerInstrumented(_callerApp, _callingUid);
         resolvedType = _resolvedType;
@@ -515,6 +522,7 @@
         callerFeatureId = from.callerFeatureId;
         callingPid = from.callingPid;
         callingUid = from.callingUid;
+        callerProcState = from.callerProcState;
         callerInstantApp = from.callerInstantApp;
         callerInstrumented = from.callerInstrumented;
         ordered = from.ordered;
@@ -600,7 +608,8 @@
                 requiredPermissions, excludedPermissions, excludedPackages, appOp, options,
                 splitReceivers, resultToApp, resultTo, resultCode, resultData, resultExtras,
                 ordered, sticky, initialSticky, userId,
-                mBackgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver);
+                mBackgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver,
+                callerProcState);
         split.enqueueTime = this.enqueueTime;
         split.enqueueRealTime = this.enqueueRealTime;
         split.enqueueClockTime = this.enqueueClockTime;
@@ -680,7 +689,7 @@
                     uid2receiverList.valueAt(i), null /* _resultToApp */, null /* _resultTo */,
                     resultCode, resultData, resultExtras, ordered, sticky, initialSticky, userId,
                     mBackgroundStartPrivileges, timeoutExempt,
-                    filterExtrasForReceiver);
+                    filterExtrasForReceiver, callerProcState);
             br.enqueueTime = this.enqueueTime;
             br.enqueueRealTime = this.enqueueRealTime;
             br.enqueueClockTime = this.enqueueClockTime;
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index e744eee..3f7d8ba 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -246,9 +246,13 @@
                 }
             }
 
+            final int callingProcessState = r != null
+                    ? r.mState.getCurProcState() : ActivityManager.PROCESS_STATE_UNKNOWN;
+
             if (providerRunning) {
                 cpi = cpr.info;
 
+
                 if (r != null && cpr.canRunHere(r)) {
                     checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, checkCrossUser,
                             cpr.name.flattenToShortString(), startTime);
@@ -266,7 +270,8 @@
                             r.uid, callingUid,
                             PROVIDER_ACQUISITION_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM,
                             PROVIDER_ACQUISITION_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL,
-                            cpi.packageName, callingPackage);
+                            cpi.packageName, callingPackage,
+                            callingProcessState, callingProcessState);
                     return holder;
                 }
 
@@ -282,6 +287,8 @@
                 checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, checkCrossUser,
                         cpr.name.flattenToShortString(), startTime);
 
+                final int providerProcessState = cpr.proc.mState.getCurProcState();
+
                 final long origId = Binder.clearCallingIdentity();
                 try {
                     checkTime(startTime, "getContentProviderImpl: incProviderCountLocked");
@@ -338,7 +345,8 @@
                                 cpr.proc.uid, callingUid,
                                 PROVIDER_ACQUISITION_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM,
                                 PROVIDER_ACQUISITION_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL,
-                                cpi.packageName, callingPackage);
+                                cpi.packageName, callingPackage,
+                                callingProcessState, providerProcessState);
                     }
                 } finally {
                     Binder.restoreCallingIdentity(origId);
@@ -516,7 +524,8 @@
                                     proc.uid, callingUid,
                                     PROVIDER_ACQUISITION_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM,
                                     PROVIDER_ACQUISITION_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL,
-                                    cpi.packageName, callingPackage);
+                                    cpi.packageName, callingPackage,
+                                    callingProcessState, proc.mState.getCurProcState());
                         } else {
                             final int packageState =
                                     ((cpr.appInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0)
@@ -541,7 +550,8 @@
                                     PROVIDER_ACQUISITION_EVENT_REPORTED,
                                     proc.uid, callingUid,
                                     PROVIDER_ACQUISITION_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD,
-                                    packageState, cpi.packageName, callingPackage);
+                                    packageState, cpi.packageName, callingPackage,
+                                    callingProcessState, ActivityManager.PROCESS_STATE_NONEXISTENT);
                         }
                         cpr.launchingApp = proc;
                         mLaunchingProviders.add(cpr);
diff --git a/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java b/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java
index 80406e6..38e7371 100644
--- a/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java
+++ b/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java
@@ -113,6 +113,11 @@
         // We use this to get the duration an API was active after
         // the stop call.
         final SparseArray<Long> mLastFgsTimeStamp = new SparseArray<>();
+
+        // A map of API types to first FGS start call timestamps
+        // We use this to get the duration an API was active after
+        // the stop call.
+        final SparseArray<Long> mFirstFgsTimeStamp = new SparseArray<>();
     }
 
     // SparseArray that tracks all UIDs that have made various
@@ -146,6 +151,7 @@
             if (fgsIndex < 0) {
                 uidState.mRunningFgs.put(apiType, new ArrayMap<>());
                 fgsIndex = uidState.mRunningFgs.indexOfKey(apiType);
+                uidState.mFirstFgsTimeStamp.put(apiType, System.currentTimeMillis());
             }
             final ArrayMap<ComponentName, ServiceRecord> fgsList =
                     uidState.mRunningFgs.valueAt(fgsIndex);
@@ -237,7 +243,7 @@
                 // there's no more FGS running for this type, just get rid of it
                 uidState.mRunningFgs.remove(apiType);
                 // but we need to keep track of the timestamp in case an API stops
-                uidState.mLastFgsTimeStamp.put(apiType, record.mFgsExitTime);
+                uidState.mLastFgsTimeStamp.put(apiType, System.currentTimeMillis());
             }
         }
         if (!apisFound.isEmpty()) {
@@ -454,8 +460,17 @@
     public void logFgsApiEvent(ServiceRecord r, int fgsState,
             @FgsApiState int apiState,
             @ForegroundServiceApiType int apiType, long timestamp) {
-        final long apiDurationBeforeFgsStart = r.mFgsEnterTime - timestamp;
-        final long apiDurationAfterFgsEnd = timestamp - r.mFgsExitTime;
+        long apiDurationBeforeFgsStart = r.createRealTime - timestamp;
+        long apiDurationAfterFgsEnd = timestamp - r.mFgsExitTime;
+        UidState uidState = mUids.get(r.appInfo.uid);
+        if (uidState != null) {
+            if (uidState.mFirstFgsTimeStamp.contains(apiType)) {
+                apiDurationBeforeFgsStart = uidState.mFirstFgsTimeStamp.get(apiType) - timestamp;
+            }
+            if (uidState.mLastFgsTimeStamp.contains(apiType)) {
+                apiDurationAfterFgsEnd = timestamp - uidState.mLastFgsTimeStamp.get(apiType);
+            }
+        }
         final int[] apiTypes = new int[1];
         apiTypes[0] = apiType;
         final long[] timeStamps = new long[1];
diff --git a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
index 7841b69..ffe5a6e 100644
--- a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
+++ b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
@@ -18,6 +18,7 @@
 
 import android.annotation.UptimeMillisLong;
 import android.app.ActivityManagerInternal.OomAdjReason;
+import android.util.TimeUtils;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -320,5 +321,8 @@
         pw.print(prefix); pw.print("isFreezeExempt="); pw.print(mFreezeExempt);
         pw.print(" isPendingFreeze="); pw.print(mPendingFreeze);
         pw.print(" " + IS_FROZEN + "="); pw.println(mFrozen);
+        pw.print(prefix); pw.print("earliestFreezableTimeMs=");
+        TimeUtils.formatDuration(mEarliestFreezableTimeMillis, nowUptime, pw);
+        pw.println();
     }
 }
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index d6495c7..267d246 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -669,6 +669,11 @@
         return mOnewayThread;
     }
 
+    @GuardedBy(anyOf = {"mService", "mProcLock"})
+    int getCurProcState() {
+        return mState.getCurProcState();
+    }
+
     @GuardedBy({"mService", "mProcLock"})
     public void makeActive(IApplicationThread thread, ProcessStatsService tracker) {
         mProfile.onProcessActive(thread, tracker);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index dccbb0a..0f5defb 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 import static android.app.PendingIntent.FLAG_IMMUTABLE;
 import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
 import static android.app.ProcessMemoryState.HOSTING_COMPONENT_TYPE_BOUND_SERVICE;
@@ -244,6 +245,11 @@
      */
     long mRestartSchedulingTime;
 
+    /**
+     * The snapshot process state when the service is requested (either start or bind).
+     */
+    int mProcessStateOnRequest;
+
     static class StartItem {
         final ServiceRecord sr;
         final boolean taskRemoved;
@@ -253,6 +259,7 @@
         final Intent intent;
         final NeededUriGrants neededGrants;
         final @Nullable String mCallingPackageName;
+        final int mCallingProcessState;
         long deliveredTime;
         int deliveryCount;
         int doneExecutingCount;
@@ -262,7 +269,8 @@
 
         StartItem(ServiceRecord _sr, boolean _taskRemoved, int _id,
                 Intent _intent, NeededUriGrants _neededGrants, int _callingId,
-                String callingProcessName, @Nullable String callingPackageName) {
+                String callingProcessName, @Nullable String callingPackageName,
+                int callingProcessState) {
             sr = _sr;
             taskRemoved = _taskRemoved;
             id = _id;
@@ -271,6 +279,7 @@
             callingId = _callingId;
             mCallingProcessName = callingProcessName;
             mCallingPackageName = callingPackageName;
+            mCallingProcessState = callingProcessState;
         }
 
         UriPermissionOwner getUriPermissionsLocked() {
@@ -873,6 +882,7 @@
             app.mServices.updateHostingComonentTypeForBindingsLocked();
         }
         app = proc;
+        updateProcessStateOnRequest();
         if (pendingConnectionGroup > 0 && proc != null) {
             final ProcessServiceRecord psr = proc.mServices;
             psr.setConnectionService(this);
@@ -899,6 +909,11 @@
         }
     }
 
+    void updateProcessStateOnRequest() {
+        mProcessStateOnRequest = app != null && app.getThread() != null && !app.isKilled()
+                ? app.mState.getCurProcState() : PROCESS_STATE_NONEXISTENT;
+    }
+
     @NonNull
     ArrayMap<IBinder, ArrayList<ConnectionRecord>> getConnections() {
         return connections;
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 8c227f5..9db9e77 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -72,6 +72,10 @@
             Settings.Global.NATIVE_FLAGS_HEALTH_CHECK_ENABLED,
     };
 
+    // TODO(b/282593625): Move this constant to DeviceConfig module
+    private static final String NAMESPACE_TETHERING_U_OR_LATER_NATIVE =
+            "tethering_u_or_later_native";
+
     // All the flags under the listed DeviceConfig scopes will be synced to native level.
     //
     // NOTE: please grant write permission system property prefix
@@ -106,7 +110,8 @@
         DeviceConfig.NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT,
         DeviceConfig.NAMESPACE_MEMORY_SAFETY_NATIVE_BOOT,
         DeviceConfig.NAMESPACE_MEMORY_SAFETY_NATIVE,
-        DeviceConfig.NAMESPACE_HDMI_CONTROL
+        DeviceConfig.NAMESPACE_HDMI_CONTROL,
+        NAMESPACE_TETHERING_U_OR_LATER_NATIVE
     };
 
     private final String[] mGlobalSettings;
diff --git a/services/core/java/com/android/server/am/UidObserverController.java b/services/core/java/com/android/server/am/UidObserverController.java
index a258208..7eeec32 100644
--- a/services/core/java/com/android/server/am/UidObserverController.java
+++ b/services/core/java/com/android/server/am/UidObserverController.java
@@ -30,6 +30,7 @@
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Message;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -104,40 +105,62 @@
         }
     }
 
-    void addUidToObserver(@NonNull IBinder observerToken, int uid) {
-        synchronized (mLock) {
-            int i = mUidObservers.beginBroadcast();
-            while (i-- > 0) {
-                var reg = (UidObserverRegistration) mUidObservers.getBroadcastCookie(i);
-                if (reg.getToken().equals(observerToken)) {
-                    reg.addUid(uid);
-                    break;
-                }
-
-                if (i == 0) {
-                    Slog.e(TAG_UID_OBSERVERS, "Unable to find UidObserver by token");
-                }
-            }
-            mUidObservers.finishBroadcast();
-        }
+    final void addUidToObserver(@NonNull IBinder observerToken, int uid) {
+        Message msg = Message.obtain(mHandler, ActivityManagerService.ADD_UID_TO_OBSERVER_MSG,
+                uid, /*arg2*/ 0, observerToken);
+        mHandler.sendMessage(msg);
     }
 
-    void removeUidFromObserver(@NonNull IBinder observerToken, int uid) {
-        synchronized (mLock) {
-            int i = mUidObservers.beginBroadcast();
-            while (i-- > 0) {
-                var reg = (UidObserverRegistration) mUidObservers.getBroadcastCookie(i);
-                if (reg.getToken().equals(observerToken)) {
-                    reg.removeUid(uid);
-                    break;
-                }
-
-                if (i == 0) {
-                    Slog.e(TAG_UID_OBSERVERS, "Unable to find UidObserver by token");
-                }
+    /**
+     * Add a uid to the list of uids an observer is interested in. Must be run on the same thread
+     * as mDispatchRunnable.
+     *
+     * @param observerToken The token identifier for a UidObserver
+     * @param uid The uid to add to the list of watched uids
+     */
+    public final void addUidToObserverImpl(@NonNull IBinder observerToken, int uid) {
+        int i = mUidObservers.beginBroadcast();
+        while (i-- > 0) {
+            var reg = (UidObserverRegistration) mUidObservers.getBroadcastCookie(i);
+            if (reg.getToken().equals(observerToken)) {
+                reg.addUid(uid);
+                break;
             }
-            mUidObservers.finishBroadcast();
+
+            if (i == 0) {
+                Slog.e(TAG_UID_OBSERVERS, "Unable to find UidObserver by token");
+            }
         }
+        mUidObservers.finishBroadcast();
+    }
+
+    final void removeUidFromObserver(@NonNull IBinder observerToken, int uid) {
+        Message msg = Message.obtain(mHandler, ActivityManagerService.REMOVE_UID_FROM_OBSERVER_MSG,
+                uid, /*arg2*/ 0, observerToken);
+        mHandler.sendMessage(msg);
+    }
+
+    /**
+     * Remove a uid from the list of uids an observer is interested in. Must be run on the same
+     * thread as mDispatchRunnable.
+     *
+     * @param observerToken The token identifier for a UidObserver
+     * @param uid The uid to remove from the list of watched uids
+     */
+    public final void removeUidFromObserverImpl(@NonNull IBinder observerToken, int uid) {
+        int i = mUidObservers.beginBroadcast();
+        while (i-- > 0) {
+            var reg = (UidObserverRegistration) mUidObservers.getBroadcastCookie(i);
+            if (reg.getToken().equals(observerToken)) {
+                reg.removeUid(uid);
+                break;
+            }
+
+            if (i == 0) {
+                Slog.e(TAG_UID_OBSERVERS, "Unable to find UidObserver by token");
+            }
+        }
+        mUidObservers.finishBroadcast();
     }
 
     int enqueueUidChange(@Nullable ChangeRecord currentRecord, int uid, int change, int procState,
@@ -429,21 +452,23 @@
                 }
             }
 
-            pw.println();
-            pw.print("  mUidChangeDispatchCount=");
-            pw.print(mUidChangeDispatchCount);
-            pw.println();
-            pw.println("  Slow UID dispatches:");
-            for (int i = 0; i < count; i++) {
-                final UidObserverRegistration reg = (UidObserverRegistration)
-                        mUidObservers.getRegisteredCallbackCookie(i);
-                pw.print("    ");
-                pw.print(mUidObservers.getRegisteredCallbackItem(i).getClass().getTypeName());
-                pw.print(": ");
-                pw.print(reg.mSlowDispatchCount);
-                pw.print(" / Max ");
-                pw.print(reg.mMaxDispatchTime);
-                pw.println("ms");
+            if (dumpPackage == null) {
+                pw.println();
+                pw.print("  mUidChangeDispatchCount=");
+                pw.print(mUidChangeDispatchCount);
+                pw.println();
+                pw.println("  Slow UID dispatches:");
+                for (int i = 0; i < count; i++) {
+                    final UidObserverRegistration reg = (UidObserverRegistration)
+                            mUidObservers.getRegisteredCallbackCookie(i);
+                    pw.print("    ");
+                    pw.print(mUidObservers.getRegisteredCallbackItem(i).getClass().getTypeName());
+                    pw.print(": ");
+                    pw.print(reg.mSlowDispatchCount);
+                    pw.print(" / Max ");
+                    pw.print(reg.mMaxDispatchTime);
+                    pw.println("ms");
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index b86da88..fc72a77 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -2210,10 +2210,11 @@
                 mDeviceInventory.setPreferredDevicesForStrategyInt(
                         mAccessibilityStrategyId, Arrays.asList(defaultDevice));
             } else {
-                mDeviceInventory.removePreferredDevicesForStrategInt(mCommunicationStrategyId);
-                mDeviceInventory.removePreferredDevicesForStrategInt(mAccessibilityStrategyId);
+                mDeviceInventory.removePreferredDevicesForStrategyInt(mCommunicationStrategyId);
+                mDeviceInventory.removePreferredDevicesForStrategyInt(mAccessibilityStrategyId);
             }
             mDeviceInventory.applyConnectedDevicesRoles();
+            mDeviceInventory.reapplyExternalDevicesRoles();
         } else {
             mDeviceInventory.setPreferredDevicesForStrategyInt(
                     mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice));
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 7b2e732..219dda3 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -361,23 +361,34 @@
                         AudioSystem.DEVICE_STATE_AVAILABLE,
                         di.mDeviceCodecFormat);
             }
-            mAppliedStrategyRoles.clear();
             mAppliedStrategyRolesInt.clear();
-            mAppliedPresetRoles.clear();
             mAppliedPresetRolesInt.clear();
             applyConnectedDevicesRoles_l();
         }
+        reapplyExternalDevicesRoles();
+    }
+
+    /*package*/ void reapplyExternalDevicesRoles() {
+        synchronized (mDevicesLock) {
+            mAppliedStrategyRoles.clear();
+            mAppliedPresetRoles.clear();
+        }
         synchronized (mPreferredDevices) {
             mPreferredDevices.forEach((strategy, devices) -> {
-                setPreferredDevicesForStrategy(strategy, devices); });
+                setPreferredDevicesForStrategy(strategy, devices);
+            });
         }
         synchronized (mNonDefaultDevices) {
             mNonDefaultDevices.forEach((strategy, devices) -> {
                 addDevicesRoleForStrategy(strategy, AudioSystem.DEVICE_ROLE_DISABLED,
-                        devices, false /* internal */); });
+                        devices, false /* internal */);
+            });
         }
         synchronized (mPreferredDevicesForCapturePreset) {
-            // TODO: call audiosystem to restore
+            mPreferredDevicesForCapturePreset.forEach((capturePreset, devices) -> {
+                setDevicesRoleForCapturePreset(
+                        capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
+            });
         }
     }
 
@@ -823,7 +834,7 @@
         return status;
     }
     // Only used for internal requests
-    /*package*/ int removePreferredDevicesForStrategInt(int strategy) {
+    /*package*/ int removePreferredDevicesForStrategyInt(int strategy) {
         return clearDevicesRoleForStrategy(
                     strategy, AudioSystem.DEVICE_ROLE_PREFERRED, true /*internal */);
     }
@@ -1163,6 +1174,7 @@
             return mAudioSystem.removeDevicesRoleForStrategy(s, r, d); });
         purgeRoles(mAppliedPresetRolesInt, (p, r, d) -> {
             return mAudioSystem.removeDevicesRoleForCapturePreset(p, r, d); });
+        reapplyExternalDevicesRoles();
     }
 
     @GuardedBy("mDevicesLock")
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d0b6cdc..ac03c82 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1368,6 +1368,7 @@
         intentFilter.addAction(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
         intentFilter.addAction(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
         intentFilter.addAction(ACTION_CHECK_MUSIC_ACTIVE);
+        intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
 
         mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null,
                 Context.RECEIVER_EXPORTED);
@@ -3277,6 +3278,7 @@
             if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
                 streamType = mVolumeControlStream;
             } else {
+                // TODO discard activity on a muted stream?
                 final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
                 final boolean activeForReal;
                 if (maybeActiveStreamType == AudioSystem.STREAM_RING
@@ -3480,9 +3482,10 @@
             }
         } else if (isStreamMutedByRingerOrZenMode(streamTypeAlias) && streamState.mIsMuted) {
             // if the stream is currently muted streams by ringer/zen mode
-            // then it cannot be unmuted (without FLAG_ALLOW_RINGER_MODES)
+            // then it cannot be unmuted (without FLAG_ALLOW_RINGER_MODES) with an unmute or raise
             if (direction == AudioManager.ADJUST_TOGGLE_MUTE
-                    || direction == AudioManager.ADJUST_UNMUTE) {
+                    || direction == AudioManager.ADJUST_UNMUTE
+                    || direction == AudioManager.ADJUST_RAISE) {
                 adjustVolume = false;
             }
         }
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
index aa5f9fa..7fa4d6c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
@@ -573,7 +573,7 @@
         final BiometricSchedulerOperation operation = mCurrentOperation;
         mHandler.postDelayed(() -> {
             if (operation == mCurrentOperation) {
-                Counter.logIncrement("biometric.scheduler_watchdog_triggered_count");
+                Counter.logIncrement("biometric.value_scheduler_watchdog_triggered_count");
                 clearScheduler();
             }
         }, 10000);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
index 44ae454..c212e8e 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
@@ -19,6 +19,7 @@
 import static com.android.server.inputmethod.InputMethodManagerService.DEBUG;
 import static com.android.server.inputmethod.InputMethodUtils.NOT_A_SUBTYPE_ID;
 
+import android.annotation.Nullable;
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -65,8 +66,8 @@
     private boolean mShowImeWithHardKeyboard;
 
     @GuardedBy("ImfLock.class")
-    private final InputMethodDialogWindowContext mDialogWindowContext =
-            new InputMethodDialogWindowContext();
+    @Nullable
+    private InputMethodDialogWindowContext mDialogWindowContext;
 
     InputMethodMenuController(InputMethodManagerService service) {
         mService = service;
@@ -124,11 +125,13 @@
                 }
             }
 
+            if (mDialogWindowContext == null) {
+                mDialogWindowContext = new InputMethodDialogWindowContext();
+            }
             final Context dialogWindowContext = mDialogWindowContext.get(displayId);
             mDialogBuilder = new AlertDialog.Builder(dialogWindowContext);
             mDialogBuilder.setOnCancelListener(dialog -> hideInputMethodMenu());
 
-            // TODO(b/277061090): refactor UI components should not be created while holding a lock.
             final Context dialogContext = mDialogBuilder.getContext();
             final TypedArray a = dialogContext.obtainStyledAttributes(null,
                     com.android.internal.R.styleable.DialogPreference,
@@ -196,11 +199,10 @@
             attrs.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
             attrs.setTitle("Select input method");
             w.setAttributes(attrs);
-            // TODO(b/277062834) decouple/remove dependency on IMMS
             mService.updateSystemUiLocked();
             mService.sendOnNavButtonFlagsChangedLocked();
+            mSwitchingDialog.show();
         }
-        mSwitchingDialog.show();
     }
 
     private boolean isScreenLocked() {
@@ -274,7 +276,6 @@
         private final int mTextViewResourceId;
         private final List<ImeSubtypeListItem> mItemsList;
         public int mCheckedItem;
-
         private ImeSubtypeListAdapter(Context context, int textViewResourceId,
                 List<ImeSubtypeListItem> itemsList, int checkedItem) {
             super(context, textViewResourceId, itemsList);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
old mode 100755
new mode 100644
index e56eba6..b39e860
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -119,6 +119,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 
 import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.ALLOW_DISMISS_ONGOING;
+import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.WAKE_LOCK_FOR_POSTING_NOTIFICATION;
 import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
@@ -223,6 +224,8 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -234,6 +237,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.VibrationEffect;
+import android.os.WorkSource;
 import android.permission.PermissionManager;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
@@ -559,6 +563,7 @@
     private PermissionHelper mPermissionHelper;
     private UsageStatsManagerInternal mUsageStatsManagerInternal;
     private TelecomManager mTelecomManager;
+    private PowerManager mPowerManager;
     private PostNotificationTrackerFactory mPostNotificationTrackerFactory;
 
     final IBinder mForegroundToken = new Binder();
@@ -923,7 +928,7 @@
         if (oldFlags != flags) {
             summary.getSbn().getNotification().flags = flags;
             mHandler.post(new EnqueueNotificationRunnable(userId, summary, isAppForeground,
-                    mPostNotificationTrackerFactory.newTracker()));
+                    mPostNotificationTrackerFactory.newTracker(null)));
         }
     }
 
@@ -1457,7 +1462,7 @@
                         // want to adjust the flag behaviour.
                         mHandler.post(new EnqueueNotificationRunnable(r.getUser().getIdentifier(),
                                 r, true /* isAppForeground*/,
-                                mPostNotificationTrackerFactory.newTracker()));
+                                mPostNotificationTrackerFactory.newTracker(null)));
                     }
                 }
             }
@@ -1488,7 +1493,7 @@
                         mHandler.post(
                                 new EnqueueNotificationRunnable(r.getUser().getIdentifier(), r,
                                         /* foreground= */ true,
-                                        mPostNotificationTrackerFactory.newTracker()));
+                                        mPostNotificationTrackerFactory.newTracker(null)));
                     }
                 }
             }
@@ -1843,7 +1848,7 @@
                 }
             } else if (action.equals(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)) {
                 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
-                if (userHandle >= 0) {
+                if (userHandle >= 0 && !mDpm.isKeepProfilesRunningEnabled()) {
                     cancelAllNotificationsInt(MY_UID, MY_PID, null, null, 0, 0, true, userHandle,
                             REASON_PROFILE_TURNED_OFF, null);
                     mSnoozeHelper.clearData(userHandle);
@@ -2233,7 +2238,7 @@
             UsageStatsManagerInternal usageStatsManagerInternal,
             TelecomManager telecomManager, NotificationChannelLogger channelLogger,
             SystemUiSystemPropertiesFlags.FlagResolver flagResolver,
-            PermissionManager permissionManager,
+            PermissionManager permissionManager, PowerManager powerManager,
             PostNotificationTrackerFactory postNotificationTrackerFactory) {
         mHandler = handler;
         Resources resources = getContext().getResources();
@@ -2265,6 +2270,7 @@
         mDpm = dpm;
         mUm = userManager;
         mTelecomManager = telecomManager;
+        mPowerManager = powerManager;
         mPostNotificationTrackerFactory = postNotificationTrackerFactory;
         mPlatformCompat = IPlatformCompat.Stub.asInterface(
                 ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
@@ -2568,6 +2574,7 @@
                 getContext().getSystemService(TelecomManager.class),
                 new NotificationChannelLoggerImpl(), SystemUiSystemPropertiesFlags.getResolver(),
                 getContext().getSystemService(PermissionManager.class),
+                getContext().getSystemService(PowerManager.class),
                 new PostNotificationTrackerFactory() {});
 
         publishBinderService(Context.NOTIFICATION_SERVICE, mService, /* allowIsolated= */ false,
@@ -2684,7 +2691,7 @@
                     final boolean isAppForeground =
                             mActivityManager.getPackageImportance(pkg) == IMPORTANCE_FOREGROUND;
                     mHandler.post(new EnqueueNotificationRunnable(userId, r, isAppForeground,
-                            mPostNotificationTrackerFactory.newTracker()));
+                            mPostNotificationTrackerFactory.newTracker(null)));
                 }
             }
 
@@ -6577,7 +6584,7 @@
     void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,
             final int callingPid, final String tag, final int id, final Notification notification,
             int incomingUserId, boolean postSilently) {
-        PostNotificationTracker tracker = mPostNotificationTrackerFactory.newTracker();
+        PostNotificationTracker tracker = acquireWakeLockForPost(pkg, callingUid);
         boolean enqueued = false;
         try {
             enqueued = enqueueNotificationInternal(pkg, opPkg, callingUid, callingPid, tag, id,
@@ -6589,6 +6596,22 @@
         }
     }
 
+    private PostNotificationTracker acquireWakeLockForPost(String pkg, int uid) {
+        if (mFlagResolver.isEnabled(WAKE_LOCK_FOR_POSTING_NOTIFICATION)) {
+            // The package probably doesn't have WAKE_LOCK permission and should not require it.
+            return Binder.withCleanCallingIdentity(() -> {
+                WakeLock wakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+                        "NotificationManagerService:post:" + pkg);
+                wakeLock.setWorkSource(new WorkSource(uid, pkg));
+                // TODO(b/275044361): Adjust to a more reasonable number when we have the data.
+                wakeLock.acquire(30_000);
+                return mPostNotificationTrackerFactory.newTracker(wakeLock);
+            });
+        } else {
+            return mPostNotificationTrackerFactory.newTracker(null);
+        }
+    }
+
     /**
      * @return True if we successfully processed the notification and handed off the task of
      * enqueueing it to a background thread; false otherwise.
@@ -7106,7 +7129,7 @@
                             mHandler.post(
                                     new NotificationManagerService.EnqueueNotificationRunnable(
                                             r.getUser().getIdentifier(), r, isAppForeground,
-                                            mPostNotificationTrackerFactory.newTracker()));
+                                            mPostNotificationTrackerFactory.newTracker(null)));
                         }
                     }
                 }
@@ -12168,20 +12191,20 @@
     }
 
     interface PostNotificationTrackerFactory {
-        default PostNotificationTracker newTracker() {
-            return new PostNotificationTracker();
+        default PostNotificationTracker newTracker(@Nullable WakeLock optionalWakelock) {
+            return new PostNotificationTracker(optionalWakelock);
         }
     }
 
     static class PostNotificationTracker {
         @ElapsedRealtimeLong private final long mStartTime;
-        @Nullable private NotificationRecordLogger.NotificationReported mReport;
+        @Nullable private final WakeLock mWakeLock;
         private boolean mOngoing;
 
         @VisibleForTesting
-        PostNotificationTracker() {
-            // TODO(b/275044361): (Conditionally) receive a wakelock.
+        PostNotificationTracker(@Nullable WakeLock wakeLock) {
             mStartTime = SystemClock.elapsedRealtime();
+            mWakeLock = wakeLock;
             mOngoing = true;
             if (DBG) {
                 Slog.d(TAG, "PostNotification: Started");
@@ -12199,9 +12222,8 @@
         }
 
         /**
-         * Cancels the tracker (TODO(b/275044361): releasing the acquired WakeLock). Either
-         * {@link #finish} or {@link #cancel} (exclusively) should be called on this object before
-         * it's discarded.
+         * Cancels the tracker (releasing the acquired WakeLock). Either {@link #finish} or
+         * {@link #cancel} (exclusively) should be called on this object before it's discarded.
          */
         void cancel() {
             if (!isOngoing()) {
@@ -12209,9 +12231,9 @@
                 return;
             }
             mOngoing = false;
-
-            // TODO(b/275044361): Release wakelock.
-
+            if (mWakeLock != null) {
+                Binder.withCleanCallingIdentity(() -> mWakeLock.release());
+            }
             if (DBG) {
                 long elapsedTime = SystemClock.elapsedRealtime() - mStartTime;
                 Slog.d(TAG, TextUtils.formatSimple("PostNotification: Abandoned after %d ms",
@@ -12220,9 +12242,9 @@
         }
 
         /**
-         * Finishes the tracker (TODO(b/275044361): releasing the acquired WakeLock) and returns the
-         * time elapsed since the operation started, in milliseconds. Either {@link #finish} or
-         * {@link #cancel} (exclusively) should be called on this object before it's discarded.
+         * Finishes the tracker (releasing the acquired WakeLock) and returns the time elapsed since
+         * the operation started, in milliseconds. Either {@link #finish} or {@link #cancel}
+         * (exclusively) should be called on this object before it's discarded.
          */
         @DurationMillisLong
         long finish() {
@@ -12232,9 +12254,9 @@
                 return elapsedTime;
             }
             mOngoing = false;
-
-            // TODO(b/275044361): Release wakelock.
-
+            if (mWakeLock != null) {
+                Binder.withCleanCallingIdentity(() -> mWakeLock.release());
+            }
             if (DBG) {
                 Slog.d(TAG,
                         TextUtils.formatSimple("PostNotification: Finished in %d ms", elapsedTime));
diff --git a/services/core/java/com/android/server/notification/TEST_MAPPING b/services/core/java/com/android/server/notification/TEST_MAPPING
new file mode 100644
index 0000000..59b2bc1
--- /dev/null
+++ b/services/core/java/com/android/server/notification/TEST_MAPPING
@@ -0,0 +1,49 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsNotificationTestCases",
+      "options": [
+        {
+          "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        },
+        {
+          "exclude-annotation": "org.junit.Ignore"
+        },
+        {
+          "exclude-annotation": "android.platform.test.annotations.LargeTest"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.LargeTest"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksUiServicesTests",
+      "options": [
+        {
+          "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        },
+        {
+          "exclude-annotation": "org.junit.Ignore"
+        },
+        {
+          "exclude-annotation": "android.platform.test.annotations.LargeTest"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.LargeTest"
+        }
+      ]
+    }
+  ],
+  "postsubmit": [
+    {
+      "name": "CtsNotificationTestCases"
+    }
+  ]
+}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 06db5be..50f1673 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -2145,7 +2145,7 @@
         final String pkgName = pkg.getPackageName();
         final int[] installedForUsers = installRequest.getOriginUsers();
         final int installReason = installRequest.getInstallReason();
-        final String installerPackageName = installRequest.getSourceInstallerPackageName();
+        final String installerPackageName = installRequest.getInstallerPackageName();
 
         if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.getPath());
         synchronized (mPm.mLock) {
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index 95e7904..3464874 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -366,12 +366,6 @@
     public String getApexModuleName() {
         return mApexModuleName;
     }
-
-    @Nullable
-    public String getSourceInstallerPackageName() {
-        return mInstallArgs.mInstallSource.mInstallerPackageName;
-    }
-
     public boolean isRollback() {
         return mInstallArgs != null
                 && mInstallArgs.mInstallReason == PackageManager.INSTALL_REASON_ROLLBACK;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 6491fd1..a911537 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -511,7 +511,7 @@
             }
         } catch (FileNotFoundException e) {
             // Missing sessions are okay, probably first boot
-        } catch (IOException | XmlPullParserException e) {
+        } catch (IOException | XmlPullParserException | ArrayIndexOutOfBoundsException e) {
             Slog.wtf(TAG, "Failed reading install sessions", e);
         } finally {
             IoUtils.closeQuietly(fis);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index bba8043..db47306 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3409,7 +3409,7 @@
     }
 
     @Nullable
-    private String getDevicePolicyManagementRoleHolderPackageName(int userId) {
+    public String getDevicePolicyManagementRoleHolderPackageName(int userId) {
         return Binder.withCleanCallingIdentity(() -> {
             RoleManager roleManager = mContext.getSystemService(RoleManager.class);
             List<String> roleHolders =
diff --git a/services/core/java/com/android/server/pm/ResilientAtomicFile.java b/services/core/java/com/android/server/pm/ResilientAtomicFile.java
index 19aa4f8..54ca426 100644
--- a/services/core/java/com/android/server/pm/ResilientAtomicFile.java
+++ b/services/core/java/com/android/server/pm/ResilientAtomicFile.java
@@ -230,7 +230,9 @@
                             + Log.getStackTraceString(e));
         }
 
-        mCurrentFile.delete();
+        if (!mCurrentFile.delete()) {
+            throw new IllegalStateException("Failed to remove " + mCurrentFile);
+        }
         mCurrentFile = null;
     }
 
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index f2d1357..aaf13eb 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3714,11 +3714,16 @@
             if (parser.getName().equals(TAG_PERMISSIONS)) {
                 final LegacyPermissionState legacyState;
                 if (ps.hasSharedUser()) {
-                    legacyState = getSettingLPr(ps.getSharedUserAppId()).getLegacyPermissionState();
+                    final SettingBase sharedUserSettings = getSettingLPr(
+                            ps.getSharedUserAppId());
+                    legacyState = sharedUserSettings != null
+                            ? sharedUserSettings.getLegacyPermissionState() : null;
                 } else {
                     legacyState = ps.getLegacyPermissionState();
                 }
-                readInstallPermissionsLPr(parser, legacyState, users);
+                if (legacyState != null) {
+                    readInstallPermissionsLPr(parser, legacyState, users);
+                }
             } else if (parser.getName().equals(TAG_USES_STATIC_LIB)) {
                 readUsesStaticLibLPw(parser, ps);
             } else if (parser.getName().equals(TAG_USES_SDK_LIB)) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index a020728..5b3514c 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -2547,10 +2547,7 @@
         enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APP_PREDICTIONS,
                 "getShareTargets");
         final ComponentName chooser = injectChooserActivity();
-        final String pkg = (chooser != null
-                && mPackageManagerInternal.getComponentEnabledSetting(chooser,
-                injectBinderCallingUid(), userId) == PackageManager.COMPONENT_ENABLED_STATE_ENABLED)
-                ? chooser.getPackageName() : mContext.getPackageName();
+        final String pkg = chooser != null ? chooser.getPackageName() : mContext.getPackageName();
         synchronized (mLock) {
             throwIfUserLockedL(userId);
             final List<ShortcutManager.ShareShortcutInfo> shortcutInfoList = new ArrayList<>();
diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
index ba82577..08934c6 100644
--- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java
+++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
@@ -724,6 +724,10 @@
         for (PackageInfo info : pkgInfos) {
             result.add(info.packageName);
         }
+
+        // Role holder may be null, but ArraySet handles it correctly.
+        result.remove(mPm.getDevicePolicyManagementRoleHolderPackageName(userId));
+
         return result;
     }
 
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index d108e14..d55f85c 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -986,11 +986,14 @@
     }
 
     /** @see ApplicationInfo#privateFlagsExt */
-    public static int appInfoPrivateFlagsExt(int pkgWithoutStateFlags,
+    private static int appInfoPrivateFlagsExt(int pkgWithoutStateFlags,
                                              @Nullable PackageStateInternal pkgSetting) {
         // @formatter:off
-        // TODO: Add state specific flags
-        return pkgWithoutStateFlags;
+        int flags = pkgWithoutStateFlags;
+        if (pkgSetting != null) {
+            flags |= flag(pkgSetting.getCpuAbiOverride() != null, ApplicationInfo.PRIVATE_FLAG_EXT_CPU_OVERRIDE);
+        }
+        return flags;
         // @formatter:on
     }
 
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 3e7ae33..2499529 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -141,6 +141,7 @@
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageState;
 import com.android.server.pm.pkg.PackageStateInternal;
+import com.android.server.pm.pkg.SharedUserApi;
 import com.android.server.pm.pkg.component.ComponentMutateUtils;
 import com.android.server.pm.pkg.component.ParsedPermission;
 import com.android.server.pm.pkg.component.ParsedPermissionGroup;
@@ -4538,8 +4539,13 @@
             final int appId = ps.getAppId();
             final LegacyPermissionState legacyState;
             if (ps.hasSharedUser()) {
-                legacyState = mPackageManagerInt.getSharedUserApi(
-                        ps.getSharedUserAppId()).getSharedUserLegacyPermissionState();
+                final int sharedUserId = ps.getSharedUserAppId();
+                SharedUserApi sharedUserApi = mPackageManagerInt.getSharedUserApi(sharedUserId);
+                if (sharedUserApi == null) {
+                    Slog.wtf(TAG, "Missing shared user Api for " + sharedUserId);
+                    return;
+                }
+                legacyState = sharedUserApi.getSharedUserLegacyPermissionState();
             } else {
                 legacyState = ps.getLegacyPermissionState();
             }
@@ -4584,8 +4590,13 @@
             ps.setInstallPermissionsFixed(false);
             final LegacyPermissionState legacyState;
             if (ps.hasSharedUser()) {
-                legacyState = mPackageManagerInt.getSharedUserApi(
-                        ps.getSharedUserAppId()).getSharedUserLegacyPermissionState();
+                final int sharedUserId = ps.getSharedUserAppId();
+                SharedUserApi sharedUserApi = mPackageManagerInt.getSharedUserApi(sharedUserId);
+                if (sharedUserApi == null) {
+                    Slog.wtf(TAG, "Missing shared user Api for " + sharedUserId);
+                    return;
+                }
+                legacyState = sharedUserApi.getSharedUserLegacyPermissionState();
             } else {
                 legacyState = ps.getLegacyPermissionState();
             }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index b8c5b3f..695a0cf 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -40,13 +40,17 @@
 import android.annotation.RequiresPermission;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
-import android.app.AppOpsManager;
 import android.app.SynchronousUserSwitchObserver;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
+import android.content.AttributionSource;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.PermissionChecker;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.database.ContentObserver;
@@ -62,6 +66,7 @@
 import android.os.BatteryManagerInternal;
 import android.os.BatterySaverPolicyConfig;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerExecutor;
 import android.os.IBinder;
@@ -277,6 +282,18 @@
      */
     private static final long ENHANCED_DISCHARGE_PREDICTION_BROADCAST_MIN_DELAY_MS = 60 * 1000L;
 
+    /**
+     * Apps targeting Android U and above need to define
+     * {@link android.Manifest.permission#TURN_SCREEN_ON} in their manifest for
+     * {@link android.os.PowerManager#ACQUIRE_CAUSES_WAKEUP} to have any effect.
+     * Note that most applications should use {@link android.R.attr#turnScreenOn} or
+     * {@link android.app.Activity#setTurnScreenOn(boolean)} instead, as this prevents the
+     * previous foreground app from being resumed first when the screen turns on.
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    public static final long REQUIRE_TURN_SCREEN_ON_PERMISSION = 216114297L;
+
     /** Reason ID for holding display suspend blocker. */
     private static final String HOLDING_DISPLAY_SUSPEND_BLOCKER = "holding display";
 
@@ -304,8 +321,9 @@
     private final SystemPropertiesWrapper mSystemProperties;
     private final Clock mClock;
     private final Injector mInjector;
+    private final PermissionCheckerWrapper mPermissionCheckerWrapper;
+    private final PowerPropertiesWrapper mPowerPropertiesWrapper;
 
-    private AppOpsManager mAppOpsManager;
     private LightsManager mLightsManager;
     private BatteryManagerInternal mBatteryManagerInternal;
     private DisplayManagerInternal mDisplayManagerInternal;
@@ -1029,9 +1047,64 @@
             return new LowPowerStandbyController(context, looper);
         }
 
-        AppOpsManager createAppOpsManager(Context context) {
-            return context.getSystemService(AppOpsManager.class);
+        PermissionCheckerWrapper createPermissionCheckerWrapper() {
+            return PermissionChecker::checkPermissionForDataDelivery;
         }
+
+        PowerPropertiesWrapper createPowerPropertiesWrapper() {
+            return new PowerPropertiesWrapper() {
+                @Override
+                public boolean waive_target_sdk_check_for_turn_screen_on() {
+                    return PowerProperties.waive_target_sdk_check_for_turn_screen_on().orElse(
+                            false);
+                }
+
+                @Override
+                public boolean permissionless_turn_screen_on() {
+                    return PowerProperties.permissionless_turn_screen_on().orElse(false);
+                }
+            };
+        }
+    }
+
+    /** Interface for checking an app op permission */
+    @VisibleForTesting
+    interface PermissionCheckerWrapper {
+        /**
+         * Checks whether a given data access chain described by the given {@link AttributionSource}
+         * has a given permission and whether the app op that corresponds to this permission
+         * is allowed.
+         * See {@link PermissionChecker#checkPermissionForDataDelivery} for more details.
+         *
+         * @param context Context for accessing resources.
+         * @param permission The permission to check.
+         * @param pid The process id for which to check. Use {@link PermissionChecker#PID_UNKNOWN}
+         *    if the PID is not known.
+         * @param attributionSource the permission identity
+         * @param message A message describing the reason the permission was checked
+         * @return The permission check result which is any of
+         *     {@link PermissionChecker#PERMISSION_GRANTED},
+         *     {@link PermissionChecker#PERMISSION_SOFT_DENIED},
+         *     or {@link PermissionChecker#PERMISSION_HARD_DENIED}.
+         */
+        int checkPermissionForDataDelivery(@NonNull Context context, @NonNull String permission,
+                int pid, @NonNull AttributionSource attributionSource, @Nullable String message);
+    }
+
+    /** Interface for querying {@link PowerProperties} */
+    @VisibleForTesting
+    interface PowerPropertiesWrapper {
+        /**
+         * Waives the minimum target-sdk check for android.os.PowerManager#ACQUIRE_CAUSES_WAKEUP
+         * and only allows the flag for apps holding android.permission.TURN_SCREEN_ON
+         */
+        boolean waive_target_sdk_check_for_turn_screen_on();
+
+        /**
+         * Allows apps to turn the screen on with android.os.PowerManager#ACQUIRE_CAUSES_WAKEUP
+         * without being granted android.app.AppOpsManager#OP_TURN_SCREEN_ON.
+         */
+        boolean permissionless_turn_screen_on();
     }
 
     final Constants mConstants;
@@ -1086,8 +1159,8 @@
                 Looper.getMainLooper());
         mInattentiveSleepWarningOverlayController =
                 mInjector.createInattentiveSleepWarningController();
-
-        mAppOpsManager = injector.createAppOpsManager(mContext);
+        mPermissionCheckerWrapper = mInjector.createPermissionCheckerWrapper();
+        mPowerPropertiesWrapper = mInjector.createPowerPropertiesWrapper();
 
         mPowerGroupWakefulnessChangeListener = new PowerGroupWakefulnessChangeListener();
 
@@ -1562,19 +1635,29 @@
     }
 
     @RequiresPermission(value = android.Manifest.permission.TURN_SCREEN_ON, conditional = true)
-    private boolean isAcquireCausesWakeupFlagAllowed(String opPackageName, int opUid) {
+    private boolean isAcquireCausesWakeupFlagAllowed(String opPackageName, int opUid, int opPid) {
         if (opPackageName == null) {
             return false;
         }
-        if (mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_TURN_SCREEN_ON, opUid, opPackageName)
-                == AppOpsManager.MODE_ALLOWED) {
-            if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TURN_SCREEN_ON)
-                    == PackageManager.PERMISSION_GRANTED) {
-                Slog.i(TAG, "Allowing device wake-up from app " + opPackageName);
-                return true;
-            }
+        if (PermissionChecker.PERMISSION_GRANTED
+                == mPermissionCheckerWrapper.checkPermissionForDataDelivery(mContext,
+                android.Manifest.permission.TURN_SCREEN_ON, opPid,
+                new AttributionSource(opUid, opPackageName, /* attributionTag= */ null),
+                /* message= */ "ACQUIRE_CAUSES_WAKEUP for " + opPackageName)) {
+            Slog.i(TAG, "Allowing device wake-up from app " + opPackageName);
+            return true;
         }
-        if (PowerProperties.permissionless_turn_screen_on().orElse(false)) {
+        // CompatChanges#isChangeEnabled() returns false for apps with targetSdk < UDC and ensures
+        // backwards compatibility.
+        // waive_target_sdk_check_for_turn_screen_on() returns false by default and may be set to
+        // true on form factors with a more strict policy (e.g. TV)
+        if (!CompatChanges.isChangeEnabled(REQUIRE_TURN_SCREEN_ON_PERMISSION, opUid)
+                && !mPowerPropertiesWrapper.waive_target_sdk_check_for_turn_screen_on()) {
+            Slog.i(TAG, "Allowing device wake-up without android.permission.TURN_SCREEN_ON for "
+                    + opPackageName);
+            return true;
+        }
+        if (mPowerPropertiesWrapper.permissionless_turn_screen_on()) {
             Slog.d(TAG, "Device wake-up allowed by debug.power.permissionless_turn_screen_on");
             return true;
         }
@@ -1589,6 +1672,7 @@
                 && isScreenLock(wakeLock)) {
             String opPackageName;
             int opUid;
+            int opPid = PermissionChecker.PID_UNKNOWN;
             if (wakeLock.mWorkSource != null && !wakeLock.mWorkSource.isEmpty()) {
                 WorkSource workSource = wakeLock.mWorkSource;
                 WorkChain workChain = getFirstNonEmptyWorkChain(workSource);
@@ -1603,10 +1687,12 @@
             } else {
                 opPackageName = wakeLock.mPackageName;
                 opUid = wakeLock.mOwnerUid;
+                opPid = wakeLock.mOwnerPid;
             }
             Integer powerGroupId = wakeLock.getPowerGroupId();
             // powerGroupId is null if the wakelock associated display is no longer available
-            if (powerGroupId != null && isAcquireCausesWakeupFlagAllowed(opPackageName, opUid)) {
+            if (powerGroupId != null
+                    && isAcquireCausesWakeupFlagAllowed(opPackageName, opUid, opPid)) {
                 if (powerGroupId == Display.INVALID_DISPLAY_GROUP) {
                     // wake up all display groups
                     if (DEBUG_SPEW) {
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperData.java b/services/core/java/com/android/server/wallpaper/WallpaperData.java
index 9ff6a0d..d87fca4 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperData.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperData.java
@@ -133,16 +133,14 @@
      */
     final Rect cropHint = new Rect(0, 0, 0, 0);
 
-    WallpaperData(int userId, File wallpaperDir, String inputFileName, String cropFileName) {
-        this.userId = userId;
-        wallpaperFile = new File(wallpaperDir, inputFileName);
-        cropFile = new File(wallpaperDir, cropFileName);
-    }
-
     WallpaperData(int userId, @SetWallpaperFlags int wallpaperType) {
-        this(userId, getWallpaperDir(userId),
-                (wallpaperType == FLAG_LOCK) ? WALLPAPER_LOCK_ORIG : WALLPAPER,
-                (wallpaperType == FLAG_LOCK) ? WALLPAPER_LOCK_CROP : WALLPAPER_CROP);
+        this.userId = userId;
+        this.mWhich = wallpaperType;
+        File wallpaperDir = getWallpaperDir(userId);
+        String wallpaperFileName = (wallpaperType == FLAG_LOCK) ? WALLPAPER_LOCK_ORIG : WALLPAPER;
+        String cropFileName = (wallpaperType == FLAG_LOCK) ? WALLPAPER_LOCK_CROP : WALLPAPER_CROP;
+        this.wallpaperFile = new File(wallpaperDir, wallpaperFileName);
+        this.cropFile = new File(wallpaperDir, cropFileName);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index a079875..9e9b344 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1588,7 +1588,7 @@
         mShuttingDown = false;
         mImageWallpaper = ComponentName.unflattenFromString(
                 context.getResources().getString(R.string.image_wallpaper_component));
-        mDefaultWallpaperComponent = WallpaperManager.getCmfDefaultWallpaperComponent(context);
+        mDefaultWallpaperComponent = WallpaperManager.getDefaultWallpaperComponent(context);
         mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
         mIPackageManager = AppGlobals.getPackageManager();
diff --git a/services/core/java/com/android/server/wm/AbsAppSnapshotController.java b/services/core/java/com/android/server/wm/AbsAppSnapshotController.java
index bd07622..10a2b97 100644
--- a/services/core/java/com/android/server/wm/AbsAppSnapshotController.java
+++ b/services/core/java/com/android/server/wm/AbsAppSnapshotController.java
@@ -167,6 +167,9 @@
     }
 
     final TaskSnapshot recordSnapshotInner(TYPE source, boolean allowSnapshotHome) {
+        if (shouldDisableSnapshots()) {
+            return null;
+        }
         final boolean snapshotHome = allowSnapshotHome && source.isActivityTypeHome();
         final TaskSnapshot snapshot = captureSnapshot(source, snapshotHome);
         if (snapshot == null) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 2b2100e..9f16a844 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -4281,6 +4281,7 @@
 
         mTaskSupervisor.getActivityMetricsLogger().notifyActivityRemoved(this);
         mTaskSupervisor.mStoppingActivities.remove(this);
+        mLetterboxUiController.destroy();
         waitingToShow = false;
 
         // Defer removal of this activity when either a child is animating, or app transition is on
@@ -4350,8 +4351,6 @@
             mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
         }
 
-        mLetterboxUiController.destroy();
-
         if (!delayed) {
             updateReportedVisibilityLocked();
         }
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index 90af4c6..1eb56f1 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -280,6 +280,10 @@
             return false;
         }
 
+        if (isKeepProfilesRunningEnabled() && !isPackageSuspended()) {
+            return false;
+        }
+
         IntentSender target = createIntentSenderForOriginalIntent(mCallingUid,
                 FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT);
 
@@ -322,8 +326,7 @@
 
     private boolean interceptSuspendedPackageIfNeeded() {
         // Do not intercept if the package is not suspended
-        if (mAInfo == null || mAInfo.applicationInfo == null ||
-                (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) == 0) {
+        if (!isPackageSuspended()) {
             return false;
         }
         final PackageManagerInternal pmi = mService.getPackageManagerInternalLocked();
@@ -467,6 +470,17 @@
         return true;
     }
 
+    private boolean isPackageSuspended() {
+        return mAInfo != null && mAInfo.applicationInfo != null
+                && (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) != 0;
+    }
+
+    private static boolean isKeepProfilesRunningEnabled() {
+        DevicePolicyManagerInternal dpmi =
+                LocalServices.getService(DevicePolicyManagerInternal.class);
+        return dpmi == null || dpmi.isKeepProfilesRunningEnabled();
+    }
+
     /**
      * Called when an activity is successfully launched.
      */
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 0ebec11..a0a45e6 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1573,8 +1573,10 @@
             // existence change.
             transitionController.collectExistenceChange(started);
         } else if (result == START_DELIVERED_TO_TOP && newTransition != null
-                // An activity has changed order/visibility so this isn't just deliver-to-top
-                && mMovedToTopActivity == null) {
+                // An activity has changed order/visibility or the task is occluded by a transient
+                // activity, so this isn't just deliver-to-top
+                && mMovedToTopActivity == null
+                && !transitionController.isTransientHide(startedActivityRootTask)) {
             // We just delivered to top, so there isn't an actual transition here.
             if (!forceTransientTransition) {
                 newTransition.abort();
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index a650d77..47b51ac 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2012,7 +2012,7 @@
             synchronized (mGlobalLock) {
                 final DisplayContent dc = mRootWindowContainer.getDisplayContent(displayId);
                 if (dc == null) return;
-                final Task task = dc.getTask((t) -> t.isLeafTask() && t.isFocusable(),
+                final Task task = dc.getTask((t) -> t.isLeafTask() && t.isTopActivityFocusable(),
                         true /*  traverseTopToBottom */);
                 if (task == null) return;
                 setFocusedTask(task.mTaskId, null /* touchedActivity */);
@@ -4505,8 +4505,12 @@
         // to set debug system properties. To ensure that system properties are set
         // only when allowed, we check the current UID.
         if (Process.myUid() == Process.SYSTEM_UID) {
-            SystemProperties.set("debug.tracing.mcc", Integer.toString(values.mcc));
-            SystemProperties.set("debug.tracing.mnc", Integer.toString(values.mnc));
+            if (values.mcc != 0) {
+                SystemProperties.set("debug.tracing.mcc", Integer.toString(values.mcc));
+            }
+            if (values.mnc != 0) {
+                SystemProperties.set("debug.tracing.mnc", Integer.toString(values.mnc));
+            }
         }
 
         if (!initLocale && !values.getLocales().isEmpty() && values.userSetLocale) {
diff --git a/services/core/java/com/android/server/wm/AppWarnings.java b/services/core/java/com/android/server/wm/AppWarnings.java
index 123a74d..f7ccc0d 100644
--- a/services/core/java/com/android/server/wm/AppWarnings.java
+++ b/services/core/java/com/android/server/wm/AppWarnings.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
 import android.content.res.Configuration;
 import android.os.Build;
 import android.os.Handler;
@@ -178,6 +179,14 @@
      * @param r activity record for which the warning may be displayed
      */
     public void showDeprecatedAbiDialogIfNeeded(ActivityRecord r) {
+        final boolean isUsingAbiOverride = (r.info.applicationInfo.privateFlagsExt
+                & ApplicationInfo.PRIVATE_FLAG_EXT_CPU_OVERRIDE) != 0;
+        if (isUsingAbiOverride) {
+            // The abiOverride flag was specified during installation, which means that if the app
+            // is currently running in 32-bit mode, it is intended. Do not show the warning dialog.
+            return;
+        }
+        // The warning dialog can also be disabled for debugging purpose
         final boolean disableDeprecatedAbiDialog = SystemProperties.getBoolean(
                 "debug.wm.disable_deprecated_abi_dialog", false);
         if (disableDeprecatedAbiDialog) {
diff --git a/services/core/java/com/android/server/wm/DeviceStateController.java b/services/core/java/com/android/server/wm/DeviceStateController.java
index 31b1069..db4762e 100644
--- a/services/core/java/com/android/server/wm/DeviceStateController.java
+++ b/services/core/java/com/android/server/wm/DeviceStateController.java
@@ -111,9 +111,13 @@
     }
 
     /**
-     * @return true if the rotation direction on the Z axis should be reversed.
+     * @return true if the rotation direction on the Z axis should be reversed for the default
+     * display.
      */
-    boolean shouldReverseRotationDirectionAroundZAxis() {
+    boolean shouldReverseRotationDirectionAroundZAxis(@NonNull DisplayContent displayContent) {
+        if (!displayContent.isDefaultDisplay) {
+            return false;
+        }
         return ArrayUtils.contains(mReverseRotationAroundZAxisStates, mCurrentState);
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 6aec969..7fc86b0 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -5602,17 +5602,14 @@
      */
     void requestTransitionAndLegacyPrepare(@WindowManager.TransitionType int transit,
             @WindowManager.TransitionFlags int flags) {
-        prepareAppTransition(transit, flags);
-        mTransitionController.requestTransitionIfNeeded(transit, flags,
-                null /* trigger */, this);
+        requestTransitionAndLegacyPrepare(transit, flags, null /* trigger */);
     }
 
     /** @see #requestTransitionAndLegacyPrepare(int, int) */
     void requestTransitionAndLegacyPrepare(@WindowManager.TransitionType int transit,
-            @Nullable WindowContainer trigger) {
-        prepareAppTransition(transit);
-        mTransitionController.requestTransitionIfNeeded(transit, 0 /* flags */,
-                trigger, this);
+            @WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger) {
+        prepareAppTransition(transit, flags);
+        mTransitionController.requestTransitionIfNeeded(transit, flags, trigger, this);
     }
 
     void executeAppTransition() {
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 8be36f0..b681c19 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -950,7 +950,7 @@
     }
 
     void freezeRotation(int rotation) {
-        if (mDeviceStateController.shouldReverseRotationDirectionAroundZAxis()) {
+        if (mDeviceStateController.shouldReverseRotationDirectionAroundZAxis(mDisplayContent)) {
             rotation = RotationUtils.reverseRotationDirectionAroundZAxis(rotation);
         }
 
@@ -1225,7 +1225,7 @@
         if (mFoldController != null && mFoldController.shouldIgnoreSensorRotation()) {
             sensorRotation = -1;
         }
-        if (mDeviceStateController.shouldReverseRotationDirectionAroundZAxis()) {
+        if (mDeviceStateController.shouldReverseRotationDirectionAroundZAxis(mDisplayContent)) {
             sensorRotation = RotationUtils.reverseRotationDirectionAroundZAxis(sensorRotation);
         }
         mLastSensorRotation = sensorRotation;
diff --git a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
index 1fbf593..2b34bb2 100644
--- a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
@@ -42,6 +42,7 @@
 import android.app.servertransaction.RefreshCallbackItem;
 import android.app.servertransaction.ResumeActivityItem;
 import android.content.pm.ActivityInfo.ScreenOrientation;
+import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.hardware.camera2.CameraManager;
 import android.os.Handler;
@@ -423,7 +424,18 @@
             // for the activity embedding case.
             if (topActivity.getTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
                     && isTreatmentEnabledForActivity(topActivity, /* mustBeFullscreen */ false)) {
-                showToast(R.string.display_rotation_camera_compat_toast_in_split_screen);
+                final PackageManager packageManager = mWmService.mContext.getPackageManager();
+                try {
+                    showToast(
+                            R.string.display_rotation_camera_compat_toast_in_multi_window,
+                            (String) packageManager.getApplicationLabel(
+                                    packageManager.getApplicationInfo(packageName, /* flags */ 0)));
+                } catch (PackageManager.NameNotFoundException e) {
+                    ProtoLog.e(WM_DEBUG_ORIENTATION,
+                            "DisplayRotationCompatPolicy: Multi-window toast not shown as "
+                                    + "package '%s' cannot be found.",
+                            packageName);
+                }
             }
         }
     }
@@ -434,6 +446,15 @@
                 () -> Toast.makeText(mWmService.mContext, stringRes, Toast.LENGTH_LONG).show());
     }
 
+    @VisibleForTesting
+    void showToast(@StringRes int stringRes, @NonNull String applicationLabel) {
+        UiThread.getHandler().post(
+                () -> Toast.makeText(
+                        mWmService.mContext,
+                        mWmService.mContext.getString(stringRes, applicationLabel),
+                        Toast.LENGTH_LONG).show());
+    }
+
     private synchronized void notifyCameraClosed(@NonNull String cameraId) {
         ProtoLog.v(WM_DEBUG_ORIENTATION,
                 "Display id=%d is notified that Camera %s is closed, scheduling rotation update.",
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 1a322ff..5e2618b 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -454,7 +454,7 @@
         if (mSource.getType() == WindowInsets.Type.ime()) {
             setClientVisible(target.isRequestedVisible(WindowInsets.Type.ime()));
         }
-        final Transaction t = mDisplayContent.getSyncTransaction();
+        final Transaction t = mWindowContainer.getSyncTransaction();
         mWindowContainer.startAnimation(t, mAdapter, !mClientVisible /* hidden */,
                 ANIMATION_TYPE_INSETS_CONTROL);
 
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 99878a3..ad9c3b2 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -19,17 +19,21 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_LAUNCHER_CLEAR_SNAPSHOT;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_OCCLUDING;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_UNOCCLUDING;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
 import static android.view.WindowManager.TRANSIT_OPEN;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT;
@@ -171,10 +175,11 @@
         final KeyguardDisplayState state = getDisplayState(displayId);
         final boolean aodChanged = aodShowing != state.mAodShowing;
         final boolean aodRemoved = state.mAodShowing && !aodShowing;
+        final boolean goingAwayRemoved = state.mKeyguardGoingAway && keyguardShowing;
         // If keyguard is going away, but SystemUI aborted the transition, need to reset state.
         // Do not reset keyguardChanged status when only AOD is removed.
         final boolean keyguardChanged = (keyguardShowing != state.mKeyguardShowing)
-                || (state.mKeyguardGoingAway && keyguardShowing && !aodRemoved);
+                || (goingAwayRemoved && !aodRemoved);
         if (aodRemoved) {
             updateDeferTransitionForAod(false /* waiting */);
         }
@@ -214,6 +219,15 @@
             if (keyguardShowing) {
                 state.mDismissalRequested = false;
             }
+            if (goingAwayRemoved) {
+                // Keyguard dismiss is canceled. Send a transition to undo the changes and clean up
+                // before holding the sleep token again.
+                final DisplayContent dc = mRootWindowContainer.getDefaultDisplay();
+                dc.requestTransitionAndLegacyPrepare(
+                        TRANSIT_TO_FRONT, TRANSIT_FLAG_KEYGUARD_APPEARING);
+                dc.mWallpaperController.showWallpaperInTransition(false /* showHome */);
+                mWindowManager.executeAppTransition();
+            }
         }
 
         // Update the sleep token first such that ensureActivitiesVisible has correct sleep token
@@ -269,7 +283,7 @@
             updateKeyguardSleepToken();
 
             // Make the home wallpaper visible
-            dc.mWallpaperController.showHomeWallpaperInTransition();
+            dc.mWallpaperController.showWallpaperInTransition(true /* showHome */);
             // Some stack visibility might change (e.g. docked stack)
             mRootWindowContainer.resumeFocusedTasksTopActivities();
             mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
@@ -413,10 +427,12 @@
                 if (isDisplayOccluded(DEFAULT_DISPLAY)) {
                     mRootWindowContainer.getDefaultDisplay().requestTransitionAndLegacyPrepare(
                             TRANSIT_KEYGUARD_OCCLUDE,
+                            TRANSIT_FLAG_KEYGUARD_OCCLUDING,
                             topActivity != null ? topActivity.getRootTask() : null);
                 } else {
                     mRootWindowContainer.getDefaultDisplay().requestTransitionAndLegacyPrepare(
-                            TRANSIT_KEYGUARD_UNOCCLUDE, 0 /* flags */);
+                            TRANSIT_KEYGUARD_UNOCCLUDE,
+                            TRANSIT_FLAG_KEYGUARD_UNOCCLUDING);
                 }
                 updateKeyguardSleepToken(DEFAULT_DISPLAY);
                 mWindowManager.executeAppTransition();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 4995236..bc7fa3112 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2357,10 +2357,14 @@
                 final Transition transition = new Transition(TRANSIT_SLEEP, 0 /* flags */,
                         display.mTransitionController, mWmService.mSyncEngine);
                 final TransitionController.OnStartCollect sendSleepTransition = (deferred) -> {
-                    display.mTransitionController.requestStartTransition(transition,
-                            null /* trigger */, null /* remote */, null /* display */);
-                    // Force playing immediately so that unrelated ops can't be collected.
-                    transition.playNow();
+                    if (deferred && !display.shouldSleep()) {
+                        transition.abort();
+                    } else {
+                        display.mTransitionController.requestStartTransition(transition,
+                                null /* trigger */, null /* remote */, null /* display */);
+                        // Force playing immediately so that unrelated ops can't be collected.
+                        transition.playNow();
+                    }
                 };
                 if (!display.mTransitionController.isCollecting()) {
                     // Since this bypasses sync, submit directly ignoring whether sync-engine
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index bb6f805..7104739 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3290,6 +3290,12 @@
             scheduleAnimation();
         }
 
+        // Let organizer manage task visibility for shell transition. So don't change it's
+        // visibility during collecting.
+        if (mTransitionController.isCollecting() && mCreatedByOrganizer) {
+            return;
+        }
+
         // We intend to let organizer manage task visibility but it doesn't
         // have enough information until we finish shell transitions.
         // In the mean time we do an easy fix here.
@@ -5687,17 +5693,28 @@
     }
 
     private boolean moveTaskToBackInner(@NonNull Task task) {
-        moveToBack("moveTaskToBackInner", task);
-
-        if (inPinnedWindowingMode()) {
-            mTaskSupervisor.removeRootTask(this);
-            return true;
+        if (mTransitionController.isShellTransitionsEnabled()) {
+            // Preventing from update surface position for WindowState if configuration changed,
+            // because the position is depends on WindowFrame, so update the position before
+            // relayout will only update it to "old" position.
+            mAtmService.deferWindowLayout();
         }
+        try {
+            moveToBack("moveTaskToBackInner", task);
 
-        mRootWindowContainer.ensureVisibilityAndConfig(null /* starting */,
-                mDisplayContent.mDisplayId, false /* markFrozenIfConfigChanged */,
-                false /* deferResume */);
+            if (inPinnedWindowingMode()) {
+                mTaskSupervisor.removeRootTask(this);
+                return true;
+            }
 
+            mRootWindowContainer.ensureVisibilityAndConfig(null /* starting */,
+                    mDisplayContent.mDisplayId, false /* markFrozenIfConfigChanged */,
+                    false /* deferResume */);
+        } finally {
+            if (mTransitionController.isShellTransitionsEnabled()) {
+                mAtmService.continueWindowLayout();
+            }
+        }
         ActivityRecord topActivity = getDisplayArea().topRunningActivity();
         Task topRootTask = topActivity.getRootTask();
         if (topRootTask != null && topRootTask != this && topActivity.isState(RESUMED)) {
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index c6c3b14..0c1f33c 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1017,8 +1017,11 @@
         if (isTopActivityLaunchedBehind()) {
             return TASK_FRAGMENT_VISIBILITY_VISIBLE;
         }
+        final WindowContainer<?> parent = getParent();
         final Task thisTask = asTask();
-        if (thisTask != null && mTransitionController.isTransientHide(thisTask)) {
+        if (thisTask != null && parent.asTask() == null
+                && mTransitionController.isTransientHide(thisTask)) {
+            // Keep transient-hide root tasks visible. Non-root tasks still follow standard rule.
             return TASK_FRAGMENT_VISIBILITY_VISIBLE;
         }
 
@@ -1028,7 +1031,6 @@
 
         // This TaskFragment is only considered visible if all its parent TaskFragments are
         // considered visible, so check the visibility of all ancestor TaskFragment first.
-        final WindowContainer parent = getParent();
         if (parent.asTaskFragment() != null) {
             final int parentVisibility = parent.asTaskFragment().getVisibility(starting);
             if (parentVisibility == TASK_FRAGMENT_VISIBILITY_INVISIBLE) {
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index b938b9e..795d022 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -52,7 +52,6 @@
 import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
 import static android.window.TransitionInfo.FLAG_MOVED_TO_TOP;
 import static android.window.TransitionInfo.FLAG_NO_ANIMATION;
-import static android.window.TransitionInfo.FLAG_OCCLUDES_KEYGUARD;
 import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER;
 import static android.window.TransitionInfo.FLAG_TASK_LAUNCHING_BEHIND;
 import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
@@ -691,6 +690,7 @@
         if (!wc.mDisplayContent.getDisplayPolicy().isScreenOnFully()
                 || wc.mDisplayContent.getDisplayInfo().state == Display.STATE_OFF) {
             mFlags |= WindowManager.TRANSIT_FLAG_INVISIBLE;
+            return;
         }
 
         if (mContainerFreezer == null) {
@@ -1191,7 +1191,11 @@
         // processed all the participants first (in particular, we want to trigger pip-enter first)
         for (int i = 0; i < mParticipants.size(); ++i) {
             final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord();
-            if (ar != null) {
+            // If the activity was just inserted to an invisible task, it will keep INITIALIZING
+            // state. Then no need to notify the callback to avoid clearing some states
+            // unexpectedly, e.g. launch-task-behind.
+            if (ar != null && (ar.isVisibleRequested()
+                    || !ar.isState(ActivityRecord.State.INITIALIZING))) {
                 mController.dispatchLegacyAppTransitionFinished(ar);
             }
         }
@@ -2245,11 +2249,17 @@
             WindowContainer<?> ancestor = findCommonAncestor(sortedTargets, wc);
 
             // Make leash based on highest (z-order) direct child of ancestor with a participant.
+            // Check whether the ancestor is belonged to last parent, shouldn't happen.
+            final boolean hasReparent = !wc.isDescendantOf(ancestor);
             WindowContainer leashReference = wc;
-            while (leashReference.getParent() != ancestor) {
-                leashReference = leashReference.getParent();
+            if (hasReparent) {
+                Slog.e(TAG, "Did not find common ancestor! Ancestor= " + ancestor
+                        + " target= " + wc);
+            } else {
+                while (leashReference.getParent() != ancestor) {
+                    leashReference = leashReference.getParent();
+                }
             }
-
             final SurfaceControl rootLeash = leashReference.makeAnimationLeash().setName(
                     "Transition Root: " + leashReference.getName()).build();
             rootLeash.setUnreleasedWarningCallSite("Transition.calculateTransitionRoots");
@@ -2308,23 +2318,13 @@
                 task.fillTaskInfo(tinfo);
                 change.setTaskInfo(tinfo);
                 change.setRotationAnimation(getTaskRotationAnimation(task));
-                final ActivityRecord topMostActivity = task.getTopMostActivity();
-                change.setAllowEnterPip(topMostActivity != null
-                        && topMostActivity.checkEnterPictureInPictureAppOpsState());
                 final ActivityRecord topRunningActivity = task.topRunningActivity();
-                if (topRunningActivity != null && task.mDisplayContent != null
-                        // Display won't be rotated for multi window Task, so the fixed rotation
-                        // won't be applied. This can happen when the windowing mode is changed
-                        // before the previous fixed rotation is applied.
-                        && (!task.inMultiWindowMode() || !topRunningActivity.inMultiWindowMode())) {
-                    // If Activity is in fixed rotation, its will be applied with the next rotation,
-                    // when the Task is still in the previous rotation.
-                    final int taskRotation = task.getWindowConfiguration().getDisplayRotation();
-                    final int activityRotation = topRunningActivity.getWindowConfiguration()
-                            .getDisplayRotation();
-                    if (taskRotation != activityRotation) {
-                        change.setEndFixedRotation(activityRotation);
+                if (topRunningActivity != null) {
+                    if (topRunningActivity.info.supportsPictureInPicture()) {
+                        change.setAllowEnterPip(
+                                topRunningActivity.checkEnterPictureInPictureAppOpsState());
                     }
+                    setEndFixedRotationIfNeeded(change, task, topRunningActivity);
                 }
             } else if ((info.mFlags & ChangeInfo.FLAG_SEAMLESS_ROTATION) != 0) {
                 change.setRotationAnimation(ROTATION_ANIMATION_SEAMLESS);
@@ -2432,6 +2432,48 @@
         }
         return animOptions;
     }
+
+    private static void setEndFixedRotationIfNeeded(@NonNull TransitionInfo.Change change,
+            @NonNull Task task, @NonNull ActivityRecord taskTopRunning) {
+        if (!taskTopRunning.isVisibleRequested()) {
+            // Fixed rotation only applies to opening or changing activity.
+            return;
+        }
+        if (task.inMultiWindowMode() && taskTopRunning.inMultiWindowMode()) {
+            // Display won't be rotated for multi window Task, so the fixed rotation won't be
+            // applied. This can happen when the windowing mode is changed before the previous
+            // fixed rotation is applied. Check both task and activity because the activity keeps
+            // fullscreen mode when the task is entering PiP.
+            return;
+        }
+        final int taskRotation = task.getWindowConfiguration().getDisplayRotation();
+        final int activityRotation = taskTopRunning.getWindowConfiguration()
+                .getDisplayRotation();
+        // If the Activity uses fixed rotation, its rotation will be applied to display after
+        // the current transition is done, while the Task is still in the previous rotation.
+        if (taskRotation != activityRotation) {
+            change.setEndFixedRotation(activityRotation);
+            return;
+        }
+
+        // For example, the task is entering PiP so it no longer decides orientation. If the next
+        // orientation source (it could be an activity which was behind the PiP or launching to top)
+        // will change display rotation, then set the fixed rotation hint as well so the animation
+        // can consider the rotated position.
+        if (!task.inPinnedWindowingMode() || taskTopRunning.mDisplayContent.inTransition()) {
+            return;
+        }
+        final WindowContainer<?> orientationSource =
+                taskTopRunning.mDisplayContent.getLastOrientationSource();
+        if (orientationSource == null) {
+            return;
+        }
+        final int nextRotation = orientationSource.getWindowConfiguration().getDisplayRotation();
+        if (taskRotation != nextRotation) {
+            change.setEndFixedRotation(nextRotation);
+        }
+    }
+
     /**
      * Finds the top-most common ancestor of app targets.
      *
@@ -2454,6 +2496,20 @@
                 // Skip the non-app window or windows on a different display
                 continue;
             }
+            // Re-initiate the last parent as the initial ancestor instead of the top target.
+            // When move a leaf task from organized task to display area, try to keep the transition
+            // root be the original organized task for close transition animation.
+            // Otherwise, shell will use wrong root layer to play animation.
+            // Note: Since the target is sorted, so only need to do this at the lowest target.
+            if (change.mStartParent != null && wc.getParent() != null
+                    && change.mStartParent.isAttached() && wc.getParent() != change.mStartParent
+                    && i == targets.size() - 1) {
+                final int transitionMode = change.getTransitMode(wc);
+                if (transitionMode == TRANSIT_CLOSE || transitionMode == TRANSIT_TO_BACK) {
+                    ancestor = change.mStartParent;
+                    continue;
+                }
+            }
             while (!wc.isDescendantOf(ancestor)) {
                 ancestor = ancestor.getParent();
             }
@@ -2820,9 +2876,6 @@
                     }
                 }
             }
-            if (occludesKeyguard(wc)) {
-                flags |= FLAG_OCCLUDES_KEYGUARD;
-            }
             if ((mFlags & FLAG_CHANGE_NO_ANIMATION) != 0
                     && (mFlags & FLAG_CHANGE_YES_ANIMATION) == 0) {
                 flags |= FLAG_NO_ANIMATION;
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 1c6a412..0cb6f14 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -16,10 +16,10 @@
 
 package com.android.server.wm;
 
+import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
 import static android.view.WindowManager.TRANSIT_NONE;
 import static android.view.WindowManager.TRANSIT_OPEN;
 
@@ -619,9 +619,9 @@
             }
             // Make the collecting transition wait until this request is ready.
             mCollectingTransition.setReady(readyGroupRef, false);
-            if ((flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) {
-                // Add keyguard flag to dismiss keyguard
-                mCollectingTransition.addFlag(flags);
+            if ((flags & KEYGUARD_VISIBILITY_TRANSIT_FLAGS) != 0) {
+                // Add keyguard flags to affect keyguard visibility
+                mCollectingTransition.addFlag(flags & KEYGUARD_VISIBILITY_TRANSIT_FLAGS);
             }
         } else {
             newTransition = requestStartTransition(createTransition(type, flags),
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 20ce98c..7f41ff1 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -339,12 +339,12 @@
     }
 
     /**
-     * Change the visibility if wallpaper is home screen only.
+     * Make one wallpaper visible, according to {@attr showHome}.
      * This is called during the keyguard unlocking transition
-     * (see {@link KeyguardController#keyguardGoingAway(int, int)}) and thus assumes that if the
-     * system wallpaper is shared with lock, then it needs no animation.
+     * (see {@link KeyguardController#keyguardGoingAway(int, int)}),
+     * or when a keyguard unlock is cancelled (see {@link KeyguardController})
      */
-    public void showHomeWallpaperInTransition() {
+    public void showWallpaperInTransition(boolean showHome) {
         updateWallpaperWindowsTarget(mFindResults);
 
         if (!mFindResults.hasTopShowWhenLockedWallpaper()) {
@@ -357,9 +357,9 @@
             // Shared wallpaper, ensure its visibility
             showWhenLocked.mToken.asWallpaperToken().updateWallpaperWindows(true);
         } else {
-            // Separate lock and home wallpapers: show home wallpaper and hide lock
-            hideWhenLocked.mToken.asWallpaperToken().updateWallpaperWindowsInTransition(true);
-            showWhenLocked.mToken.asWallpaperToken().updateWallpaperWindowsInTransition(false);
+            // Separate lock and home wallpapers: show the correct wallpaper in transition
+            hideWhenLocked.mToken.asWallpaperToken().updateWallpaperWindowsInTransition(showHome);
+            showWhenLocked.mToken.asWallpaperToken().updateWallpaperWindowsInTransition(!showHome);
         }
     }
 
@@ -401,6 +401,19 @@
         // swiping through Launcher pages).
         final Rect wallpaperFrame = wallpaperWin.getFrame();
 
+        final int diffWidth = wallpaperFrame.width() - lastWallpaperBounds.width();
+        final int diffHeight = wallpaperFrame.height() - lastWallpaperBounds.height();
+        if ((wallpaperWin.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0
+                && Math.abs(diffWidth) > 1 && Math.abs(diffHeight) > 1) {
+            Slog.d(TAG, "Skip wallpaper offset with inconsistent orientation, bounds="
+                    + lastWallpaperBounds + " frame=" + wallpaperFrame);
+            // With FLAG_SCALED, the requested size should at least make the frame match one of
+            // side. If both sides contain differences, the client side may not have updated the
+            // latest size according to the current orientation. So skip calculating the offset to
+            // avoid the wallpaper not filling the screen.
+            return false;
+        }
+
         int newXOffset = 0;
         int newYOffset = 0;
         boolean rawChanged = false;
@@ -417,7 +430,7 @@
         float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
         // Difference between width of wallpaper image, and the last size of the wallpaper.
         // This is the horizontal surplus from the prior configuration.
-        int availw = wallpaperFrame.width() - lastWallpaperBounds.width();
+        int availw = diffWidth;
 
         int displayOffset = getDisplayWidthOffset(availw, lastWallpaperBounds,
                 wallpaperWin.isRtl());
@@ -442,9 +455,7 @@
 
         float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
         float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
-        int availh = wallpaperWin.getFrame().bottom - wallpaperWin.getFrame().top
-                - lastWallpaperBounds.height();
-        offset = availh > 0 ? -(int)(availh * wpy + .5f) : 0;
+        offset = diffHeight > 0 ? -(int) (diffHeight * wpy + .5f) : 0;
         if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
             offset += mLastWallpaperDisplayOffsetY;
         }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d84c85c..67572bf 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -88,6 +88,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
 import static android.view.WindowManager.TRANSIT_NONE;
+import static android.view.WindowManager.TRANSIT_OPEN;
 import static android.view.WindowManager.fixScale;
 import static android.view.WindowManagerGlobal.ADD_OKAY;
 import static android.view.WindowManagerGlobal.RELAYOUT_RES_CANCEL_AND_REDRAW;
@@ -3591,6 +3592,7 @@
 
     public void setCurrentUser(@UserIdInt int newUserId) {
         synchronized (mGlobalLock) {
+            mAtmService.getTransitionController().requestTransitionIfNeeded(TRANSIT_OPEN, null);
             mCurrentUserId = newUserId;
             mPolicy.setCurrentUserLw(newUserId);
             mKeyguardDisableHandler.setCurrentUser(newUserId);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index 5ba2283..9c1d765 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -16,6 +16,7 @@
 
 package com.android.server.devicepolicy;
 
+import static android.app.admin.DevicePolicyIdentifiers.USER_CONTROL_DISABLED_PACKAGES_POLICY;
 import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_TARGET_USER_ID;
 import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_UPDATE_RESULT_KEY;
 import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_CONFLICTING_ADMIN_POLICY;
@@ -100,7 +101,7 @@
     private final UserManager mUserManager;
 
     // TODO(b/256849338): add more granular locks
-    private final Object mLock = new Object();
+    private final Object mLock;
 
     /**
      * Map of <userId, Map<policyKey, policyState>>
@@ -121,9 +122,11 @@
 
     DevicePolicyEngine(
             @NonNull Context context,
-            @NonNull DeviceAdminServiceController deviceAdminServiceController) {
+            @NonNull DeviceAdminServiceController deviceAdminServiceController,
+            @NonNull Object lock) {
         mContext = Objects.requireNonNull(context);
         mDeviceAdminServiceController = Objects.requireNonNull(deviceAdminServiceController);
+        mLock = Objects.requireNonNull(lock);
         mUserManager = mContext.getSystemService(UserManager.class);
         mLocalPolicies = new SparseArray<>();
         mGlobalPolicies = new HashMap<>();
@@ -151,8 +154,8 @@
             PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
 
             if (policyDefinition.isNonCoexistablePolicy()) {
-                setNonCoexistableLocalPolicy(policyDefinition, localPolicyState, enforcingAdmin,
-                        value, userId, skipEnforcePolicy);
+                setNonCoexistableLocalPolicyLocked(policyDefinition, localPolicyState,
+                        enforcingAdmin, value, userId, skipEnforcePolicy);
                 return;
             }
 
@@ -172,10 +175,20 @@
             // the data structures.
             if (!skipEnforcePolicy) {
                 if (policyChanged) {
-                    onLocalPolicyChanged(policyDefinition, enforcingAdmin, userId);
+                    onLocalPolicyChangedLocked(policyDefinition, enforcingAdmin, userId);
                 }
                 boolean policyEnforced = Objects.equals(
                         localPolicyState.getCurrentResolvedPolicy(), value);
+                // TODO(b/285532044): remove hack and handle properly
+                if (!policyEnforced
+                        && policyDefinition.getPolicyKey().getIdentifier().equals(
+                        USER_CONTROL_DISABLED_PACKAGES_POLICY)) {
+                    PolicyValue<Set<String>> parsedValue = (PolicyValue<Set<String>>) value;
+                    PolicyValue<Set<String>> parsedResolvedValue =
+                            (PolicyValue<Set<String>>) localPolicyState.getCurrentResolvedPolicy();
+                    policyEnforced = (parsedResolvedValue != null && parsedValue != null
+                            && parsedResolvedValue.getValue().containsAll(parsedValue.getValue()));
+                }
                 sendPolicyResultToAdmin(
                         enforcingAdmin,
                         policyDefinition,
@@ -200,7 +213,7 @@
      *
      * <p>Passing a {@code null} value means the policy set by this admin should be removed.
      */
-    private <V> void setNonCoexistableLocalPolicy(
+    private <V> void setNonCoexistableLocalPolicyLocked(
             PolicyDefinition<V> policyDefinition,
             PolicyState<V> localPolicyState,
             EnforcingAdmin enforcingAdmin,
@@ -255,8 +268,8 @@
             PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
 
             if (policyDefinition.isNonCoexistablePolicy()) {
-                setNonCoexistableLocalPolicy(policyDefinition, localPolicyState, enforcingAdmin,
-                        /* value= */ null, userId, /* skipEnforcePolicy= */ false);
+                setNonCoexistableLocalPolicyLocked(policyDefinition, localPolicyState,
+                        enforcingAdmin, /* value= */ null, userId, /* skipEnforcePolicy= */ false);
                 return;
             }
 
@@ -271,7 +284,7 @@
             }
 
             if (policyChanged) {
-                onLocalPolicyChanged(policyDefinition, enforcingAdmin, userId);
+                onLocalPolicyChangedLocked(policyDefinition, enforcingAdmin, userId);
             }
 
             // For a removePolicy to be enforced, it means no current policy exists
@@ -337,7 +350,7 @@
     /**
      * Enforces the new policy and notifies relevant admins.
      */
-    private <V> void onLocalPolicyChanged(
+    private <V> void onLocalPolicyChangedLocked(
             @NonNull PolicyDefinition<V> policyDefinition,
             @NonNull EnforcingAdmin enforcingAdmin,
             int userId) {
@@ -347,7 +360,7 @@
                 policyDefinition, localPolicyState.getCurrentResolvedPolicy(), userId);
 
         // Send policy updates to admins who've set it locally
-        sendPolicyChangedToAdmins(
+        sendPolicyChangedToAdminsLocked(
                 localPolicyState,
                 enforcingAdmin,
                 policyDefinition,
@@ -358,7 +371,7 @@
         // Send policy updates to admins who've set it globally
         if (hasGlobalPolicyLocked(policyDefinition)) {
             PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition);
-            sendPolicyChangedToAdmins(
+            sendPolicyChangedToAdminsLocked(
                     globalPolicyState,
                     enforcingAdmin,
                     policyDefinition,
@@ -413,11 +426,22 @@
             // the data structures.
             if (!skipEnforcePolicy) {
                 if (policyChanged) {
-                    onGlobalPolicyChanged(policyDefinition, enforcingAdmin);
+                    onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin);
                 }
 
                 boolean policyAppliedGlobally = Objects.equals(
                         globalPolicyState.getCurrentResolvedPolicy(), value);
+                // TODO(b/285532044): remove hack and handle properly
+                if (!policyAppliedGlobally
+                        && policyDefinition.getPolicyKey().getIdentifier().equals(
+                                USER_CONTROL_DISABLED_PACKAGES_POLICY)) {
+                    PolicyValue<Set<String>> parsedValue = (PolicyValue<Set<String>>) value;
+                    PolicyValue<Set<String>> parsedResolvedValue =
+                            (PolicyValue<Set<String>>) globalPolicyState.getCurrentResolvedPolicy();
+                    policyAppliedGlobally = (parsedResolvedValue != null && parsedValue != null
+                            && parsedResolvedValue.getValue().containsAll(parsedValue.getValue()));
+                }
+
                 boolean policyApplied = policyAppliedGlobally && policyAppliedOnAllUsers;
 
                 sendPolicyResultToAdmin(
@@ -451,7 +475,7 @@
             boolean policyChanged = policyState.removePolicy(enforcingAdmin);
 
             if (policyChanged) {
-                onGlobalPolicyChanged(policyDefinition, enforcingAdmin);
+                onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin);
             }
 
             applyGlobalPolicyOnUsersWithLocalPoliciesLocked(policyDefinition, enforcingAdmin,
@@ -477,7 +501,7 @@
     /**
      * Enforces the new policy globally and notifies relevant admins.
      */
-    private <V> void onGlobalPolicyChanged(
+    private <V> void onGlobalPolicyChangedLocked(
             @NonNull PolicyDefinition<V> policyDefinition,
             @NonNull EnforcingAdmin enforcingAdmin) {
         PolicyState<V> policyState = getGlobalPolicyStateLocked(policyDefinition);
@@ -485,7 +509,7 @@
         enforcePolicy(policyDefinition, policyState.getCurrentResolvedPolicy(),
                 UserHandle.USER_ALL);
 
-        sendPolicyChangedToAdmins(
+        sendPolicyChangedToAdminsLocked(
                 policyState,
                 enforcingAdmin,
                 policyDefinition,
@@ -530,7 +554,7 @@
                         policyDefinition,
                         localPolicyState.getCurrentResolvedPolicy(),
                         userId);
-                sendPolicyChangedToAdmins(
+                sendPolicyChangedToAdminsLocked(
                         localPolicyState,
                         enforcingAdmin,
                         policyDefinition,
@@ -539,8 +563,20 @@
                         userId);
 
             }
-            isAdminPolicyApplied &= Objects.equals(
-                    value, localPolicyState.getCurrentResolvedPolicy());
+            // TODO(b/285532044): remove hack and handle properly
+            if (policyDefinition.getPolicyKey().getIdentifier().equals(
+                    USER_CONTROL_DISABLED_PACKAGES_POLICY)) {
+                if (!Objects.equals(value, localPolicyState.getCurrentResolvedPolicy())) {
+                    PolicyValue<Set<String>> parsedValue = (PolicyValue<Set<String>>) value;
+                    PolicyValue<Set<String>> parsedResolvedValue =
+                            (PolicyValue<Set<String>>) localPolicyState.getCurrentResolvedPolicy();
+                    isAdminPolicyApplied &= (parsedResolvedValue != null && parsedValue != null
+                            && parsedResolvedValue.getValue().containsAll(parsedValue.getValue()));
+                }
+            } else {
+                isAdminPolicyApplied &= Objects.equals(
+                        value, localPolicyState.getCurrentResolvedPolicy());
+            }
         }
         return isAdminPolicyApplied;
     }
@@ -711,34 +747,35 @@
     }
 
     <V> void transferPolicies(EnforcingAdmin oldAdmin, EnforcingAdmin newAdmin) {
-        Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet());
-        for (PolicyKey policy : globalPolicies) {
-            PolicyState<?> policyState = mGlobalPolicies.get(policy);
-            if (policyState.getPoliciesSetByAdmins().containsKey(oldAdmin)) {
-                PolicyDefinition<V> policyDefinition =
-                        (PolicyDefinition<V>) policyState.getPolicyDefinition();
-                PolicyValue<V> policyValue =
-                        (PolicyValue<V>) policyState.getPoliciesSetByAdmins().get(oldAdmin);
-                setGlobalPolicy(policyDefinition, newAdmin, policyValue);
-            }
-        }
-
-        for (int i = 0; i < mLocalPolicies.size(); i++) {
-            int userId = mLocalPolicies.keyAt(i);
-            Set<PolicyKey> localPolicies = new HashSet<>(
-                    mLocalPolicies.get(userId).keySet());
-            for (PolicyKey policy : localPolicies) {
-                PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy);
+        synchronized (mLock) {
+            Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet());
+            for (PolicyKey policy : globalPolicies) {
+                PolicyState<?> policyState = mGlobalPolicies.get(policy);
                 if (policyState.getPoliciesSetByAdmins().containsKey(oldAdmin)) {
                     PolicyDefinition<V> policyDefinition =
                             (PolicyDefinition<V>) policyState.getPolicyDefinition();
                     PolicyValue<V> policyValue =
                             (PolicyValue<V>) policyState.getPoliciesSetByAdmins().get(oldAdmin);
-                    setLocalPolicy(policyDefinition, newAdmin, policyValue, userId);
+                    setGlobalPolicy(policyDefinition, newAdmin, policyValue);
+                }
+            }
+
+            for (int i = 0; i < mLocalPolicies.size(); i++) {
+                int userId = mLocalPolicies.keyAt(i);
+                Set<PolicyKey> localPolicies = new HashSet<>(
+                        mLocalPolicies.get(userId).keySet());
+                for (PolicyKey policy : localPolicies) {
+                    PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy);
+                    if (policyState.getPoliciesSetByAdmins().containsKey(oldAdmin)) {
+                        PolicyDefinition<V> policyDefinition =
+                                (PolicyDefinition<V>) policyState.getPolicyDefinition();
+                        PolicyValue<V> policyValue =
+                                (PolicyValue<V>) policyState.getPoliciesSetByAdmins().get(oldAdmin);
+                        setLocalPolicy(policyDefinition, newAdmin, policyValue, userId);
+                    }
                 }
             }
         }
-
         removePoliciesForAdmin(oldAdmin);
     }
 
@@ -802,7 +839,7 @@
             mLocalPolicies.get(userId).put(
                     policyDefinition.getPolicyKey(), new PolicyState<>(policyDefinition));
         }
-        return getPolicyState(mLocalPolicies.get(userId), policyDefinition);
+        return getPolicyStateLocked(mLocalPolicies.get(userId), policyDefinition);
     }
 
     private <V> void removeLocalPolicyStateLocked(
@@ -824,14 +861,14 @@
             mGlobalPolicies.put(
                     policyDefinition.getPolicyKey(), new PolicyState<>(policyDefinition));
         }
-        return getPolicyState(mGlobalPolicies, policyDefinition);
+        return getPolicyStateLocked(mGlobalPolicies, policyDefinition);
     }
 
     private <V> void removeGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition) {
         mGlobalPolicies.remove(policyDefinition.getPolicyKey());
     }
 
-    private static <V> PolicyState<V> getPolicyState(
+    private static <V> PolicyState<V> getPolicyStateLocked(
             Map<PolicyKey, PolicyState<?>> policies, PolicyDefinition<V> policyDefinition) {
         try {
             // This will not throw an exception because policyDefinition is of type V, so unless
@@ -901,7 +938,7 @@
     }
 
     // TODO(b/261430877): Finalise the decision on which admins to send the updates to.
-    private <V> void sendPolicyChangedToAdmins(
+    private <V> void sendPolicyChangedToAdminsLocked(
             PolicyState<V> policyState,
             EnforcingAdmin callingAdmin,
             PolicyDefinition<V> policyDefinition,
@@ -1176,17 +1213,19 @@
             if (parentInfo == null || parentInfo.getUserHandle().getIdentifier() == userId) {
                 return;
             }
-            if (!mLocalPolicies.contains(parentInfo.getUserHandle().getIdentifier())) {
-                return;
-            }
-            for (Map.Entry<PolicyKey, PolicyState<?>> entry : mLocalPolicies.get(
-                    parentInfo.getUserHandle().getIdentifier()).entrySet()) {
-                enforcePolicyOnUser(userId, entry.getValue());
+            synchronized (mLock) {
+                if (!mLocalPolicies.contains(parentInfo.getUserHandle().getIdentifier())) {
+                    return;
+                }
+                for (Map.Entry<PolicyKey, PolicyState<?>> entry : mLocalPolicies.get(
+                        parentInfo.getUserHandle().getIdentifier()).entrySet()) {
+                    enforcePolicyOnUserLocked(userId, entry.getValue());
+                }
             }
         });
     }
 
-    private <V> void enforcePolicyOnUser(int userId, PolicyState<V> policyState) {
+    private <V> void enforcePolicyOnUserLocked(int userId, PolicyState<V> policyState) {
         if (!policyState.getPolicyDefinition().isInheritable()) {
             return;
         }
@@ -1205,26 +1244,28 @@
      */
     @NonNull
     DevicePolicyState getDevicePolicyState() {
-        Map<UserHandle, Map<PolicyKey, android.app.admin.PolicyState<?>>> policies =
-                new HashMap<>();
-        for (int i = 0; i < mLocalPolicies.size(); i++) {
-            UserHandle user = UserHandle.of(mLocalPolicies.keyAt(i));
-            policies.put(user, new HashMap<>());
-            for (PolicyKey policyKey : mLocalPolicies.valueAt(i).keySet()) {
-                policies.get(user).put(
-                        policyKey,
-                        mLocalPolicies.valueAt(i).get(policyKey).getParcelablePolicyState());
+        synchronized (mLock) {
+            Map<UserHandle, Map<PolicyKey, android.app.admin.PolicyState<?>>> policies =
+                    new HashMap<>();
+            for (int i = 0; i < mLocalPolicies.size(); i++) {
+                UserHandle user = UserHandle.of(mLocalPolicies.keyAt(i));
+                policies.put(user, new HashMap<>());
+                for (PolicyKey policyKey : mLocalPolicies.valueAt(i).keySet()) {
+                    policies.get(user).put(
+                            policyKey,
+                            mLocalPolicies.valueAt(i).get(policyKey).getParcelablePolicyState());
+                }
             }
-        }
-        if (!mGlobalPolicies.isEmpty()) {
-            policies.put(UserHandle.ALL, new HashMap<>());
-            for (PolicyKey policyKey : mGlobalPolicies.keySet()) {
-                policies.get(UserHandle.ALL).put(
-                        policyKey,
-                        mGlobalPolicies.get(policyKey).getParcelablePolicyState());
+            if (!mGlobalPolicies.isEmpty()) {
+                policies.put(UserHandle.ALL, new HashMap<>());
+                for (PolicyKey policyKey : mGlobalPolicies.keySet()) {
+                    policies.get(UserHandle.ALL).put(
+                            policyKey,
+                            mGlobalPolicies.get(policyKey).getParcelablePolicyState());
+                }
             }
+            return new DevicePolicyState(policies);
         }
-        return new DevicePolicyState(policies);
     }
 
 
@@ -1232,23 +1273,25 @@
      * Removes all local and global policies set by that admin.
      */
     void removePoliciesForAdmin(EnforcingAdmin admin) {
-        Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet());
-        for (PolicyKey policy : globalPolicies) {
-            PolicyState<?> policyState = mGlobalPolicies.get(policy);
-            if (policyState.getPoliciesSetByAdmins().containsKey(admin)) {
-                removeGlobalPolicy(policyState.getPolicyDefinition(), admin);
-            }
-        }
-
-        for (int i = 0; i < mLocalPolicies.size(); i++) {
-            Set<PolicyKey> localPolicies = new HashSet<>(
-                    mLocalPolicies.get(mLocalPolicies.keyAt(i)).keySet());
-            for (PolicyKey policy : localPolicies) {
-                PolicyState<?> policyState = mLocalPolicies.get(
-                        mLocalPolicies.keyAt(i)).get(policy);
+        synchronized (mLock) {
+            Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet());
+            for (PolicyKey policy : globalPolicies) {
+                PolicyState<?> policyState = mGlobalPolicies.get(policy);
                 if (policyState.getPoliciesSetByAdmins().containsKey(admin)) {
-                    removeLocalPolicy(
-                            policyState.getPolicyDefinition(), admin, mLocalPolicies.keyAt(i));
+                    removeGlobalPolicy(policyState.getPolicyDefinition(), admin);
+                }
+            }
+
+            for (int i = 0; i < mLocalPolicies.size(); i++) {
+                Set<PolicyKey> localPolicies = new HashSet<>(
+                        mLocalPolicies.get(mLocalPolicies.keyAt(i)).keySet());
+                for (PolicyKey policy : localPolicies) {
+                    PolicyState<?> policyState = mLocalPolicies.get(
+                            mLocalPolicies.keyAt(i)).get(policy);
+                    if (policyState.getPoliciesSetByAdmins().containsKey(admin)) {
+                        removeLocalPolicy(
+                                policyState.getPolicyDefinition(), admin, mLocalPolicies.keyAt(i));
+                    }
                 }
             }
         }
@@ -1258,23 +1301,25 @@
      * Removes all local policies for the provided {@code userId}.
      */
     private void removeLocalPoliciesForUser(int userId) {
-        if (!mLocalPolicies.contains(userId)) {
-            // No policies on user
-            return;
-        }
-
-        Set<PolicyKey> localPolicies = new HashSet<>(mLocalPolicies.get(userId).keySet());
-        for (PolicyKey policy : localPolicies) {
-            PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy);
-            Set<EnforcingAdmin> admins = new HashSet<>(
-                    policyState.getPoliciesSetByAdmins().keySet());
-            for (EnforcingAdmin admin : admins) {
-                removeLocalPolicy(
-                        policyState.getPolicyDefinition(), admin, userId);
+        synchronized (mLock) {
+            if (!mLocalPolicies.contains(userId)) {
+                // No policies on user
+                return;
             }
-        }
 
-        mLocalPolicies.remove(userId);
+            Set<PolicyKey> localPolicies = new HashSet<>(mLocalPolicies.get(userId).keySet());
+            for (PolicyKey policy : localPolicies) {
+                PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy);
+                Set<EnforcingAdmin> admins = new HashSet<>(
+                        policyState.getPoliciesSetByAdmins().keySet());
+                for (EnforcingAdmin admin : admins) {
+                    removeLocalPolicy(
+                            policyState.getPolicyDefinition(), admin, userId);
+                }
+            }
+
+            mLocalPolicies.remove(userId);
+        }
     }
 
     /**
@@ -1342,7 +1387,7 @@
      */
     private void updateDeviceAdminServiceOnPolicyRemoveLocked(
             @NonNull EnforcingAdmin enforcingAdmin) {
-        if (doesAdminHavePolicies(enforcingAdmin)) {
+        if (doesAdminHavePoliciesLocked(enforcingAdmin)) {
             return;
         }
         int userId = enforcingAdmin.getUserId();
@@ -1365,7 +1410,7 @@
                 /* actionForLog= */ "policy-removed");
     }
 
-    private boolean doesAdminHavePolicies(@NonNull EnforcingAdmin enforcingAdmin) {
+    private boolean doesAdminHavePoliciesLocked(@NonNull EnforcingAdmin enforcingAdmin) {
         for (PolicyKey policy : mGlobalPolicies.keySet()) {
             PolicyState<?> policyState = mGlobalPolicies.get(policy);
             if (policyState.getPoliciesSetByAdmins().containsKey(enforcingAdmin)) {
@@ -1386,13 +1431,17 @@
 
     @NonNull
     private Set<EnforcingAdmin> getEnforcingAdminsOnUser(int userId) {
-        return mEnforcingAdmins.contains(userId)
-                ? mEnforcingAdmins.get(userId) : Collections.emptySet();
+        synchronized (mLock) {
+            return mEnforcingAdmins.contains(userId)
+                    ? mEnforcingAdmins.get(userId) : Collections.emptySet();
+        }
     }
 
     private void write() {
-        Log.d(TAG, "Writing device policies to file.");
-        new DevicePoliciesReaderWriter().writeToFileLocked();
+        synchronized (mLock) {
+            Log.d(TAG, "Writing device policies to file.");
+            new DevicePoliciesReaderWriter().writeToFileLocked();
+        }
     }
 
     // TODO(b/256852787): trigger resolving logic after loading policies as roles are recalculated
@@ -1402,11 +1451,11 @@
         synchronized (mLock) {
             clear();
             new DevicePoliciesReaderWriter().readFromFileLocked();
-            reapplyAllPolicies();
+            reapplyAllPoliciesLocked();
         }
     }
 
-    private <V> void reapplyAllPolicies() {
+    private <V> void reapplyAllPoliciesLocked() {
         for (PolicyKey policy : mGlobalPolicies.keySet()) {
             PolicyState<?> policyState = mGlobalPolicies.get(policy);
             // Policy definition and value will always be of the same type
@@ -1436,10 +1485,8 @@
      * <p>Note that this doesn't clear any enforcements, it only clears the data structures.
      */
     void clearAllPolicies() {
-        synchronized (mLock) {
-            clear();
-            write();
-        }
+        clear();
+        write();
     }
     private void clear() {
         synchronized (mLock) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a5b1548..e44b8cd 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2093,7 +2093,8 @@
         mUserData = new SparseArray<>();
         mOwners = makeOwners(injector, pathProvider);
 
-        mDevicePolicyEngine = new DevicePolicyEngine(mContext, mDeviceAdminServiceController);
+        mDevicePolicyEngine = new DevicePolicyEngine(
+                mContext, mDeviceAdminServiceController, getLockObject());
 
         if (!mHasFeature) {
             // Skip the rest of the initialization
@@ -7840,27 +7841,29 @@
                 throw new SecurityException("Cannot wipe data. " + restriction
                         + " restriction is set for user " + userId);
             }
+        });
 
-            boolean isSystemUser = userId == UserHandle.USER_SYSTEM;
-            boolean wipeDevice;
-            if (factoryReset == null || !mInjector.isChangeEnabled(EXPLICIT_WIPE_BEHAVIOUR,
-                    adminPackage,
-                    userId)) {
-                // Legacy mode
-                wipeDevice = isSystemUser;
+        boolean isSystemUser = userId == UserHandle.USER_SYSTEM;
+        boolean wipeDevice;
+        if (factoryReset == null || !mInjector.isChangeEnabled(EXPLICIT_WIPE_BEHAVIOUR,
+                adminPackage,
+                userId)) {
+            // Legacy mode
+            wipeDevice = isSystemUser;
+        } else {
+            // Explicit behaviour
+            if (factoryReset) {
+                EnforcingAdmin enforcingAdmin = enforcePermissionsAndGetEnforcingAdmin(
+                        /*admin=*/ null,
+                        /*permission=*/ new String[]{MANAGE_DEVICE_POLICY_WIPE_DATA,
+                                MASTER_CLEAR},
+                        USES_POLICY_WIPE_DATA,
+                        adminPackage,
+                        factoryReset ? UserHandle.USER_ALL :
+                                getAffectedUser(calledOnParentInstance));
+                wipeDevice = true;
             } else {
-                // Explicit behaviour
-                if (factoryReset) {
-                    EnforcingAdmin enforcingAdmin = enforcePermissionsAndGetEnforcingAdmin(
-                            /*admin=*/ null,
-                            /*permission=*/ new String[]{MANAGE_DEVICE_POLICY_WIPE_DATA,
-                                    MASTER_CLEAR},
-                            USES_POLICY_WIPE_DATA,
-                            adminPackage,
-                            factoryReset ? UserHandle.USER_ALL :
-                                    getAffectedUser(calledOnParentInstance));
-                    wipeDevice = true;
-                } else {
+                mInjector.binderWithCleanCallingIdentity(() -> {
                     Preconditions.checkCallAuthorization(!isSystemUser,
                             "User %s is a system user and cannot be removed", userId);
                     boolean isLastNonHeadlessUser = getUserInfo(userId).isFull()
@@ -7871,9 +7874,11 @@
                             "Removing user %s would leave the device without any active users. "
                                     + "Consider factory resetting the device instead.",
                             userId);
-                    wipeDevice = false;
-                }
+                });
+                wipeDevice = false;
             }
+        }
+        mInjector.binderWithCleanCallingIdentity(() -> {
             if (wipeDevice) {
                 forceWipeDeviceNoLock(
                         (flags & WIPE_EXTERNAL_STORAGE) != 0,
diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java
index 774f62d..fd478dc 100644
--- a/services/print/java/com/android/server/print/UserState.java
+++ b/services/print/java/com/android/server/print/UserState.java
@@ -31,6 +31,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
+import android.app.ActivityOptions;
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
@@ -245,10 +246,13 @@
             intent.putExtra(PrintManager.EXTRA_PRINT_JOB, printJob);
             intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
 
+            ActivityOptions activityOptions = ActivityOptions.makeBasic()
+                    .setPendingIntentCreatorBackgroundActivityStartMode(
+                            ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED);
             IntentSender intentSender = PendingIntent.getActivityAsUser(
                     mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT
-                    | PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
-                    null, new UserHandle(mUserId)) .getIntentSender();
+                            | PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
+                    activityOptions.toBundle(), new UserHandle(mUserId)).getIntentSender();
 
             Bundle result = new Bundle();
             result.putParcelable(PrintManager.EXTRA_PRINT_JOB, printJob);
diff --git a/services/tests/PackageManagerServiceTests/server/Android.bp b/services/tests/PackageManagerServiceTests/server/Android.bp
index 1146271..3176f06 100644
--- a/services/tests/PackageManagerServiceTests/server/Android.bp
+++ b/services/tests/PackageManagerServiceTests/server/Android.bp
@@ -106,6 +106,10 @@
         ":PackageParserTestApp6",
     ],
     resource_zips: [":PackageManagerServiceServerTests_apks_as_resources"],
+
+    data: [
+        ":StubTestApp",
+    ],
 }
 
 // Rules to copy all the test apks to the intermediate raw resource directory
diff --git a/services/tests/PackageManagerServiceTests/server/AndroidTest.xml b/services/tests/PackageManagerServiceTests/server/AndroidTest.xml
index 1b93527..a0ef03c 100644
--- a/services/tests/PackageManagerServiceTests/server/AndroidTest.xml
+++ b/services/tests/PackageManagerServiceTests/server/AndroidTest.xml
@@ -23,6 +23,14 @@
         <option name="install-arg" value="-g" />
         <option name="test-file-name" value="PackageManagerServiceServerTests.apk" />
     </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="settings put global verifier_engprod 1" />
+    </target_preparer>
+
+    <!-- Load additional APKs onto device -->
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="push" value="StubTestApp.apk->/data/local/tmp/servicestests/StubTestApp.apk"/>
+    </target_preparer>
 
     <option name="test-tag" value="PackageManagerServiceServerTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java
index b82ffb4..435f0d7 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -32,7 +32,6 @@
 import android.content.IIntentReceiver;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -70,7 +69,7 @@
 @RunWith(AndroidJUnit4.class)
 public class PackageManagerServiceTest {
 
-    private static final String PACKAGE_NAME = "com.android.frameworks.servicestests";
+    private static final String PACKAGE_NAME = "com.android.server.pm.test.service.server";
 
     private static final String TEST_DATA_PATH = "/data/local/tmp/servicestests/";
     private static final String TEST_APP_APK = "StubTestApp.apk";
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
index dc92376..ca4a404 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
@@ -66,6 +66,7 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.LargeTest;
 import androidx.test.filters.SmallTest;
 import androidx.test.filters.Suppress;
@@ -2506,6 +2507,7 @@
     }
 
     @LargeTest
+    @FlakyTest(bugId = 283797480)
     public void testCheckSignaturesRotatedAgainstRotated() throws Exception {
         // checkSignatures should be successful when both apps have been signed with the same
         // rotated key since the initial signature comparison between the two apps should
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index a614c4d..2bc66ac 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -27,6 +27,7 @@
 import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_TOP;
 import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
+import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
 import static android.util.DebugUtils.valueToString;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
@@ -742,24 +743,24 @@
 
         broadcastIntent(intent1, null, true);
         assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER),
-                StickyBroadcast.create(intent1, false, Process.myUid()));
+                StickyBroadcast.create(intent1, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
         assertNull(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER));
         assertNull(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER));
 
         broadcastIntent(intent2, options.toBundle(), true);
         assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER),
-                StickyBroadcast.create(intent1, false, Process.myUid()));
+                StickyBroadcast.create(intent1, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
         assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER),
-                StickyBroadcast.create(intent2, true, Process.myUid()));
+                StickyBroadcast.create(intent2, true, Process.myUid(), PROCESS_STATE_UNKNOWN));
         assertNull(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER));
 
         broadcastIntent(intent3, null, true);
         assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER),
-                StickyBroadcast.create(intent1, false, Process.myUid()));
+                StickyBroadcast.create(intent1, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
         assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER),
-                StickyBroadcast.create(intent2, true, Process.myUid()));
+                StickyBroadcast.create(intent2, true, Process.myUid(), PROCESS_STATE_UNKNOWN));
         assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER),
-                StickyBroadcast.create(intent3, false, Process.myUid()));
+                StickyBroadcast.create(intent3, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
     }
 
     @SuppressWarnings("GuardedBy")
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
index 948687a..ccaaa87 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
+
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED;
 import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD;
@@ -246,7 +248,7 @@
         return new BroadcastRecord(mImpl, intent, mProcess, PACKAGE_RED, null, 21, 42, false, null,
                 null, null, null, AppOpsManager.OP_NONE, options, receivers, null, resultTo,
                 Activity.RESULT_OK, null, null, ordered, false, false, UserHandle.USER_SYSTEM,
-                BackgroundStartPrivileges.NONE, false, null);
+                BackgroundStartPrivileges.NONE, false, null, PROCESS_STATE_UNKNOWN);
     }
 
     private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue,
@@ -1407,7 +1409,7 @@
                 eq(BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST),
                 eq(BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD),
                 anyLong(), anyLong(), anyLong(), anyInt(), nullable(String.class),
-                anyString(), anyInt(), anyInt()),
+                anyString(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt()),
                 times(1));
     }
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
index 4989f84..0f75ea5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_FINISH_RECEIVER;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_START_RECEIVER;
 import static android.os.UserHandle.USER_SYSTEM;
@@ -611,7 +612,7 @@
                 callerApp.getPid(), callerApp.info.uid, false, null, null, null, null,
                 AppOpsManager.OP_NONE, options, receivers, callerApp, resultTo,
                 Activity.RESULT_OK, null, resultExtras, ordered, false, false, userId,
-                BackgroundStartPrivileges.NONE, false, null);
+                BackgroundStartPrivileges.NONE, false, null, PROCESS_STATE_UNKNOWN);
     }
 
     private void assertHealth() {
@@ -1599,7 +1600,7 @@
                 null, null, null, null, AppOpsManager.OP_NONE, BroadcastOptions.makeBasic(),
                 List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN)), null, null,
                 Activity.RESULT_OK, null, null, false, false, false, UserHandle.USER_SYSTEM,
-                backgroundStartPrivileges, false, null);
+                backgroundStartPrivileges, false, null, PROCESS_STATE_UNKNOWN);
         enqueueBroadcast(r);
 
         waitForIdle();
@@ -1904,6 +1905,34 @@
     }
 
     @Test
+    public void testReplacePending_diffReceivers() throws Exception {
+        final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
+        final ProcessRecord receiverGreenApp = makeActiveProcessRecord(PACKAGE_GREEN);
+        final ProcessRecord receiverBlueApp = makeActiveProcessRecord(PACKAGE_BLUE);
+        final ProcessRecord receiverYellowApp = makeActiveProcessRecord(PACKAGE_YELLOW);
+        final BroadcastFilter receiverGreen = makeRegisteredReceiver(receiverGreenApp);
+        final BroadcastFilter receiverBlue = makeRegisteredReceiver(receiverBlueApp);
+        final BroadcastFilter receiverYellow = makeRegisteredReceiver(receiverYellowApp);
+
+        final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED)
+                .addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+
+        enqueueBroadcast(makeBroadcastRecord(airplane, callerApp, List.of(
+                withPriority(receiverGreen, 10),
+                withPriority(receiverBlue, 5),
+                withPriority(receiverYellow, 0))));
+        enqueueBroadcast(makeBroadcastRecord(airplane, callerApp, List.of(
+                withPriority(receiverGreen, 10),
+                withPriority(receiverBlue, 5))));
+
+        waitForIdle();
+
+        verifyScheduleRegisteredReceiver(times(1), receiverGreenApp, airplane);
+        verifyScheduleRegisteredReceiver(times(1), receiverBlueApp, airplane);
+        verifyScheduleRegisteredReceiver(never(), receiverYellowApp, airplane);
+    }
+
+    @Test
     public void testIdleAndBarrier() throws Exception {
         final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
         final ProcessRecord receiverApp = makeActiveProcessRecord(PACKAGE_GREEN);
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java
index 08952ea..f0efb79 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
 import static android.app.ActivityManager.RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
 import static android.content.Intent.ACTION_BOOT_COMPLETED;
 import static android.content.Intent.ACTION_LOCKED_BOOT_COMPLETED;
@@ -958,7 +959,8 @@
                 userId,
                 BackgroundStartPrivileges.NONE,
                 false /* timeoutExempt */,
-                filterExtrasForReceiver);
+                filterExtrasForReceiver,
+                PROCESS_STATE_UNKNOWN);
     }
 
     private static int getAppId(int i) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
index c5ff8cc..dd23d9f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
@@ -28,6 +28,7 @@
 import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX;
 import static com.android.server.job.JobSchedulerService.RARE_INDEX;
 import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+import static com.android.server.job.JobSchedulerService.sUptimeMillisClock;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -148,6 +149,9 @@
         // Used in JobConcurrencyManager.
         doReturn(mock(UserManagerInternal.class))
                 .when(() -> LocalServices.getService(UserManagerInternal.class));
+        // Used in JobStatus.
+        doReturn(mock(JobSchedulerInternal.class))
+                .when(() -> LocalServices.getService(JobSchedulerInternal.class));
         // Called via IdleController constructor.
         when(mContext.getPackageManager()).thenReturn(mock(PackageManager.class));
         when(mContext.getResources()).thenReturn(mock(Resources.class));
@@ -168,6 +172,8 @@
         JobSchedulerService.sSystemClock = Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
         JobSchedulerService.sElapsedRealtimeClock =
                 Clock.fixed(SystemClock.elapsedRealtimeClock().instant(), ZoneOffset.UTC);
+        // Make sure the uptime is at least 24 hours so that tests that rely on high uptime work.
+        sUptimeMillisClock = getAdvancedClock(sUptimeMillisClock, 24 * HOUR_IN_MILLIS);
         // Called by DeviceIdlenessTracker
         when(mContext.getSystemService(UiModeManager.class)).thenReturn(mock(UiModeManager.class));
 
@@ -313,6 +319,260 @@
     }
 
     @Test
+    public void testGetMinJobExecutionGuaranteeMs_timeoutSafeguards_disabled() {
+        JobStatus jobUij = createJobStatus("testGetMinJobExecutionGuaranteeMs_timeoutSafeguards",
+                createJobInfo(1)
+                        .setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
+        JobStatus jobEj = createJobStatus("testGetMinJobExecutionGuaranteeMs_timeoutSafeguards",
+                createJobInfo(2).setExpedited(true));
+        JobStatus jobReg = createJobStatus("testGetMinJobExecutionGuaranteeMs_timeoutSafeguards",
+                createJobInfo(3));
+        spyOn(jobUij);
+        when(jobUij.shouldTreatAsUserInitiatedJob()).thenReturn(true);
+        jobUij.startedAsUserInitiatedJob = true;
+        spyOn(jobEj);
+        when(jobEj.shouldTreatAsExpeditedJob()).thenReturn(true);
+        jobEj.startedAsExpeditedJob = true;
+
+        mService.mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC = false;
+        mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT = 2;
+        mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT = 2;
+        mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT = 2;
+        mService.updateQuotaTracker();
+        mService.resetScheduleQuota();
+
+        // Safeguards disabled -> no penalties.
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+        // 1 UIJ timeout. No max execution penalty yet.
+        mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+        // 2 UIJ timeouts. Safeguards disabled -> no penalties.
+        jobUij.madeActive =
+                sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS;
+        mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+        // 1 EJ timeout. No max execution penalty yet.
+        mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+        // 2 EJ timeouts. Safeguards disabled -> no penalties.
+        jobEj.madeActive =
+                sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS;
+        mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+        // 1 reg timeout. No max execution penalty yet.
+        mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+        // 2 Reg timeouts. Safeguards disabled -> no penalties.
+        jobReg.madeActive =
+                sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_GUARANTEE_MS;
+        mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobReg));
+    }
+
+    @Test
+    public void testGetMinJobExecutionGuaranteeMs_timeoutSafeguards_enabled() {
+        JobStatus jobUij = createJobStatus("testGetMinJobExecutionGuaranteeMs_timeoutSafeguards",
+                createJobInfo(1)
+                        .setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
+        JobStatus jobEj = createJobStatus("testGetMinJobExecutionGuaranteeMs_timeoutSafeguards",
+                createJobInfo(2).setExpedited(true));
+        JobStatus jobReg = createJobStatus("testGetMinJobExecutionGuaranteeMs_timeoutSafeguards",
+                createJobInfo(3));
+        spyOn(jobUij);
+        when(jobUij.shouldTreatAsUserInitiatedJob()).thenReturn(true);
+        jobUij.startedAsUserInitiatedJob = true;
+        spyOn(jobEj);
+        when(jobEj.shouldTreatAsExpeditedJob()).thenReturn(true);
+        jobEj.startedAsExpeditedJob = true;
+
+        mService.mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC = true;
+        mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT = 2;
+        mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT = 2;
+        mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT = 2;
+        mService.updateQuotaTracker();
+        mService.resetScheduleQuota();
+
+        // No timeouts -> no penalties.
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+        // 1 UIJ timeout. No execution penalty yet.
+        mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+        // Not a timeout -> 1 UIJ timeout. No execution penalty yet.
+        jobUij.madeActive = sUptimeMillisClock.millis() - 1;
+        mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+        // 2 UIJ timeouts. Min execution penalty only for UIJs.
+        jobUij.madeActive =
+                sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS;
+        mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+        // 1 EJ timeout. No max execution penalty yet.
+        mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+        // 2 EJ timeouts. Max execution penalty for EJs.
+        jobEj.madeActive =
+                sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS;
+        mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+        // 1 reg timeout. No max execution penalty yet.
+        mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+        // 2 Reg timeouts. Max execution penalty for regular jobs.
+        jobReg.madeActive =
+                sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_GUARANTEE_MS;
+        mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobReg));
+    }
+
+    @Test
     public void testGetMaxJobExecutionTimeMs() {
         JobStatus jobUIDT = createJobStatus("testGetMaxJobExecutionTimeMs",
                 createJobInfo(10)
@@ -327,7 +587,7 @@
         doReturn(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
                 .when(quotaController).getMaxJobExecutionTimeMsLocked(any());
         doReturn(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
-                .when(quotaController).getMaxJobExecutionTimeMsLocked(any());
+                .when(tareController).getMaxJobExecutionTimeMsLocked(any());
 
         grantRunUserInitiatedJobsPermission(true);
         assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
@@ -337,6 +597,306 @@
                 mService.getMaxJobExecutionTimeMs(jobUIDT));
     }
 
+    @Test
+    public void testGetMaxJobExecutionTimeMs_timeoutSafeguards_disabled() {
+        JobStatus jobUij = createJobStatus("testGetMaxJobExecutionTimeMs_timeoutSafeguards",
+                createJobInfo(1)
+                        .setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
+        JobStatus jobEj = createJobStatus("testGetMaxJobExecutionTimeMs_timeoutSafeguards",
+                createJobInfo(2).setExpedited(true));
+        JobStatus jobReg = createJobStatus("testGetMaxJobExecutionTimeMs_timeoutSafeguards",
+                createJobInfo(3));
+        spyOn(jobUij);
+        when(jobUij.shouldTreatAsUserInitiatedJob()).thenReturn(true);
+        jobUij.startedAsUserInitiatedJob = true;
+        spyOn(jobEj);
+        when(jobEj.shouldTreatAsExpeditedJob()).thenReturn(true);
+        jobEj.startedAsExpeditedJob = true;
+
+        QuotaController quotaController = mService.getQuotaController();
+        spyOn(quotaController);
+        TareController tareController = mService.getTareController();
+        spyOn(tareController);
+        doReturn(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
+                .when(quotaController).getMaxJobExecutionTimeMsLocked(any());
+        doReturn(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
+                .when(tareController).getMaxJobExecutionTimeMsLocked(any());
+
+        mService.mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC = false;
+        mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT = 2;
+        mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT = 2;
+        mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT = 2;
+        mService.updateQuotaTracker();
+        mService.resetScheduleQuota();
+
+        // Safeguards disabled -> no penalties.
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+
+        // 1 UIJ timeout. No max execution penalty yet.
+        mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+
+        // 2 UIJ timeouts. Safeguards disabled -> no penalties.
+        jobUij.madeActive =
+                sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS;
+        mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+
+        // 1 EJ timeout. No max execution penalty yet.
+        mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+
+        // 2 EJ timeouts. Safeguards disabled -> no penalties.
+        jobEj.madeActive =
+                sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS;
+        mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+
+        // 1 reg timeout. No max execution penalty yet.
+        mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+
+        // 2 Reg timeouts. Safeguards disabled -> no penalties.
+        jobReg.madeActive =
+                sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_GUARANTEE_MS;
+        mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+    }
+
+    @Test
+    public void testGetMaxJobExecutionTimeMs_timeoutSafeguards_enabled() {
+        JobStatus jobUij = createJobStatus("testGetMaxJobExecutionTimeMs_timeoutSafeguards",
+                createJobInfo(1)
+                        .setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
+        JobStatus jobEj = createJobStatus("testGetMaxJobExecutionTimeMs_timeoutSafeguards",
+                createJobInfo(2).setExpedited(true));
+        JobStatus jobReg = createJobStatus("testGetMaxJobExecutionTimeMs_timeoutSafeguards",
+                createJobInfo(3));
+        spyOn(jobUij);
+        when(jobUij.shouldTreatAsUserInitiatedJob()).thenReturn(true);
+        jobUij.startedAsUserInitiatedJob = true;
+        spyOn(jobEj);
+        when(jobEj.shouldTreatAsExpeditedJob()).thenReturn(true);
+        jobEj.startedAsExpeditedJob = true;
+
+        QuotaController quotaController = mService.getQuotaController();
+        spyOn(quotaController);
+        TareController tareController = mService.getTareController();
+        spyOn(tareController);
+        doReturn(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
+                .when(quotaController).getMaxJobExecutionTimeMsLocked(any());
+        doReturn(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
+                .when(tareController).getMaxJobExecutionTimeMsLocked(any());
+
+        mService.mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC = true;
+        mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT = 2;
+        mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT = 2;
+        mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT = 2;
+        mService.updateQuotaTracker();
+        mService.resetScheduleQuota();
+
+        // No timeouts -> no penalties.
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+
+        // 1 UIJ timeout. No max execution penalty yet.
+        mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+
+        // Not a timeout -> 1 UIJ timeout. No max execution penalty yet.
+        jobUij.madeActive = sUptimeMillisClock.millis() - 1;
+        mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+
+        // 2 UIJ timeouts. Max execution penalty only for UIJs.
+        jobUij.madeActive =
+                sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS;
+        mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+
+        // 1 EJ timeout. No max execution penalty yet.
+        mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+
+        // Not a timeout -> 1 EJ timeout. No max execution penalty yet.
+        jobEj.madeActive = sUptimeMillisClock.millis() - 1;
+        mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+
+        // 2 EJ timeouts. Max execution penalty for EJs.
+        jobEj.madeActive =
+                sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS;
+        mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+
+        // 1 reg timeout. No max execution penalty yet.
+        mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+
+        // Not a timeout -> 1 reg timeout. No max execution penalty yet.
+        jobReg.madeActive = sUptimeMillisClock.millis() - 1;
+        mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+
+        // 2 Reg timeouts. Max execution penalty for regular jobs.
+        jobReg.madeActive =
+                sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_GUARANTEE_MS;
+        mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+        grantRunUserInitiatedJobsPermission(true);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        grantRunUserInitiatedJobsPermission(false);
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobUij));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
+    }
+
     /**
      * Confirm that
      * {@link JobSchedulerService#getRescheduleJobForFailureLocked(JobStatus, int, int)}
@@ -1226,6 +1786,7 @@
         mService.mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION = false;
         mService.mConstants.API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = true;
         mService.updateQuotaTracker();
+        mService.resetScheduleQuota();
 
         final JobInfo job = createJobInfo().setPersisted(true).build();
         for (int i = 0; i < 500; ++i) {
@@ -1249,6 +1810,7 @@
         mService.mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION = false;
         mService.mConstants.API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = false;
         mService.updateQuotaTracker();
+        mService.resetScheduleQuota();
 
         final JobInfo job = createJobInfo().setPersisted(true).build();
         for (int i = 0; i < 500; ++i) {
@@ -1270,6 +1832,7 @@
         mService.mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION = false;
         mService.mConstants.API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = true;
         mService.updateQuotaTracker();
+        mService.resetScheduleQuota();
 
         final JobInfo job = createJobInfo().setPersisted(true).build();
         for (int i = 0; i < 500; ++i) {
@@ -1292,6 +1855,7 @@
         mService.mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION = false;
         mService.mConstants.API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = true;
         mService.updateQuotaTracker();
+        mService.resetScheduleQuota();
 
         final JobInfo job = createJobInfo().setPersisted(true).build();
         for (int i = 0; i < 500; ++i) {
@@ -1315,6 +1879,7 @@
         mService.mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION = false;
         mService.mConstants.API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = false;
         mService.updateQuotaTracker();
+        mService.resetScheduleQuota();
 
         final JobInfo job = createJobInfo().setPersisted(false).build();
         final JobWorkItem item = new JobWorkItem.Builder().build();
@@ -1337,6 +1902,7 @@
         mService.mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION = false;
         mService.mConstants.API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = false;
         mService.updateQuotaTracker();
+        mService.resetScheduleQuota();
 
         final JobInfo job = createJobInfo().setPersisted(true).build();
         final JobWorkItem item = new JobWorkItem.Builder().build();
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
index 2180a78..2b56ea8 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -73,6 +73,7 @@
 import android.util.DataUnit;
 
 import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerInternal;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.JobSchedulerService.Constants;
 import com.android.server.net.NetworkPolicyManagerInternal;
@@ -124,6 +125,10 @@
         LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
         LocalServices.addService(NetworkPolicyManagerInternal.class, mNetPolicyManagerInternal);
 
+        // Used in JobStatus.
+        LocalServices.removeServiceForTest(JobSchedulerInternal.class);
+        LocalServices.addService(JobSchedulerInternal.class, mock(JobSchedulerInternal.class));
+
         // Freeze the clocks at this moment in time
         JobSchedulerService.sSystemClock =
                 Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
index 05780eb..1de7e37 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -21,6 +21,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX;
+import static com.android.server.job.JobSchedulerService.EXEMPTED_INDEX;
 import static com.android.server.job.JobSchedulerService.FREQUENT_INDEX;
 import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
 import static com.android.server.job.JobSchedulerService.RARE_INDEX;
@@ -45,6 +46,8 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.when;
 
@@ -582,6 +585,40 @@
     }
 
     @Test
+    public void testGetEffectiveStandbyBucket_buggyApp() {
+        when(mJobSchedulerInternal.isAppConsideredBuggy(
+                anyInt(), anyString(), anyInt(), anyString()))
+                .thenReturn(true);
+
+        final JobInfo jobInfo = new JobInfo.Builder(1234, TEST_JOB_COMPONENT).build();
+        JobStatus job = createJobStatus(jobInfo);
+
+        // Exempt apps be exempting.
+        job.setStandbyBucket(EXEMPTED_INDEX);
+        assertEquals(EXEMPTED_INDEX, job.getEffectiveStandbyBucket());
+
+        // Actual bucket is higher than the buggy cap, so the cap comes into effect.
+        job.setStandbyBucket(ACTIVE_INDEX);
+        assertEquals(WORKING_INDEX, job.getEffectiveStandbyBucket());
+
+        // Buckets at the cap or below shouldn't be affected.
+        job.setStandbyBucket(WORKING_INDEX);
+        assertEquals(WORKING_INDEX, job.getEffectiveStandbyBucket());
+
+        job.setStandbyBucket(FREQUENT_INDEX);
+        assertEquals(FREQUENT_INDEX, job.getEffectiveStandbyBucket());
+
+        job.setStandbyBucket(RARE_INDEX);
+        assertEquals(RARE_INDEX, job.getEffectiveStandbyBucket());
+
+        job.setStandbyBucket(RESTRICTED_INDEX);
+        assertEquals(RESTRICTED_INDEX, job.getEffectiveStandbyBucket());
+
+        job.setStandbyBucket(NEVER_INDEX);
+        assertEquals(NEVER_INDEX, job.getEffectiveStandbyBucket());
+    }
+
+    @Test
     public void testModifyingInternalFlags() {
         final JobInfo jobInfo =
                 new JobInfo.Builder(101, new ComponentName("foo", "bar"))
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java
index fb59ea2..7cc01e1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java
@@ -58,6 +58,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerInternal;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.controllers.PrefetchController.PcConstants;
 
@@ -135,6 +136,9 @@
         when(mJobSchedulerService.getPackagesForUidLocked(anyInt()))
                 .thenAnswer(invocationOnMock
                         -> mPackagesForUid.get(invocationOnMock.getArgument(0)));
+        // Used in JobStatus.
+        doReturn(mock(JobSchedulerInternal.class))
+                .when(() -> LocalServices.getService(JobSchedulerInternal.class));
 
         // Freeze the clocks at 24 hours after this moment in time. Several tests create sessions
         // in the past, and PrefetchController sometimes floors values at 0, so if the test time
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index 6f713e0..dce162c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -85,6 +85,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.server.LocalServices;
 import com.android.server.PowerAllowlistInternal;
+import com.android.server.job.JobSchedulerInternal;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.JobStore;
 import com.android.server.job.controllers.QuotaController.ExecutionStats;
@@ -190,6 +191,8 @@
         doReturn(mPowerAllowlistInternal)
                 .when(() -> LocalServices.getService(PowerAllowlistInternal.class));
         // Used in JobStatus.
+        doReturn(mock(JobSchedulerInternal.class))
+                .when(() -> LocalServices.getService(JobSchedulerInternal.class));
         doReturn(mPackageManagerInternal)
                 .when(() -> LocalServices.getService(PackageManagerInternal.class));
         // Used in QuotaController.Handler.
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt
index cfef0b2..5fd270e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt
@@ -48,6 +48,7 @@
         const val UNINSTALLER_PACKAGE = "com.android.test.known.uninstaller"
         const val VERIFIER_PACKAGE = "com.android.test.known.verifier"
         const val PERMISSION_CONTROLLER_PACKAGE = "com.android.test.known.permission"
+        const val MGMT_ROLE_HOLDER_PACKAGE = "com.android.test.know.device_management"
         const val TEST_USER_ID = 0
     }
 
@@ -119,6 +120,8 @@
         Mockito.doReturn(arrayOf(PERMISSION_CONTROLLER_PACKAGE)).`when`(pms)
                 .getKnownPackageNamesInternal(any(),
                         eq(KnownPackages.PACKAGE_PERMISSION_CONTROLLER), eq(TEST_USER_ID))
+        Mockito.doReturn(MGMT_ROLE_HOLDER_PACKAGE).`when`(pms)
+                .getDevicePolicyManagementRoleHolderPackageName(eq(TEST_USER_ID))
     }
 
     private fun createPackageManagerService(vararg stageExistingPackages: String):
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
index f9a8ead..5cca5fa 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
@@ -128,13 +128,14 @@
     fun setPackagesSuspended_forQuietMode() {
         val knownPackages = arrayOf(DEVICE_ADMIN_PACKAGE, DEFAULT_HOME_PACKAGE, DIALER_PACKAGE,
                 INSTALLER_PACKAGE, UNINSTALLER_PACKAGE, VERIFIER_PACKAGE,
-                PERMISSION_CONTROLLER_PACKAGE)
+                PERMISSION_CONTROLLER_PACKAGE, MGMT_ROLE_HOLDER_PACKAGE)
         val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 knownPackages, true /* suspended */, null /* appExtras */,
                 null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
                 TEST_USER_ID, deviceOwnerUid, true /* forQuietMode */)!!
 
-        assertThat(failedNames.size).isEqualTo(0)
+        assertThat(failedNames.size).isEqualTo(1)
+        assertThat(failedNames[0]).isEqualTo(MGMT_ROLE_HOLDER_PACKAGE)
     }
 
     @Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
index 51e521d..206af5b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
@@ -17,8 +17,10 @@
 package com.android.server.wallpaper;
 
 import static android.app.WallpaperManager.COMMAND_REAPPLY;
+import static android.app.WallpaperManager.FLAG_LOCK;
 import static android.app.WallpaperManager.FLAG_SYSTEM;
 import static android.os.FileObserver.CLOSE_WRITE;
+import static android.os.UserHandle.MIN_SECONDARY_USER_ID;
 import static android.os.UserHandle.USER_SYSTEM;
 import static android.view.Display.DEFAULT_DISPLAY;
 
@@ -106,6 +108,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
+import java.util.List;
 
 /**
  * Tests for the {@link WallpaperManagerService} class.
@@ -172,12 +175,12 @@
         sImageWallpaperComponentName = ComponentName.unflattenFromString(
                 sContext.getResources().getString(R.string.image_wallpaper_component));
         // Mock default wallpaper as image wallpaper if there is no pre-defined default wallpaper.
-        sDefaultWallpaperComponent = WallpaperManager.getCmfDefaultWallpaperComponent(sContext);
+        sDefaultWallpaperComponent = WallpaperManager.getDefaultWallpaperComponent(sContext);
 
         if (sDefaultWallpaperComponent == null) {
             sDefaultWallpaperComponent = sImageWallpaperComponentName;
             doReturn(sImageWallpaperComponentName).when(() ->
-                    WallpaperManager.getCmfDefaultWallpaperComponent(any()));
+                    WallpaperManager.getDefaultWallpaperComponent(any()));
         } else {
             sContext.addMockService(sDefaultWallpaperComponent, sWallpaperService);
         }
@@ -262,6 +265,25 @@
     }
 
     /**
+     * Tests that the fundamental fields are set by the main WallpaperData constructor
+     */
+    @Test
+    public void testWallpaperDataConstructor() {
+        final int testUserId = MIN_SECONDARY_USER_ID;
+        for (int which: List.of(FLAG_LOCK, FLAG_SYSTEM)) {
+            WallpaperData newWallpaperData = new WallpaperData(testUserId, which);
+            assertEquals(which, newWallpaperData.mWhich);
+            assertEquals(testUserId, newWallpaperData.userId);
+
+            WallpaperData wallpaperData = mService.getWallpaperSafeLocked(testUserId, which);
+            assertEquals(wallpaperData.cropFile.getAbsolutePath(),
+                    newWallpaperData.cropFile.getAbsolutePath());
+            assertEquals(wallpaperData.wallpaperFile.getAbsolutePath(),
+                    newWallpaperData.wallpaperFile.getAbsolutePath());
+        }
+    }
+
+    /**
      * Tests that internal basic data should be correct after boot up.
      */
     @Test
@@ -405,10 +427,7 @@
             fail("exception occurred while writing system wallpaper attributes");
         }
 
-        WallpaperData shouldMatchSystem = new WallpaperData(systemWallpaperData.userId,
-                systemWallpaperData.wallpaperFile.getParentFile(),
-                systemWallpaperData.wallpaperFile.getAbsolutePath(),
-                systemWallpaperData.cropFile.getAbsolutePath());
+        WallpaperData shouldMatchSystem = new WallpaperData(0, FLAG_SYSTEM);
         try {
             TypedXmlPullParser parser = Xml.newBinaryPullParser();
             mService.mWallpaperDataParser.parseWallpaperAttributes(parser, shouldMatchSystem, true);
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index cfeaf0b..16e1b45 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -114,7 +114,6 @@
         ":SimpleServiceTestApp1",
         ":SimpleServiceTestApp2",
         ":SimpleServiceTestApp3",
-        ":StubTestApp",
         ":SuspendTestApp",
         ":MediaButtonReceiverHolderTestHelperApp",
         "data/broken_shortcut.xml",
diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml
index b304968..fbb0ca1 100644
--- a/services/tests/servicestests/AndroidTest.xml
+++ b/services/tests/servicestests/AndroidTest.xml
@@ -44,11 +44,6 @@
         <option name="teardown-command" value="rm -rf /data/local/tmp/servicestests"/>
     </target_preparer>
 
-    <!-- Load additional APKs onto device -->
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
-        <option name="push" value="StubTestApp.apk->/data/local/tmp/servicestests/StubTestApp.apk"/>
-    </target_preparer>
-
     <option name="test-tag" value="FrameworksServicesTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.frameworks.servicestests" />
diff --git a/services/tests/servicestests/src/com/android/server/credentials/MetricUtilitiesTest.java b/services/tests/servicestests/src/com/android/server/credentials/MetricUtilitiesTest.java
index b46f1a6..50ea487 100644
--- a/services/tests/servicestests/src/com/android/server/credentials/MetricUtilitiesTest.java
+++ b/services/tests/servicestests/src/com/android/server/credentials/MetricUtilitiesTest.java
@@ -15,14 +15,27 @@
  */
 package com.android.server.credentials;
 
+import android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.server.credentials.metrics.BrowsedAuthenticationMetric;
+import com.android.server.credentials.metrics.CandidateAggregateMetric;
+import com.android.server.credentials.metrics.CandidateBrowsingPhaseMetric;
+import com.android.server.credentials.metrics.ChosenProviderFinalPhaseMetric;
 import com.android.server.credentials.metrics.InitialPhaseMetric;
 
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.security.cert.CertificateException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * Given the secondary-system nature of the MetricUtilities, we expect absolutely nothing to
  * throw an error. If one presents itself, that is problematic.
@@ -33,6 +46,11 @@
 @SmallTest
 public final class MetricUtilitiesTest {
 
+    @Before
+    public void setUp() throws CertificateException {
+        final Context context = ApplicationProvider.getApplicationContext();
+    }
+
     @Test
     public void logApiCalledInitialPhase_nullInitPhaseMetricAndNegativeSequence_success() {
         MetricUtilities.logApiCalledInitialPhase(null, -1);
@@ -49,4 +67,102 @@
                 MetricUtilities.getHighlyUniqueInteger());
         MetricUtilities.logApiCalledInitialPhase(validInitPhaseMetric, 1);
     }
+
+    @Test
+    public void logApiCalledTotalCandidate_nullCandidateNegativeSequence_success() {
+        MetricUtilities.logApiCalledAggregateCandidate(null, -1);
+    }
+
+    @Test
+    public void logApiCalledTotalCandidate_invalidCandidatePhasePositiveSequence_success() {
+        MetricUtilities.logApiCalledAggregateCandidate(new CandidateAggregateMetric(-1), 1);
+    }
+
+    @Test
+    public void logApiCalledTotalCandidate_validPhaseMetric_success() {
+        MetricUtilities.logApiCalledAggregateCandidate(
+                new CandidateAggregateMetric(MetricUtilities.getHighlyUniqueInteger()), 1);
+    }
+
+    @Test
+    public void logApiCalledNoUidFinal_nullNoUidFinalNegativeSequenceAndStatus_success() {
+        MetricUtilities.logApiCalledNoUidFinal(null, null,
+                -1, -1);
+    }
+
+    @Test
+    public void logApiCalledNoUidFinal_invalidNoUidFinalPhasePositiveSequenceAndStatus_success() {
+        MetricUtilities.logApiCalledNoUidFinal(new ChosenProviderFinalPhaseMetric(-1, -1),
+                List.of(new CandidateBrowsingPhaseMetric()), 1, 1);
+    }
+
+    @Test
+    public void logApiCalledNoUidFinal_validNoUidFinalMetric_success() {
+        MetricUtilities.logApiCalledNoUidFinal(
+                new ChosenProviderFinalPhaseMetric(MetricUtilities.getHighlyUniqueInteger(),
+                        MetricUtilities.getHighlyUniqueInteger()),
+                List.of(new CandidateBrowsingPhaseMetric()), 1, 1);
+    }
+
+    @Test
+    public void logApiCalledCandidate_nullMapNullInitFinalNegativeSequence_success() {
+        MetricUtilities.logApiCalledCandidatePhase(null, -1,
+                null);
+    }
+
+    @Test
+    public void logApiCalledCandidate_invalidProvidersCandidatePositiveSequence_success() {
+        Map<String, ProviderSession> testMap = new HashMap<>();
+        testMap.put("s", null);
+        MetricUtilities.logApiCalledCandidatePhase(testMap, 1,
+                null);
+    }
+
+    @Test
+    public void logApiCalledCandidateGet_nullMapFinalNegativeSequence_success() {
+        MetricUtilities.logApiCalledCandidateGetMetric(null, -1);
+    }
+
+    @Test
+    public void logApiCalledCandidateGet_invalidProvidersCandidatePositiveSequence_success() {
+        Map<String, ProviderSession> testMap = new HashMap<>();
+        testMap.put("s", null);
+        MetricUtilities.logApiCalledCandidateGetMetric(testMap, 1);
+    }
+
+    @Test
+    public void logApiCalledAuthMetric_nullAuthMetricNegativeSequence_success() {
+        MetricUtilities.logApiCalledAuthenticationMetric(null, -1);
+    }
+
+    @Test
+    public void logApiCalledAuthMetric_invalidAuthMetricPositiveSequence_success() {
+        MetricUtilities.logApiCalledAuthenticationMetric(new BrowsedAuthenticationMetric(-1), 1);
+    }
+
+    @Test
+    public void logApiCalledAuthMetric_nullAuthMetricPositiveSequence_success() {
+        MetricUtilities.logApiCalledAuthenticationMetric(
+                new BrowsedAuthenticationMetric(MetricUtilities.getHighlyUniqueInteger()), -1);
+    }
+
+    @Test
+    public void logApiCalledFinal_nullFinalNegativeSequenceAndStatus_success() {
+        MetricUtilities.logApiCalledFinalPhase(null, null,
+                -1, -1);
+    }
+
+    @Test
+    public void logApiCalledFinal_invalidFinalPhasePositiveSequenceAndStatus_success() {
+        MetricUtilities.logApiCalledFinalPhase(new ChosenProviderFinalPhaseMetric(-1, -1),
+                List.of(new CandidateBrowsingPhaseMetric()), 1, 1);
+    }
+
+    @Test
+    public void logApiCalledFinal_validFinalMetric_success() {
+        MetricUtilities.logApiCalledFinalPhase(
+                new ChosenProviderFinalPhaseMetric(MetricUtilities.getHighlyUniqueInteger(),
+                        MetricUtilities.getHighlyUniqueInteger()),
+                List.of(new CandidateBrowsingPhaseMetric()), 1, 1);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 933f002..5c6164e 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -18,8 +18,6 @@
 
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
-import static android.app.AppOpsManager.MODE_ALLOWED;
-import static android.app.AppOpsManager.MODE_ERRORED;
 import static android.os.PowerManager.USER_ACTIVITY_EVENT_BUTTON;
 import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
 import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
@@ -44,6 +42,7 @@
 import static org.mockito.Mockito.atMost;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -51,13 +50,14 @@
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManagerInternal;
-import android.app.AppOpsManager;
 import android.attention.AttentionManagerInternal;
+import android.compat.testing.PlatformCompatChangeRule;
+import android.content.AttributionSource;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.PackageManager;
+import android.content.PermissionChecker;
 import android.content.res.Resources;
 import android.hardware.SensorManager;
 import android.hardware.display.AmbientDisplayConfiguration;
@@ -95,7 +95,6 @@
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.power.PowerManagerService.BatteryReceiver;
 import com.android.server.power.PowerManagerService.BinderService;
-import com.android.server.power.PowerManagerService.Injector;
 import com.android.server.power.PowerManagerService.NativeWrapper;
 import com.android.server.power.PowerManagerService.UserSwitchedReceiver;
 import com.android.server.power.PowerManagerService.WakeLock;
@@ -105,9 +104,14 @@
 import com.android.server.power.batterysaver.BatterySavingStats;
 import com.android.server.testutils.OffsettableClock;
 
+import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
+import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
+
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.mockito.ArgumentCaptor;
 import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
@@ -150,12 +154,13 @@
     @Mock private WirelessChargerDetector mWirelessChargerDetectorMock;
     @Mock private AmbientDisplayConfiguration mAmbientDisplayConfigurationMock;
     @Mock private SystemPropertiesWrapper mSystemPropertiesMock;
-    @Mock private AppOpsManager mAppOpsManagerMock;
     @Mock private LowPowerStandbyController mLowPowerStandbyControllerMock;
     @Mock private Callable<Void> mInvalidateInteractiveCachesMock;
+    @Mock private InattentiveSleepWarningController mInattentiveSleepWarningControllerMock;
+    @Mock private PowerManagerService.PermissionCheckerWrapper mPermissionCheckerWrapperMock;
+    @Mock private PowerManagerService.PowerPropertiesWrapper mPowerPropertiesWrapper;
 
-    @Mock
-    private InattentiveSleepWarningController mInattentiveSleepWarningControllerMock;
+    @Rule public TestRule compatChangeRule = new PlatformCompatChangeRule();
 
     private PowerManagerService mService;
     private ContextWrapper mContextSpy;
@@ -231,7 +236,7 @@
     }
 
     private PowerManagerService createService() {
-        mService = new PowerManagerService(mContextSpy, new Injector() {
+        mService = new PowerManagerService(mContextSpy, new PowerManagerService.Injector() {
             @Override
             Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
                     SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
@@ -327,8 +332,13 @@
             }
 
             @Override
-            AppOpsManager createAppOpsManager(Context context) {
-                return mAppOpsManagerMock;
+            PowerManagerService.PermissionCheckerWrapper createPermissionCheckerWrapper() {
+                return mPermissionCheckerWrapperMock;
+            }
+
+            @Override
+            PowerManagerService.PowerPropertiesWrapper createPowerPropertiesWrapper() {
+                return mPowerPropertiesWrapper;
             }
         });
         return mService;
@@ -589,6 +599,7 @@
     }
 
     @Test
+    @EnableCompatChanges({PowerManagerService.REQUIRE_TURN_SCREEN_ON_PERMISSION})
     public void testWakefulnessAwake_AcquireCausesWakeup_turnScreenOnAllowed() {
         createService();
         startSystem();
@@ -597,11 +608,12 @@
         IBinder token = new Binder();
         String tag = "acq_causes_wakeup";
         String packageName = "pkg.name";
-        when(mAppOpsManagerMock.checkOpNoThrow(AppOpsManager.OP_TURN_SCREEN_ON,
-                Binder.getCallingUid(), packageName)).thenReturn(MODE_ALLOWED);
-        when(mContextSpy.checkCallingOrSelfPermission(
-                android.Manifest.permission.TURN_SCREEN_ON)).thenReturn(
-                PackageManager.PERMISSION_GRANTED);
+        AttributionSource attrSrc = new AttributionSource(Binder.getCallingUid(),
+                packageName, /* attributionTag= */ null);
+
+        doReturn(PermissionChecker.PERMISSION_GRANTED).when(
+                mPermissionCheckerWrapperMock).checkPermissionForDataDelivery(any(),
+                eq(android.Manifest.permission.TURN_SCREEN_ON), anyInt(), eq(attrSrc), anyString());
 
         // First, ensure that a normal full wake lock does not cause a wakeup
         int flags = PowerManager.FULL_WAKE_LOCK;
@@ -626,6 +638,35 @@
     }
 
     @Test
+    @DisableCompatChanges({PowerManagerService.REQUIRE_TURN_SCREEN_ON_PERMISSION})
+    public void testWakefulnessAwake_AcquireCausesWakeupOldSdk_turnScreenOnAllowed() {
+        createService();
+        startSystem();
+        forceSleep();
+
+        IBinder token = new Binder();
+        String tag = "acq_causes_wakeup";
+        String packageName = "pkg.name";
+        AttributionSource attrSrc = new AttributionSource(Binder.getCallingUid(),
+                packageName, /* attributionTag= */ null);
+
+        // verify that the wakeup is allowed for apps targeting older sdks, and therefore won't have
+        // the TURN_SCREEN_ON permission granted
+        doReturn(PermissionChecker.PERMISSION_HARD_DENIED).when(
+                mPermissionCheckerWrapperMock).checkPermissionForDataDelivery(any(),
+                eq(android.Manifest.permission.TURN_SCREEN_ON), anyInt(), eq(attrSrc), anyString());
+
+        doReturn(false).when(mPowerPropertiesWrapper).waive_target_sdk_check_for_turn_screen_on();
+
+        int flags = PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
+        mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
+                null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, null);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
+    }
+
+    @Test
+    @EnableCompatChanges({PowerManagerService.REQUIRE_TURN_SCREEN_ON_PERMISSION})
     public void testWakefulnessAwake_AcquireCausesWakeup_turnScreenOnDenied() {
         createService();
         startSystem();
@@ -634,30 +675,43 @@
         IBinder token = new Binder();
         String tag = "acq_causes_wakeup";
         String packageName = "pkg.name";
-        when(mAppOpsManagerMock.checkOpNoThrow(AppOpsManager.OP_TURN_SCREEN_ON,
-                Binder.getCallingUid(), packageName)).thenReturn(MODE_ERRORED);
+        AttributionSource attrSrc = new AttributionSource(Binder.getCallingUid(),
+                packageName, /* attributionTag= */ null);
+        doReturn(PermissionChecker.PERMISSION_HARD_DENIED).when(
+                mPermissionCheckerWrapperMock).checkPermissionForDataDelivery(any(),
+                eq(android.Manifest.permission.TURN_SCREEN_ON), anyInt(), eq(attrSrc), anyString());
 
+        doReturn(false).when(mPowerPropertiesWrapper).waive_target_sdk_check_for_turn_screen_on();
+        doReturn(false).when(mPowerPropertiesWrapper).permissionless_turn_screen_on();
 
-        // Verify that flag has no effect when OP_TURN_SCREEN_ON is not allowed
+        // Verify that flag has no effect when TURN_SCREEN_ON is not allowed for apps targeting U+
         int flags = PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
         mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
                 null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, null);
-        if (PowerProperties.permissionless_turn_screen_on().orElse(false)) {
-            assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
-        } else {
-            assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
-        }
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
         mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
+    }
 
-        when(mAppOpsManagerMock.checkOpNoThrow(AppOpsManager.OP_TURN_SCREEN_ON,
-                Binder.getCallingUid(), packageName)).thenReturn(MODE_ALLOWED);
-        when(mContextSpy.checkCallingOrSelfPermission(
-                android.Manifest.permission.TURN_SCREEN_ON)).thenReturn(
-                PackageManager.PERMISSION_DENIED);
+    @Test
+    @EnableCompatChanges({PowerManagerService.REQUIRE_TURN_SCREEN_ON_PERMISSION})
+    public void testWakefulnessAwake_AcquireCausesWakeupOldSdk_turnScreenOnDenied() {
+        createService();
+        startSystem();
+        forceSleep();
 
-        // Verify that the flag has no effect when OP_TURN_SCREEN_ON is allowed but
-        // android.permission.TURN_SCREEN_ON is denied
-        flags = PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
+        IBinder token = new Binder();
+        String tag = "acq_causes_wakeup";
+        String packageName = "pkg.name";
+        AttributionSource attrSrc = new AttributionSource(Binder.getCallingUid(),
+                packageName, /* attributionTag= */ null);
+        doReturn(PermissionChecker.PERMISSION_HARD_DENIED).when(
+                mPermissionCheckerWrapperMock).checkPermissionForDataDelivery(any(),
+                eq(android.Manifest.permission.TURN_SCREEN_ON), anyInt(), eq(attrSrc), anyString());
+
+        doReturn(true).when(mPowerPropertiesWrapper).waive_target_sdk_check_for_turn_screen_on();
+
+        // Verify that flag has no effect when TURN_SCREEN_ON is not allowed for apps targeting U+
+        int flags = PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
         mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
                 null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, null);
         if (PowerProperties.permissionless_turn_screen_on().orElse(false)) {
diff --git a/services/tests/uiservicestests/AndroidManifest.xml b/services/tests/uiservicestests/AndroidManifest.xml
index f44c1d1..4315254 100644
--- a/services/tests/uiservicestests/AndroidManifest.xml
+++ b/services/tests/uiservicestests/AndroidManifest.xml
@@ -20,6 +20,7 @@
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
+    <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
     <uses-permission android:name="android.permission.MANAGE_USERS" />
     <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
     <uses-permission android:name="android.permission.ACCESS_NOTIFICATIONS" />
@@ -36,6 +37,7 @@
     <uses-permission android:name="android.permission.WRITE_ALLOWLISTED_DEVICE_CONFIG" />
     <uses-permission android:name="android.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG" />
     <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
 
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
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 9166b3d..2a0c745 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -61,6 +61,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.Build.VERSION_CODES.O_MR1;
 import static android.os.Build.VERSION_CODES.P;
+import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
 import static android.os.UserHandle.USER_SYSTEM;
 import static android.os.UserManager.USER_TYPE_FULL_SECONDARY;
 import static android.os.UserManager.USER_TYPE_PROFILE_CLONE;
@@ -80,6 +81,7 @@
 import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.ALLOW_DISMISS_ONGOING;
 import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.FSI_FORCE_DEMOTE;
 import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.SHOW_STICKY_HUN_FOR_DENIED_FSI;
+import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.WAKE_LOCK_FOR_POSTING_NOTIFICATION;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
 import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_ADJUSTED;
 import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED;
@@ -119,12 +121,14 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 import static java.util.Collections.emptyList;
 import static java.util.Collections.singletonList;
 
 import android.Manifest;
+import android.annotation.Nullable;
 import android.annotation.SuppressLint;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
@@ -181,11 +185,14 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Parcel;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.WorkSource;
 import android.permission.PermissionManager;
 import android.provider.DeviceConfig;
 import android.provider.MediaStore;
@@ -351,6 +358,9 @@
     private PermissionManager mPermissionManager;
     @Mock
     private DevicePolicyManagerInternal mDevicePolicyManager;
+    @Mock
+    private PowerManager mPowerManager;
+    private final ArrayList<WakeLock> mAcquiredWakeLocks = new ArrayList<>();
     private final TestPostNotificationTrackerFactory mPostNotificationTrackerFactory =
             new TestPostNotificationTrackerFactory();
 
@@ -431,8 +441,9 @@
         private final List<PostNotificationTracker> mCreatedTrackers = new ArrayList<>();
 
         @Override
-        public PostNotificationTracker newTracker() {
-            PostNotificationTracker tracker = PostNotificationTrackerFactory.super.newTracker();
+        public PostNotificationTracker newTracker(@Nullable WakeLock optionalWakeLock) {
+            PostNotificationTracker tracker = PostNotificationTrackerFactory.super.newTracker(
+                    optionalWakeLock);
             mCreatedTrackers.add(tracker);
             return tracker;
         }
@@ -563,6 +574,20 @@
 
         when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
 
+        // Use the real PowerManager to back up the mock w.r.t. creating WakeLocks.
+        // This is because 1) we need a mock to verify() calls and tracking the created WakeLocks,
+        // but 2) PowerManager and WakeLock perform their own checks (e.g. correct arguments, don't
+        // call release twice, etc) and we want the test to fail if such misuse happens, too.
+        PowerManager realPowerManager = mContext.getSystemService(PowerManager.class);
+        when(mPowerManager.newWakeLock(anyInt(), anyString())).then(
+                (Answer<WakeLock>) invocation -> {
+                    WakeLock wl = realPowerManager.newWakeLock(invocation.getArgument(0),
+                            invocation.getArgument(1));
+                    mAcquiredWakeLocks.add(wl);
+                    return wl;
+                });
+        mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, true);
+
         // apps allowed as convos
         mService.setStringArrayResourceValue(PKG_O);
 
@@ -579,7 +604,7 @@
                 mock(TelephonyManager.class),
                 mAmi, mToastRateLimiter, mPermissionHelper, mock(UsageStatsManagerInternal.class),
                 mTelecomManager, mLogger, mTestFlagResolver, mPermissionManager,
-                mPostNotificationTrackerFactory);
+                mPowerManager, mPostNotificationTrackerFactory);
         // Return first true for RoleObserver main-thread check
         when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false);
         mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper);
@@ -686,6 +711,13 @@
     }
 
     @After
+    public void assertAllWakeLocksReleased() {
+        for (WakeLock wakeLock : mAcquiredWakeLocks) {
+            assertThat(wakeLock.isHeld()).isFalse();
+        }
+    }
+
+    @After
     public void tearDown() throws Exception {
         if (mFile != null) mFile.delete();
         clearDeviceConfig();
@@ -1486,7 +1518,7 @@
 
         NotificationManagerService.PostNotificationRunnable runnable =
                 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
-                        r.getUid(), mPostNotificationTrackerFactory.newTracker());
+                        r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
         runnable.run();
         waitForIdle();
 
@@ -1507,7 +1539,7 @@
 
         NotificationManagerService.PostNotificationRunnable runnable =
                 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
-                        r.getUid(), mPostNotificationTrackerFactory.newTracker());
+                        r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
         runnable.run();
         waitForIdle();
 
@@ -1803,6 +1835,112 @@
     }
 
     @Test
+    public void enqueueNotification_acquiresAndReleasesWakeLock() throws Exception {
+        mBinderService.enqueueNotificationWithTag(PKG, PKG,
+                "enqueueNotification_acquiresAndReleasesWakeLock", 0,
+                generateNotificationRecord(null).getNotification(), 0);
+
+        verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString());
+        assertThat(mAcquiredWakeLocks).hasSize(1);
+        assertThat(mAcquiredWakeLocks.get(0).isHeld()).isTrue();
+
+        waitForIdle();
+
+        assertThat(mAcquiredWakeLocks).hasSize(1);
+        assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse();
+    }
+
+    @Test
+    public void enqueueNotification_throws_acquiresAndReleasesWakeLock() throws Exception {
+        // Simulate not enqueued due to rejected inputs.
+        assertThrows(Exception.class,
+                () -> mBinderService.enqueueNotificationWithTag(PKG, PKG,
+                        "enqueueNotification_throws_acquiresAndReleasesWakeLock", 0,
+                        /* notification= */ null, 0));
+
+        verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString());
+        assertThat(mAcquiredWakeLocks).hasSize(1);
+        assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse();
+    }
+
+    @Test
+    public void enqueueNotification_notEnqueued_acquiresAndReleasesWakeLock() throws Exception {
+        // Simulate not enqueued due to snoozing inputs.
+        when(mSnoozeHelper.getSnoozeContextForUnpostedNotification(anyInt(), any(), any()))
+                .thenReturn("zzzzzzz");
+
+        mBinderService.enqueueNotificationWithTag(PKG, PKG,
+                "enqueueNotification_notEnqueued_acquiresAndReleasesWakeLock", 0,
+                generateNotificationRecord(null).getNotification(), 0);
+
+        verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString());
+        assertThat(mAcquiredWakeLocks).hasSize(1);
+        assertThat(mAcquiredWakeLocks.get(0).isHeld()).isTrue();
+
+        waitForIdle();
+
+        assertThat(mAcquiredWakeLocks).hasSize(1);
+        assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse();
+    }
+
+    @Test
+    public void enqueueNotification_notPosted_acquiresAndReleasesWakeLock() throws Exception {
+        // Simulate enqueued but not posted due to missing small icon.
+        Notification notif = new Notification.Builder(mContext, mTestNotificationChannel.getId())
+                .setContentTitle("foo")
+                .build();
+
+        mBinderService.enqueueNotificationWithTag(PKG, PKG,
+                "enqueueNotification_notPosted_acquiresAndReleasesWakeLock", 0,
+                notif, 0);
+
+        verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString());
+        assertThat(mAcquiredWakeLocks).hasSize(1);
+        assertThat(mAcquiredWakeLocks.get(0).isHeld()).isTrue();
+
+        waitForIdle();
+
+        // NLSes were not called.
+        verify(mListeners, never()).prepareNotifyPostedLocked(any(), any(), anyBoolean());
+
+        assertThat(mAcquiredWakeLocks).hasSize(1);
+        assertThat(mAcquiredWakeLocks.get(0).isHeld()).isFalse();
+    }
+
+    @Test
+    public void enqueueNotification_setsWakeLockWorkSource() throws Exception {
+        // Use a "full" mock for the PowerManager (instead of the one that delegates to the real
+        // service) so we can return a mocked WakeLock that we can verify() on.
+        reset(mPowerManager);
+        WakeLock wakeLock = mock(WakeLock.class);
+        when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(wakeLock);
+
+        mBinderService.enqueueNotificationWithTag(PKG, PKG,
+                "enqueueNotification_setsWakeLockWorkSource", 0,
+                generateNotificationRecord(null).getNotification(), 0);
+        waitForIdle();
+
+        InOrder inOrder = inOrder(mPowerManager, wakeLock);
+        inOrder.verify(mPowerManager).newWakeLock(eq(PARTIAL_WAKE_LOCK), anyString());
+        inOrder.verify(wakeLock).setWorkSource(eq(new WorkSource(mUid, PKG)));
+        inOrder.verify(wakeLock).acquire(anyLong());
+        inOrder.verify(wakeLock).release();
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void enqueueNotification_wakeLockFlagOff_noWakeLock() throws Exception {
+        mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, false);
+
+        mBinderService.enqueueNotificationWithTag(PKG, PKG,
+                "enqueueNotification_setsWakeLockWorkSource", 0,
+                generateNotificationRecord(null).getNotification(), 0);
+        waitForIdle();
+
+        verifyZeroInteractions(mPowerManager);
+    }
+
+    @Test
     public void testCancelNonexistentNotification() throws Exception {
         mBinderService.cancelNotificationWithTag(PKG, PKG,
                 "testCancelNonexistentNotification", 0, 0);
@@ -4361,7 +4499,7 @@
         mService.addEnqueuedNotification(r);
         NotificationManagerService.PostNotificationRunnable runnable =
                 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
-                        r.getUid(), mPostNotificationTrackerFactory.newTracker());
+                        r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
         runnable.run();
         waitForIdle();
 
@@ -4380,7 +4518,7 @@
         NotificationManagerService.PostNotificationRunnable runnable =
                 mService.new PostNotificationRunnable(update.getKey(),
                         update.getSbn().getPackageName(), update.getUid(),
-                        mPostNotificationTrackerFactory.newTracker());
+                        mPostNotificationTrackerFactory.newTracker(null));
         runnable.run();
         waitForIdle();
 
@@ -4400,7 +4538,7 @@
         NotificationManagerService.PostNotificationRunnable runnable =
                 mService.new PostNotificationRunnable(update.getKey(),
                         update.getSbn().getPackageName(), update.getUid(),
-                        mPostNotificationTrackerFactory.newTracker());
+                        mPostNotificationTrackerFactory.newTracker(null));
         runnable.run();
         waitForIdle();
 
@@ -4420,7 +4558,7 @@
         NotificationManagerService.PostNotificationRunnable runnable =
                 mService.new PostNotificationRunnable(update.getKey(),
                         update.getSbn().getPackageName(),
-                        update.getUid(), mPostNotificationTrackerFactory.newTracker());
+                        update.getUid(), mPostNotificationTrackerFactory.newTracker(null));
         runnable.run();
         waitForIdle();
 
@@ -4434,13 +4572,13 @@
         mService.addEnqueuedNotification(r);
         NotificationManagerService.PostNotificationRunnable runnable =
                 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
-                        r.getUid(), mPostNotificationTrackerFactory.newTracker());
+                        r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
         runnable.run();
 
         r = generateNotificationRecord(mTestNotificationChannel, 1, null, false);
         r.setCriticality(CriticalNotificationExtractor.CRITICAL);
         runnable = mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
-                r.getUid(), mPostNotificationTrackerFactory.newTracker());
+                r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
         mService.addEnqueuedNotification(r);
 
         runnable.run();
@@ -5090,7 +5228,7 @@
                 mService.new PostNotificationRunnable(original.getKey(),
                         original.getSbn().getPackageName(),
                         original.getUid(),
-                        mPostNotificationTrackerFactory.newTracker());
+                        mPostNotificationTrackerFactory.newTracker(null));
         runnable.run();
         waitForIdle();
 
@@ -5114,7 +5252,7 @@
                 mService.new PostNotificationRunnable(update.getKey(),
                         update.getSbn().getPackageName(),
                         update.getUid(),
-                        mPostNotificationTrackerFactory.newTracker());
+                        mPostNotificationTrackerFactory.newTracker(null));
         runnable.run();
         waitForIdle();
 
@@ -7536,7 +7674,7 @@
 
         NotificationManagerService.PostNotificationRunnable runnable =
                 mService.new PostNotificationRunnable(update.getKey(), r.getSbn().getPackageName(),
-                        r.getUid(), mPostNotificationTrackerFactory.newTracker());
+                        r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
         runnable.run();
         waitForIdle();
 
@@ -10234,7 +10372,7 @@
         mService.addEnqueuedNotification(r);
         NotificationManagerService.PostNotificationRunnable runnable =
                 mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
-                        r.getUid(), mPostNotificationTrackerFactory.newTracker());
+                        r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
         runnable.run();
         waitForIdle();
 
@@ -10251,7 +10389,7 @@
 
         mService.addEnqueuedNotification(r);
         runnable = mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
-                r.getUid(), mPostNotificationTrackerFactory.newTracker());
+                r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
         runnable.run();
         waitForIdle();
 
@@ -10268,7 +10406,7 @@
 
         mService.addEnqueuedNotification(r);
         runnable = mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
-                r.getUid(), mPostNotificationTrackerFactory.newTracker());
+                r.getUid(), mPostNotificationTrackerFactory.newTracker(null));
         runnable.run();
         waitForIdle();
 
@@ -10361,7 +10499,7 @@
         // normal blocked notifications - blocked
         mService.addEnqueuedNotification(r);
         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
-                mPostNotificationTrackerFactory.newTracker()).run();
+                mPostNotificationTrackerFactory.newTracker(null)).run();
         waitForIdle();
 
         verify(mUsageStats).registerBlocked(any());
@@ -10379,7 +10517,7 @@
 
         mService.addEnqueuedNotification(r);
         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
-                mPostNotificationTrackerFactory.newTracker()).run();
+                mPostNotificationTrackerFactory.newTracker(null)).run();
         waitForIdle();
 
         verify(mUsageStats).registerBlocked(any());
@@ -10392,7 +10530,7 @@
 
         mService.addEnqueuedNotification(r);
         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
-                mPostNotificationTrackerFactory.newTracker()).run();
+                mPostNotificationTrackerFactory.newTracker(null)).run();
         waitForIdle();
 
         verify(mUsageStats, never()).registerBlocked(any());
@@ -10406,7 +10544,7 @@
 
         mService.addEnqueuedNotification(r);
         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
-                mPostNotificationTrackerFactory.newTracker()).run();
+                mPostNotificationTrackerFactory.newTracker(null)).run();
         waitForIdle();
 
         verify(mUsageStats, never()).registerBlocked(any());
@@ -10420,7 +10558,7 @@
 
         mService.addEnqueuedNotification(r);
         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
-                mPostNotificationTrackerFactory.newTracker()).run();
+                mPostNotificationTrackerFactory.newTracker(null)).run();
         waitForIdle();
 
         verify(mUsageStats).registerBlocked(any());
@@ -10435,7 +10573,7 @@
 
         mService.addEnqueuedNotification(r);
         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
-                mPostNotificationTrackerFactory.newTracker()).run();
+                mPostNotificationTrackerFactory.newTracker(null)).run();
         waitForIdle();
 
         verify(mUsageStats).registerBlocked(any());
@@ -10448,7 +10586,7 @@
 
         mService.addEnqueuedNotification(r);
         mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), r.getUid(),
-                mPostNotificationTrackerFactory.newTracker()).run();
+                mPostNotificationTrackerFactory.newTracker(null)).run();
         waitForIdle();
 
         verify(mUsageStats).registerBlocked(any());
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
index 66c1e35..81c573d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
@@ -48,6 +48,7 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.os.Looper;
+import android.os.PowerManager;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.permission.PermissionManager;
@@ -169,6 +170,7 @@
                     mock(UsageStatsManagerInternal.class), mock(TelecomManager.class),
                     mock(NotificationChannelLogger.class), new TestableFlagResolver(),
                     mock(PermissionManager.class),
+                    mock(PowerManager.class),
                     new NotificationManagerService.PostNotificationTrackerFactory() {});
         } catch (SecurityException e) {
             if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
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 cb984f8..3ff433e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1996,7 +1996,8 @@
 
         assertTrue(activity.isSnapshotCompatible(snapshot));
 
-        setRotatedScreenOrientationSilently(activity);
+        doReturn(task.getWindowConfiguration().getRotation() + 1).when(mDisplayContent)
+                .rotationForActivityInDifferentOrientation(activity);
 
         assertFalse(activity.isSnapshotCompatible(snapshot));
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index 4890f3e6..bcb0c6b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -250,9 +250,22 @@
     }
 
     @Test
-    public void testInterceptQuietProfile() {
-        // GIVEN that the user the activity is starting as is currently in quiet mode
+    public void testInterceptQuietProfile_keepProfilesRunningEnabled() {
+        // GIVEN that the user the activity is starting as is currently in quiet mode and
+        // profiles are kept running when in quiet mode.
         when(mUserManager.isQuietModeEnabled(eq(UserHandle.of(TEST_USER_ID)))).thenReturn(true);
+        when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(true);
+
+        // THEN calling intercept returns false because package also has to be suspended.
+        assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null,  null, 0, 0, null));
+    }
+
+    @Test
+    public void testInterceptQuietProfile_keepProfilesRunningDisabled() {
+        // GIVEN that the user the activity is starting as is currently in quiet mode and
+        // profiles are stopped when in quiet mode (pre-U behavior, no profile app suspension).
+        when(mUserManager.isQuietModeEnabled(eq(UserHandle.of(TEST_USER_ID)))).thenReturn(true);
+        when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(false);
 
         // THEN calling intercept returns true
         assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null,  null, 0, 0, null));
@@ -263,10 +276,28 @@
     }
 
     @Test
-    public void testInterceptQuietProfileWhenPackageSuspended() {
+    public void testInterceptQuietProfileWhenPackageSuspended_keepProfilesRunningEnabled() {
+        // GIVEN that the user the activity is starting as is currently in quiet mode,
+        // the package is suspended and profiles are kept running while in quiet mode.
         suspendPackage("com.test.suspending.package");
-        // GIVEN that the user the activity is starting as is currently in quiet mode
         when(mUserManager.isQuietModeEnabled(eq(UserHandle.of(TEST_USER_ID)))).thenReturn(true);
+        when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(true);
+
+        // THEN calling intercept returns true
+        assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+
+        // THEN the returned intent is the quiet mode intent
+        assertTrue(UnlaunchableAppActivity.createInQuietModeDialogIntent(TEST_USER_ID)
+                .filterEquals(mInterceptor.mIntent));
+    }
+
+    @Test
+    public void testInterceptQuietProfileWhenPackageSuspended_keepProfilesRunningDisabled() {
+        // GIVEN that the user the activity is starting as is currently in quiet mode,
+        // the package is suspended and profiles are stopped while in quiet mode.
+        suspendPackage("com.test.suspending.package");
+        when(mUserManager.isQuietModeEnabled(eq(UserHandle.of(TEST_USER_ID)))).thenReturn(true);
+        when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(false);
 
         // THEN calling intercept returns true
         assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 0044e2e..4290f4b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
@@ -1059,4 +1060,18 @@
         assertEquals(0, mAtm.getActivityInterceptorCallbacks().size());
         mAtm.mInternal.unregisterActivityStartInterceptor(SYSTEM_FIRST_ORDERED_ID);
     }
+
+    @Test
+    public void testFocusTopTask() {
+        final ActivityRecord homeActivity = new ActivityBuilder(mAtm)
+                .setTask(mRootWindowContainer.getDefaultTaskDisplayArea().getOrCreateRootHomeTask())
+                .build();
+        final Task pinnedTask = new TaskBuilder(mSupervisor).setCreateActivity(true)
+                .setWindowingMode(WINDOWING_MODE_PINNED)
+                .build();
+        mAtm.focusTopTask(mDisplayContent.mDisplayId);
+
+        assertTrue(homeActivity.getTask().isFocused());
+        assertFalse(pinnedTask.isFocused());
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
index 3ca35ef..8e015d4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
@@ -40,7 +40,9 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
@@ -51,6 +53,8 @@
 import android.app.servertransaction.ResumeActivityItem;
 import android.content.ComponentName;
 import android.content.pm.ActivityInfo.ScreenOrientation;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Configuration.Orientation;
 import android.hardware.camera2.CameraManager;
@@ -84,7 +88,7 @@
     private static final String TEST_PACKAGE_2 = "com.test.package.two";
     private static final String CAMERA_ID_1 = "camera-1";
     private static final String CAMERA_ID_2 = "camera-2";
-
+    private static final String TEST_PACKAGE_1_LABEL = "testPackage1";
     private CameraManager mMockCameraManager;
     private Handler mMockHandler;
     private LetterboxConfiguration mLetterboxConfiguration;
@@ -133,17 +137,27 @@
     }
 
     @Test
-    public void testOpenedCameraInSplitScreen_showToast() {
+    public void testOpenedCameraInSplitScreen_showToast() throws Exception {
         configureActivity(SCREEN_ORIENTATION_PORTRAIT);
         spyOn(mTask);
         spyOn(mDisplayRotationCompatPolicy);
         doReturn(WINDOWING_MODE_MULTI_WINDOW).when(mActivity).getWindowingMode();
         doReturn(WINDOWING_MODE_MULTI_WINDOW).when(mTask).getWindowingMode();
 
+        final PackageManager mockPackageManager = mock(PackageManager.class);
+        final ApplicationInfo mockApplicationInfo = mock(ApplicationInfo.class);
+        when(mContext.getPackageManager()).thenReturn(mockPackageManager);
+        when(mockPackageManager.getApplicationInfo(anyString(), anyInt()))
+                .thenReturn(mockApplicationInfo);
+
+        doReturn(TEST_PACKAGE_1_LABEL).when(mockPackageManager)
+                .getApplicationLabel(mockApplicationInfo);
+
         mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
 
         verify(mDisplayRotationCompatPolicy).showToast(
-                R.string.display_rotation_camera_compat_toast_in_split_screen);
+                R.string.display_rotation_camera_compat_toast_in_multi_window,
+                TEST_PACKAGE_1_LABEL);
     }
 
     @Test
@@ -157,7 +171,8 @@
         mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
 
         verify(mDisplayRotationCompatPolicy, never()).showToast(
-                R.string.display_rotation_camera_compat_toast_in_split_screen);
+                R.string.display_rotation_camera_compat_toast_in_multi_window,
+                TEST_PACKAGE_1_LABEL);
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 04e1d9c..2a8f0ffc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -59,10 +59,10 @@
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
 import android.hardware.devicestate.DeviceStateManager;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.PowerManagerInternal;
 import android.os.SystemClock;
-import android.os.Handler;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
 import android.view.DisplayAddress;
@@ -518,7 +518,8 @@
         mBuilder.build();
         configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
 
-        when(mDeviceStateController.shouldReverseRotationDirectionAroundZAxis()).thenReturn(true);
+        when(mDeviceStateController.shouldReverseRotationDirectionAroundZAxis(mMockDisplayContent))
+                .thenReturn(true);
 
         thawRotation();
 
@@ -544,7 +545,8 @@
     @Test
     public void testFreezeRotation_reverseRotationDirectionAroundZAxis_yes() throws Exception {
         mBuilder.build();
-        when(mDeviceStateController.shouldReverseRotationDirectionAroundZAxis()).thenReturn(true);
+        when(mDeviceStateController.shouldReverseRotationDirectionAroundZAxis(mMockDisplayContent))
+                .thenReturn(true);
 
         freezeRotation(Surface.ROTATION_90);
         assertEquals(Surface.ROTATION_270, mTarget.getUserRotation());
@@ -553,7 +555,8 @@
     @Test
     public void testFreezeRotation_reverseRotationDirectionAroundZAxis_no() throws Exception {
         mBuilder.build();
-        when(mDeviceStateController.shouldReverseRotationDirectionAroundZAxis()).thenReturn(false);
+        when(mDeviceStateController.shouldReverseRotationDirectionAroundZAxis(mMockDisplayContent))
+                .thenReturn(false);
 
         freezeRotation(Surface.ROTATION_90);
         assertEquals(Surface.ROTATION_90, mTarget.getUserRotation());
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
index fb29d3a..abf21a5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
@@ -641,6 +641,31 @@
         // Home split secondary and home task should be invisible.
         assertEquals(TASK_FRAGMENT_VISIBILITY_INVISIBLE,
                 splitSecondary.getVisibility(null /* starting */));
+
+        // Put another task on top of primary split.
+        final Task topSplitPrimary = new TaskBuilder(mSupervisor).setParentTask(organizer.mPrimary)
+                .setCreateActivity(true).build();
+        doReturn(false).when(topSplitPrimary).isTranslucent(any());
+        // Convert the fullscreen translucent task to opaque.
+        doReturn(false).when(translucentRootTask).isTranslucent(any());
+        translucentRootTask.moveToFront("test");
+        // The tasks of primary split are occluded by the fullscreen opaque task.
+        assertEquals(TASK_FRAGMENT_VISIBILITY_INVISIBLE,
+                organizer.mPrimary.getVisibility(null /* starting */));
+        assertEquals(TASK_FRAGMENT_VISIBILITY_INVISIBLE,
+                topSplitPrimary.getVisibility(null /* starting */));
+        // Make primary split root transient-hide.
+        spyOn(splitPrimary.mTransitionController);
+        doReturn(true).when(splitPrimary.mTransitionController).isTransientHide(
+                organizer.mPrimary);
+        // The split root and its top become visible.
+        assertEquals(TASK_FRAGMENT_VISIBILITY_VISIBLE,
+                organizer.mPrimary.getVisibility(null /* starting */));
+        assertEquals(TASK_FRAGMENT_VISIBILITY_VISIBLE,
+                topSplitPrimary.getVisibility(null /* starting */));
+        // The bottom of primary split becomes invisible because it is occluded by topSplitPrimary.
+        assertEquals(TASK_FRAGMENT_VISIBILITY_INVISIBLE,
+                splitPrimary.getVisibility(null /* starting */));
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 2dd34eb..082122e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -406,7 +406,6 @@
         clearInvocations(translucentActivity.mLetterboxUiController);
 
         // We destroy the first opaque activity
-        mActivity.setState(DESTROYED, "testing");
         mActivity.removeImmediately();
 
         // Check that updateInheritedLetterbox() is invoked again
@@ -4654,14 +4653,6 @@
         return c;
     }
 
-    private static void resizeDisplay(DisplayContent displayContent, int width, int height) {
-        displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity,
-                displayContent.mBaseDisplayPhysicalXDpi, displayContent.mBaseDisplayPhysicalYDpi);
-        final Configuration c = new Configuration();
-        displayContent.computeScreenConfiguration(c);
-        displayContent.onRequestedOverrideConfigurationChanged(c);
-    }
-
     private static void setNeverConstrainDisplayApisFlag(@Nullable String value,
             boolean makeDefault) {
         DeviceConfig.setProperty(NAMESPACE_CONSTRAIN_DISPLAY_APIS,
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index b59f027..1126726 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -1346,6 +1346,16 @@
         activity1.setVisible(false);
         abortTransition.abort();
         assertTrue(activity1.isVisible());
+
+        // The mLaunchTaskBehind flag of an invisible initializing activity should not be cleared.
+        final Transition noChangeTransition = controller.createTransition(TRANSIT_OPEN);
+        noChangeTransition.collect(activity1);
+        activity1.setVisibleRequested(false);
+        activity1.setState(ActivityRecord.State.INITIALIZING, "test");
+        activity1.mLaunchTaskBehind = true;
+        mWm.mSyncEngine.abort(noChangeTransition.getSyncId());
+        noChangeTransition.finishTransition();
+        assertTrue(activity1.mLaunchTaskBehind);
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index 01ddcca..f3d8114 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -127,6 +127,10 @@
     public void testWallpaperSizeWithFixedTransform() {
         // No wallpaper
         final DisplayContent dc = mDisplayContent;
+        if (dc.mBaseDisplayHeight == dc.mBaseDisplayWidth) {
+            // Make sure the size is different when changing orientation.
+            resizeDisplay(dc, 500, 1000);
+        }
 
         // No wallpaper WSA Surface
         final WindowState wallpaperWindow = createWallpaperWindow(dc);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index ddc729f..be8ee78 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -71,6 +71,7 @@
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.res.Configuration;
 import android.graphics.Insets;
 import android.graphics.Rect;
 import android.hardware.HardwareBuffer;
@@ -946,6 +947,14 @@
         dc.setRotationAnimation(null);
     }
 
+    static void resizeDisplay(DisplayContent displayContent, int width, int height) {
+        displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity,
+                displayContent.mBaseDisplayPhysicalXDpi, displayContent.mBaseDisplayPhysicalYDpi);
+        final Configuration c = new Configuration();
+        displayContent.computeScreenConfiguration(c);
+        displayContent.onRequestedOverrideConfigurationChanged(c);
+    }
+
     // The window definition for UseTestDisplay#addWindows. The test can declare to add only
     // necessary windows, that avoids adding unnecessary overhead of unused windows.
     static final int W_NOTIFICATION_SHADE = TYPE_NOTIFICATION_SHADE;
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 1888943..5b1c6b1 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -10318,7 +10318,7 @@
         sDefaults.putInt(KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT,
                 CellSignalStrengthLte.USE_RSRP);
         sDefaults.putInt(KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT, 300);
-        sDefaults.putInt(KEY_PREFERRED_IKE_PROTOCOL_INT, 0);
+        sDefaults.putInt(KEY_PREFERRED_IKE_PROTOCOL_INT, -1);
         // Default wifi configurations.
         sDefaults.putAll(Wifi.getDefaults());
         sDefaults.putBoolean(ENABLE_EAP_METHOD_PREFIX_BOOL, false);
diff --git a/tests/InputMethodStressTest/Android.bp b/tests/InputMethodStressTest/Android.bp
index 27640a5..84845c6 100644
--- a/tests/InputMethodStressTest/Android.bp
+++ b/tests/InputMethodStressTest/Android.bp
@@ -30,7 +30,6 @@
     ],
     test_suites: [
         "general-tests",
-        "vts",
     ],
     data: [
         ":SimpleTestIme",
diff --git a/tests/InputMethodStressTest/AndroidTest.xml b/tests/InputMethodStressTest/AndroidTest.xml
index bedf099..bfebb42 100644
--- a/tests/InputMethodStressTest/AndroidTest.xml
+++ b/tests/InputMethodStressTest/AndroidTest.xml
@@ -19,6 +19,7 @@
     <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
 
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_abi_dialog 1" />
         <option name="run-command" value="settings put secure show_ime_with_hard_keyboard 1" />
         <option name="teardown-command" value="settings delete secure show_ime_with_hard_keyboard" />
     </target_preparer>
diff --git a/tests/SilkFX/res/layout/gainmap_transform_test.xml b/tests/SilkFX/res/layout/gainmap_transform_test.xml
new file mode 100644
index 0000000..5aeb536
--- /dev/null
+++ b/tests/SilkFX/res/layout/gainmap_transform_test.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<com.android.test.silkfx.hdr.GainmapTransformsTest xmlns:android="http://schemas.android.com/apk/res/android"
+                                               android:layout_width="match_parent"
+                                               android:layout_height="match_parent"
+                                               android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+
+        <Button
+            android:id="@+id/original"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="Original" />
+
+        <Button
+            android:id="@+id/scaled"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="Scaled (1/3)" />
+
+        <Button
+            android:id="@+id/rotate_90"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="Rotate 90" />
+
+        <Button
+            android:id="@+id/rotate_90_scaled"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="Rot90+Scale" />
+
+        <Button
+            android:id="@+id/crop"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="Crop" />
+
+        <Button
+            android:id="@+id/crop_200"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="Crop 200" />
+
+    </LinearLayout>
+
+    <TextView
+        android:id="@+id/source_info"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="horizontal">
+
+        <LinearLayout
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:orientation="vertical"
+            android:layout_weight="1">
+
+            <TextView
+                android:id="@+id/sdr_label"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+
+            <ImageView
+                android:id="@+id/sdr_source"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_margin="8dp"
+                android:scaleType="fitStart" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:orientation="vertical"
+            android:layout_weight="1">
+
+            <TextView
+                android:id="@+id/gainmap_label"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+
+            <ImageView
+                android:id="@+id/gainmap"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_margin="8dp"
+                android:scaleType="fitStart" />
+        </LinearLayout>
+
+    </LinearLayout>
+
+</com.android.test.silkfx.hdr.GainmapTransformsTest>
\ No newline at end of file
diff --git a/tests/SilkFX/src/com/android/test/silkfx/Main.kt b/tests/SilkFX/src/com/android/test/silkfx/Main.kt
index a6cdbb9..59a6078 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/Main.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/Main.kt
@@ -55,7 +55,9 @@
                 Demo("Color Grid", R.layout.color_grid),
                 Demo("Gradient Sweep", R.layout.gradient_sweep),
                 Demo("Gainmap Image", R.layout.gainmap_image),
-                Demo("Gainmap Decode Test", R.layout.gainmap_decode_test, commonControls = false)
+                Demo("Gainmap Decode Test", R.layout.gainmap_decode_test, commonControls = false),
+                Demo("Gainmap Transform Test", R.layout.gainmap_transform_test,
+                        commonControls = false)
         )),
         DemoGroup("Materials", listOf(
                 Demo("Glass", GlassActivity::class),
diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt
index a004fb5..585320ae 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt
@@ -17,7 +17,12 @@
 package com.android.test.silkfx.hdr
 
 import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.ColorMatrixColorFilter
+import android.graphics.Gainmap
 import android.graphics.ImageDecoder
+import android.graphics.Paint
 import android.graphics.Rect
 import android.util.AttributeSet
 import android.widget.Button
@@ -34,6 +39,25 @@
     CropedSquaredScaled33
 }
 
+fun gainmapVisualizer(gainmap: Gainmap): Bitmap {
+    val map = gainmap.gainmapContents
+    val gainmapVisualizer = Bitmap.createBitmap(map.width, map.height,
+            Bitmap.Config.ARGB_8888)
+    val canvas = Canvas(gainmapVisualizer!!)
+    val paint = Paint()
+    paint.colorFilter = ColorMatrixColorFilter(
+            floatArrayOf(
+                    0f, 0f, 0f, 1f, 0f,
+                    0f, 0f, 0f, 1f, 0f,
+                    0f, 0f, 0f, 1f, 0f,
+                    0f, 0f, 0f, 0f, 255f
+            )
+    )
+    canvas.drawBitmap(map, 0f, 0f, paint)
+    canvas.setBitmap(null)
+    return gainmapVisualizer
+}
+
 class GainmapDecodeTest(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) {
 
     private fun decode(mode: DecodeMode) {
@@ -71,7 +95,7 @@
             }
         }
 
-        val gainmapContents = gainmapImage.gainmap!!.gainmapContents!!
+        val gainmapContents = gainmapImage.gainmap?.let { gainmapVisualizer(it) }
         val sdrBitmap = gainmapImage.also { it.gainmap = null }
 
         findViewById<ImageView>(R.id.sdr_source)!!.setImageBitmap(sdrBitmap)
@@ -80,7 +104,7 @@
 
         findViewById<ImageView>(R.id.gainmap)!!.setImageBitmap(gainmapContents)
         findViewById<TextView>(R.id.gainmap_label)!!.text =
-            "Gainmap Size: ${gainmapContents.width}x${gainmapContents.height}"
+            "Gainmap Size: ${gainmapContents?.width ?: 0}x${gainmapContents?.height ?: 0}"
     }
 
     override fun onFinishInflate() {
diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapTransformsTest.kt b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapTransformsTest.kt
new file mode 100644
index 0000000..20984fa
--- /dev/null
+++ b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapTransformsTest.kt
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.silkfx.hdr
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.ImageDecoder
+import android.graphics.Matrix
+import android.util.AttributeSet
+import android.widget.Button
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.TextView
+import com.android.test.silkfx.R
+
+class GainmapTransformsTest(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) {
+
+    private val sourceImage = loadSample()
+
+    private fun loadSample(): Bitmap {
+        val source = ImageDecoder.createSource(resources.assets,
+                "gainmaps/${context.assets.list("gainmaps")!![0]}")
+
+        return ImageDecoder.decodeBitmap(source) { decoder, info, source ->
+            decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE
+        }
+    }
+
+    private fun process(transform: (Bitmap) -> Bitmap) {
+        val result = transform(sourceImage)
+
+        val gainmapContents = result.gainmap?.let { gainmapVisualizer(it) }
+        val sdrBitmap = result.also { it.gainmap = null }
+
+        findViewById<ImageView>(R.id.sdr_source)!!.setImageBitmap(sdrBitmap)
+        findViewById<TextView>(R.id.sdr_label)!!.text =
+                "SDR Size: ${sdrBitmap.width}x${sdrBitmap.height}"
+
+        findViewById<ImageView>(R.id.gainmap)!!.setImageBitmap(gainmapContents)
+        findViewById<TextView>(R.id.gainmap_label)!!.text =
+                "Gainmap Size: ${gainmapContents?.width ?: 0}x${gainmapContents?.height ?: 0}"
+    }
+
+    override fun onFinishInflate() {
+        super.onFinishInflate()
+        val sourceInfo = findViewById<TextView>(R.id.source_info)!!
+        sourceInfo.text = "Original size ${sourceImage.width}x${sourceImage.height}"
+        process { it.copy(Bitmap.Config.ARGB_8888, false) }
+
+        findViewById<Button>(R.id.original)!!.setOnClickListener {
+            process { it.copy(Bitmap.Config.ARGB_8888, false) }
+        }
+
+        findViewById<Button>(R.id.scaled)!!.setOnClickListener {
+            process { Bitmap.createScaledBitmap(it, it.width / 3, it.height / 3, true) }
+        }
+
+        findViewById<Button>(R.id.rotate_90)!!.setOnClickListener {
+            process {
+                val width: Int = it.width
+                val height: Int = it.height
+
+                val m = Matrix()
+                m.setRotate(90.0f, (width / 2).toFloat(), (height / 2).toFloat())
+                Bitmap.createBitmap(it, 0, 0, width, height, m, false)
+            }
+        }
+
+        findViewById<Button>(R.id.rotate_90_scaled)!!.setOnClickListener {
+            process {
+                val width: Int = it.width
+                val height: Int = it.height
+
+                val m = Matrix()
+                m.setRotate(90.0f, (width / 2).toFloat(), (height / 2).toFloat())
+                m.preScale(.3f, .3f)
+                Bitmap.createBitmap(it, 0, 0, width, height, m, false)
+            }
+        }
+
+        findViewById<Button>(R.id.crop)!!.setOnClickListener {
+            process {
+                val width: Int = it.width
+                val height: Int = it.height
+                Bitmap.createBitmap(it, width / 2, height / 2,
+                        width / 4, height / 4, null, false)
+            }
+        }
+
+        findViewById<Button>(R.id.crop_200)!!.setOnClickListener {
+            process {
+                val width: Int = it.width
+                val height: Int = it.height
+
+                val m = Matrix()
+                m.setRotate(200.0f, (width / 2).toFloat(), (height / 2).toFloat())
+                Bitmap.createBitmap(it, width / 2, height / 2,
+                        width / 4, height / 4, m, false)
+            }
+        }
+    }
+}
\ No newline at end of file